API Programming in C++

The following is a sample API program in the C++ language.


Top of page

Example: C++ Source for EDAAPP

          //////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\
// \\
// EDAAPP.CPP -- A Sample C++ API application \\
// \\
//////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\

#define SCR_WIDTH (80L)
#define EDA_TYPES
#define EDA_VARIABLES
#define LINT_ARGS
#include "eda.h"

#include <stdlib.h>
#include <iostream.h>
#include <iomanip.h>
#include <string.h>
#include <ctype.h>

////////////////////////////////////////////////////////////////////////
// Sample client application program. //
// //
// APP1 demonstrates API client behavior. //
// APP1 gives the user a choice of servers, connects with one and then //
// takes SQL requests from the user and sends them to the server. //
// //
// The style used here is aimed at helping your comprehension. All of //
// the features demonstrated here may be used in your applications if //
// they are appropriate for you. Before using any code examples from //
// this program, be sure that you understand them. //
// //
// If you are reading this code as an example, start from the bottom, //
// (main) and work your way through the calling tree. If you run //
// this program in the debugger, simply step through each function. //
// //
//////////////////////////////////////////////////////////////////////////
const char *hexchars = "0123456789ABCDEF";

const char *messages[] = {
"Not supported in this release. ", "Internal API error. ",
"Access denied. ", "Tuple misaligned. ",
"Bad parameter value. ", "Memory overflow. ",
"Invalid operation. ", "Data receive error. ",
"Data send error. ", "Error disconnecting from server.",
"Error connecting to server. ", "Error closing EDALINK. ",
"Error opening EDALINK. ", "SCB initialized ",
"SCB uninitialized. ", "Too many SCB's. ",
"Invalid sid. ", "Too many EDA contexts. ",
"Invalid eid. ", "OK. ",
"Field not found. ", "No field information available. ",
"Break occurred. ", "Tuple has been truncated. ",
"End of tuple answer set. ", "Timeout occurred. ",
"End of transmission from server."
};

EDA_ID eid; // EDA id for this application.
EDA_scb scb; // A session control block.
long width; // Width of current output line.


////////////////////////////////////////////////////////////////////////////
// //
// Class edaapi contains EDA application interface processing functions. //
// //
/////////////////////////////////////////////////////////////////////////////

