Main Page Class Hierarchy Compound List File List Compound Members File Members

# request_template.cpp

Go to the documentation of this file.

    00001 /*
    00002  * request_template.cpp -- Example of a request message class for use
    00003  *                         in the mutable server model.
    00004  *
    00005  *                       In addition to passport handling, this example
    00006  *                       class is expected to also handle an integer and
    00007  *                       a char string of undetermined length (to demonstrate
    00008  *                       memory allocation and cleanup).
    00009  */
    00010
    00011 // START WITH THE CLASS DECLARATION IN THE .h FILE.
    00012
    00013 //******************************************************************************
    00014 // STEP 1: Do a global replacement of the string "RequestTemplate"
    00015 //         with the name of the new class
    00016 //******************************************************************************
    00017
    00018
    00019 //******************************************************************************
    00020 // STEP 2: Replace the name of the include file for the class declaration
    00021 //
    00022 //******************************************************************************
    00023 #include "request_template.h"
    00024
    00025
    00026 // THIS INCLUDE IS USED FOR THIS EXAMPLE, AND MAY NOT BE NEEDED FOR REAL
    00027 // IMPLEMENTATIONS.
    00028 #include <string.h>
    00029
    00030 //******************************************************************************
    00031 // STEP 3: Update the constructor to initialize all variables that were
    00032 //         declared in the .h (Base classes will initialize their own
    00033 //         variables as needed).
    00034 //
    00035 //******************************************************************************
    00036 //------------------------------------------------------------------------------
    00037 RequestTemplate::RequestTemplate()
    00038 {
    00039    // Any pointers that will reference memory allocated by this class
    00040    // MUST be NULLified here.
    00041    MyInt = 0;
    00042    MyCharPointer = NULL; // allocated in SetMyString()
    00043    MyStringLength = -1;  // indicates not even end-of-string
    00044 }
    00045
    00046 //******************************************************************************
    00047 // STEP 4: If the destructor declaration was included in the .h file,
    00048 //         implement it here, otherwise remove this method.
    00049 //
    00050 //******************************************************************************
    00051 //------------------------------------------------------------------------------
    00052 RequestTemplate::~RequestTemplate()
    00053 {
    00054    if ( MyCharPointer != NULL )
    00055    {
    00056       delete [] MyCharPointer;
    00057    }
    00058    // The class can't be used after destruction, so there is no need
    00059    // to set MyCharPointer back to NULL.
    00060 }
    00061
    00062 //******************************************************************************
    00063 // STEP 5: Implement the accessor methods declared for this specific class:
    00064 //         (there are four of them for this example)
    00065 //
    00066 //******************************************************************************
    00067
    00068 //------------------------------------------------------------------------------
    00069 void RequestTemplate::SetMyInteger( int p_int ) { MyInt = p_int; }
    00070 //------------------------------------------------------------------------------
    00071 bool RequestTemplate::SetMyString( const char * p_str )
    00072 {
    00073    bool return_status = true;  // assume good, unless error encountered
    00074
    00075    if (   p_str == NULL
    00076        || MyStringLength < strlen(p_str)
    00077       )
    00078    {
    00079       // Attempting to set the string to NULL
    00080       // Or the buffer is not large enough to contain it
    00081
    00082       // Drop any unrequired memory
    00083
    00084       if ( MyCharPointer != NULL )
    00085       {
    00086          delete [] MyCharPointer;
    00087
    00088          // MUST set the pointer to NULL to prevent a second
    00089          // attempt to deallocate when the destructor is called.
    00090          MyCharPointer = NULL;
    00091       }
    00092
    00093       MyStringLength = -1;
    00094    }
    00095
    00096
    00097    if ( p_str != NULL )
    00098    {
    00099       // Attempting to set the string to something
    00100       //
    00101
    00102       // [re]-allocate the buffer if needed
    00103
    00104       if ( MyCharPointer == NULL )
    00105       {
    00106          MyStringLength = strlen(p_str);
    00107
    00108          if ( (MyCharPointer = new char[ MyStringLength + 1 ]) == NULL )
    00109          {
    00110             // failed to get buffer memory
    00111             return_status = false;
    00112          }
    00113       }
    00114
    00115       if ( MyCharPointer != NULL )
    00116       {
    00117          // Have a buffer, assume it is of sufficient length.
    00118          // Copy the string into the memory
    00119
    00120          strcpy( MyCharPointer, p_str );
    00121       }
    00122    }
    00123
    00124    return return_status;
    00125 }
    00126 //------------------------------------------------------------------------------
    00127 int RequestTemplate::GetMyInteger() const { return MyInt; }
    00128 //------------------------------------------------------------------------------
    00129 char * RequestTemplate::GetMyString() const { return MyCharPointer; }
    00130
    00131 //******************************************************************************
    00132 // STEP 6: Implement the virtual methods that were declared but not defined
    00133 //         in the Base classes from which this one is derived.
    00134 //         (Deriving from MutableServerRequest means there are three, there may
    00135 //         be a different number for a different base class).
    00136 //
    00137 //******************************************************************************
    00138
    00139 //------------------------------------------------------------------------------
    00140 long RequestTemplate::BufferInitAlloc()
    00141 {
    00142    long ExpectedBufferLength = 0;
    00143
    00144    // First, call the immediate base class's method to get the buffer length
    00145    // required by all base classes.
    00146    //
    00147    // THIS CALL MUST BE INCLUDED IN THIS METHOD,
    00148    // AND IT MUST BE CALLED FOR THE CLASS FROM WHICH THIS ONE IS DERIVED.
    00149    //
    00150    ExpectedBufferLength = MutableServerRequest::BufferInitAlloc();
    00151
    00152
    00153    // NOW, ADD THE ADDITIONAL BUFFER LENGTH NEEDED BY THIS CLASS
    00154    //
    00155    // FOR SIMPLE MESSAGE CLASSES, THIS METHOD MIGHT BE SIMPLER.
    00156    // THE MAIN PURPOSE OF THE METHOD IS HELP REDUCE MEMORY REALLOCATIONS
    00157    // WHEN THE FINAL LENGTH OF THE MESSAGE IS UNKNOWN AT CODE TIME.
    00158    // FOR EXAMPLE, FOR MESSAGES THAT MIGHT HAVE ANY NUMBER OF DATA VALUES
    00159    // (i.e. like a message with zero or n passport lines).
    00160    //
    00161
    00162
    00163    // For this example, assume that MyInt won't be more than 15 digits:
    00164
    00165    ExpectedBufferLength += 15;
    00166
    00167    // Presuming that the int and string values for this class will be
    00168    // separated by '\n', add the length needed for that single char:
    00169
    00170    ExpectedBufferLength += 1;
    00171
    00172    // Add then length of the string, if the string is not NULL
    00173
    00174    if ( MyCharPointer != NULL )
    00175    {
    00176       ExpectedBufferLength += strlen( MyCharPointer );
    00177    }
    00178
    00179    // For this example, assume that we will always have an empty line
    00180    // even if the string contents are NULL
    00181    ExpectedBufferLength += 1;  // '\n'
    00182
    00183
    00184    return ExpectedBufferLength;
    00185 }
    00186 //------------------------------------------------------------------------------
    00187 void RequestTemplate::FormatDerivativeData()
    00188 {
    00189    // First, prepare the leading part of the buffer....that is, prepare
    00190    // the buffer part used by the base class(es):
    00191    //
    00192    // THIS CALL MUST BE PERFORMED AT THE START OF THIS METHOD,
    00193    // AND IT MUST BE CALLED FOR THE CLASS FROM WHICH THIS ONE IS DERIVED.
    00194    //
    00195    MutableServerRequest::FormatDerivativeData();
    00196
    00197    // NOW FORMAT AND APPEND THE BUFFER CONTENTS FOR THIS CLASS.
    00198
    00199    // For this example, we've got an int and possibly a char string.
    00200    // Each of which will be on a "line" terminated with '\n'
    00201
    00202    // THE ACTUAL BUFFER IS IMPLEMENTED WITH A C++ basic_string TYPE.
    00203    // A CHAR VALUE MAY BE APPENDED TO THE BUFFER WITH += AS SHOWN:
    00204
    00205    char _myint[18];
    00206
    00207    // format the MyInt line (including the line terminator)
    00208    //
    00209    sprintf( _myint, "%d\n MyInt );
    00210
    00211    MessageBuffer += _myint;
    00212
    00213    // Add the string, if it is not null
    00214
    00215    if ( MyCharPointer != NULL )
    00216    {
    00217       MessageBuffer += MyCharPointer;
    00218    }
    00219
    00220    // Terminate the string line
    00221
    00222    MessageBuffer += "\n";
    00223
    00224    // THE BASE CLASS PROCESSING WILL TERMINATE THE ENTIRE MESSAGE
    00225    // WITH AN ADDITIONAL '\N'
    00226
    00227 }
    00228 //------------------------------------------------------------------------------
    00229 void RequestTemplate::ParseDerivativeData()
    00230 {
    00231    // First, parse the leading part of the buffer....that is,
    00232    // the buffer part used by the base class(es):
    00233    //
    00234    // THIS CALL MUST BE PERFORMED AT THE START OF THIS METHOD,
    00235    // AND IT MUST BE CALLED FOR THE CLASS FROM WHICH THIS ONE IS DERIVED.
    00236    //
    00237    MutableServerRequest::ParseDerivativeData();
    00238
    00239    long _index;            // end of line index
    00240    std::string _readline;  // work buffer
    00241
    00242    // NOW PARSE THE PORTION OF THE BUFFER RELEVANT TO THIS MESSAGE CLASS
    00243
    00244    // NOTE THAT ALL ERRORS ARE REPORTED BY THROWING A worm_exception OBJECT.
    00245    // THERE ARE TWO WAYS TO FORMAT THE ERROR MESSAGE CONTAINED THEREIN, BOTH
    00246    // ARE DEMONSTRATE HEREIN.
    00247    //
    00248    // FYI, THE worm_exception IS CAUGHT AND REPORTED BY THE SERVER
    00249
    00250
    00251    // - - - - - - - - - - - - - - - - - - - - - - - - - -
    00252    // Handle the example's first data line
    00253
    00254
    00255    // Find the end of the next line in the buffer
    00256    //
    00257    if ( (_index = MessageBuffer.find("\n")) == MessageBuffer.npos )
    00258    {
    00259       // First way to throw a worm_exception object
    00260       throw worm_exception("Unterminated message while parsing RequestTemplate MyInt line");
    00261    }
    00262
    00263    // extract the line from the buffer
    00264    //
    00265    _readline = MessageBuffer.substr( 0 , _index );
    00266
    00267
    00268    // Remove the line from the buffer
    00269    //
    00270    MessageBuffer.erase( 0 , _index + 1 );
    00271
    00272
    00273    // Parse the line's value  (MyInt)
    00274    //
    00275    if ( sscanf( _readline.c_str(), "%d", &MyInt ) != 1 )
    00276    {
    00277       // Second way to throw a worm_exception object -- append string (int, float) value
    00278       worm_exception my_exception("RequestTemplate::ParseDerivativeData() Error: ");
    00279                      my_exception += "Failed to parse MyInt value";
    00280       throw my_exception;
    00281    }
    00282
    00283
    00284    // - - - - - - - - - - - - - - - - - - - - - - - - - -
    00285    // Handle the example's second data line
    00286    //    (the string value [which may be empty])
    00287
    00288    // Find then end of the next line in the buffer
    00289    //
    00290    if ( (_index = MessageBuffer.find("\n")) == MessageBuffer.npos )
    00291    {
    00292       throw worm_exception("Unterminated message while parsing RequestTemplate MyString line");
    00293    }
    00294
    00295    // extract the line from the buffer
    00296    //
    00297    _readline = MessageBuffer.substr( 0 , _index );
    00298
    00299    // Remove the line from the buffer
    00300    //
    00301    MessageBuffer.erase( 0 , _index + 1 );
    00302
    00303    // Set the string value
    00304    //
    00305    if ( _readline.size() == 0 )
    00306    {
    00307       // empty line
    00308       SetMyString( NULL );
    00309    }
    00310    else
    00311    {
    00312       // something in the line
    00313       SetMyString( _readline.c_str() );
    00314    }
    00315
    00316    // Any remaining buffer (resulting from further class derivation or
    00317    // just the end-of-message '\n') parse elsewhere
    00318 }
    00319 //------------------------------------------------------------------------------