input.h
#ifndef WREPORT_BUFR_INPUT_H
#define WREPORT_BUFR_INPUT_H
#include <wreport/error.h>
#include <wreport/var.h>
#include <wreport/bulletin.h>
#include <string>
#include <functional>
namespace wreport {
struct Bulletin;
namespace bulletin {
struct AssociatedField;
}
namespace bufr {
struct DispatchToSubsets
{
Bulletin& out;
unsigned subset_count;
DispatchToSubsets(Bulletin& out, unsigned subset_count) : out(out), subset_count(subset_count) {}
void add_missing(Varinfo info)
{
for (unsigned i = 0; i < subset_count; ++i)
out.subsets[i].store_variable_undef(info);
}
void add_same(const Var& var)
{
for (unsigned i = 0; i < subset_count; ++i)
out.subsets[i].store_variable(Var(var));
}
void add_var(unsigned subset, Var&& var)
{
out.subsets[subset].store_variable(var);
}
};
class Input
{
protected:
void scan_section_length(unsigned sec_no);
public:
const uint8_t* data;
size_t data_len;
const char* fname = nullptr;
size_t start_offset = 0;
unsigned s4_cursor = 0;
uint8_t pbyte = 0;
int pbyte_len = 0;
unsigned sec[6];
Input(const std::string& in);
void scan_lead_sections();
void scan_other_sections(bool has_optional);
unsigned offset() const { return s4_cursor; }
unsigned bits_left() const { return (data_len - s4_cursor) * 8 + pbyte_len; }
inline unsigned read_byte(unsigned pos) const
{
return (unsigned)data[pos];
}
inline unsigned read_byte(unsigned section, unsigned pos) const
{
return (unsigned)data[sec[section] + pos];
}
unsigned read_number(unsigned pos, unsigned byte_len) const
{
unsigned res = 0;
for (unsigned i = 0; i < byte_len; ++i)
{
res <<= 8;
res |= data[pos + i];
}
return res;
}
inline unsigned read_number(unsigned section, unsigned pos, unsigned byte_len) const
{
return read_number(sec[section] + pos, byte_len);
}
uint32_t get_bits(unsigned n)
{
uint32_t result = 0;
if (s4_cursor == data_len)
parse_error("end of buffer while looking for %d bits of bit-packed data", n);
// TODO: review and benchmark and possibly simplify
// (a possible alternative approach is to keep a current bitmask that
// starts at 0x80 and is shifted right by 1 at each read until it
// reaches 0, and get rid of pbyte_len)
for (unsigned i = 0; i < n; i++)
{
if (pbyte_len == 0)
{
pbyte_len = 8;
pbyte = data[s4_cursor++];
}
result <<= 1;
if (pbyte & 0x80)
result |= 1;
pbyte <<= 1;
pbyte_len--;
}
return result;
}
void skip_bits(unsigned n)
{
if (s4_cursor == data_len)
parse_error("end of buffer while looking for %d bits of bit-packed data", n);
for (unsigned i = 0; i < n; i++)
{
if (pbyte_len == 0)
{
pbyte_len = 8;
pbyte = data[s4_cursor++];
}
pbyte <<= 1;
pbyte_len--;
}
}
void debug_dump_next_bits(const char* desc, unsigned count, const std::vector<unsigned>& groups={}) const;
void debug_find_sequence(const char* pattern) const;
void parse_error(const char* fmt, ...) const WREPORT_THROWF_ATTRS(2, 3);
void parse_error(unsigned pos, const char* fmt, ...) const WREPORT_THROWF_ATTRS(3, 4);
void parse_error(unsigned section, unsigned pos, const char* fmt, ...) const WREPORT_THROWF_ATTRS(4, 5);
void check_available_data(unsigned pos, size_t datalen, const char* expected);
void check_available_message_data(unsigned section, unsigned pos, size_t datalen, const char* expected);
void check_available_section_data(unsigned section, unsigned pos, size_t datalen, const char* expected);
void decode_compressed_number(Var& dest, uint32_t base, unsigned diffbits);
void decode_number(Var& dest);
bool decode_compressed_base(Varinfo info, uint32_t& base, uint32_t& diffbits);
void decode_compressed_number(Varinfo info, unsigned subsets, std::function<void(unsigned, Var&&)> dest);
void decode_string(Varinfo info, unsigned subsets, DispatchToSubsets& dest);
void decode_compressed_number(Varinfo info, unsigned subsets, DispatchToSubsets& dest);
void decode_compressed_number_af(Varinfo info, const bulletin::AssociatedField& afield, unsigned subsets, std::function<void(unsigned, Var&&)> dest);
void decode_compressed_semantic_number(Var& dest, unsigned subsets);
bool decode_string(unsigned bit_len, char* str, size_t& len);
void decode_string(Var& dest);
void decode_string(Var& dest, unsigned subsets);
void decode_string(Varinfo info, unsigned subsets, std::function<void(unsigned, Var&&)> dest);
void decode_binary(Var& dest);
std::string decode_uncompressed_bitmap(unsigned size);
std::string decode_compressed_bitmap(unsigned size);
};
}
}
#endif
wreport::Bulletin
Storage for the decoded data of a BUFR or CREX message.
Definition bulletin.h:30
wreport::Var
A physical variable.
Definition var.h:25
wreport::bufr::Input::data_len
size_t data_len
Input buffer size.
Definition input.h:59
wreport::bufr::Input::read_byte
unsigned read_byte(unsigned pos) const
Read a byte value at offset pos.
Definition input.h:129
wreport::bufr::Input::Input
Input(const std::string &in)
Wrap a string iinto a Input.
wreport::bufr::Input::get_bits
uint32_t get_bits(unsigned n)
Get the integer value of the next 'n' bits from the decode input n must be <= 32.
Definition input.h:165
wreport::bufr::Input::check_available_section_data
void check_available_section_data(unsigned section, unsigned pos, size_t datalen, const char *expected)
Check that the given section in the input buffer contains at least datalen characters after offset po...
wreport::bufr::Input::decode_compressed_number
void decode_compressed_number(Var &dest, uint32_t base, unsigned diffbits)
Decode a compressed number as described by dest.info(), ad set it as value for dest.
wreport::bufr::Input::debug_dump_next_bits
void debug_dump_next_bits(const char *desc, unsigned count, const std::vector< unsigned > &groups={}) const
Dump to stderr 'count' bits of 'buf', starting at the 'ofs-th' bit.
wreport::bufr::Input::pbyte
uint8_t pbyte
Byte we are currently decoding.
Definition input.h:83
wreport::bufr::Input::decode_uncompressed_bitmap
std::string decode_uncompressed_bitmap(unsigned size)
Decode an uncompressed bitmap of size bits.
wreport::bufr::Input::scan_other_sections
void scan_other_sections(bool has_optional)
Scan the message filling in the sec[] array of section start offsets of all sections from 2 on.
wreport::bufr::Input::bits_left
unsigned bits_left() const
Return the number of bits left in the message to be decoded.
Definition input.h:126
wreport::bufr::Input::scan_lead_sections
void scan_lead_sections()
Scan the message filling in the sec[] array of start offsets of sections 0 and 1.
wreport::bufr::Input::scan_section_length
void scan_section_length(unsigned sec_no)
Scan length of section sec_no, filling in the start of the next section in sec[sec_no + 1].
wreport::bufr::Input::offset
unsigned offset() const
Return the current decoding byte offset.
Definition input.h:123
wreport::bufr::Input::s4_cursor
unsigned s4_cursor
Offset of the byte we are currently decoding.
Definition input.h:80
wreport::bufr::Input::check_available_data
void void void void check_available_data(unsigned pos, size_t datalen, const char *expected)
Check that the input buffer contains at least datalen characters after offset pos; throw error_parse ...
wreport::bufr::Input::read_number
unsigned read_number(unsigned pos, unsigned byte_len) const
Read a big endian integer value byte_len bytes long, at offset pos.
Definition input.h:141
wreport::bufr::Input::decode_compressed_number_af
void decode_compressed_number_af(Varinfo info, const bulletin::AssociatedField &afield, unsigned subsets, std::function< void(unsigned, Var &&)> dest)
Decode a number as described by info from a compressed bufr with subsets subsets, and send the result...
wreport::bufr::Input::debug_find_sequence
void debug_find_sequence(const char *pattern) const
Match the given pattern as regexp on the still unread input bitstream, with bits converted to a strin...
wreport::bufr::Input::sec
unsigned sec[6]
Offsets of the start of BUFR sections.
Definition input.h:89
wreport::bufr::Input::start_offset
size_t start_offset
File offset of the start of the message.
Definition input.h:77
wreport::bufr::Input::check_available_message_data
void check_available_message_data(unsigned section, unsigned pos, size_t datalen, const char *expected)
Check that the input buffer contains at least datalen characters after offset pos in section section;...
wreport::bufr::Input::read_byte
unsigned read_byte(unsigned section, unsigned pos) const
Read a byte value at offset pos inside section section.
Definition input.h:135
wreport::bufr::Input::read_number
unsigned read_number(unsigned section, unsigned pos, unsigned byte_len) const
Read a big endian integer value byte_len bytes long, at offset pos inside section section.
Definition input.h:156
wreport::bufr::Input::data
const uint8_t * data
Input buffer.
Definition input.h:56
wreport::bufr::Input::skip_bits
void skip_bits(unsigned n)
Skip the next n bits.
Definition input.h:196
wreport::bufr::Input::fname
const char * fname
Input file name (optional).
Definition input.h:68
wreport::bufr::Input::decode_binary
void decode_binary(Var &dest)
Decode a generic binary value as-is, as described by dest.info(), ad set it as value for dest.
wreport::bufr::Input::decode_compressed_base
bool decode_compressed_base(Varinfo info, uint32_t &base, uint32_t &diffbits)
Decode the base value for a variable in a compressed BUFR.
wreport::bufr::Input::decode_compressed_bitmap
std::string decode_compressed_bitmap(unsigned size)
Decode a "compressed" bitmap of size bits.
wreport::bufr::Input::decode_compressed_semantic_number
void decode_compressed_semantic_number(Var &dest, unsigned subsets)
Decode a number as described by dest.info(), and set it as value for dest.
wreport::bufr::Input::pbyte_len
int pbyte_len
Bits left in pbyte to decode.
Definition input.h:86
wreport::bufr::Input::parse_error
void parse_error(const char *fmt,...) const WREPORT_THROWF_ATTRS(2
Throw an error_parse at the current decoding location.
wreport::bufr::Input::decode_number
void decode_number(Var &dest)
Decode a number as described by dest.info(), and set it as value for dest.
error.h
wreport exceptions.
WREPORT_THROWF_ATTRS
#define WREPORT_THROWF_ATTRS(a, b)
Tell the compiler that a function always throws and expects printf-style arguments.
Definition error.h:56
wreport::bulletin
The bulletin namespace contains bulletin implementation details, internals and utility functions.
Definition input.h:13
wreport
String functions.
Definition benchmark.h:13
wreport::Varinfo
const _Varinfo * Varinfo
Varinfo reference.
Definition fwd.h:11
wreport::bufr::DispatchToSubsets
Definition input.h:20
wreport::bulletin::AssociatedField
Definition associated_fields.h:13