class edaapi {
public:
static void check_stat( const char *cmd ) {
char m_str[40];
if (scb.status == EDA_END_OF_SET && scb.count == -1)
cout << "\n<<< No data returned. >>>" << endl;
else if (scb.status == EDA_END_OF_SET)
cout << "\n<<< " << scb.count << " record(s) processed. >>>" << endl;
else if (scb.status != 0) {
strncpy(m_str, cmd, 12);
m_str[12] = '\0';
cout << "\n[APP1] " << m_str << " : "
"Ret Code = " << scb.status << " : " ;
strncpy(m_str, messages[(int) scb.status - EDA_API_MAX_ERROR], 38);
m_str[38] = '\0';
cout << m_str << endl;
}
return;
}

void check_init( const char *cmd ) {
char m_str[40];
if (scb.status != 0) {
strncpy(m_str, cmd, 12);
m_str[12] = '\0';
cout << "\n[APP1] " << m_str << " : "
"Ret Code = " << scb.status << " : " ;
strncpy(m_str, messages[(int) scb.status - EDA_API_MAX_ERROR], 38);
m_str[38] = '\0';
cout << m_str << endl;
}
return;
}

/////////////////////////////////////////////////////////////
// Member function initialize_eda for initializing the API. //
//////////////////////////////////////////////////////////////

void initialize_eda() {
long MAJOR_VERSION = EDA_VAR_MAJOR;
long MINOR_VERSION = EDA_VAR_MINOR;
long VAR_AUTOCOMMIT = EDA_VAR_AUTOCOMMIT;
long VAR_OFF = 0;
long major, minor;

EDAINSPECT( NULL, NULL, &MAJOR_VERSION, &major, &(scb.status));
EDAINSPECT( NULL, NULL, &MINOR_VERSION, &minor, &(scb.status));

cout << "\nAPP 1 : Initializing API, Version " << major
<< " Release " << minor << endl;

EDAINIT( &eid, &(scb.status) );

check_init( "EDAINIT " );
if (scb.status < EDA_SUCCESS)
exit(1);

// Turn off AUTO COMMIT.
EDASET( &eid, NULL, &VAR_AUTOCOMMIT, &VAR_OFF, &(scb.status));

check_stat( scb.command );
if (scb.status != EDA_SUCCESS)
exit(1);
}

///////////////////////////////////////////////////////////////////////
// Member choose_server displays the available EDA servers and allows //
// user to choose one for this session. Then it connects the server. //
// No user/password support is provide here. //
////////////////////////////////////////////////////////////////////////

void choose_server() {
long N_SERVERS = 18;
long BUFFRLEN = 256;
char user[21];
char password[21];
long u_len = 0, p_len = 0;
char buffr[256];
char *server;
long ii, j, len;

EDASERVERS( &eid, buffr, &BUFFRLEN, &(scb.status));
EDAINSPECT( &eid, NULL, &N_SERVERS, &ii, &(scb.status));

// Get the number of servers (EDA Entities) and their names.

buffr[ii*8] = '\0';
cout << "\nThe following server(s) are available: ";
for (j=0; j<ii; j++)
cout << &buffr[8*j] << " " ;
cout << endl;

// Show the first server as a default to the user.

buffr[8] = '\0'; // NULL terminate the first entity as a string.
// The rest of buffr[] is scratch space in cin.get().

cout << "\nEnter Server name (default \"" << buffr << "\"): " <<flush;
cin.get( &buffr[9], (int)BUFFRLEN-9 );
server = &buffr[9];

if (server) {
len = strlen(server);
cin.get(server[len]); // Clear <cr> from input.
server[len] = '\0'; // Replace <cr> with null.
}
if (!server || len < 1) {
server = buffr;
len = 8;
}

cout << "\nEnter User Name: " << flush;
cin.get(user,21);
cin.get(user[21]);
cout << "\nEnter Password: " << flush;
cin.get(password,21);
cin.get(password[21]);

// Establish the connection with the server.

EDACONNECT(&eid, &scb, user, &u_len, password, &p_len, server, &len);
check_stat( scb.command );
if (scb.status != EDA_SUCCESS)
exit(1);
}

/////////////////////////////////////////////////////////////////////
// Member check_msg prints all pending messages on standard output. //
//////////////////////////////////////////////////////////////////////

static void check_msg() {
char m_str[40];
memset (m_str, 0, 40);
if (scb.msg_type == 1)
strcat(m_str, "\n[EDA-");
else
strcat(m_str, "\n[RPC-");
strncat(m_str, scb.msg_org, 8);
m_str[13] = '\0';
if (memcmp(scb.msg_org, "SMART ", 8) || scb.msg_text[0] != '0') {
cout << m_str << "] (" << scb.msg_code << ") "
<< scb.msg_text << endl;
}

while (scb.msg_pending) {
EDAACCEPT(&scb);
if (scb.msg_type == 1)
strcat( m_str, "\n[EDA-");
else
strcat( m_str, "\n[RPC-");
strncat( m_str, scb.msg_org, 8);
m_str[13] = '\0';
if (memcmp(scb.msg_org, "SMART ", 8) || scb.msg_text[0] != '0')
{
cout << m_str << "] (" << scb.msg_code << ") "
<< scb.msg_text << endl;
}
}
}
    //////////////////////////////////////////////////////////////////////////
// Member functions to display the given field types to standard output. //
///////////////////////////////////////////////////////////////////////////

static void display(char *loc) { // Alphanumeric data display
cout << loc << " " ;
}

static void display(long *loc) { // Integer data display
cout << setprecision(0) << *(long *)loc << " " ;
}

static void display(float *loc) { // Float data display
cout << setprecision(4) << *(float *)loc << " " ;
}

static void display(double *loc) { // Double data display
cout << setprecision(4) << *(double *)loc << " " ;
}

static void display(char *loc, int dcml) { // Packed decimal display
long num = 0;
double dnum;

for (int i=0; i<7; i++) {
num = num * 10 + ((loc[i] & 0xf0) >> 4);
num = num * 10 + (loc[i] & 0x0f);
}
num = num * 10 + ((loc[7] & 0xf0) >> 4);
if ((loc[7] & 0x0f) == 0xD)
num = -num;
dnum = num;
long iii = 0;
for (iii=0; iii<dcml; iii++)
dnum /= 10;
display((double *)&dnum);
}

static void display(char *loc, long length) { // Binary data display
int val;
for (int i=0; i<(int)length; i++) {
val = (loc[i] & 0xF0) >> 4;
cout << setprecision(0) << hexchars[val] ;
val = (loc[i] & 0x0F);
cout << hexchars[val] ;
}
cout << " " ;
}

static void display() { // Null field display
cout << "...." ;
cout << " " ;
}

static void check_line(long length) { // Make sure output line
if ((width + length) > SCR_WIDTH) { // is not too long.
cout << endl;
width = 0;
}
}


////////////////////////////////////////////////////////////////////////////
// Member process_response to receive an answer set from the server after //
// an SQL or RPC call. Zero, one or more messages may be received with the //
// answer set. The last status is returned (success, error, etc). //
/////////////////////////////////////////////////////////////////////////////

static void process_response() {
EDA_info_area info_area;
char *tup; // Pointer to tuple buffer
char *fld; // Pointer to field within buffer
long cnbr; // Column number
long is_null = EDA_IS_NOT_NULL;
long fmt_type = EDA_BINARY;

// Determine the size of response information and allocate a buffer.

cnbr = 1;
EDAINFO(&scb, &cnbr, &info_area);
check_stat( scb.command );
if ((scb.status < EDA_SUCCESS) && scb.status != EDA_NO_FIELD_INFO)
return;

tup = (char *) malloc((int) scb.b_size + 1);
if (tup == NULL) {
scb.status = EDA_MEMORY_OVERFLOW;
check_stat( scb.command );
return;
}

tup[scb.b_size] = '\0';
cout.setf(ios::fixed);

EDAFETCH(&scb, tup, &(scb.b_size), &fmt_type);
check_stat( scb.command );
if (scb.status < EDA_SUCCESS)
return;

if (scb.msg_type != 0)
check_msg();

////////////////////////////////////////////////////////////
// Process tuples from the answer set and display messages //
// until an EDA_END_OF_SET status is returned by EDAFETCH. //
/////////////////////////////////////////////////////////////

while (scb.status != EDA_END_OF_SET) {
cout << '\n';
width = 0;
cnbr = 0;
while (++cnbr <= scb.nbrcols) {
EDAINFO(&scb, &cnbr, &info_area);
check_stat( scb.command );
if (scb.status < EDA_SUCCESS)
return;
EDANULL(&scb, &cnbr, &is_null);
check_stat( scb.command );
if (scb.status < EDA_SUCCESS)
return;
if (is_null == EDA_IS_NULL) {
check_line(info_area.length);
cout.width((int)info_area.length);
display();
width += info_area.length + 2;
continue;
}
fld = tup + info_area.b_offset;
switch ((short) info_area.type) {
case EDA_I_TYPE_CODE:
case EDA_DATE_TYPE_CODE:
check_line(info_area.length);
cout.width((int)info_area.length);
display((long *)fld);
width += info_area.length + 2;
break;
case EDA_F_TYPE_CODE:
check_line(info_area.length);
cout.width((int)info_area.length);
display((float *)fld);
width += info_area.length + 2;
break;
case EDA_D_TYPE_CODE:
check_line(info_area.length);
cout.width((int)info_area.length);
display((double *)fld);
width += info_area.length + 2;
break;
case EDA_A_TYPE_CODE:
case EDA_K_TYPE_CODE:
case EDA_T_TYPE_CODE:
fld[info_area.length]='\0';
display((char *)fld);
width = (width+info_area.length)%SCR_WIDTH + 2;
break;
case EDA_P_TYPE_CODE:
check_line(info_area.length);
cout.width((int)info_area.length);
display((char *)fld, (int)info_area.dcml);
width += info_area.length + 2;
break;
case EDA_B_TYPE_CODE:
check_line(info_area.length);
cout.width((int)info_area.length);
display((char *)fld, (long)info_area.b_size);
width = (width+info_area.length)%SCR_WIDTH + 2;
break;
}

}
cout << endl;
EDAFETCH(&scb, tup, &(scb.b_size), &fmt_type);
check_stat( scb.command );
if (scb.status < EDA_SUCCESS)
return;
if (scb.msg_type != 0)
check_msg();
}
free(tup);
return;
}

//////////////////////////////////////////////////////////
// Member query_results parses through the answer set(s) //
// of user queries and writes to standard output. //
///////////////////////////////////////////////////////////

static void query_results() {
int more = 1;
int answer_sets = 0;

if (scb.msg_type != 0)
check_msg();

while (more) {
process_response();
if (scb.status)
return;

EDAQUIT(&scb);

if (scb.status == EDA_END_OF_TRAN)
more = 0;

if (scb.msg_type != 0)
check_msg();
answer_sets++;
}

if (answer_sets > 1)
cout << "\nServer responded with " << answer_sets << " answer sets."
<< endl;
}

////////////////////////////////////////////////////////////////////////////
// //
// Member process_queries accepts a query from standard input. Queries are //
// delimited by semicolons (';'). Each query is limited to 800 bytes. An //
// empty query will signal completion of input (you can hit EOF or ";"). //
// It calls class member query_results which handles data and messages. //
// //
/////////////////////////////////////////////////////////////////////////////

void process_queries() {
long est1 = 1;
long est2 = 1;
long ZERO = 0;
long ONE = 1;
int SLEN = 799;
EDA_info_area info_area;
char sbuffer[800];
char c;
long i;

cout << "\n\n<<< Successfully connected to server. >>>\n" << endl;

do {
cout << "________________________________________________________________________________\n"
"> Enter SQL command; Enter ';' to quit."
"\n> " << flush;
do {
cin.get(c);
} while (isspace(c));

for (i=0; i<SLEN && c != EOF && c != ';'; i++) {
if (isspace(c)) // Turn <cr>'s & tabs into ordinary spaces.
c = ' ';
else if (c == '\\') // Use a \ as an escape character.
cin.get(c);
sbuffer[i] = c;
cin.get(c);
}
if (i <= 0)
break;
sbuffer[i++] = ';';

EDASQL(&scb, sbuffer, &i, &est1, &est2, NULL, &ZERO, &ONE);
EDAINFO(&scb, &ONE, &info_area);
check_stat( "EDAINFO " );
if ((scb.status < EDA_SUCCESS) && scb.status != EDA_NO_FIELD_INFO)
break;

query_results();
if (scb.status > EDA_SUCCESS) // Ignore warning states.
scb.status = EDA_SUCCESS;
} while(scb.status == EDA_SUCCESS && c != EOF);

EDATERM ( &eid, &(scb.status) ); // End of Context.
cout << "\n\n<<< Exiting.... >>>\n\n";
}
}; // Class "edaapi" contains sample functions which use API calls.
// All API calls are in upper case letters (i.e. EDAINIT ).



/////////////////////////////////////////////////////////////////////////////
// //
// This is main(). It will initialize the API and make a connection //
// with the server entity chosen by the user. It will check the status of //
// the connection before continuing to process user's SQL queries. At the //
// end, when a null query is entered by user, it will terminate the session. //
// //
///////////////////////////////////////////////////////////////////////////////

int main()
{
edaapi *eda_p = new edaapi; // Create an instantiation of API
// pointed to by eda_p.

eda_p->initialize_eda(); // Intialize the API.

eda_p->choose_server(); // Choose and connect to a server entity.

eda_p->process_queries(); // Process user queries until EOF.

exit(0);
return 0;
}
 

iWay Software