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 //------------------------------------------------------------------------------

Generated on Tue May 6 09:16:07 2003 for Earthworm Libs by doxygen1.3-rc3