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
00022
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
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
00051
if ( !
skipto (in,
'{') )
00052
return NULL_NCODE;
00053
00054
00055
clear( );
00056
00057
try {
00058
00059
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
00067
while (
true )
00068 {
00069
00070 ch = in . peek( );
00071
00072
00073
if ( ch == EOF )
00074
AMOS_THROW_IO (
"Unbalanced message nesting");
00075
00076
else if ( ch ==
'{' )
00077 {
00078 subs_m . push_back (
Message_t ( ));
00079 subs_m . back( ) .
read (in);
00080
continue;
00081 }
00082
00083
else if ( ch ==
'}' )
00084 {
00085
skipto (in,
NL_CHAR);
00086
break;
00087 }
00088
00089
else if ( ch ==
NL_CHAR )
00090 {
00091 in . get( );
00092
continue;
00093 }
00094
00095
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
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
00109
if ( data .
empty( ) )
00110 {
00111 getline (in, data,
FIELD_TERMINATOR);
00112
00113
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
00133
setField (name, data);
00134 }
00135 }
00136
catch (
Exception_t) {
00137
00138
00139
clear( );
00140
throw;
00141 }
00142
00143
return true;
00144 }
00145
00146
00147
00148 void Message_t::setField (
NCode_t fcode,
const string & data)
00149 {
00150
if ( data .
empty( ) )
00151
return;
00152
00153
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
00159 fields_m [fcode] = data;
00160 }
00161
00162
00163
00164 NCode_t Message_t::skip (istream & in)
00165 {
00166
int i;
00167
char ch;
00168 string name (
NCODE_SIZE,
NULL_CHAR);
00169
00170
00171
if ( !
skipto (in,
'{') )
00172
return NULL_NCODE;
00173
00174
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
00181 i = 1;
00182
while ( i != 0 )
00183 {
00184
00185 ch = in . get( );
00186
if ( !in . good( ) )
00187
AMOS_THROW_IO (
"Unbalanced message nesting");
00188
00189
00190
if ( ch ==
'{' )
00191 i ++;
00192
else if ( ch ==
'}' )
00193 i --;
00194
00195
00196
if ( ch !=
NL_CHAR )
00197
skipto (in,
NL_CHAR);
00198 }
00199
00200
return Encode (name);
00201 }
00202
00203
00204
00205 void Message_t::write (ostream & out)
const
00206
{
00207
bool mline =
false;
00208
00209
00210 out <<
'{' <<
Decode (mcode_m) << endl;
00211
00212
00213 hash_map<NCode_t,string>
::const_iterator mi;
00214
for ( mi = fields_m .
begin( ); mi != fields_m .
end( ); mi ++ )
00215 {
00216
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
00229 vector<Message_t>
::const_iterator vi;
00230
for ( vi = subs_m .
begin( ); vi != subs_m .
end( ); vi ++ )
00231 vi ->
write (out);
00232
00233
00234 out <<
'}' << endl;
00235
00236
00237
if ( !out . good( ) )
00238
AMOS_THROW_IO (
"Message write failure");
00239 }