00001 /* 00002 * result_template.cpp -- Template of a result message class for use 00003 * in the mutable server model. 00004 * 00005 * See request_template.cpp for example code and comments 00006 * or magserverresult.cpp for a detailed implementation example. 00007 */ 00008 00009 // START WITH THE CLASS DECLARATION IN THE .h FILE. 00010 00011 //****************************************************************************** 00012 // STEP 1: Do a global replacement of the string "ResultTemplate" 00013 // with the name of the new class 00014 //****************************************************************************** 00015 00016 00017 //****************************************************************************** 00018 // STEP 2: Replace the name of the include file for the class declaration 00019 // 00020 //****************************************************************************** 00021 #include "result_template.h" 00022 00023 00024 00025 //****************************************************************************** 00026 // STEP 3: Update the constructor to initialize all variables that were 00027 // declared in the .h (Base classes will initialize their own 00028 // variables as needed). 00029 // 00030 //****************************************************************************** 00031 //------------------------------------------------------------------------------ 00032 ResultTemplate::ResultTemplate() 00033 { 00034 // INITIALIZE ANY CLASS VARIABLES 00035 00036 // Any pointers that will reference memory allocated by this class 00037 // MUST be NULLified here. 00038 00039 } 00040 00041 //****************************************************************************** 00042 // STEP 4: If the destructor declaration was included in the .h file, 00043 // uncomment and implement it here, otherwise remove this method. 00044 // 00045 //****************************************************************************** 00046 //------------------------------------------------------------------------------ 00047 /* 00048 ResultTemplate::~ResultTemplate() 00049 { 00050 // MEMORY ALLOCATED WITHIN THIS CLASS MUST BE DELETED HERE 00051 // (IF NOT PREVIOUSLY) 00052 00053 // EXAMPLE 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 //****************************************************************************** 00064 // STEP 5: Implement the accessor methods declared for this specific class: 00065 // (these examples equate to those in the template .h file) 00066 // 00067 //****************************************************************************** 00068 00069 //------------------------------------------------------------------------------ 00070 /* 00071 void ResultTemplate::SetMyInt( int parameterA ) 00072 { 00073 MyInt = parameterA; 00074 } 00075 */ 00076 //------------------------------------------------------------------------------ 00077 /* 00078 int ResultTemplate::GetMyInt() { return MyInt; } 00079 */ 00080 00081 00082 //****************************************************************************** 00083 // STEP 6: Implement the virtual methods that were declared but not defined 00084 // in the Base classes from which this one is derived. 00085 // (Deriving from MutableServerResult means there are three, there may 00086 // be a different number for a different base class). 00087 // 00088 //****************************************************************************** 00089 00090 00091 //------------------------------------------------------------------------------ 00092 long ResultTemplate::BufferInitAlloc() 00093 { 00094 long ExpectedBufferLength = 0; 00095 00096 // First, call the immediate base class's method to get the buffer length 00097 // required by all base classes. 00098 // 00099 // THIS CALL MUST BE INCLUDED IN THIS METHOD, 00100 // AND IT MUST BE CALLED FOR THE CLASS FROM WHICH THIS ONE IS DERIVED. 00101 // 00102 ExpectedBufferLength = MutableServerResult::BufferInitAlloc(); 00103 00104 // ADD THE ADDITIONAL BUFFER LENGTH NEEDED BY THIS CLASS'S VARIABLES 00105 // 00106 // Assuming a single int value which will never be more than 15 digits, 00107 // it might be as simple as the line below. For more complex results 00108 // (for example magnitude results that might have n channels included), 00109 // it could be much more complex. 00110 00111 ExpectedBufferLength += 15; 00112 00113 return ExpectedBufferLength; 00114 } 00115 //------------------------------------------------------------------------------ 00116 //------------------------------------------------------------------------------ 00117 void ResultTemplate::FormatDerivativeData() 00118 { 00119 // First, prepare the leading part of the buffer....that is, prepare 00120 // the buffer part used by the base class(es): 00121 // 00122 // THIS CALL MUST BE PERFORMED AT THE START OF THIS METHOD, 00123 // AND IT MUST BE CALLED FOR THE CLASS FROM WHICH THIS ONE IS DERIVED. 00124 // 00125 MutableServerResult::FormatDerivativeData(); 00126 00127 00128 // NOW FORMAT AND APPEND THE BUFFER CONTENTS FOR THIS CLASS. 00129 00130 // THE ACTUAL BUFFER IS IMPLEMENTED WITH A C++ basic_string TYPE. 00131 // A CHAR VALUE MAY BE APPENDED TO THE BUFFER WITH += 00132 // 00133 // MessageBuffer += "SOME STRING VALUE"; 00134 00135 00136 // GENERALLY, THIS CLASS HEIRARCHY BREAKS MESSAGES INTO MULTIPLE LINES 00137 // WITH '\n'. THE END OF THE MESSAGE IS MARKED WITH AN ADDITIONAL '\n'. 00138 00139 00140 /* 00141 // Say that this class has some result value of type int, the code to 00142 // include that value in the message buffer might look something like: 00143 00144 char _myint[18]; 00145 00146 sprintf( _myint, "%d\n MyInt ); 00147 00148 MessageBuffer += _myint; 00149 */ 00150 } 00151 //------------------------------------------------------------------------------ 00152 //------------------------------------------------------------------------------ 00153 void ResultTemplate::ParseDerivativeData() 00154 { 00155 // One of the first things done as part of the parse process is that the 00156 // message is put into the (base class's) variable MessageBuffer 00157 // 00158 // Lines are then snipped off the front of the buffer as they are processed. 00159 // 00160 00161 // First, parse the leading part of the buffer....that is, 00162 // the buffer part used by the base class(es): 00163 // 00164 // THIS CALL MUST BE PERFORMED AT THE START OF THIS METHOD, 00165 // AND IT MUST BE CALLED FOR THE CLASS FROM WHICH THIS ONE IS DERIVED. 00166 // 00167 MutableServerResult::ParseDerivativeData(); 00168 00169 00170 long _index; // end of line index 00171 std::string _readline; // work buffer 00172 00173 00174 // NOW PARSE THE PORTION OF THE BUFFER RELEVANT TO THIS MESSAGE CLASS 00175 00176 // NOTE THAT ALL ERRORS ARE REPORTED BY THROWING A worm_exception OBJECT. 00177 // THERE ARE TWO WAYS TO FORMAT THE ERROR MESSAGE CONTAINED THEREIN, EITHER 00178 // WITH A SIMPLE STRING: 00179 // 00180 // throw worm_exception("My error message"); 00181 // 00182 // OR BUILT UP FROM STRINGS AND VARAIBLES 00183 // 00184 // worm_exception my_exception("ResultTemplate::ParseDerivativeData() Error: "); 00185 // my_exception += SomeStringVariable; 00186 // my_exception += " "; 00187 // my_exception += SomeOtherStringVariable; 00188 // throw my_exception; 00189 // 00190 // FYI, THE worm_exception IS CAUGHT AND REPORTED BY THE SERVER 00191 00192 00193 // MESSAGE LINES ARE GENERALLY HANDLED WITH ONE OR MORE REPETITIONS OF 00194 // THE FOLLOWING FOUR STEPS. 00195 // THE MESSAGE IS TERMINATED WITH AN EMPTY LINE ('\n' ALONE), 00196 // THUS, EITHER HAVE A FIXED NUMBER OF LINES FOR THE CLASS, OR BE 00197 // PREPARED FOR MESSAGE TERMINATION. 00198 00199 00200 // 1. Find the end of the next line in the buffer 00201 // 00202 if ( (_index = MessageBuffer.find("\n")) == MessageBuffer.npos ) 00203 { 00204 // First way to throw a worm_exception object 00205 throw worm_exception("Unterminated message while parsing ResultTemplate line"); 00206 } 00207 00208 // 2. Extract the line from the buffer 00209 // 00210 _readline = MessageBuffer.substr( 0 , _index ); 00211 00212 // 3. Remove the line from the buffer 00213 // 00214 MessageBuffer.erase( 0 , _index + 1 ); 00215 00216 // 4. Parse the message line 00217 00218 if ( sscanf( _readline.c_str() 00219 , "%d %d %s" 00220 , &MyIntVariable 00221 , &MySecondIntVariable 00222 , MyCharVariable 00223 ) != 3 00224 ) 00225 { 00226 worm_exception my_exception("ResultTemplate::ParseDerivativeData() Error: Invalid line\n" ); 00227 my_exception += _readline.c_str(); 00228 throw my_exception; 00229 } 00230 00231 // NOTE THAT THE ABOVE 'MyXXXVariables' ARE EXPECTED TO BE CLASS VARIABLES, 00232 // THUS AFTER PARSING, THIS CLASS BECOMES A DATA CONTAINER ALONG WITH 00233 // MESSAGE FORMATTER/PARSER 00234 00235 } 00236 00237 //------------------------------------------------------------------------------ 00238