dcparser: use vector_uchar for blobs, step towards Python 3 compat

Closes #298
This commit is contained in:
rdb 2018-12-19 12:45:32 +01:00
parent 840f28ef18
commit e4f493b872
27 changed files with 2016 additions and 1960 deletions

View File

@ -262,6 +262,38 @@ pack_string(DCPackData &pack_data, const string &value,
}
}
/**
* Packs the indicated numeric or string value into the stream.
*/
void DCArrayParameter::
pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const {
// We can only pack a string if the array element type is char or int8.
DCSimpleParameter *simple_type = _element_type->as_simple_parameter();
if (simple_type == nullptr) {
pack_error = true;
return;
}
size_t blob_size = value.size();
switch (simple_type->get_type()) {
case ST_char:
case ST_uint8:
case ST_int8:
_array_size_range.validate(blob_size, range_error);
if (_num_length_bytes != 0) {
nassertv(_num_length_bytes == 2);
do_pack_uint16(pack_data.get_write_pointer(2), blob_size);
}
pack_data.append_data((const char *)value.data(), blob_size);
break;
default:
pack_error = true;
}
}
/**
* Packs the arrayParameter's specified default value (or a sensible default
* if no value is specified) into the stream. Returns true if the default
@ -339,6 +371,46 @@ unpack_string(const char *data, size_t length, size_t &p, string &value,
}
}
/**
* Unpacks the current numeric or string value from the stream.
*/
void DCArrayParameter::
unpack_blob(const char *data, size_t length, size_t &p, vector_uchar &value,
bool &pack_error, bool &range_error) const {
// We can only unpack a string if the array element type is char or int8.
DCSimpleParameter *simple_type = _element_type->as_simple_parameter();
if (simple_type == nullptr) {
pack_error = true;
return;
}
size_t blob_size;
switch (simple_type->get_type()) {
case ST_char:
case ST_uint8:
case ST_int8:
if (_num_length_bytes != 0) {
blob_size = do_unpack_uint16(data + p);
p += 2;
} else {
nassertv(_array_size >= 0);
blob_size = _array_size;
}
if (p + blob_size > length) {
pack_error = true;
return;
}
value = vector_uchar((const unsigned char *)data + p,
(const unsigned char *)data + p + blob_size);
p += blob_size;
break;
default:
pack_error = true;
}
}
/**
* Returns true if the other interface is bitwise the same as this one--that
* is, a uint32 only matches a uint32, etc. Names of components, and range

View File

@ -51,9 +51,13 @@ public:
virtual void generate_hash(HashGenerator &hashgen) const;
virtual void pack_string(DCPackData &pack_data, const std::string &value,
bool &pack_error, bool &range_error) const;
virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const;
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
virtual void unpack_string(const char *data, size_t length, size_t &p,
std::string &value, bool &pack_error, bool &range_error) const;
virtual void unpack_blob(const char *data, size_t length, size_t &p,
vector_uchar &value, bool &pack_error, bool &range_error) const;
protected:
virtual bool do_check_match(const DCPackerInterface *other) const;

View File

@ -88,11 +88,11 @@ get_element(int n) const {
* If the element is an array-type element, the returned value will include
* the two-byte length preceding the array data.
*
* This is deprecated; use get_element() instead.
* @deprecated use get_element() instead.
*/
string DCAtomicField::
vector_uchar DCAtomicField::
get_element_default(int n) const {
nassertr(n >= 0 && n < (int)_elements.size(), string());
nassertr(n >= 0 && n < (int)_elements.size(), vector_uchar());
return _elements[n]->get_default_value();
}
@ -100,7 +100,7 @@ get_element_default(int n) const {
* Returns true if the nth element of the field has a default value specified,
* false otherwise.
*
* This is deprecated; use get_element() instead.
* @deprecated use get_element() instead.
*/
bool DCAtomicField::
has_element_default(int n) const {
@ -113,7 +113,7 @@ has_element_default(int n) const {
* for documentary purposes; it does not generally affect operation. If a
* name is not specified, this will be the empty string.
*
* This method is deprecated; use get_element()->get_name() instead.
* @deprecated use get_element()->get_name() instead.
*/
string DCAtomicField::
get_element_name(int n) const {

View File

@ -40,7 +40,7 @@ PUBLISHED:
DCParameter *get_element(int n) const;
// These five methods are deprecated and will be removed soon.
std::string get_element_default(int n) const;
vector_uchar get_element_default(int n) const;
bool has_element_default(int n) const;
std::string get_element_name(int n) const;
DCSubatomicType get_element_type(int n) const;

View File

@ -587,7 +587,7 @@ receive_update_other(PyObject *distobj, DatagramIterator &di) const {
*/
void DCClass::
direct_update(PyObject *distobj, const string &field_name,
const string &value_blob) {
const vector_uchar &value_blob) {
DCField *field = get_field_by_name(field_name);
nassertv_always(field != nullptr);
@ -606,7 +606,14 @@ direct_update(PyObject *distobj, const string &field_name,
void DCClass::
direct_update(PyObject *distobj, const string &field_name,
const Datagram &datagram) {
direct_update(distobj, field_name, datagram.get_message());
DCField *field = get_field_by_name(field_name);
nassertv_always(field != nullptr);
DCPacker packer;
packer.set_unpack_data((const char *)datagram.get_data(), datagram.get_length(), false);
packer.begin_unpack(field);
field->receive_update(packer, distobj);
packer.end_unpack();
}
#endif // HAVE_PYTHON

View File

@ -95,7 +95,7 @@ PUBLISHED:
void receive_update_other(PyObject *distobj, DatagramIterator &di) const;
void direct_update(PyObject *distobj, const std::string &field_name,
const std::string &value_blob);
const vector_uchar &value_blob);
void direct_update(PyObject *distobj, const std::string &field_name,
const Datagram &datagram);
bool pack_required_field(Datagram &datagram, PyObject *distobj,

View File

@ -42,7 +42,7 @@ has_default_value() const {
* explicitly set (e.g. has_default_value() returns true), returns that
* value; otherwise, returns an implicit default for the field.
*/
INLINE const std::string &DCField::
INLINE const vector_uchar &DCField::
get_default_value() const {
if (_default_value_stale) {
((DCField *)this)->refresh_default_value();
@ -172,8 +172,8 @@ set_class(DCClass *dclass) {
* Establishes a default value for this field.
*/
INLINE void DCField::
set_default_value(const std::string &default_value) {
_default_value = default_value;
set_default_value(vector_uchar default_value) {
_default_value = std::move(default_value);
_has_default_value = true;
_default_value_stale = false;
}

View File

@ -162,7 +162,7 @@ as_parameter() const {
* is an error.
*/
string DCField::
format_data(const string &packed_data, bool show_field_names) {
format_data(const vector_uchar &packed_data, bool show_field_names) {
DCPacker packer;
packer.set_unpack_data(packed_data);
packer.begin_unpack(this);
@ -178,20 +178,20 @@ format_data(const string &packed_data, bool show_field_names) {
* above) that represents the value of this field, parse the string and return
* the corresponding packed data. Returns empty string if there is an error.
*/
string DCField::
vector_uchar DCField::
parse_string(const string &formatted_string) {
DCPacker packer;
packer.begin_pack(this);
if (!packer.parse_and_pack(formatted_string)) {
// Parse error.
return string();
return vector_uchar();
}
if (!packer.end_pack()) {
// Data type mismatch.
return string();
return vector_uchar();
}
return packer.get_string();
return packer.get_bytes();
}
/**
@ -200,7 +200,7 @@ parse_string(const string &formatted_string) {
* record. Returns true if all fields are valid, false otherwise.
*/
bool DCField::
validate_ranges(const string &packed_data) const {
validate_ranges(const vector_uchar &packed_data) const {
DCPacker packer;
packer.set_unpack_data(packed_data);
packer.begin_unpack(this);
@ -209,7 +209,7 @@ validate_ranges(const string &packed_data) const {
return false;
}
return (packer.get_num_unpacked_bytes() == packed_data.length());
return (packer.get_num_unpacked_bytes() == packed_data.size());
}
#ifdef HAVE_PYTHON
@ -488,7 +488,7 @@ pack_default_value(DCPackData &pack_data, bool &) const {
// The default behavior is to pack the default value if we got it;
// otherwise, to return false and let the packer visit our nested elements.
if (!_default_value_stale) {
pack_data.append_data(_default_value.data(), _default_value.length());
pack_data.append_data((const char *)_default_value.data(), _default_value.size());
return true;
}
@ -566,7 +566,8 @@ refresh_default_value() {
if (!packer.end_pack()) {
std::cerr << "Error while packing default value for " << get_name() << "\n";
} else {
_default_value.assign(packer.get_data(), packer.get_length());
const unsigned char *data = (const unsigned char *)packer.get_data();
_default_value = vector_uchar(data, data + packer.get_length());
}
_default_value_stale = false;
}

View File

@ -53,13 +53,13 @@ PUBLISHED:
virtual DCParameter *as_parameter();
virtual const DCParameter *as_parameter() const;
std::string format_data(const std::string &packed_data, bool show_field_names = true);
std::string parse_string(const std::string &formatted_string);
std::string format_data(const vector_uchar &packed_data, bool show_field_names = true);
vector_uchar parse_string(const std::string &formatted_string);
bool validate_ranges(const std::string &packed_data) const;
bool validate_ranges(const vector_uchar &packed_data) const;
INLINE bool has_default_value() const;
INLINE const std::string &get_default_value() const;
INLINE const vector_uchar &get_default_value() const;
INLINE bool is_bogus_field() const;
@ -98,7 +98,7 @@ public:
INLINE void set_number(int number);
INLINE void set_class(DCClass *dclass);
INLINE void set_default_value(const std::string &default_value);
INLINE void set_default_value(vector_uchar default_value);
#ifdef HAVE_PYTHON
static std::string get_pystr(PyObject *value);
@ -115,7 +115,7 @@ protected:
bool _bogus_field;
private:
std::string _default_value;
vector_uchar _default_value;
#ifdef WITHIN_PANDA
PStatCollector _field_update_pcollector;

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
// Filename: dcLexer.lxx
// Created by: drose (05Oct00)
//
//
////////////////////////////////////////////////////////////////////
*/
@ -103,12 +103,12 @@ dcyyerror(const std::string &msg) {
if (!dc_filename.empty()) {
cerr << " in " << dc_filename;
}
cerr
cerr
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
indent(cerr, col_number-1)
<< "^\n" << msg << "\n\n";
error_count++;
}
@ -120,10 +120,10 @@ dcyywarning(const std::string &msg) {
if (!dc_filename.empty()) {
cerr << " in " << dc_filename;
}
cerr
cerr
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
indent(cerr, col_number-1)
<< "^\n" << msg << "\n\n";
warning_count++;
@ -313,9 +313,9 @@ scan_quoted_string(char quote_mark) {
// scan_hex_string reads a string of hexadecimal digits delimited by
// angle brackets and returns the representative string.
static std::string
static vector_uchar
scan_hex_string() {
std::string result;
vector_uchar result;
// We don't touch the current line number and column number during
// scanning, so that if we detect an error while scanning the string
@ -345,24 +345,24 @@ scan_hex_string() {
line_number = line;
col_number = col;
dcyyerror("Invalid hex digit.");
return std::string();
return vector_uchar();
}
odd = !odd;
if (odd) {
last = value;
} else {
result += (char)((last << 4) | value);
result.push_back((unsigned char)((last << 4) | value));
}
c = read_char(line, col);
}
if (c == EOF) {
dcyyerror("This hex string is unterminated.");
return std::string();
return vector_uchar();
} else if (odd) {
dcyyerror("Odd number of hex digits.");
return std::string();
return vector_uchar();
}
line_number = line;
@ -382,7 +382,7 @@ eat_c_comment() {
int col = col_number;
int c, last_c;
last_c = '\0';
c = read_char(line, col);
while (c != EOF && !(last_c == '*' && c == '/')) {
@ -440,12 +440,12 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
yyless(1);
}
[ \t\r] {
[ \t\r] {
// Eat whitespace.
accept();
}
"//".* {
"//".* {
// Eat C++-style comments.
accept();
}
@ -453,7 +453,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
"/*" {
// Eat C-style comments.
accept();
eat_c_comment();
eat_c_comment();
}
@ -607,7 +607,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
return KW_CHAR;
}
{UNSIGNED_INTEGERNUM} {
{UNSIGNED_INTEGERNUM} {
// An unsigned integer number.
accept();
@ -626,11 +626,11 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
dcyylval.u.uint64 = next_value + (*p - '0');
++p;
}
return UNSIGNED_INTEGER;
}
{SIGNED_INTEGERNUM} {
{SIGNED_INTEGERNUM} {
// A signed integer number.
accept();
@ -671,14 +671,14 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
dcyyerror("Number out of range.");
dcyylval.u.int64 = 1;
}
}
}
return SIGNED_INTEGER;
}
{UNSIGNED_HEXNUM} {
// A hexadecimal integer number.
accept();
accept();
// As above, we'll decode the hex string by hand.
dcyylval.str = dcyytext;
@ -700,15 +700,15 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
++p;
}
return UNSIGNED_INTEGER;
return UNSIGNED_INTEGER;
}
{REALNUM} {
{REALNUM} {
// A floating-point number.
accept();
dcyylval.u.real = patof(dcyytext);
accept();
dcyylval.u.real = patof(dcyytext);
dcyylval.str = dcyytext;
return REAL;
return REAL;
}
["] {
@ -728,11 +728,11 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
[<] {
// Long hex string.
accept();
dcyylval.str = scan_hex_string();
dcyylval.bytes = scan_hex_string();
return HEX_STRING;
}
[A-Za-z_][A-Za-z_0-9]* {
[A-Za-z_][A-Za-z_0-9]* {
// Identifier or keyword.
accept();
dcyylval.str = dcyytext;
@ -750,7 +750,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
. {
// Send any other printable character as itself.
accept();
accept();
return dcyytext[0];
}

View File

@ -217,16 +217,30 @@ pack_string(const std::string &value) {
}
/**
* Adds the indicated string value into the stream, representing a single pre-
* packed field element, or a whole group of field elements at once.
* Packs the indicated numeric or string value into the stream.
*/
INLINE void DCPacker::
pack_literal_value(const std::string &value) {
pack_blob(const vector_uchar &value) {
nassertv(_mode == M_pack || _mode == M_repack);
if (_current_field == nullptr) {
_pack_error = true;
} else {
_pack_data.append_data(value.data(), value.length());
_current_field->pack_blob(_pack_data, value, _pack_error, _range_error);
advance();
}
}
/**
* Adds the indicated string value into the stream, representing a single pre-
* packed field element, or a whole group of field elements at once.
*/
INLINE void DCPacker::
pack_literal_value(const vector_uchar &value) {
nassertv(_mode == M_pack || _mode == M_repack);
if (_current_field == nullptr) {
_pack_error = true;
} else {
_pack_data.append_data((const char *)value.data(), value.size());
advance();
}
}
@ -345,16 +359,36 @@ unpack_string() {
return value;
}
/**
* Unpacks the current binary data value from the stream.
*/
INLINE vector_uchar DCPacker::
unpack_blob() {
vector_uchar value;
nassertr(_mode == M_unpack, value);
if (_current_field == nullptr) {
_pack_error = true;
} else {
_current_field->unpack_blob(_unpack_data, _unpack_length, _unpack_p,
value, _pack_error, _range_error);
advance();
}
return value;
}
/**
* Returns the literal string that represents the packed value of the current
* field, and advances the field pointer.
*/
INLINE std::string DCPacker::
INLINE vector_uchar DCPacker::
unpack_literal_value() {
size_t start = _unpack_p;
unpack_skip();
nassertr(_unpack_p >= start, std::string());
return std::string(_unpack_data + start, _unpack_p - start);
nassertr(_unpack_p >= start, vector_uchar());
return vector_uchar((const unsigned char *)_unpack_data + start,
(const unsigned char *)_unpack_data + _unpack_p);
}
/**
@ -453,16 +487,33 @@ unpack_string(std::string &value) {
}
}
/**
* Unpacks the current numeric or string value from the stream.
*/
INLINE void DCPacker::
unpack_blob(vector_uchar &value) {
nassertv(_mode == M_unpack);
if (_current_field == nullptr) {
_pack_error = true;
} else {
_current_field->unpack_blob(_unpack_data, _unpack_length, _unpack_p,
value, _pack_error, _range_error);
advance();
}
}
/**
* Returns the literal string that represents the packed value of the current
* field, and advances the field pointer.
*/
INLINE void DCPacker::
unpack_literal_value(std::string &value) {
unpack_literal_value(vector_uchar &value) {
size_t start = _unpack_p;
unpack_skip();
nassertv(_unpack_p >= start);
value.assign(_unpack_data + start, _unpack_p - start);
value = vector_uchar((const unsigned char *)_unpack_data + start,
(const unsigned char *)_unpack_data + _unpack_p);
}
/**
@ -541,6 +592,15 @@ get_string() const {
return _pack_data.get_string();
}
/**
* Returns the packed data buffer as a bytes object. Also see get_data().
*/
INLINE vector_uchar DCPacker::
get_bytes() const {
const unsigned char *p = (const unsigned char *)_pack_data.get_data();
return vector_uchar(p, p + _pack_data.get_length());
}
/**
* Returns the total number of bytes in the unpack data buffer. This is the
* buffer used when unpacking; it is separate from the pack data returned by
@ -601,9 +661,9 @@ take_data() {
* between packing sessions.
*/
INLINE void DCPacker::
append_data(const char *buffer, size_t size) {
append_data(const unsigned char *buffer, size_t size) {
nassertv(_mode == M_idle);
_pack_data.append_data(buffer, size);
_pack_data.append_data((const char *)buffer, size);
}
/**
@ -728,6 +788,16 @@ raw_pack_string(const std::string &value) {
_pack_data.append_data(value.data(), value.length());
}
/**
* Packs the data into the buffer between packing sessions.
*/
INLINE void DCPacker::
raw_pack_blob(const vector_uchar &value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value.size());
_pack_data.append_data((const char *)value.data(), value.size());
}
/**
* Unpacks the data from the buffer between unpacking sessions.
*/
@ -870,6 +940,16 @@ raw_unpack_string() {
return value;
}
/**
* Unpacks the data from the buffer between unpacking sessions.
*/
INLINE vector_uchar DCPacker::
raw_unpack_blob() {
vector_uchar value;
raw_unpack_blob(value);
return value;
}
/**
* Unpacks the data from the buffer between unpacking sessions.
*/
@ -971,6 +1051,24 @@ raw_unpack_string(std::string &value) {
_unpack_p += string_length;
}
/**
* Unpacks the data from the buffer between unpacking sessions.
*/
INLINE void DCPacker::
raw_unpack_blob(vector_uchar &value) {
nassertv(_mode == M_idle && _unpack_data != nullptr);
unsigned int blob_size = raw_unpack_uint16();
if (_unpack_p + blob_size > _unpack_length) {
_pack_error = true;
return;
}
const unsigned char *p = (const unsigned char *)_unpack_data + _unpack_p;
value = vector_uchar(p, p + blob_size);
_unpack_p += blob_size;
}
/**
* Advances to the next field after a call to pack_value() or pop().
*/

View File

@ -114,12 +114,12 @@ end_pack() {
* version of begin_unpack() that takes only one parameter.
*/
void DCPacker::
set_unpack_data(const string &data) {
set_unpack_data(const vector_uchar &data) {
nassertv(_mode == M_idle);
char *buffer = new char[data.length()];
memcpy(buffer, data.data(), data.length());
set_unpack_data(buffer, data.length(), true);
char *buffer = new char[data.size()];
memcpy(buffer, data.data(), data.size());
set_unpack_data(buffer, data.size(), true);
}
/**
@ -721,11 +721,11 @@ pack_object(PyObject *object) {
pack_string(string(buffer, length));
}
} else if (PyBytes_Check(object)) {
char *buffer;
const unsigned char *buffer;
Py_ssize_t length;
PyBytes_AsStringAndSize(object, &buffer, &length);
PyBytes_AsStringAndSize(object, (char **)&buffer, &length);
if (buffer) {
pack_string(string(buffer, length));
pack_blob(vector_uchar(buffer, buffer + length));
}
#else
} else if (PyString_Check(object) || PyUnicode_Check(object)) {
@ -1118,9 +1118,9 @@ enquote_string(ostream &out, char quote_mark, const string &str) {
* Outputs the indicated string as a hex constant.
*/
void DCPacker::
output_hex_string(ostream &out, const string &str) {
output_hex_string(ostream &out, const vector_uchar &str) {
out << '<';
for (string::const_iterator pi = str.begin();
for (vector_uchar::const_iterator pi = str.begin();
pi != str.end();
++pi) {
char buffer[10];

View File

@ -41,7 +41,7 @@ PUBLISHED:
void begin_pack(const DCPackerInterface *root);
bool end_pack();
void set_unpack_data(const std::string &data);
void set_unpack_data(const vector_uchar &data);
public:
void set_unpack_data(const char *unpack_data, size_t unpack_length,
bool owns_unpack_data);
@ -75,7 +75,8 @@ PUBLISHED:
INLINE void pack_int64(int64_t value);
INLINE void pack_uint64(uint64_t value);
INLINE void pack_string(const std::string &value);
INLINE void pack_literal_value(const std::string &value);
INLINE void pack_blob(const vector_uchar &value);
INLINE void pack_literal_value(const vector_uchar &value);
void pack_default_value();
INLINE double unpack_double();
@ -84,7 +85,8 @@ PUBLISHED:
INLINE int64_t unpack_int64();
INLINE uint64_t unpack_uint64();
INLINE std::string unpack_string();
INLINE std::string unpack_literal_value();
INLINE vector_uchar unpack_blob();
INLINE vector_uchar unpack_literal_value();
void unpack_validate();
void unpack_skip();
@ -97,7 +99,8 @@ public:
INLINE void unpack_int64(int64_t &value);
INLINE void unpack_uint64(uint64_t &value);
INLINE void unpack_string(std::string &value);
INLINE void unpack_literal_value(std::string &value);
INLINE void unpack_blob(vector_uchar &value);
INLINE void unpack_literal_value(vector_uchar &value);
PUBLISHED:
@ -119,6 +122,7 @@ PUBLISHED:
INLINE size_t get_length() const;
INLINE std::string get_string() const;
INLINE vector_uchar get_bytes() const;
INLINE size_t get_unpack_length() const;
INLINE std::string get_unpack_string() const;
public:
@ -126,7 +130,7 @@ public:
INLINE const char *get_data() const;
INLINE char *take_data();
INLINE void append_data(const char *buffer, size_t size);
INLINE void append_data(const unsigned char *buffer, size_t size);
INLINE char *get_write_pointer(size_t size);
INLINE const char *get_unpack_data() const;
@ -148,6 +152,7 @@ PUBLISHED:
INLINE void raw_pack_uint64(uint64_t value);
INLINE void raw_pack_float64(double value);
INLINE void raw_pack_string(const std::string &value);
INLINE void raw_pack_blob(const vector_uchar &value);
// this is a hack to allw me to get in and out of 32bit Mode Faster need to
// agree with channel_type in dcbase.h
@ -165,6 +170,7 @@ PUBLISHED:
INLINE uint64_t raw_unpack_uint64();
INLINE double raw_unpack_float64();
INLINE std::string raw_unpack_string();
INLINE vector_uchar raw_unpack_blob();
public:
INLINE void raw_unpack_int8(int &value);
@ -177,10 +183,11 @@ public:
INLINE void raw_unpack_uint64(uint64_t &value);
INLINE void raw_unpack_float64(double &value);
INLINE void raw_unpack_string(std::string &value);
INLINE void raw_unpack_blob(vector_uchar &value);
public:
static void enquote_string(std::ostream &out, char quote_mark, const std::string &str);
static void output_hex_string(std::ostream &out, const std::string &str);
static void output_hex_string(std::ostream &out, const vector_uchar &str);
private:
INLINE void advance();

View File

@ -248,6 +248,14 @@ pack_string(DCPackData &, const string &, bool &pack_error, bool &) const {
pack_error = true;
}
/**
* Packs the indicated numeric or string value into the stream.
*/
void DCPackerInterface::
pack_blob(DCPackData &, const vector_uchar &, bool &pack_error, bool &) const {
pack_error = true;
}
/**
* Packs the field's specified default value (or a sensible default if no
* value is specified) into the stream. Returns true if the default value is
@ -306,6 +314,14 @@ unpack_string(const char *, size_t, size_t &, string &, bool &pack_error, bool &
pack_error = true;
}
/**
* Unpacks the current numeric or string value from the stream.
*/
void DCPackerInterface::
unpack_blob(const char *, size_t, size_t &, vector_uchar &, bool &pack_error, bool &) const {
pack_error = true;
}
/**
* Internally unpacks the current numeric or string value and validates it
* against the type range limits, but does not return the value. Returns true

View File

@ -16,6 +16,7 @@
#include "dcbase.h"
#include "dcSubatomicType.h"
#include "vector_uchar.h"
class DCFile;
class DCField;
@ -37,8 +38,8 @@ enum DCPackType {
// These PackTypes are all fundamental types, and should be packed (or
// unpacked) with the corresponding call to pack_double(), pack_int(), etc.
// PT_blob is the same as PT_string, but implies that the string contains
// binary data.
// PT_blob is similar to PT_string, except that it contains arbitrary binary
// data instead of just UTF-8 text.
PT_double,
PT_int,
PT_uint,
@ -113,6 +114,8 @@ public:
bool &pack_error, bool &range_error) const;
virtual void pack_string(DCPackData &pack_data, const std::string &value,
bool &pack_error, bool &range_error) const;
virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const;
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
virtual void unpack_double(const char *data, size_t length, size_t &p,
@ -127,6 +130,8 @@ public:
uint64_t &value, bool &pack_error, bool &range_error) const;
virtual void unpack_string(const char *data, size_t length, size_t &p,
std::string &value, bool &pack_error, bool &range_error) const;
virtual void unpack_blob(const char *data, size_t length, size_t &p,
vector_uchar &value, bool &pack_error, bool &range_error) const;
virtual bool unpack_validate(const char *data, size_t length, size_t &p,
bool &pack_error, bool &range_error) const;
virtual bool unpack_skip(const char *data, size_t length, size_t &p,

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,19 @@
/* A Bison parser, made by GNU Bison 2.4.2. */
/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
@ -27,66 +26,74 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_DCYY_BUILT_TMP_DCPARSER_YXX_H_INCLUDED
# define YY_DCYY_BUILT_TMP_DCPARSER_YXX_H_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int dcyydebug;
#endif
/* Tokens. */
/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
UNSIGNED_INTEGER = 258,
SIGNED_INTEGER = 259,
REAL = 260,
STRING = 261,
HEX_STRING = 262,
IDENTIFIER = 263,
KEYWORD = 264,
KW_DCLASS = 265,
KW_STRUCT = 266,
KW_FROM = 267,
KW_IMPORT = 268,
KW_TYPEDEF = 269,
KW_KEYWORD = 270,
KW_SWITCH = 271,
KW_CASE = 272,
KW_DEFAULT = 273,
KW_BREAK = 274,
KW_INT8 = 275,
KW_INT16 = 276,
KW_INT32 = 277,
KW_INT64 = 278,
KW_UINT8 = 279,
KW_UINT16 = 280,
KW_UINT32 = 281,
KW_UINT64 = 282,
KW_FLOAT64 = 283,
KW_STRING = 284,
KW_BLOB = 285,
KW_BLOB32 = 286,
KW_INT8ARRAY = 287,
KW_INT16ARRAY = 288,
KW_INT32ARRAY = 289,
KW_UINT8ARRAY = 290,
KW_UINT16ARRAY = 291,
KW_UINT32ARRAY = 292,
KW_UINT32UINT8ARRAY = 293,
KW_CHAR = 294,
START_DC = 295,
START_PARAMETER_VALUE = 296,
START_PARAMETER_DESCRIPTION = 297
};
enum yytokentype
{
UNSIGNED_INTEGER = 258,
SIGNED_INTEGER = 259,
REAL = 260,
STRING = 261,
IDENTIFIER = 262,
HEX_STRING = 263,
KEYWORD = 264,
KW_DCLASS = 265,
KW_STRUCT = 266,
KW_FROM = 267,
KW_IMPORT = 268,
KW_TYPEDEF = 269,
KW_KEYWORD = 270,
KW_SWITCH = 271,
KW_CASE = 272,
KW_DEFAULT = 273,
KW_BREAK = 274,
KW_INT8 = 275,
KW_INT16 = 276,
KW_INT32 = 277,
KW_INT64 = 278,
KW_UINT8 = 279,
KW_UINT16 = 280,
KW_UINT32 = 281,
KW_UINT64 = 282,
KW_FLOAT64 = 283,
KW_STRING = 284,
KW_BLOB = 285,
KW_BLOB32 = 286,
KW_INT8ARRAY = 287,
KW_INT16ARRAY = 288,
KW_INT32ARRAY = 289,
KW_UINT8ARRAY = 290,
KW_UINT16ARRAY = 291,
KW_UINT32ARRAY = 292,
KW_UINT32UINT8ARRAY = 293,
KW_CHAR = 294,
START_DC = 295,
START_PARAMETER_VALUE = 296,
START_PARAMETER_DESCRIPTION = 297
};
#endif
/* Tokens. */
#define UNSIGNED_INTEGER 258
#define SIGNED_INTEGER 259
#define REAL 260
#define STRING 261
#define HEX_STRING 262
#define IDENTIFIER 263
#define IDENTIFIER 262
#define HEX_STRING 263
#define KEYWORD 264
#define KW_DCLASS 265
#define KW_STRUCT 266
@ -122,15 +129,11 @@
#define START_PARAMETER_VALUE 296
#define START_PARAMETER_DESCRIPTION 297
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE dcyylval;
int dcyyparse (void);
#endif /* !YY_DCYY_BUILT_TMP_DCPARSER_YXX_H_INCLUDED */

View File

@ -57,7 +57,7 @@ dc_init_parser(istream &in, const string &filename, DCFile &file) {
}
void
dc_init_parser_parameter_value(istream &in, const string &filename,
dc_init_parser_parameter_value(istream &in, const string &filename,
DCPacker &packer) {
dc_file = nullptr;
current_packer = &packer;
@ -89,15 +89,16 @@ dc_cleanup_parser() {
%token <u.uint64> UNSIGNED_INTEGER
%token <u.int64> SIGNED_INTEGER
%token <u.real> REAL
%token <str> STRING HEX_STRING IDENTIFIER
%token <str> STRING IDENTIFIER
%token <bytes> HEX_STRING
%token <u.keyword> KEYWORD
%token KW_DCLASS
%token KW_STRUCT
%token KW_FROM
%token KW_IMPORT
%token KW_TYPEDEF
%token KW_KEYWORD
%token KW_DCLASS
%token KW_STRUCT
%token KW_FROM
%token KW_IMPORT
%token KW_TYPEDEF
%token KW_KEYWORD
%token KW_SWITCH
%token KW_CASE
%token KW_DEFAULT
@ -224,7 +225,7 @@ import:
{
dc_file->add_import_module($2);
}
| KW_FROM import_identifier KW_IMPORT
| KW_FROM import_identifier KW_IMPORT
{
dc_file->add_import_module($2);
}
@ -255,7 +256,7 @@ typedef_decl:
{
if ($2 != nullptr) {
DCTypedef *dtypedef = new DCTypedef($2);
if (!dc_file->add_typedef(dtypedef)) {
DCTypedef *old_typedef = dc_file->get_typedef_by_name(dtypedef->get_name());
if (old_typedef->is_bogus_typedef()) {
@ -294,7 +295,7 @@ dclass_or_struct:
;
dclass:
KW_DCLASS optional_name
KW_DCLASS optional_name
{
current_class = new DCClass(dc_file, $2, false, false);
}
@ -322,7 +323,7 @@ dclass_name:
if (dclass->is_struct()) {
yyerror("struct name not allowed");
}
$$ = dclass;
}
}
@ -398,7 +399,7 @@ dclass_field:
;
struct:
KW_STRUCT optional_name
KW_STRUCT optional_name
{
current_class = new DCClass(dc_file, $2, true, false);
}
@ -426,7 +427,7 @@ struct_name:
if (!dstruct->is_struct()) {
yyerror("struct name required");
}
$$ = dstruct;
}
}
@ -538,7 +539,7 @@ unnamed_parameter:
named_parameter_with_default:
named_parameter
| named_parameter '='
| named_parameter '='
{
current_packer = &default_packer;
current_packer->clear_data();
@ -553,7 +554,7 @@ named_parameter_with_default:
is_valid = $1->is_valid();
}
if (current_packer->end_pack()) {
$1->set_default_value(current_packer->get_string());
$1->set_default_value(current_packer->get_bytes());
} else {
if (is_valid) {
@ -568,7 +569,7 @@ named_parameter_with_default:
unnamed_parameter_with_default:
unnamed_parameter
| unnamed_parameter '='
| unnamed_parameter '='
{
current_packer = &default_packer;
current_packer->clear_data();
@ -583,7 +584,7 @@ unnamed_parameter_with_default:
is_valid = $1->is_valid();
}
if (current_packer->end_pack()) {
$1->set_default_value(current_packer->get_string());
$1->set_default_value(current_packer->get_bytes());
} else {
if (is_valid) {
@ -663,7 +664,7 @@ simple_type_name:
$$ = simple_param;
}
| simple_type_name '%' number
{
{
DCSimpleParameter *simple_param = $1->as_simple_parameter();
nassertr(simple_param != nullptr, 0);
if (!simple_param->is_numeric_type()) {
@ -703,10 +704,10 @@ type_name:
dtypedef = new DCTypedef($1);
}
}
dc_file->add_typedef(dtypedef);
}
$$ = dtypedef->make_new_parameter();
}
}
@ -974,7 +975,7 @@ parameter_value:
{
if ($1 != current_packer->get_current_field_name()) {
ostringstream strm;
strm << "Got '" << $1 << "', expected '"
strm << "Got '" << $1 << "', expected '"
<< current_packer->get_current_field_name() << "'";
yyerror(strm.str());
}
@ -1005,7 +1006,7 @@ parameter_actual_value:
{
current_packer->pack_literal_value($1);
}
| '{'
| '{'
{
current_packer->push();
}
@ -1013,7 +1014,7 @@ parameter_actual_value:
{
current_packer->pop();
}
| '['
| '['
{
current_packer->push();
}
@ -1021,7 +1022,7 @@ parameter_actual_value:
{
current_packer->pop();
}
| '('
| '('
{
current_packer->push();
}
@ -1223,7 +1224,7 @@ molecular_atom_list:
if ($3 != nullptr) {
current_molecular->add_atomic($3);
if (!$3->is_bogus_field() && !current_molecular->compare_keywords(*$3)) {
yyerror("Mismatched keywords in molecule between " +
yyerror("Mismatched keywords in molecule between " +
current_molecular->get_atomic(0)->get_name() + " and " +
$3->get_name());
}
@ -1283,7 +1284,7 @@ switch_case:
yyerror("Invalid value for switch parameter");
current_switch->add_invalid_case();
} else {
int case_index = current_switch->add_case(current_packer->get_string());
int case_index = current_switch->add_case(current_packer->get_bytes());
if (case_index == -1) {
yyerror("Duplicate case value");
}

View File

@ -16,6 +16,7 @@
#include "dcbase.h"
#include "dcSubatomicType.h"
#include "vector_uchar.h"
class DCFile;
class DCClass;
@ -61,6 +62,7 @@ public:
const DCKeyword *keyword;
} u;
std::string str;
vector_uchar bytes;
};
// The yacc-generated code expects to use the symbol 'YYSTYPE' to refer to the

View File

@ -1069,6 +1069,52 @@ pack_string(DCPackData &pack_data, const string &value,
}
}
/**
* Packs the indicated numeric or string value into the stream.
*/
void DCSimpleParameter::
pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const {
size_t blob_size = value.size();
switch (_type) {
case ST_char:
case ST_uint8:
case ST_int8:
if (blob_size == 0) {
pack_error = true;
} else {
if (blob_size != 1) {
range_error = true;
}
_uint_range.validate((unsigned int)value[0], range_error);
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)value[0]);
}
break;
case ST_string:
case ST_blob:
_uint_range.validate(blob_size, range_error);
validate_uint_limits(blob_size, 16, range_error);
if (_num_length_bytes != 0) {
do_pack_uint16(pack_data.get_write_pointer(2), blob_size);
}
pack_data.append_data((const char *)value.data(), blob_size);
break;
case ST_blob32:
_uint_range.validate(blob_size, range_error);
if (_num_length_bytes != 0) {
do_pack_uint32(pack_data.get_write_pointer(4), blob_size);
}
pack_data.append_data((const char *)value.data(), blob_size);
break;
default:
pack_error = true;
}
}
/**
* Packs the simpleParameter's specified default value (or a sensible default
* if no value is specified) into the stream. Returns true if the default
@ -1937,6 +1983,79 @@ unpack_string(const char *data, size_t length, size_t &p, string &value,
return;
}
/**
* Unpacks the current numeric or string value from the stream.
*/
void DCSimpleParameter::
unpack_blob(const char *data, size_t length, size_t &p, vector_uchar &value,
bool &pack_error, bool &range_error) const {
// If the type is a single byte, unpack it into a string of length 1.
switch (_type) {
case ST_char:
case ST_int8:
case ST_uint8:
{
if (p + 1 > length) {
pack_error = true;
return;
}
unsigned int int_value = do_unpack_uint8(data + p);
_uint_range.validate(int_value, range_error);
value.resize(1);
value[0] = int_value;
p++;
}
return;
default:
break;
}
size_t blob_size;
if (_num_length_bytes == 0) {
blob_size = _fixed_byte_size;
} else {
switch (_type) {
case ST_string:
case ST_blob:
if (p + 2 > length) {
pack_error = true;
return;
}
blob_size = do_unpack_uint16(data + p);
p += 2;
break;
case ST_blob32:
if (p + 4 > length) {
pack_error = true;
return;
}
blob_size = do_unpack_uint32(data + p);
p += 4;
break;
default:
pack_error = true;
return;
}
}
_uint_range.validate(blob_size, range_error);
if (p + blob_size > length) {
pack_error = true;
return;
}
value = vector_uchar((const unsigned char *)data + p,
(const unsigned char *)data + p + blob_size);
p += blob_size;
return;
}
/**
* Internally unpacks the current numeric or string value and validates it
* against the type range limits, but does not return the value. Returns true

View File

@ -62,6 +62,8 @@ public:
bool &pack_error, bool &range_error) const;
virtual void pack_string(DCPackData &pack_data, const std::string &value,
bool &pack_error, bool &range_error) const;
virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const;
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
virtual void unpack_double(const char *data, size_t length, size_t &p,
@ -76,6 +78,8 @@ public:
uint64_t &value, bool &pack_error, bool &range_error) const;
virtual void unpack_string(const char *data, size_t length, size_t &p,
std::string &value, bool &pack_error, bool &range_error) const;
virtual void unpack_blob(const char *data, size_t length, size_t &p,
vector_uchar &value, bool &pack_error, bool &range_error) const;
virtual bool unpack_validate(const char *data, size_t length, size_t &p,
bool &pack_error, bool &range_error) const;
virtual bool unpack_skip(const char *data, size_t length, size_t &p,

View File

@ -109,7 +109,7 @@ get_num_cases() const {
* if no case has this value.
*/
int DCSwitch::
get_case_by_value(const string &case_value) const {
get_case_by_value(const vector_uchar &case_value) const {
CasesByValue::const_iterator vi;
vi = _cases_by_value.find(case_value);
if (vi != _cases_by_value.end()) {
@ -140,9 +140,9 @@ get_default_case() const {
/**
* Returns the packed value associated with the indicated case.
*/
string DCSwitch::
vector_uchar DCSwitch::
get_value(int case_index) const {
nassertr(case_index >= 0 && case_index < (int)_cases.size(), string());
nassertr(case_index >= 0 && case_index < (int)_cases.size(), vector_uchar());
return _cases[case_index]->_value;
}
@ -198,7 +198,7 @@ is_field_valid() const {
* -1. This is normally called only by the parser.
*/
int DCSwitch::
add_case(const string &value) {
add_case(const vector_uchar &value) {
int case_index = (int)_cases.size();
if (!_cases_by_value.insert(CasesByValue::value_type(value, case_index)).second) {
add_invalid_case();
@ -283,7 +283,8 @@ add_break() {
const DCPackerInterface *DCSwitch::
apply_switch(const char *value_data, size_t length) const {
CasesByValue::const_iterator vi;
vi = _cases_by_value.find(string(value_data, length));
vi = _cases_by_value.find(vector_uchar((const unsigned char *)value_data,
(const unsigned char *)value_data + length));
if (vi != _cases_by_value.end()) {
return _cases[(*vi).second]->_fields;
}
@ -421,7 +422,7 @@ generate_hash(HashGenerator &hashgen) const {
Cases::const_iterator ci;
for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
const SwitchCase *dcase = (*ci);
hashgen.add_string(dcase->_value);
hashgen.add_blob(dcase->_value);
const SwitchFields *fields = dcase->_fields;
hashgen.add_int(fields->_fields.size());
@ -702,7 +703,7 @@ do_check_match(const DCPackerInterface *) const {
*
*/
DCSwitch::SwitchCase::
SwitchCase(const string &value, DCSwitch::SwitchFields *fields) :
SwitchCase(const vector_uchar &value, DCSwitch::SwitchFields *fields) :
_value(value),
_fields(fields)
{

View File

@ -40,18 +40,18 @@ PUBLISHED:
DCField *get_key_parameter() const;
int get_num_cases() const;
int get_case_by_value(const std::string &case_value) const;
int get_case_by_value(const vector_uchar &case_value) const;
DCPackerInterface *get_case(int n) const;
DCPackerInterface *get_default_case() const;
std::string get_value(int case_index) const;
vector_uchar get_value(int case_index) const;
int get_num_fields(int case_index) const;
DCField *get_field(int case_index, int n) const;
DCField *get_field_by_name(int case_index, const std::string &name) const;
public:
bool is_field_valid() const;
int add_case(const std::string &value);
int add_case(const vector_uchar &value);
void add_invalid_case();
bool add_default();
bool add_field(DCField *field);
@ -98,13 +98,13 @@ public:
class SwitchCase {
public:
SwitchCase(const std::string &value, SwitchFields *fields);
SwitchCase(const vector_uchar &value, SwitchFields *fields);
~SwitchCase();
bool do_check_match_switch_case(const SwitchCase *other) const;
public:
std::string _value;
vector_uchar _value;
SwitchFields *_fields;
};
@ -137,7 +137,7 @@ private:
bool _fields_added;
// This map indexes into the _cases vector, above.
typedef pmap<std::string, int> CasesByValue;
typedef pmap<vector_uchar, int> CasesByValue;
CasesByValue _cases_by_value;
};

View File

@ -56,6 +56,18 @@ add_string(const std::string &str) {
}
}
/**
* Adds a blob to the hash, by breaking it down into a sequence of integers.
*/
void HashGenerator::
add_blob(const vector_uchar &bytes) {
add_int(bytes.size());
vector_uchar::const_iterator bi;
for (bi = bytes.begin(); bi != bytes.end(); ++bi) {
add_int(*bi);
}
}
/**
* Returns the hash number generated.
*/

View File

@ -16,6 +16,7 @@
#include "dcbase.h"
#include "primeNumberGenerator.h"
#include "vector_uchar.h"
/**
* This class generates an arbitrary hash number from a sequence of ints.
@ -26,6 +27,7 @@ public:
void add_int(int num);
void add_string(const std::string &str);
void add_blob(const vector_uchar &bytes);
unsigned long get_hash() const;

View File

@ -891,7 +891,7 @@ describe_message(std::ostream &out, const string &prefix,
const Datagram &dg) const {
DCPacker packer;
packer.set_unpack_data(dg.get_message());
packer.set_unpack_data((const char *)dg.get_data(), dg.get_length(), false);
CHANNEL_TYPE do_id;
int msg_type;
bool is_update = false;