Use vector_uchar instead of string for binary network/file data

This distinction allows us to better support Python 3, since it will raise exceptions when trying to put arbitrary binary data in a str object.

This also adds some convenience functions for efficiently initializing a Datagram or PTA_uchar from a vector_uchar.
This commit is contained in:
rdb 2018-04-02 23:16:03 +02:00
parent fadbcd91e5
commit e9ae7dcc40
25 changed files with 143 additions and 167 deletions

View File

@ -803,8 +803,9 @@ handle_update_field_owner() {
Py_DECREF(dclass_this); Py_DECREF(dclass_this);
// check if we should forward this update to the owner view // check if we should forward this update to the owner view
vector_uchar data = _di.get_remaining_bytes();
DCPacker packer; DCPacker packer;
packer.set_unpack_data(_di.get_remaining_bytes()); packer.set_unpack_data((const char *)data.data(), data.size(), false);
int field_id = packer.raw_unpack_uint16(); int field_id = packer.raw_unpack_uint16();
DCField *field = dclass->get_field_by_index(field_id); DCField *field = dclass->get_field_by_index(field_id);
if (field->is_ownrecv()) { if (field->is_ownrecv()) {
@ -845,8 +846,9 @@ handle_update_field_owner() {
Py_DECREF(dclass_this); Py_DECREF(dclass_this);
// check if we should forward this update to the owner view // check if we should forward this update to the owner view
vector_uchar data = _di.get_remaining_bytes();
DCPacker packer; DCPacker packer;
packer.set_unpack_data(_di.get_remaining_bytes()); packer.set_unpack_data((const char *)data.data(), data.size(), false);
int field_id = packer.raw_unpack_uint16(); int field_id = packer.raw_unpack_uint16();
DCField *field = dclass->get_field_by_index(field_id); DCField *field = dclass->get_field_by_index(field_id);
if (true) {//field->is_broadcast()) { if (true) {//field->is_broadcast()) {

View File

@ -146,14 +146,15 @@ open_read(istream *source, bool owns_source, const string &password) {
int iv_length = EVP_CIPHER_iv_length(cipher); int iv_length = EVP_CIPHER_iv_length(cipher);
_read_block_size = EVP_CIPHER_block_size(cipher); _read_block_size = EVP_CIPHER_block_size(cipher);
string iv = sr.extract_bytes(iv_length); unsigned char *iv = (unsigned char *)alloca(iv_length);
iv_length = (int)sr.extract_bytes(iv, iv_length);
_read_ctx = EVP_CIPHER_CTX_new(); _read_ctx = EVP_CIPHER_CTX_new();
nassertv(_read_ctx != NULL); nassertv(_read_ctx != NULL);
// Initialize the context // Initialize the context
int result; int result;
result = EVP_DecryptInit(_read_ctx, cipher, NULL, (unsigned char *)iv.data()); result = EVP_DecryptInit(_read_ctx, cipher, NULL, (unsigned char *)iv);
nassertv(result > 0); nassertv(result > 0);
result = EVP_CIPHER_CTX_set_key_length(_read_ctx, key_length); result = EVP_CIPHER_CTX_set_key_length(_read_ctx, key_length);
@ -170,7 +171,7 @@ open_read(istream *source, bool owns_source, const string &password) {
unsigned char *key = (unsigned char *)alloca(key_length); unsigned char *key = (unsigned char *)alloca(key_length);
result = result =
PKCS5_PBKDF2_HMAC_SHA1((const char *)password.data(), password.length(), PKCS5_PBKDF2_HMAC_SHA1((const char *)password.data(), password.length(),
(unsigned char *)iv.data(), iv.length(), iv, iv_length,
count * iteration_count_factor + 1, count * iteration_count_factor + 1,
key_length, key); key_length, key);
nassertv(result > 0); nassertv(result > 0);

View File

@ -117,16 +117,18 @@ extract_bytes(unsigned char *into, size_t size) {
* Extracts the indicated number of bytes in the stream and returns them as a * Extracts the indicated number of bytes in the stream and returns them as a
* string. Returns empty string at end-of-file. * string. Returns empty string at end-of-file.
*/ */
string StreamReader:: vector_uchar StreamReader::
extract_bytes(size_t size) { extract_bytes(size_t size) {
vector_uchar buffer;
if (_in->eof() || _in->fail()) { if (_in->eof() || _in->fail()) {
return string(); return buffer;
} }
char *buffer = (char *)alloca(size); buffer.resize(size);
_in->read(buffer, size); _in->read((char *)&buffer[0], size);
size_t read_bytes = _in->gcount(); size_t read_bytes = _in->gcount();
return string(buffer, read_bytes); buffer.resize(read_bytes);
return buffer;
} }
/** /**

View File

@ -19,6 +19,7 @@
#include "numeric_types.h" #include "numeric_types.h"
#include "littleEndian.h" #include "littleEndian.h"
#include "bigEndian.h" #include "bigEndian.h"
#include "vector_uchar.h"
/** /**
* A class to read sequential binary data directly from an istream. Its * A class to read sequential binary data directly from an istream. Its
@ -71,7 +72,7 @@ PUBLISHED:
EXTENSION(BLOCKING PyObject *readlines()); EXTENSION(BLOCKING PyObject *readlines());
public: public:
BLOCKING string extract_bytes(size_t size); BLOCKING vector_uchar extract_bytes(size_t size);
BLOCKING string readline(); BLOCKING string readline();
private: private:

View File

@ -583,9 +583,7 @@ add_multifile_record(PT(MultifileRecord) mfr) {
* Verifies magic number, returns the number of multifiles or -1 if invalid * Verifies magic number, returns the number of multifiles or -1 if invalid
*/ */
int DownloadDb::Db:: int DownloadDb::Db::
parse_header(const string &data) { parse_header(Datagram dg) {
Datagram dg(data);
// Make sure we have a good header // Make sure we have a good header
DatagramIterator di(dg); DatagramIterator di(dg);
uint32_t magic_number = di.get_uint32(); uint32_t magic_number = di.get_uint32();
@ -623,8 +621,7 @@ parse_header(const string &data) {
* record * record
*/ */
int DownloadDb::Db:: int DownloadDb::Db::
parse_record_header(const string &data) { parse_record_header(Datagram dg) {
Datagram dg(data);
DatagramIterator di(dg); DatagramIterator di(dg);
int32_t record_length = di.get_int32(); int32_t record_length = di.get_int32();
downloader_cat.spam() downloader_cat.spam()
@ -639,14 +636,12 @@ parse_record_header(const string &data) {
* Parses a multifile record (mfr) and returns one * Parses a multifile record (mfr) and returns one
*/ */
PT(DownloadDb::MultifileRecord) DownloadDb::Db:: PT(DownloadDb::MultifileRecord) DownloadDb::Db::
parse_mfr(const string &data) { parse_mfr(Datagram dg) {
PT(DownloadDb::MultifileRecord) mfr = new DownloadDb::MultifileRecord; PT(DownloadDb::MultifileRecord) mfr = new DownloadDb::MultifileRecord;
Datagram dg(data);
DatagramIterator di(dg); DatagramIterator di(dg);
int32_t mfr_name_length = di.get_int32(); mfr->_name = di.get_string32();
mfr->_name = di.extract_bytes(mfr_name_length);
mfr->_phase = di.get_float64(); mfr->_phase = di.get_float64();
mfr->_size = di.get_int32(); mfr->_size = di.get_int32();
mfr->_status = di.get_int32(); mfr->_status = di.get_int32();
@ -676,14 +671,12 @@ parse_mfr(const string &data) {
* Parses a file record (fr) and returns one * Parses a file record (fr) and returns one
*/ */
PT(DownloadDb::FileRecord) DownloadDb::Db:: PT(DownloadDb::FileRecord) DownloadDb::Db::
parse_fr(const string &data) { parse_fr(Datagram dg) {
PT(DownloadDb::FileRecord) fr = new DownloadDb::FileRecord; PT(DownloadDb::FileRecord) fr = new DownloadDb::FileRecord;
Datagram dg(data);
DatagramIterator di(dg); DatagramIterator di(dg);
int32_t fr_name_length = di.get_int32(); fr->_name = di.get_string32();
fr->_name = di.extract_bytes(fr_name_length);
// At one time, we stored files in the database with a backslash separator. // At one time, we stored files in the database with a backslash separator.
// Nowadays we use a forward slash, but we should make sure we properly // Nowadays we use a forward slash, but we should make sure we properly
@ -706,15 +699,14 @@ parse_fr(const string &data) {
bool DownloadDb::Db:: bool DownloadDb::Db::
read(StreamReader &sr, bool want_server_info) { read(StreamReader &sr, bool want_server_info) {
// Read the header // Read the header
string header; vector_uchar header = sr.extract_bytes(_header_length);
header = sr.extract_bytes(_header_length);
if (header.size() != (size_t)_header_length) { if (header.size() != (size_t)_header_length) {
downloader_cat.error() << "truncated db file" << endl; downloader_cat.error() << "truncated db file" << endl;
return false; return false;
} }
// Parse the header // Parse the header
int num_multifiles = parse_header(header); int num_multifiles = parse_header(Datagram(move(header)));
if (num_multifiles < 0) { if (num_multifiles < 0) {
downloader_cat.error() << "invalid db header" << endl; downloader_cat.error() << "invalid db header" << endl;
return false; return false;
@ -727,26 +719,26 @@ read(StreamReader &sr, bool want_server_info) {
// of the record // of the record
int mfr_header_length = sizeof(int32_t); int mfr_header_length = sizeof(int32_t);
string mfr_header = sr.extract_bytes(mfr_header_length); vector_uchar mfr_header = sr.extract_bytes(mfr_header_length);
if (mfr_header.size() != (size_t)mfr_header_length) { if (mfr_header.size() != (size_t)mfr_header_length) {
downloader_cat.error() << "invalid mfr header" << endl; downloader_cat.error() << "invalid mfr header" << endl;
return false; return false;
} }
// Parse the header // Parse the header
int mfr_length = parse_record_header(mfr_header); int mfr_length = parse_record_header(Datagram(move(mfr_header)));
// Ok, now that we know the size of the mfr, read it in Make a buffer to // Ok, now that we know the size of the mfr, read it in Make a buffer to
// read the multifile record into do not count the header length twice // read the multifile record into do not count the header length twice
int read_length = (mfr_length - mfr_header_length); int read_length = (mfr_length - mfr_header_length);
string mfr_record = sr.extract_bytes(read_length); vector_uchar mfr_record = sr.extract_bytes(read_length);
if (mfr_record.size() != (size_t)read_length) { if (mfr_record.size() != (size_t)read_length) {
downloader_cat.error() << "invalid mfr record" << endl; downloader_cat.error() << "invalid mfr record" << endl;
return false; return false;
} }
// Parse the mfr // Parse the mfr
PT(DownloadDb::MultifileRecord) mfr = parse_mfr(mfr_record); PT(DownloadDb::MultifileRecord) mfr = parse_mfr(Datagram(move(mfr_record)));
// Only read in the individual file info if you are the server // Only read in the individual file info if you are the server
if (want_server_info) { if (want_server_info) {
@ -758,27 +750,27 @@ read(StreamReader &sr, bool want_server_info) {
int fr_header_length = sizeof(int32_t); int fr_header_length = sizeof(int32_t);
// Read the header // Read the header
string fr_header = sr.extract_bytes(fr_header_length); vector_uchar fr_header = sr.extract_bytes(fr_header_length);
if (fr_header.size() != (size_t)fr_header_length) { if (fr_header.size() != (size_t)fr_header_length) {
downloader_cat.error() << "invalid fr header" << endl; downloader_cat.error() << "invalid fr header" << endl;
return false; return false;
} }
// Parse the header // Parse the header
int fr_length = parse_record_header(fr_header); int fr_length = parse_record_header(Datagram(move(fr_header)));
// Ok, now that we know the size of the mfr, read it in do not count // Ok, now that we know the size of the mfr, read it in do not count
// the header length twice // the header length twice
int read_length = (fr_length - fr_header_length); int read_length = (fr_length - fr_header_length);
string fr_record = sr.extract_bytes(read_length); vector_uchar fr_record = sr.extract_bytes(read_length);
if (fr_record.size() != (size_t)read_length) { if (fr_record.size() != (size_t)read_length) {
downloader_cat.error() << "invalid fr record" << endl; downloader_cat.error() << "invalid fr record" << endl;
return false; return false;
} }
// Parse the file record // Parse the file record
PT(DownloadDb::FileRecord) fr = parse_fr(fr_record); PT(DownloadDb::FileRecord) fr = parse_fr(Datagram(move(fr_record)));
// Add this file record to the current multifilerecord // Add this file record to the current multifilerecord
mfr->add_file_record(fr); mfr->add_file_record(fr);
@ -900,12 +892,10 @@ write_header(ostream &write_stream) {
// Write the number of multifiles // Write the number of multifiles
dg.add_int32(get_num_multifiles()); dg.add_int32(get_num_multifiles());
string msg = dg.get_message();
// Seek back to the beginning of the write stream // Seek back to the beginning of the write stream
write_stream.seekp(0); write_stream.seekp(0);
// Overwrite the old bogus header with the real header // Overwrite the old bogus header with the real header
write_stream.write(msg.data(), msg.length()); write_stream.write((const char *)dg.get_data(), dg.get_length());
return true; return true;
} }
@ -1100,17 +1090,8 @@ read_version_map(StreamReader &sr) {
for (int i = 0; i < num_entries; i++) { for (int i = 0; i < num_entries; i++) {
// Get the length of the file name
int name_length = sr.get_int32();
if (sr.get_istream()->fail()) {
return false;
}
downloader_cat.spam()
<< "DownloadDb::read_version_map() - name length: " << name_length
<< endl;
// Get the file name // Get the file name
string name = sr.extract_bytes(name_length); string name = sr.get_string32();
downloader_cat.spam() downloader_cat.spam()
<< "DownloadDb::read_version_map() - name: " << name << endl; << "DownloadDb::read_version_map() - name: " << name << endl;

View File

@ -171,10 +171,10 @@ public:
bool multifile_exists(string mfname) const; bool multifile_exists(string mfname) const;
PT(MultifileRecord) get_multifile_record_named(string mfname) const; PT(MultifileRecord) get_multifile_record_named(string mfname) const;
void add_multifile_record(PT(MultifileRecord) mfr); void add_multifile_record(PT(MultifileRecord) mfr);
int parse_header(const string &data); int parse_header(Datagram dg);
int parse_record_header(const string &data); int parse_record_header(Datagram dg);
PT(MultifileRecord) parse_mfr(const string &data); PT(MultifileRecord) parse_mfr(Datagram dg);
PT(FileRecord) parse_fr(const string &data); PT(FileRecord) parse_fr(Datagram dg);
bool read(StreamReader &sr, bool want_server_info); bool read(StreamReader &sr, bool want_server_info);
bool write(StreamWriter &sw, bool want_server_info); bool write(StreamWriter &sw, bool want_server_info);
Filename _filename; Filename _filename;

View File

@ -50,17 +50,17 @@ SSReader::
bool SSReader:: bool SSReader::
do_receive_datagram(Datagram &dg) { do_receive_datagram(Datagram &dg) {
if (_tcp_header_size == 0) { if (_tcp_header_size == 0) {
_data_expected = _data_so_far.length(); _data_expected = _data_so_far.size();
} }
if (_data_expected == 0) { if (_data_expected == 0) {
// Read the first two bytes: the datagram length. // Read the first two bytes: the datagram length.
while ((int)_data_so_far.length() < _tcp_header_size) { while ((int)_data_so_far.size() < _tcp_header_size) {
int ch = _istream->get(); int ch = _istream->get();
if (_istream->eof() || _istream->fail()) { if (_istream->eof() || _istream->fail()) {
_istream->clear(); _istream->clear();
return false; return false;
} }
_data_so_far += (char)ch; _data_so_far.push_back((unsigned char)ch);
} }
Datagram header(_data_so_far); Datagram header(_data_so_far);
@ -70,7 +70,7 @@ do_receive_datagram(Datagram &dg) {
} else if (_tcp_header_size == 4) { } else if (_tcp_header_size == 4) {
_data_expected = di.get_uint32(); _data_expected = di.get_uint32();
} }
_data_so_far = _data_so_far.substr(_tcp_header_size); _data_so_far.erase(_data_so_far.begin(), _data_so_far.begin() + _tcp_header_size);
if (_data_expected == 0) { if (_data_expected == 0) {
// Empty datagram. // Empty datagram.
@ -84,20 +84,19 @@ do_receive_datagram(Datagram &dg) {
static const size_t buffer_size = 1024; static const size_t buffer_size = 1024;
char buffer[buffer_size]; char buffer[buffer_size];
size_t read_count = min(_data_expected - _data_so_far.length(), size_t read_count = min(_data_expected - _data_so_far.size(), buffer_size);
buffer_size);
_istream->read(buffer, read_count); _istream->read(buffer, read_count);
size_t count = _istream->gcount(); size_t count = _istream->gcount();
while (count != 0) { while (count != 0) {
_data_so_far.append(buffer, count); _data_so_far.insert(_data_so_far.end(), buffer, buffer + count);
read_count = min(_data_expected - _data_so_far.length(), read_count = min(_data_expected - _data_so_far.size(),
buffer_size); buffer_size);
_istream->read(buffer, read_count); _istream->read(buffer, read_count);
count = _istream->gcount(); count = _istream->gcount();
} }
if (_data_so_far.length() < _data_expected) { if (_data_so_far.size() < _data_expected) {
// Not yet here. Clear the istream error flag and return false to // Not yet here. Clear the istream error flag and return false to
// indicate more coming. // indicate more coming.
_istream->clear(); _istream->clear();
@ -108,7 +107,7 @@ do_receive_datagram(Datagram &dg) {
dg.append_data(_data_so_far); dg.append_data(_data_so_far);
_data_expected = 0; _data_expected = 0;
_data_so_far = string(); _data_so_far.clear();
return true; return true;
} }

View File

@ -21,6 +21,7 @@
#include "pdeque.h" #include "pdeque.h"
#include "typedReferenceCount.h" #include "typedReferenceCount.h"
#include "pointerTo.h" #include "pointerTo.h"
#include "vector_uchar.h"
// At the present, this module is not compiled if OpenSSL is not available, // At the present, this module is not compiled if OpenSSL is not available,
// since the only current use for it is to implement OpenSSL-defined // since the only current use for it is to implement OpenSSL-defined
@ -54,7 +55,7 @@ private:
istream *_istream; istream *_istream;
size_t _data_expected; size_t _data_expected;
string _data_so_far; vector_uchar _data_so_far;
int _tcp_header_size; int _tcp_header_size;
#ifdef SIMULATE_NETWORK_DELAY #ifdef SIMULATE_NETWORK_DELAY

View File

@ -42,58 +42,16 @@ Datagram(const void *data, size_t size) :
* Constructs a datagram from an existing block of data. * Constructs a datagram from an existing block of data.
*/ */
INLINE Datagram:: INLINE Datagram::
Datagram(const string &data) : Datagram(vector_uchar data) :
_data(move(data)),
#ifdef STDFLOAT_DOUBLE #ifdef STDFLOAT_DOUBLE
_stdfloat_double(true) _stdfloat_double(true)
#else #else
_stdfloat_double(false) _stdfloat_double(false)
#endif #endif
{ {
append_data(data);
} }
/**
*
*/
INLINE Datagram::
Datagram(const Datagram &copy) :
_data(copy._data),
_stdfloat_double(copy._stdfloat_double)
{
}
/**
*
*/
INLINE void Datagram::
operator = (const Datagram &copy) {
_data = copy._data;
_stdfloat_double = copy._stdfloat_double;
}
#ifdef USE_MOVE_SEMANTICS
/**
*
*/
INLINE Datagram::
Datagram(Datagram &&from) NOEXCEPT :
_data(move(from._data)),
_stdfloat_double(from._stdfloat_double)
{
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
/**
*
*/
INLINE void Datagram::
operator = (Datagram &&from) NOEXCEPT {
_data = move(from._data);
_stdfloat_double = from._stdfloat_double;
}
#endif // USE_MOVE_SEMANTICS
/** /**
* Adds a boolean value to the datagram. * Adds a boolean value to the datagram.
*/ */
@ -291,7 +249,7 @@ add_string(const string &str) {
add_uint16((uint16_t)str.length()); add_uint16((uint16_t)str.length());
// Add the string // Add the string
append_data(str); append_data(str.data(), str.length());
} }
/** /**
@ -304,18 +262,18 @@ add_string32(const string &str) {
add_uint32((uint32_t)str.length()); add_uint32((uint32_t)str.length());
// Add the string // Add the string
append_data(str); append_data(str.data(), str.length());
} }
/** /**
* Adds a variable-length string to the datagram, as a NULL-terminated string. * Adds a variable-length string to the datagram, as a NULL-terminated string.
*/ */
INLINE void Datagram:: INLINE void Datagram::
add_z_string(string str) { add_z_string(const string &str) {
// We must not have any nested null characters in the string. // We must not have any nested null characters in the string.
size_t null_pos = str.find('\0'); size_t null_pos = str.find('\0');
// Add the string (sans the null character). // Add the string (sans the null character).
append_data(str.substr(0, null_pos)); append_data(str.data(), std::min<size_t>(null_pos, str.length()));
// And the null character. // And the null character.
add_uint8('\0'); add_uint8('\0');
@ -329,11 +287,11 @@ add_z_string(string str) {
INLINE void Datagram:: INLINE void Datagram::
add_fixed_string(const string &str, size_t size) { add_fixed_string(const string &str, size_t size) {
if (str.length() < size) { if (str.length() < size) {
append_data(str); append_data(str.data(), str.length());
pad_bytes(size - str.length()); pad_bytes(size - str.length());
} else { // str.length() >= size } else { // str.length() >= size
append_data(str.substr(0, size)); append_data(str.data(), size);
} }
} }
@ -341,8 +299,8 @@ add_fixed_string(const string &str, size_t size) {
* Appends some more raw data to the end of the datagram. * Appends some more raw data to the end of the datagram.
*/ */
INLINE void Datagram:: INLINE void Datagram::
append_data(const string &data) { append_data(const vector_uchar &data) {
append_data(data.data(), data.length()); append_data(data.data(), data.size());
} }
/** /**

View File

@ -39,14 +39,7 @@ class EXPCL_PANDAEXPRESS Datagram : public TypedObject {
PUBLISHED: PUBLISHED:
INLINE Datagram(); INLINE Datagram();
INLINE Datagram(const void *data, size_t size); INLINE Datagram(const void *data, size_t size);
INLINE Datagram(const string &data); INLINE explicit Datagram(vector_uchar data);
INLINE Datagram(const Datagram &copy);
INLINE void operator = (const Datagram &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE Datagram(Datagram &&from) NOEXCEPT;
INLINE void operator = (Datagram &&from) NOEXCEPT;
#endif
virtual ~Datagram(); virtual ~Datagram();
@ -80,13 +73,13 @@ PUBLISHED:
INLINE void add_string(const string &str); INLINE void add_string(const string &str);
INLINE void add_string32(const string &str); INLINE void add_string32(const string &str);
INLINE void add_z_string(string str); INLINE void add_z_string(const string &str);
INLINE void add_fixed_string(const string &str, size_t size); INLINE void add_fixed_string(const string &str, size_t size);
void add_wstring(const wstring &str); void add_wstring(const wstring &str);
void pad_bytes(size_t size); void pad_bytes(size_t size);
void append_data(const void *data, size_t size); void append_data(const void *data, size_t size);
INLINE void append_data(const string &data); INLINE void append_data(const vector_uchar &data);
void assign(const void *data, size_t size); void assign(const void *data, size_t size);

View File

@ -422,14 +422,13 @@ skip_bytes(size_t size) {
* Returns the remaining bytes in the datagram as a string, but does not * Returns the remaining bytes in the datagram as a string, but does not
* extract them from the iterator. * extract them from the iterator.
*/ */
INLINE string DatagramIterator:: INLINE vector_uchar DatagramIterator::
get_remaining_bytes() const { get_remaining_bytes() const {
nassertr(_datagram != (const Datagram *)NULL, ""); nassertr(_datagram != (const Datagram *)NULL, vector_uchar());
nassertr(_current_index <= _datagram->get_length(), ""); nassertr(_current_index <= _datagram->get_length(), vector_uchar());
const char *ptr = (const char *)_datagram->get_data(); const unsigned char *ptr = (const unsigned char *)_datagram->get_data();
size_t remaining_size = _datagram->get_length() - _current_index; return vector_uchar(ptr + _current_index, ptr + _datagram->get_length());
return string(ptr + _current_index, remaining_size);
} }
/** /**

View File

@ -119,18 +119,18 @@ get_wstring() {
* Extracts the indicated number of bytes in the datagram and returns them as * Extracts the indicated number of bytes in the datagram and returns them as
* a string. * a string.
*/ */
string DatagramIterator:: vector_uchar DatagramIterator::
extract_bytes(size_t size) { extract_bytes(size_t size) {
nassertr((int)size >= 0, ""); nassertr((int)size >= 0, vector_uchar());
nassertr(_datagram != (const Datagram *)NULL, ""); nassertr(_datagram != (const Datagram *)NULL, vector_uchar());
nassertr(_current_index + size <= _datagram->get_length(), ""); nassertr(_current_index + size <= _datagram->get_length(), vector_uchar());
const char *ptr = (const char *)_datagram->get_data(); const unsigned char *ptr = (const unsigned char *)_datagram->get_data();
size_t last_index = _current_index; ptr += _current_index;
_current_index += size; _current_index += size;
return string(ptr + last_index, size); return vector_uchar(ptr, ptr + size);
} }
/** /**

View File

@ -62,10 +62,10 @@ PUBLISHED:
wstring get_wstring(); wstring get_wstring();
INLINE void skip_bytes(size_t size); INLINE void skip_bytes(size_t size);
string extract_bytes(size_t size); vector_uchar extract_bytes(size_t size);
size_t extract_bytes(unsigned char *into, size_t size); size_t extract_bytes(unsigned char *into, size_t size);
INLINE string get_remaining_bytes() const; INLINE vector_uchar get_remaining_bytes() const;
INLINE size_t get_remaining_size() const; INLINE size_t get_remaining_size() const;
INLINE const Datagram &get_datagram() const; INLINE const Datagram &get_datagram() const;

View File

@ -143,11 +143,11 @@ set_from_hex(const string &text) {
/** /**
* Returns the HashVal as a 16-byte binary string. * Returns the HashVal as a 16-byte binary string.
*/ */
string HashVal:: vector_uchar HashVal::
as_bin() const { as_bin() const {
Datagram dg; Datagram dg;
write_datagram(dg); write_datagram(dg);
return dg.get_message(); return vector_uchar((unsigned char *)dg.get_data(), (unsigned char *)dg.get_data() + dg.get_length());
} }
/** /**
@ -155,7 +155,7 @@ as_bin() const {
* false otherwise. * false otherwise.
*/ */
bool HashVal:: bool HashVal::
set_from_bin(const string &text) { set_from_bin(const vector_uchar &text) {
nassertr(text.size() == 16, false); nassertr(text.size() == 16, false);
Datagram dg(text); Datagram dg(text);
DatagramIterator dgi(dg); DatagramIterator dgi(dg);

View File

@ -55,8 +55,8 @@ PUBLISHED:
string as_hex() const; string as_hex() const;
bool set_from_hex(const string &text); bool set_from_hex(const string &text);
string as_bin() const; vector_uchar as_bin() const;
bool set_from_bin(const string &text); bool set_from_bin(const vector_uchar &text);
INLINE void write_datagram(Datagram &destination) const; INLINE void write_datagram(Datagram &destination) const;
INLINE void read_datagram(DatagramIterator &source); INLINE void read_datagram(DatagramIterator &source);

View File

@ -2402,7 +2402,7 @@ check_signatures() {
nassertv(stream != NULL); nassertv(stream != NULL);
StreamReader reader(*stream); StreamReader reader(*stream);
size_t sig_size = reader.get_uint32(); size_t sig_size = reader.get_uint32();
string sig_string = reader.extract_bytes(sig_size); vector_uchar sig_data = reader.extract_bytes(sig_size);
size_t num_certs = reader.get_uint32(); size_t num_certs = reader.get_uint32();
@ -2470,9 +2470,7 @@ check_signatures() {
// Now check that the signature matches the hash. // Now check that the signature matches the hash.
int verify_result = int verify_result =
EVP_VerifyFinal(md_ctx, EVP_VerifyFinal(md_ctx, sig_data.data(), sig_data.size(), pkey);
(unsigned char *)sig_string.data(),
sig_string.size(), pkey);
if (verify_result == 1) { if (verify_result == 1) {
// The signature matches; save the certificate and its chain. // The signature matches; save the certificate and its chain.
_signatures.push_back(chain); _signatures.push_back(chain);

View File

@ -92,6 +92,19 @@ PointerToArray(PointerToArray<Element> &&from) NOEXCEPT :
} }
#endif // USE_MOVE_SEMANTICS #endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
/**
* Initializes the PTA from a vector.
*/
template<class Element>
INLINE PointerToArray<Element>::
PointerToArray(pvector<Element> &&from, TypeHandle type_handle) :
PointerToArrayBase<Element>(new ReferenceCountedVector<Element>(move(from))),
_type_handle(type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
/** /**
* *
*/ */
@ -710,6 +723,19 @@ ConstPointerToArray(ConstPointerToArray<Element> &&from) NOEXCEPT :
} }
#endif // USE_MOVE_SEMANTICS #endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
/**
* Initializes the PTA from a vector.
*/
template<class Element>
INLINE ConstPointerToArray<Element>::
ConstPointerToArray(pvector<Element> &&from, TypeHandle type_handle) :
PointerToArrayBase<Element>(new ReferenceCountedVector<Element>(move(from))),
_type_handle(type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
/** /**
* *
*/ */

View File

@ -141,6 +141,7 @@ public:
#ifdef USE_MOVE_SEMANTICS #ifdef USE_MOVE_SEMANTICS
INLINE PointerToArray(PointerToArray<Element> &&from) NOEXCEPT; INLINE PointerToArray(PointerToArray<Element> &&from) NOEXCEPT;
INLINE explicit PointerToArray(pvector<Element> &&from, TypeHandle type_handle = get_type_handle(Element));
#endif #endif
public: public:
@ -302,6 +303,7 @@ PUBLISHED:
#ifdef USE_MOVE_SEMANTICS #ifdef USE_MOVE_SEMANTICS
INLINE ConstPointerToArray(PointerToArray<Element> &&from) NOEXCEPT; INLINE ConstPointerToArray(PointerToArray<Element> &&from) NOEXCEPT;
INLINE ConstPointerToArray(ConstPointerToArray<Element> &&from) NOEXCEPT; INLINE ConstPointerToArray(ConstPointerToArray<Element> &&from) NOEXCEPT;
INLINE explicit ConstPointerToArray(pvector<Element> &&from, TypeHandle type_handle = get_type_handle(Element));
#endif #endif
// Duplicating the interface of vector. // Duplicating the interface of vector.

View File

@ -39,6 +39,16 @@ ReferenceCountedVector(const Element *begin, const Element *end, TypeHandle type
{ {
} }
/**
* Creates an array that takes its elements from the given vector.
*/
template<class Element>
INLINE ReferenceCountedVector<Element>::
ReferenceCountedVector(pvector<Element> &&from) :
pvector<Element>(move(from))
{
}
/** /**
* *
*/ */

View File

@ -43,6 +43,7 @@ public:
INLINE ReferenceCountedVector(TypeHandle type_handle); INLINE ReferenceCountedVector(TypeHandle type_handle);
INLINE ReferenceCountedVector(size_type initial_size, TypeHandle type_handle); INLINE ReferenceCountedVector(size_type initial_size, TypeHandle type_handle);
INLINE ReferenceCountedVector(const Element *begin, const Element *end, TypeHandle type_handle); INLINE ReferenceCountedVector(const Element *begin, const Element *end, TypeHandle type_handle);
INLINE ReferenceCountedVector(pvector<Element> &&from);
ALLOC_DELETED_CHAIN(ReferenceCountedVector<Element>); ALLOC_DELETED_CHAIN(ReferenceCountedVector<Element>);
INLINE size_type size() const; INLINE size_type size() const;

View File

@ -4207,7 +4207,9 @@ bool Texture::
do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only) { do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only) {
StreamReader ktx(in); StreamReader ktx(in);
if (ktx.extract_bytes(12) != "\xABKTX 11\xBB\r\n\x1A\n") { unsigned char magic[12];
if (ktx.extract_bytes(magic, 12) != 12 ||
memcmp(magic, "\xABKTX 11\xBB\r\n\x1A\n", 12) != 0) {
gobj_cat.error() gobj_cat.error()
<< filename << " is not a KTX file.\n"; << filename << " is not a KTX file.\n";
return false; return false;

View File

@ -106,7 +106,8 @@ WavAudioCursor(WavAudio *src, istream *stream) :
nassertv(stream != NULL); nassertv(stream != NULL);
// Beginning of "RIFF" chunk. // Beginning of "RIFF" chunk.
if (_reader.extract_bytes(4) != "RIFF") { unsigned char magic[4];
if (_reader.extract_bytes(magic, 4) != 4 || memcmp(magic, "RIFF", 4) != 0) {
movies_cat.error() movies_cat.error()
<< ".wav file is not a valid RIFF file.\n"; << ".wav file is not a valid RIFF file.\n";
return; return;
@ -114,7 +115,7 @@ WavAudioCursor(WavAudio *src, istream *stream) :
unsigned int chunk_size = _reader.get_uint32(); unsigned int chunk_size = _reader.get_uint32();
if (_reader.extract_bytes(4) != "WAVE") { if (_reader.extract_bytes(magic, 4) != 4 || memcmp(magic, "WAVE", 4) != 0) {
movies_cat.error() movies_cat.error()
<< ".wav file is a RIFF file but does not start with a WAVE chunk.\n"; << ".wav file is a RIFF file but does not start with a WAVE chunk.\n";
return; return;
@ -126,10 +127,10 @@ WavAudioCursor(WavAudio *src, istream *stream) :
while ((!have_fmt || !have_data) && _stream->good() && (bytes_read + 8) < chunk_size) { while ((!have_fmt || !have_data) && _stream->good() && (bytes_read + 8) < chunk_size) {
string subchunk_id = _reader.extract_bytes(4); _reader.extract_bytes(magic, 4);
unsigned int subchunk_size = _reader.get_uint32(); unsigned int subchunk_size = _reader.get_uint32();
if (subchunk_id == "fmt ") { if (memcmp(magic, "fmt ", 4) == 0) {
// The format chunk specifies information about the storage. // The format chunk specifies information about the storage.
nassertv(subchunk_size >= 16); nassertv(subchunk_size >= 16);
have_fmt = true; have_fmt = true;
@ -202,7 +203,7 @@ WavAudioCursor(WavAudio *src, istream *stream) :
_reader.skip_bytes(subchunk_size - read_bytes); _reader.skip_bytes(subchunk_size - read_bytes);
} }
} else if (subchunk_id == "data") { } else if (memcmp(magic, "data", 4) == 0) {
// The data chunk contains the actual sammples. // The data chunk contains the actual sammples.
if (!have_fmt) { if (!have_fmt) {
movies_cat.error() movies_cat.error()

View File

@ -82,8 +82,10 @@ play_frame(DatagramIterator &scan, BamReader *manager) {
int num_packets = scan.get_uint16(); int num_packets = scan.get_uint16();
for (int i = 0; i < num_packets; i++) { for (int i = 0; i < num_packets; i++) {
string packet = scan.get_string(); size_t size = scan.get_uint16();
_data.push_back(Datagram(packet)); vector_uchar packet(size);
scan.extract_bytes(&packet[0], size);
_data.push_back(Datagram(move(packet)));
} }
} }

View File

@ -78,9 +78,8 @@ extract_record(FltRecordReader &reader) {
bool FltBeadID:: bool FltBeadID::
extract_ancillary(FltRecordReader &reader) { extract_ancillary(FltRecordReader &reader) {
if (reader.get_opcode() == FO_long_id) { if (reader.get_opcode() == FO_long_id) {
string s = reader.get_iterator().get_remaining_bytes(); vector_uchar s = reader.get_iterator().get_remaining_bytes();
size_t zero_byte = s.find('\0'); _id.assign((const char *)s.data(), strnlen((const char *)s.data(), s.size()));
_id = s.substr(0, zero_byte);
return true; return true;
} }
@ -109,14 +108,11 @@ build_record(FltRecordWriter &writer) const {
FltError FltBeadID:: FltError FltBeadID::
write_ancillary(FltRecordWriter &writer) const { write_ancillary(FltRecordWriter &writer) const {
if (_id.length() > 7) { if (_id.length() > 7) {
Datagram dc;
// Although the manual mentions nothing of this, it is essential that the // Although the manual mentions nothing of this, it is essential that the
// length of the record be a multiple of 4 bytes. // length of the record be a multiple of 4 bytes.
string id = _id; dc.add_fixed_string(_id, (_id.length() + 3) & ~3);
while ((id.length() % 4) != 0) {
id += '\0';
}
Datagram dc(id);
FltError result = writer.write_record(FO_long_id, dc); FltError result = writer.write_record(FO_long_id, dc);
if (result != FE_ok) { if (result != FE_ok) {

View File

@ -621,7 +621,8 @@ extract_record(FltRecordReader &) {
bool FltRecord:: bool FltRecord::
extract_ancillary(FltRecordReader &reader) { extract_ancillary(FltRecordReader &reader) {
if (reader.get_opcode() == FO_comment) { if (reader.get_opcode() == FO_comment) {
_comment = reader.get_iterator().get_remaining_bytes(); vector_uchar s = reader.get_iterator().get_remaining_bytes();
_comment.assign((const char *)s.data(), strnlen((const char *)s.data(), s.size()));
return true; return true;
} }
@ -735,7 +736,7 @@ build_record(FltRecordWriter &) const {
FltError FltRecord:: FltError FltRecord::
write_ancillary(FltRecordWriter &writer) const { write_ancillary(FltRecordWriter &writer) const {
if (!_comment.empty()) { if (!_comment.empty()) {
Datagram dc(_comment); Datagram dc(_comment.data(), _comment.size());
FltError result = writer.write_record(FO_comment, dc); FltError result = writer.write_record(FO_comment, dc);
if (result != FE_ok) { if (result != FE_ok) {
return result; return result;