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