Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Message_AMOS.cc

Go to the documentation of this file.
00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 #include "Message_AMOS.hh" 00011 using namespace AMOS; 00012 using namespace std; 00013 using namespace HASHMAP; 00014 00015 #define FIELD_SEPARATOR ':' 00016 #define FIELD_TERMINATOR '.' 00017 00018 00019 00020 00021 //================================================ Message_t =================== 00022 //----------------------------------------------------- skipto ----------------- 00023 inline bool skipto (istream & in, char ch) 00024 { 00025 static const int chunk = 1024; 00026 00027 while ( true ) 00028 { 00029 in . ignore (chunk, ch); 00030 00031 if ( !in . good( ) ) 00032 return false; 00033 if ( in . gcount( ) != chunk ) 00034 return true; 00035 00036 in . unget( ); 00037 } 00038 } 00039 00040 00041 //----------------------------------------------------- read ------------------- 00042 bool Message_t::read (istream & in) 00043 { 00044 int i; 00045 char ch; 00046 string data; 00047 string chunk; 00048 string name (NCODE_SIZE, NULL_CHAR); 00049 00050 //-- Search for the beginning of the message 00051 if ( !skipto (in, '{') ) 00052 return NULL_NCODE; 00053 00054 //-- Empty the object 00055 clear( ); 00056 00057 try { 00058 00059 //-- Get the type name 00060 for ( i = 0; i < NCODE_SIZE; i ++ ) 00061 name [i] = in . get( ); 00062 if ( in . get( ) != NL_CHAR ) 00063 AMOS_THROW_IO ("Could not parse message NCode: " + name); 00064 setMessageCode (name); 00065 00066 //-- Until end of message 00067 while ( true ) 00068 { 00069 //-- Check next char 00070 ch = in . peek( ); 00071 00072 //-- If unexpected EOF 00073 if ( ch == EOF ) 00074 AMOS_THROW_IO ("Unbalanced message nesting"); 00075 //-- If a nested message, read it in 00076 else if ( ch == '{' ) 00077 { 00078 subs_m . push_back (Message_t ( )); 00079 subs_m . back( ) . read (in); 00080 continue; 00081 } 00082 //-- If end of message 00083 else if ( ch == '}' ) 00084 { 00085 skipto (in, NL_CHAR); 00086 break; 00087 } 00088 //-- If spacing 00089 else if ( ch == NL_CHAR ) 00090 { 00091 in . get( ); 00092 continue; 00093 } 00094 00095 //-- Get the field name 00096 for ( i = 0; i < NCODE_SIZE; i ++ ) 00097 name [i] = in . get( ); 00098 if ( in . get( ) != FIELD_SEPARATOR ) 00099 AMOS_THROW_IO ("Could not parse field code in '" + 00100 Decode (mcode_m) + "' message"); 00101 00102 //-- Read in first line of field 00103 getline (in, data); 00104 if ( !in . good( ) ) 00105 AMOS_THROW_IO ("Could not parse single-line field data in '" + 00106 Decode (mcode_m) + "' message"); 00107 00108 //-- If multi-line field 00109 if ( data . empty( ) ) 00110 { 00111 getline (in, data, FIELD_TERMINATOR); 00112 00113 //-- Slurp up '.'s while not the '\n.\n' pattern 00114 while ( in . peek( ) != NL_CHAR || 00115 (!data . empty( ) && *(data . rbegin( )) != NL_CHAR) ) 00116 { 00117 if ( !in . good( ) ) 00118 AMOS_THROW_IO ("Unterminated multi-line field in '" + 00119 Decode (mcode_m) + "' message"); 00120 00121 data . push_back (FIELD_TERMINATOR); 00122 getline (in, chunk, FIELD_TERMINATOR); 00123 data . append (chunk); 00124 } 00125 in . get( ); 00126 00127 if ( !in . good( ) ) 00128 AMOS_THROW_IO ("Could not parse multi-line field data in '" + 00129 Decode (mcode_m) + "' message"); 00130 } 00131 00132 //-- Set field data 00133 setField (name, data); 00134 } 00135 } 00136 catch (Exception_t) { 00137 00138 //-- Clean up and rethrow 00139 clear( ); 00140 throw; 00141 } 00142 00143 return true; 00144 } 00145 00146 00147 //----------------------------------------------------- setField --------------- 00148 void Message_t::setField (NCode_t fcode, const string & data) 00149 { 00150 if ( data . empty( ) ) 00151 return; 00152 00153 //-- Check pre-conditions 00154 string::size_type nlpos = data . rfind (NL_CHAR); 00155 if ( nlpos != string::npos && nlpos != data . size( ) - 1 ) 00156 AMOS_THROW_ARGUMENT ("Invalid multi-line message field format"); 00157 00158 //-- Insert new field, overwrite if already exists 00159 fields_m [fcode] = data; 00160 } 00161 00162 00163 //----------------------------------------------------- skip ------------------- 00164 NCode_t Message_t::skip (istream & in) // static const 00165 { 00166 int i; 00167 char ch; 00168 string name (NCODE_SIZE, NULL_CHAR); 00169 00170 //-- Search for the beginning of the message 00171 if ( !skipto (in, '{') ) 00172 return NULL_NCODE; 00173 00174 //-- Get the type name 00175 for ( i = 0; i < NCODE_SIZE; i ++ ) 00176 name [i] = in . get( ); 00177 if ( in . get( ) != NL_CHAR ) 00178 AMOS_THROW_IO ("Could not parse message header: " + name); 00179 00180 //-- Until end of message 00181 i = 1; 00182 while ( i != 0 ) 00183 { 00184 //-- Get next char 00185 ch = in . get( ); 00186 if ( !in . good( ) ) 00187 AMOS_THROW_IO ("Unbalanced message nesting"); 00188 00189 //-- Increment/decrement level counter 00190 if ( ch == '{' ) 00191 i ++; 00192 else if ( ch == '}' ) 00193 i --; 00194 00195 //-- Suck in rest of line 00196 if ( ch != NL_CHAR ) 00197 skipto (in, NL_CHAR); 00198 } 00199 00200 return Encode (name); 00201 } 00202 00203 00204 //----------------------------------------------------- write ------------------ 00205 void Message_t::write (ostream & out) const 00206 { 00207 bool mline = false; 00208 00209 //-- Write opening of message 00210 out << '{' << Decode (mcode_m) << endl; 00211 00212 //-- Write all fields 00213 hash_map<NCode_t,string>::const_iterator mi; 00214 for ( mi = fields_m . begin( ); mi != fields_m . end( ); mi ++ ) 00215 { 00216 //-- Set multi-line message flag 00217 mline = *(mi -> second . rbegin( )) == NL_CHAR ? true : false; 00218 00219 out << Decode (mi -> first) << FIELD_SEPARATOR; 00220 if ( mline ) 00221 out . put (NL_CHAR); 00222 out << mi -> second; 00223 if ( mline ) 00224 out . put (FIELD_TERMINATOR); 00225 out . put (NL_CHAR); 00226 } 00227 00228 //-- Write all sub-messages 00229 vector<Message_t>::const_iterator vi; 00230 for ( vi = subs_m . begin( ); vi != subs_m . end( ); vi ++ ) 00231 vi -> write (out); 00232 00233 //-- Close out message 00234 out << '}' << endl; 00235 00236 //-- Check stream 'goodness' 00237 if ( !out . good( ) ) 00238 AMOS_THROW_IO ("Message write failure"); 00239 }

Generated on Tue May 17 15:19:02 2005 for libAMOS by doxygen 1.3.8