00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "TextSerialize.h"
00040 #include "../util/TextCode.h"
00041
00042 namespace oasys {
00043
00044
00045 TextMarshal::TextMarshal(context_t context,
00046 ExpandableBuffer* buf,
00047 int options,
00048 const char* comment)
00049 : SerializeAction(Serialize::MARSHAL, context, options),
00050 indent_(0),
00051 buf_(buf, false)
00052 {
00053 buf_.append("# -- text marshal start --\n");
00054 if (comment != 0)
00055 buf_.append(comment);
00056 }
00057
00058
00059 void
00060 TextMarshal::process(const char* name, u_int32_t* i)
00061 {
00062 buf_.appendf("%s: %u\n", name, *i);
00063 }
00064
00065
00066 void
00067 TextMarshal::process(const char* name, u_int16_t* i)
00068 {
00069 buf_.appendf("%s: %u\n", name, (u_int32_t)*i);
00070 }
00071
00072
00073 void
00074 TextMarshal::process(const char* name, u_int8_t* i)
00075 {
00076 buf_.appendf("%s: %u\n", name, (u_int32_t)*i);
00077 }
00078
00079
00080 void
00081 TextMarshal::process(const char* name, bool* b)
00082 {
00083 buf_.appendf("%s: %s\n", name, (*b) ? "true" : "false" );
00084 }
00085
00086
00087 void
00088 TextMarshal::process(const char* name, u_char* bp, size_t len)
00089 {
00090 buf_.appendf("%s: TextCode\n", name);
00091 TextCode coder(reinterpret_cast<char*>(bp), len,
00092 buf_.expandable_buf(), 40, indent_ + 1);
00093 }
00094
00095
00096 void
00097 TextMarshal::process(const char* name, u_char** bp, size_t* lenp, int flags)
00098 {
00099 (void)flags;
00100 buf_.appendf("%s: TextCode\n", name);
00101 TextCode coder(reinterpret_cast<char*>(*bp), *lenp,
00102 buf_.expandable_buf(), 40, indent_ + 1);
00103 }
00104
00105
00106 void
00107 TextMarshal::process(const char* name, std::string* s)
00108 {
00109 buf_.appendf("%s: TextCode\n", name);
00110 TextCode coder(reinterpret_cast<const char*>(s->c_str()),
00111 strlen(s->c_str()),
00112 buf_.expandable_buf(),
00113 40, indent_ + 1);
00114 }
00115
00116
00117 void
00118 TextMarshal::process(const char* name, SerializableObject* object)
00119 {
00120 buf_.appendf("%s: SerializableObject\n", name);
00121 indent();
00122 object->serialize(this);
00123 unindent();
00124 }
00125
00126
00127
00128 void
00129 TextMarshal::add_indent()
00130 {
00131 for (int i=0; i<indent_; ++i)
00132 buf_.append('\t');
00133 }
00134
00135
00136 TextUnmarshal::TextUnmarshal(context_t context, u_char* buf,
00137 size_t length, int options)
00138 : SerializeAction(Serialize::UNMARSHAL, context, options),
00139 buf_(reinterpret_cast<char*>(buf)),
00140 length_(length),
00141 cur_(reinterpret_cast<char*>(buf))
00142 {}
00143
00144
00145 void
00146 TextUnmarshal::process(const char* name, u_int32_t* i)
00147 {
00148 if (error())
00149 return;
00150
00151 u_int32_t num;
00152 int err = get_num(name, &num);
00153
00154 if (err != 0)
00155 return;
00156
00157 *i = num;
00158 }
00159
00160
00161 void
00162 TextUnmarshal::process(const char* name, u_int16_t* i)
00163 {
00164 if (error())
00165 return;
00166
00167 u_int32_t num;
00168 int err = get_num(name, &num);
00169
00170 if (err != 0)
00171 return;
00172
00173 *i = static_cast<u_int16_t>(num);
00174 }
00175
00176
00177 void
00178 TextUnmarshal::process(const char* name, u_int8_t* i)
00179 {
00180 if (error())
00181 return;
00182
00183 u_int32_t num;
00184 int err = get_num(name, &num);
00185
00186 if (err != 0)
00187 return;
00188
00189 *i = static_cast<u_int8_t>(num);
00190 }
00191
00192
00193 void
00194 TextUnmarshal::process(const char* name, bool* b)
00195 {
00196 if (error())
00197 return;
00198
00199 char* eol;
00200 if (get_line(&eol) != 0) {
00201 signal_error();
00202 return;
00203 }
00204 ASSERT(*eol == '\n');
00205
00206 if (match_fieldname(name, eol) != 0)
00207 return;
00208
00209 if (!is_within_buf(4)) {
00210 signal_error();
00211 return;
00212 }
00213
00214 if (memcmp(cur_, "true", 4) == 0) {
00215 *b = true;
00216 cur_ = eol + 1;
00217 } else if (memcmp(cur_, "fals", 4) == 0) {
00218 *b = false;
00219 cur_ = eol + 1;
00220 } else {
00221 signal_error();
00222 return;
00223 }
00224 }
00225
00226
00227 void
00228 TextUnmarshal::process(const char* name, u_char* bp, size_t len)
00229 {
00230 if (error())
00231 return;
00232
00233 char* eol;
00234 if (get_line(&eol) != 0) {
00235 signal_error();
00236 return;
00237 }
00238
00239 if (match_fieldname(name, eol) != 0) {
00240 signal_error();
00241 return;
00242 }
00243
00244 cur_ = eol + 1;
00245 if (! is_within_buf(0)) {
00246 signal_error();
00247 return;
00248 }
00249
00250 ScratchBuffer<char*, 1024> scratch;
00251 if (get_textcode(&scratch) != 0) {
00252 signal_error();
00253 return;
00254 }
00255
00256 if (len != scratch.len()) {
00257 signal_error();
00258 return;
00259 }
00260
00261 memcpy(bp, scratch.buf(), len);
00262 }
00263
00264
00265 void
00266 TextUnmarshal::process(const char* name, u_char** bp,
00267 size_t* lenp, int flags)
00268 {
00269 (void)name;
00270 (void)bp;
00271 (void)lenp;
00272 (void)flags;
00273
00274 if (error())
00275 return;
00276
00277 NOTIMPLEMENTED;
00278 }
00279
00280
00281 void
00282 TextUnmarshal::process(const char* name, std::string* s)
00283 {
00284 if (error())
00285 return;
00286
00287 char* eol;
00288 if (get_line(&eol) != 0) {
00289 signal_error();
00290 return;
00291 }
00292
00293 if (match_fieldname(name, eol) != 0) {
00294 signal_error();
00295 return;
00296 }
00297
00298 cur_ = eol + 1;
00299 if (! is_within_buf(0)) {
00300 signal_error();
00301 return;
00302 }
00303
00304 ScratchBuffer<char*, 1024> scratch;
00305 if (get_textcode(&scratch) != 0) {
00306 signal_error();
00307 return;
00308 }
00309
00310 *s = std::string(scratch.buf(), scratch.len());
00311 }
00312
00313
00314 void
00315 TextUnmarshal::process(const char* name, SerializableObject* object)
00316 {
00317 if (error())
00318 return;
00319
00320 char* eol;
00321 if (get_line(&eol) != 0) {
00322 signal_error();
00323 return;
00324 }
00325
00326 if (match_fieldname(name, eol) != 0) {
00327 signal_error();
00328 return;
00329 }
00330
00331 cur_ = eol + 1;
00332 if (! is_within_buf(0)) {
00333 signal_error();
00334 return;
00335 }
00336
00337 object->serialize(this);
00338 }
00339
00340
00341 bool
00342 TextUnmarshal::is_within_buf(size_t offset)
00343 {
00344 return cur_ + offset < buf_ + length_;
00345 }
00346
00347
00348 int
00349 TextUnmarshal::get_line(char** end)
00350 {
00351 again:
00352 size_t offset = 0;
00353 while (is_within_buf(offset) && cur_[offset] != '\n') {
00354 ++offset;
00355 }
00356
00357 if (!is_within_buf(offset)) {
00358 return -1;
00359 }
00360
00361
00362 if (*cur_ == '#') {
00363 cur_ = &cur_[offset] + 1;
00364 goto again;
00365 }
00366
00367 *end = &cur_[offset];
00368
00369 return 0;
00370 }
00371
00372
00373 int
00374 TextUnmarshal::match_fieldname(const char* field_name, char* eol)
00375 {
00376
00377 char* field_name_ptr = 0;
00378 while (is_within_buf(0) && *cur_ != ':') {
00379 if (*cur_ != '\t' && *cur_ != ' ' && field_name_ptr == 0)
00380 field_name_ptr = cur_;
00381 ++cur_;
00382 }
00383
00384 if (*cur_ != ':' || cur_ > eol) {
00385 signal_error();
00386 return -1;
00387 }
00388
00389 if (memcmp(field_name_ptr, field_name, strlen(field_name)) != 0) {
00390 signal_error();
00391 return -1;
00392 }
00393
00394 cur_ += 2;
00395 if (!is_within_buf(0)) {
00396 signal_error();
00397 return -1;
00398 }
00399
00400 return 0;
00401 }
00402
00403
00404 int
00405 TextUnmarshal::get_num(const char* field_name, u_int32_t* num)
00406 {
00407 char* eol;
00408 if (get_line(&eol) != 0) {
00409 signal_error();
00410 return -1;
00411 }
00412
00413 ASSERT(*eol == '\n');
00414 if (match_fieldname(field_name, eol) != 0)
00415 return -1;
00416
00417 *num = strtoul(cur_, &eol, 0);
00418 ASSERT(*eol == '\n');
00419
00420 cur_ = eol + 1;
00421
00422 return 0;
00423 }
00424
00425 int
00426 TextUnmarshal::get_textcode(ExpandableBuffer* buf)
00427 {
00428
00429 size_t end_offset = 0;
00430 while (true) {
00431 if (!is_within_buf(end_offset)) {
00432 signal_error();
00433 return -1;
00434 }
00435
00436 if (cur_[end_offset] == '') {
00437 break;
00438 }
00439
00440 ++end_offset;
00441 }
00442
00443 ++end_offset;
00444 if (!is_within_buf(end_offset)) {
00445 signal_error();
00446 return -1;
00447 }
00448
00449 ASSERT(cur_[end_offset] == '\n');
00450
00451 ScratchBuffer<char*, 1024> scratch;
00452 TextUncode uncoder(cur_, end_offset, buf);
00453
00454 if (uncoder.error()) {
00455 signal_error();
00456 return -1;
00457 }
00458
00459 cur_ += end_offset + 1;
00460
00461 return 0;
00462 }
00463
00464 }