TextSerialize.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
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     // comment, skip to next line
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     // expecting {\t}* field_name: num\n 
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     // find the ^L+1, which is the end of the text coded portion
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 } // namespace oasys

Generated on Thu Jun 7 16:56:53 2007 for DTN Reference Implementation by  doxygen 1.5.1