libwreport
2.4
|
00001 /* 00002 * wreport/bulletin/buffers - Low-level I/O operations 00003 * 00004 * Copyright (C) 2005--2011 ARPA-SIM <urpsim@smr.arpa.emr.it> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 * 00019 * Author: Enrico Zini <enrico@enricozini.com> 00020 */ 00021 00022 #ifndef WREPORT_BULLETIN_BUFFERS_H 00023 #define WREPORT_BULLETIN_BUFFERS_H 00024 00025 #include <wreport/error.h> 00026 #include <wreport/varinfo.h> 00027 #include <string> 00028 #include <stdint.h> 00029 00030 namespace wreport { 00031 struct Var; 00032 00033 namespace bulletin { 00034 00038 struct CompressedVarSink 00039 { 00040 virtual ~CompressedVarSink() {} 00041 00050 virtual void operator()(const Var& var, unsigned idx) = 0; 00051 }; 00052 00056 class BufrInput 00057 { 00058 protected: 00063 void scan_section_length(unsigned sec_no); 00064 00065 public: 00067 const unsigned char* data; 00068 00070 size_t data_len; 00071 00079 const char* fname; 00080 00088 size_t start_offset; 00089 00091 unsigned s4_cursor; 00092 00094 unsigned char pbyte; 00095 00097 int pbyte_len; 00098 00100 unsigned sec[6]; 00101 00102 00109 BufrInput(const std::string& in); 00110 00112 void reset(const std::string& in); 00113 00121 void scan_lead_sections(); 00122 00134 void scan_other_sections(bool has_optional); 00135 00137 int offset() const; 00138 00140 int bits_left() const; 00141 00145 inline unsigned read_byte(unsigned pos) const 00146 { 00147 return (unsigned)data[pos]; 00148 } 00149 00153 inline unsigned read_byte(unsigned section, unsigned pos) const 00154 { 00155 return (unsigned)data[sec[section] + pos]; 00156 } 00157 00161 unsigned read_number(unsigned pos, unsigned byte_len) const; 00162 00167 inline unsigned read_number(unsigned section, unsigned pos, unsigned byte_len) const 00168 { 00169 return read_number(sec[section] + pos, byte_len); 00170 } 00171 00176 uint32_t get_bits(unsigned n); 00177 00179 void debug_dump_next_bits(int count) const; 00180 00182 void parse_error(const char* fmt, ...) const WREPORT_THROWF_ATTRS(2, 3); 00183 00185 void parse_error(unsigned pos, const char* fmt, ...) const WREPORT_THROWF_ATTRS(3, 4); 00186 00188 void parse_error(unsigned section, unsigned pos, const char* fmt, ...) const WREPORT_THROWF_ATTRS(4, 5); 00189 00202 void check_available_data(unsigned pos, size_t datalen, const char* expected); 00203 00218 void check_available_data(unsigned section, unsigned pos, size_t datalen, const char* expected); 00219 00232 void decode_number(Var& dest, uint32_t base, unsigned diffbits); 00233 00242 void decode_number(Var& dest); 00243 00248 void decode_number(Varinfo info, unsigned subsets, CompressedVarSink& dest); 00249 00261 void decode_number(Var& dest, unsigned subsets); 00262 00279 bool decode_string(unsigned bit_len, char* str, size_t& len); 00280 00292 void decode_string(Var& dest); 00293 00305 void decode_string(Var& dest, unsigned subsets); 00306 00311 void decode_string(Varinfo info, unsigned subsets, CompressedVarSink& dest); 00312 00324 void decode_binary(Var& dest); 00325 }; 00326 00330 struct BufrOutput 00331 { 00333 std::string& out; 00334 00336 uint8_t pbyte; 00337 00339 int pbyte_len; 00340 00347 BufrOutput(std::string& out); 00348 00352 void add_bits(uint32_t val, int n); 00353 00358 void raw_append(const char* str, int len) 00359 { 00360 out.append(str, len); 00361 } 00362 00364 void append_short(unsigned short val) 00365 { 00366 add_bits(val, 16); 00367 } 00368 00370 void append_byte(unsigned char val) 00371 { 00372 add_bits(val, 8); 00373 } 00374 00376 void append_missing(unsigned len_bits) 00377 { 00378 add_bits(0xffffffff, len_bits); 00379 } 00380 00382 void append_string(const Var& var, unsigned len_bits); 00383 00385 void append_string(const char* val, unsigned len_bits); 00386 00388 void append_binary(const unsigned char* val, unsigned len_bits); 00389 00391 void append_var(Varinfo info, const Var& var); 00392 00394 void append_missing(Varinfo info); 00395 00400 void flush(); 00401 }; 00402 00406 struct CrexInput 00407 { 00409 const char* data; 00410 00412 size_t data_len; 00413 00421 const char* fname; 00422 00430 size_t offset; 00431 00435 unsigned sec[5]; 00436 00438 const char* cur; 00439 00441 int has_check_digit; 00442 00444 int expected_check_digit; 00445 00446 00453 CrexInput(const std::string& in); 00454 00456 bool eof() const; 00457 00459 unsigned remaining() const; 00460 00462 void parse_error(const char* fmt, ...) const WREPORT_THROWF_ATTRS(2, 3); 00463 00472 void check_eof(const char* expected) const; 00473 00484 void check_available_data(unsigned datalen, const char* expected) const; 00485 00487 void skip_spaces(); 00488 00490 void skip_data_and_spaces(unsigned datalen); 00491 00501 void mark_section_start(unsigned num); 00502 00516 void read_word(char* buf, size_t len); 00517 00530 void parse_value(int len, int is_signed, const char** d_start, const char** d_end); 00531 00533 void debug_dump_next(const char* desc) const; 00534 }; 00535 00539 struct CrexOutput 00540 { 00542 std::string& buf; 00543 00545 int has_check_digit; 00546 00548 int expected_check_digit; 00549 00550 00557 CrexOutput(std::string& buf); 00558 00560 void raw_append(const char* str, int len); 00561 00563 void raw_appendf(const char* fmt, ...) __attribute__ ((format(printf, 2, 3))); 00564 00566 void encode_check_digit(); 00567 00569 void append_missing(Varinfo info); 00570 00572 void append_var(Varinfo info, const Var& var); 00573 }; 00574 00575 } 00576 } 00577 00578 #endif