TextSerialize.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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     // comment, skip to next line
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     // expecting {\t}* field_name: num\n 
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     // find the ^L+1, which is the end of the text coded portion
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 } // namespace oasys

Generated on Fri Dec 22 14:48:01 2006 for DTN Reference Implementation by  doxygen 1.5.1