Merge remote-tracking branch 'origin/master' into cmake

This commit is contained in:
Sam Edwards 2018-04-20 01:57:46 -06:00
commit 56a6e6a80a
39 changed files with 310 additions and 223 deletions

View File

@ -43,24 +43,26 @@ Building Panda3D
Windows Windows
------- -------
We currently build using the Microsoft Visual C++ 2010 compiler. You do not We currently build using the Microsoft Visual C++ 2015 compiler. You will
need Microsoft Visual Studio to build Panda3D, though - the relevant compilers also need to install the [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk),
are included as part of the Windows 7.1 SDK. and if you intend to target Windows XP, you will also need the
[Windows 7.1 SDK](https://www.microsoft.com/en-us/download/details.aspx?id=8279).
You will also need to have the third-party dependency libraries available for You will also need to have the third-party dependency libraries available for
the build scripts to use. These are available from one of these two URLs, the build scripts to use. These are available from one of these two URLs,
depending on whether you are on a 32-bit or 64-bit system: depending on whether you are on a 32-bit or 64-bit system, or you can
https://www.panda3d.org/download/panda3d-1.9.4/panda3d-1.9.4-tools-win32.zip [click here](https://github.com/rdb/panda3d-thirdparty) for instructions on
https://www.panda3d.org/download/panda3d-1.9.4/panda3d-1.9.4-tools-win64.zip building them from source.
(It is also possible to build using MSVC 2015 and 2017, which requires a http://rdb.name/thirdparty-vc14-x64.7z
different set of thirdparty libraries, but that is not described here.) http://rdb.name/thirdparty-vc14.7z
After acquiring these dependencies, you may simply build Panda3D from the After acquiring these dependencies, you may simply build Panda3D from the
command prompt using the following command: command prompt using the following command. (Add the `--windows-sdk=10`
option if you don't need to support Windows XP.)
```bash ```bash
makepanda\makepanda.bat --everything --installer --no-eigen makepanda\makepanda.bat --everything --installer --no-eigen --threads=2
``` ```
When the build succeeds, it will produce an .exe file that you can use to When the build succeeds, it will produce an .exe file that you can use to

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

@ -46,9 +46,24 @@ public:
typedef TYPENAME base_class::size_type size_type; typedef TYPENAME base_class::size_type size_type;
explicit pvector(TypeHandle type_handle = pvector_type_handle) : base_class(allocator(type_handle)) { } explicit pvector(TypeHandle type_handle = pvector_type_handle) : base_class(allocator(type_handle)) { }
pvector(const pvector<Type> &copy) : base_class(copy) { }
explicit pvector(size_type n, TypeHandle type_handle = pvector_type_handle) : base_class(n, Type(), allocator(type_handle)) { } explicit pvector(size_type n, TypeHandle type_handle = pvector_type_handle) : base_class(n, Type(), allocator(type_handle)) { }
explicit pvector(size_type n, const Type &value, TypeHandle type_handle = pvector_type_handle) : base_class(n, value, allocator(type_handle)) { } explicit pvector(size_type n, const Type &value, TypeHandle type_handle = pvector_type_handle) : base_class(n, value, allocator(type_handle)) { }
pvector(const Type *begin, const Type *end, TypeHandle type_handle = pvector_type_handle) : base_class(begin, end, allocator(type_handle)) { } pvector(const Type *begin, const Type *end, TypeHandle type_handle = pvector_type_handle) : base_class(begin, end, allocator(type_handle)) { }
#ifdef USE_MOVE_SEMANTICS
pvector(pvector<Type> &&from) NOEXCEPT : base_class(move(from)) {};
pvector<Type> &operator =(pvector<Type> &&from) NOEXCEPT {
base_class::operator =(move(from));
return *this;
}
#endif
pvector<Type> &operator =(const pvector<Type> &copy) {
base_class::operator =(copy);
return *this;
}
}; };
#endif // USE_STL_ALLOCATOR #endif // USE_STL_ALLOCATOR

View File

@ -5414,6 +5414,18 @@ write_function_instance(ostream &out, FunctionRemap *remap,
parameter_list += ", &" + param_name; parameter_list += ", &" + param_name;
} }
// If the default value is NULL, we also accept a None value.
bool maybe_none = false;
if (default_value != nullptr && (return_flags & RF_coerced) == 0) {
CPPExpression::Result res = param->get_default_value()->evaluate();
if (res._type == CPPExpression::RT_integer ||
res._type == CPPExpression::RT_pointer) {
if (res.as_integer() == 0) {
maybe_none = true;
}
}
}
string class_name = obj_type->get_local_name(&parser); string class_name = obj_type->get_local_name(&parser);
// need to a forward scope for this class.. // need to a forward scope for this class..
@ -5464,17 +5476,27 @@ write_function_instance(ostream &out, FunctionRemap *remap,
type->output_instance(extra_convert, param_name + "_this", &parser); type->output_instance(extra_convert, param_name + "_this", &parser);
if (is_optional) { if (is_optional && maybe_none) {
extra_convert
<< default_expr << ";\n"
<< "if (" << param_name << " != NULL && " << param_name << " != Py_None) {\n"
<< " " << param_name << "_this";
} else if (is_optional) {
extra_convert extra_convert
<< default_expr << ";\n" << default_expr << ";\n"
<< "if (" << param_name << " != NULL) {\n" << "if (" << param_name << " != NULL) {\n"
<< " " << param_name << "_this"; << " " << param_name << "_this";
} else if (maybe_none) {
extra_convert
<< " = NULL;\n"
<< "if (" << param_name << " != Py_None) {\n"
<< " " << param_name << "_this";
} }
extra_convert << " = Dtool_Coerce_" + make_safe_name(class_name) + extra_convert << " = Dtool_Coerce_" + make_safe_name(class_name) +
"(" + param_name + ", " + param_name + "_local);\n"; "(" + param_name + ", " + param_name + "_local);\n";
if (is_optional) { if (is_optional || maybe_none) {
extra_convert << "}\n"; extra_convert << "}\n";
} }
@ -5485,8 +5507,12 @@ write_function_instance(ostream &out, FunctionRemap *remap,
if (report_errors) { if (report_errors) {
// We were asked to report any errors. Let's do it. // We were asked to report any errors. Let's do it.
if (is_optional) { if (is_optional && maybe_none) {
extra_convert << "if (" << param_name << " != NULL && " << param_name << " != Py_None && !" << coerce_call << ") {\n";
} else if (is_optional) {
extra_convert << "if (" << param_name << " != NULL && !" << coerce_call << ") {\n"; extra_convert << "if (" << param_name << " != NULL && !" << coerce_call << ") {\n";
} else if (maybe_none) {
extra_convert << "if (" << param_name << " != Py_None && !" << coerce_call << ") {\n";
} else { } else {
extra_convert << "if (!" << coerce_call << ") {\n"; extra_convert << "if (!" << coerce_call << ") {\n";
} }
@ -5509,19 +5535,35 @@ write_function_instance(ostream &out, FunctionRemap *remap,
} }
extra_convert << "}\n"; extra_convert << "}\n";
} else if (is_optional && maybe_none) {
extra_param_check << " && (" << param_name << " == NULL || " << param_name << " == Py_None || " << coerce_call << ")";
} else if (is_optional) { } else if (is_optional) {
extra_param_check << " && (" << param_name << " == NULL || " << coerce_call << ")"; extra_param_check << " && (" << param_name << " == NULL || " << coerce_call << ")";
} else if (maybe_none) {
extra_param_check << " && (" << param_name << " == Py_None || " << coerce_call << ")";
} else { } else {
extra_param_check << " && " << coerce_call; extra_param_check << " && " << coerce_call;
} }
} else { } else { // The regular, non-coercion case.
type->output_instance(extra_convert, param_name + "_this", &parser); type->output_instance(extra_convert, param_name + "_this", &parser);
if (is_optional) { if (is_optional && maybe_none) {
extra_convert extra_convert
<< default_expr << ";\n" << default_expr << ";\n"
<< "if (" << param_name << " != (PyObject *)NULL) {\n" << "if (" << param_name << " != NULL && " << param_name << " != Py_None) {\n"
<< " " << param_name << "_this";
} else if (is_optional) {
extra_convert
<< default_expr << ";\n"
<< "if (" << param_name << " != NULL) {\n"
<< " " << param_name << "_this";
} else if (maybe_none) {
extra_convert
<< " = NULL;\n"
<< "if (" << param_name << " != Py_None) {\n"
<< " " << param_name << "_this"; << " " << param_name << "_this";
} }
if (const_ok && !report_errors) { if (const_ok && !report_errors) {
@ -5529,7 +5571,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
// simpler. But maybe we should just reorganize these functions // simpler. But maybe we should just reorganize these functions
// entirely? // entirely?
extra_convert << " = NULL;\n"; extra_convert << " = NULL;\n";
int indent_level = is_optional ? 2 : 0; int indent_level = (is_optional || maybe_none) ? 2 : 0;
indent(extra_convert, indent_level) indent(extra_convert, indent_level)
<< "DtoolInstance_GetPointer(" << param_name << "DtoolInstance_GetPointer(" << param_name
<< ", " << param_name << "_this" << ", " << param_name << "_this"
@ -5545,9 +5587,15 @@ write_function_instance(ostream &out, FunctionRemap *remap,
<< "\", " << const_ok << ", " << report_errors << ");\n"; << "\", " << const_ok << ", " << report_errors << ");\n";
} }
if (is_optional) { if (is_optional && maybe_none) {
extra_convert << "}\n";
extra_param_check << " && (" << param_name << " == NULL || " << param_name << " == Py_None || " << param_name << "_this != NULL)";
} else if (is_optional) {
extra_convert << "}\n"; extra_convert << "}\n";
extra_param_check << " && (" << param_name << " == NULL || " << param_name << "_this != NULL)"; extra_param_check << " && (" << param_name << " == NULL || " << param_name << "_this != NULL)";
} else if (maybe_none) {
extra_convert << "}\n";
extra_param_check << " && (" << param_name << " == Py_None || " << param_name << "_this != NULL)";
} else { } else {
extra_param_check << " && " << param_name << "_this != NULL"; extra_param_check << " && " << param_name << "_this != NULL";
} }

View File

@ -41,6 +41,11 @@ inline namespace std {
struct timeval; struct timeval;
#ifdef __cplusplus
#define NULL 0L
#else
#define NULL ((void *)0)
#endif
typedef decltype(nullptr) nullptr_t; typedef decltype(nullptr) nullptr_t;
// One day, we might extend interrogate to be able to parse this, // One day, we might extend interrogate to be able to parse this,

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

@ -552,6 +552,7 @@ if (COMPILER == "MSVC"):
PkgDisable("EGL") PkgDisable("EGL")
PkgDisable("CARBON") PkgDisable("CARBON")
PkgDisable("COCOA") PkgDisable("COCOA")
DefSymbol("FLEX", "YY_NO_UNISTD_H")
if (PkgSkip("PYTHON")==0): if (PkgSkip("PYTHON")==0):
IncDirectory("ALWAYS", SDK["PYTHON"] + "/include") IncDirectory("ALWAYS", SDK["PYTHON"] + "/include")
LibDirectory("ALWAYS", SDK["PYTHON"] + "/libs") LibDirectory("ALWAYS", SDK["PYTHON"] + "/libs")
@ -827,7 +828,7 @@ if (COMPILER=="GCC"):
SmartPkgEnable("EIGEN", "eigen3", (), ("Eigen/Dense",), target_pkg = 'ALWAYS') SmartPkgEnable("EIGEN", "eigen3", (), ("Eigen/Dense",), target_pkg = 'ALWAYS')
SmartPkgEnable("ARTOOLKIT", "", ("AR"), "AR/ar.h") SmartPkgEnable("ARTOOLKIT", "", ("AR"), "AR/ar.h")
SmartPkgEnable("FCOLLADA", "", ChooseLib(fcollada_libs, "FCOLLADA"), ("FCollada", "FCollada/FCollada.h")) SmartPkgEnable("FCOLLADA", "", ChooseLib(fcollada_libs, "FCOLLADA"), ("FCollada", "FCollada/FCollada.h"))
SmartPkgEnable("ASSIMP", "assimp", ("assimp"), "assimp") SmartPkgEnable("ASSIMP", "", ("assimp"), "assimp")
SmartPkgEnable("FFMPEG", ffmpeg_libs, ffmpeg_libs, ("libavformat/avformat.h", "libavcodec/avcodec.h", "libavutil/avutil.h")) SmartPkgEnable("FFMPEG", ffmpeg_libs, ffmpeg_libs, ("libavformat/avformat.h", "libavcodec/avcodec.h", "libavutil/avutil.h"))
SmartPkgEnable("SWSCALE", "libswscale", "libswscale", ("libswscale/swscale.h"), target_pkg = "FFMPEG", thirdparty_dir = "ffmpeg") SmartPkgEnable("SWSCALE", "libswscale", "libswscale", ("libswscale/swscale.h"), target_pkg = "FFMPEG", thirdparty_dir = "ffmpeg")
SmartPkgEnable("SWRESAMPLE","libswresample", "libswresample", ("libswresample/swresample.h"), target_pkg = "FFMPEG", thirdparty_dir = "ffmpeg") SmartPkgEnable("SWRESAMPLE","libswresample", "libswresample", ("libswresample/swresample.h"), target_pkg = "FFMPEG", thirdparty_dir = "ffmpeg")
@ -1396,7 +1397,7 @@ def CompileBison(wobj, wsrc, opts):
CopyFile(wdsth, GetOutputDir()+"/tmp/"+ifile+".h") CopyFile(wdsth, GetOutputDir()+"/tmp/"+ifile+".h")
# Finally, compile the generated source file. # Finally, compile the generated source file.
CompileCxx(wobj,wdstc,opts) CompileCxx(wobj, wdstc, opts + ["FLEX"])
######################################################################## ########################################################################
## ##

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

@ -477,6 +477,7 @@ do_remove(AsyncTask *task, bool upon_death) {
{ {
int index = find_task_on_heap(_sleeping, task); int index = find_task_on_heap(_sleeping, task);
nassertr(index != -1, false); nassertr(index != -1, false);
PT(AsyncTask) hold_task = task;
_sleeping.erase(_sleeping.begin() + index); _sleeping.erase(_sleeping.begin() + index);
make_heap(_sleeping.begin(), _sleeping.end(), AsyncTaskSortWakeTime()); make_heap(_sleeping.begin(), _sleeping.end(), AsyncTaskSortWakeTime());
cleanup_task(task, upon_death, false); cleanup_task(task, upon_death, false);
@ -486,6 +487,7 @@ do_remove(AsyncTask *task, bool upon_death) {
case AsyncTask::S_active: case AsyncTask::S_active:
{ {
// Active, but not being serviced, easy. // Active, but not being serviced, easy.
PT(AsyncTask) hold_task = task;
int index = find_task_on_heap(_active, task); int index = find_task_on_heap(_active, task);
if (index != -1) { if (index != -1) {
_active.erase(_active.begin() + index); _active.erase(_active.begin() + index);
@ -769,7 +771,6 @@ cleanup_task(AsyncTask *task, bool upon_death, bool clean_exit) {
} }
nassertv(task->_chain == this); nassertv(task->_chain == this);
PT(AsyncTask) hold_task = task;
task->_state = AsyncTask::S_inactive; task->_state = AsyncTask::S_inactive;
task->_chain = nullptr; task->_chain = nullptr;

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());
} }
/** /**
@ -358,6 +316,18 @@ get_message() const {
} }
} }
/**
* Returns the datagram's data as a bytes object.
*/
INLINE vector_uchar Datagram::
__bytes__() const {
if (!_data.empty()) {
return vector_uchar(_data.v());
} else {
return vector_uchar();
}
}
/** /**
* Returns a pointer to the beginning of the datagram's data. * Returns a pointer to the beginning of the datagram's data.
*/ */

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,17 +73,18 @@ 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);
INLINE string get_message() const; INLINE string get_message() const;
INLINE vector_uchar __bytes__() const;
INLINE const void *get_data() const; INLINE const void *get_data() const;
INLINE size_t get_length() const; INLINE size_t get_length() const;

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

@ -30,16 +30,19 @@ extern "C" {
#error Buildsystem error: BUILDING_FFMPEG not defined #error Buildsystem error: BUILDING_FFMPEG not defined
#endif #endif
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 86, 100) // Minimum supported versions:
#error Minimum supported version of libavcodec is 54.86.100. // FFmpeg: 1.1
// libav: 9.20 (for Ubuntu 14.04)
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 35, 1)
#error Minimum supported version of libavcodec is 54.35.1.
#endif #endif
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(54, 59, 106) #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(54, 20, 4)
#error Minimum supported version of libavformat is 54.59.106. #error Minimum supported version of libavformat is 54.20.4.
#endif #endif
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 13, 100) #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 3, 0)
#error Minimum supported version of libavutil is 52.13.100. #error Minimum supported version of libavutil is 52.3.0.
#endif #endif
ConfigureDef(config_ffmpeg); ConfigureDef(config_ffmpeg);

View File

@ -1767,6 +1767,7 @@ resolve_multisamples() {
} }
glgsg->_glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, fbo); glgsg->_glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, fbo);
glgsg->_glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, _fbo_multisample); glgsg->_glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, _fbo_multisample);
glgsg->_current_fbo = fbo;
// If the depth buffer is shared, resolve it only on the last to render FBO. // If the depth buffer is shared, resolve it only on the last to render FBO.
bool do_depth_blit = false; bool do_depth_blit = false;

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

@ -464,10 +464,10 @@ PUBLISHED:
MAKE_PROPERTY(keep_ram_image, get_keep_ram_image, set_keep_ram_image); MAKE_PROPERTY(keep_ram_image, get_keep_ram_image, set_keep_ram_image);
MAKE_PROPERTY(cacheable, is_cacheable); MAKE_PROPERTY(cacheable, is_cacheable);
INLINE bool compress_ram_image(CompressionMode compression = CM_on, BLOCKING INLINE bool compress_ram_image(CompressionMode compression = CM_on,
QualityLevel quality_level = QL_default, QualityLevel quality_level = QL_default,
GraphicsStateGuardianBase *gsg = NULL); GraphicsStateGuardianBase *gsg = NULL);
INLINE bool uncompress_ram_image(); BLOCKING INLINE bool uncompress_ram_image();
INLINE int get_num_ram_mipmap_images() const; INLINE int get_num_ram_mipmap_images() const;
INLINE bool has_ram_mipmap_image(int n) const; INLINE bool has_ram_mipmap_image(int n) const;

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

@ -24,23 +24,23 @@
*/ */
DatagramTCPHeader:: DatagramTCPHeader::
DatagramTCPHeader(const NetDatagram &datagram, int header_size) { DatagramTCPHeader(const NetDatagram &datagram, int header_size) {
const string &str = datagram.get_message(); size_t length = datagram.get_length();
switch (header_size) { switch (header_size) {
case 0: case 0:
break; break;
case datagram_tcp16_header_size: case datagram_tcp16_header_size:
{ {
uint16_t size = str.length(); uint16_t size = (uint16_t)length;
nassertv(size == str.length()); nassertv((size_t)size == length);
_header.add_uint16(size); _header.add_uint16(size);
} }
break; break;
case datagram_tcp32_header_size: case datagram_tcp32_header_size:
{ {
uint32_t size = str.length(); uint32_t size = (uint32_t)length;
nassertv(size == str.length()); nassertv((size_t)size == length);
_header.add_uint32(size); _header.add_uint32(size);
} }
break; break;
@ -93,8 +93,7 @@ verify_datagram(const NetDatagram &datagram, int header_size) const {
return true; return true;
} }
const string &str = datagram.get_message(); int actual_size = (int)datagram.get_length();
int actual_size = str.length();
int expected_size = get_datagram_size(header_size); int expected_size = get_datagram_size(header_size);
if (actual_size == expected_size) { if (actual_size == expected_size) {
return true; return true;

View File

@ -24,10 +24,11 @@
*/ */
DatagramUDPHeader:: DatagramUDPHeader::
DatagramUDPHeader(const NetDatagram &datagram) { DatagramUDPHeader(const NetDatagram &datagram) {
const string &str = datagram.get_message(); const unsigned char *begin = (const unsigned char *)datagram.get_data();
const unsigned char *end = begin + datagram.get_length();
uint16_t checksum = 0; uint16_t checksum = 0;
for (size_t p = 0; p < str.size(); p++) { for (const unsigned char *p = begin; p != end; ++p) {
checksum += (uint16_t)(uint8_t)str[p]; checksum += (uint16_t)(uint8_t)*p;
} }
// Now pack the header. // Now pack the header.
@ -49,11 +50,11 @@ DatagramUDPHeader(const void *data) : _header(data, datagram_udp_header_size) {
*/ */
bool DatagramUDPHeader:: bool DatagramUDPHeader::
verify_datagram(const NetDatagram &datagram) const { verify_datagram(const NetDatagram &datagram) const {
const string &str = datagram.get_message(); const unsigned char *begin = (const unsigned char *)datagram.get_data();
const unsigned char *end = begin + datagram.get_length();
uint16_t checksum = 0; uint16_t checksum = 0;
for (size_t p = 0; p < str.size(); p++) { for (const unsigned char *p = begin; p != end; ++p) {
checksum += (uint16_t)(uint8_t)str[p]; checksum += (uint16_t)(uint8_t)*p;
} }
if (checksum == get_datagram_checksum()) { if (checksum == get_datagram_checksum()) {

View File

@ -138,35 +138,45 @@ get_datagram(Datagram &data) {
return true; return true;
} }
streamsize num_bytes = (streamsize)num_bytes_32; size_t num_bytes = (size_t)num_bytes_32;
if (num_bytes_32 == (uint32_t)-1) { if (num_bytes_32 == (uint32_t)-1) {
// Another special case for a value larger than 32 bits. // Another special case for a value larger than 32 bits.
num_bytes = reader.get_uint64(); uint64_t num_bytes_64 = reader.get_uint64();
}
// Make sure we have a reasonable datagram size for putting into memory. if (_in->fail() || _in->eof()) {
nassertr(num_bytes == (size_t)num_bytes, false); _error = true;
return false;
}
num_bytes = (size_t)num_bytes_64;
// Make sure we have a reasonable datagram size for putting into memory.
if (num_bytes_64 != (uint64_t)num_bytes) {
_error = true;
return false;
}
}
// Now, read the datagram itself. We construct an empty datagram, use // Now, read the datagram itself. We construct an empty datagram, use
// pad_bytes to make it big enough, and read *directly* into the datagram's // pad_bytes to make it big enough, and read *directly* into the datagram's
// internal buffer. Doing this saves us a copy operation. // internal buffer. Doing this saves us a copy operation.
data = Datagram(); data = Datagram();
streamsize bytes_read = 0; size_t bytes_read = 0;
while (bytes_read < num_bytes) { while (bytes_read < num_bytes) {
streamsize bytes_left = num_bytes - bytes_read; size_t bytes_left = num_bytes - bytes_read;
// Hold up a second - datagrams >4MB are pretty large by bam/network // Hold up a second - datagrams >4MB are pretty large by bam/network
// standards. Let's take it 4MB at a time just in case the length is // standards. Let's take it 4MB at a time just in case the length is
// corrupt, so we don't allocate potentially a few GBs of RAM only to // corrupt, so we don't allocate potentially a few GBs of RAM only to
// find a truncated file. // find a truncated file.
bytes_left = min(bytes_left, (streamsize)4*1024*1024); bytes_left = min(bytes_left, (size_t)4*1024*1024);
PTA_uchar buffer = data.modify_array(); PTA_uchar buffer = data.modify_array();
buffer.resize(buffer.size() + bytes_left); buffer.resize(buffer.size() + bytes_left);
unsigned char *ptr = &buffer.p()[bytes_read]; unsigned char *ptr = &buffer.p()[bytes_read];
_in->read((char *)ptr, bytes_left); _in->read((char *)ptr, (streamsize)bytes_left);
if (_in->fail() || _in->eof()) { if (_in->fail() || _in->eof()) {
_error = true; _error = true;
return false; return false;

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(); DatagramIterator &di = reader.get_iterator();
size_t zero_byte = s.find('\0'); _id = di.get_fixed_string(di.get_remaining_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(); DatagramIterator &di = reader.get_iterator();
_comment = di.get_fixed_string(di.get_remaining_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;

View File

@ -88,8 +88,8 @@ def test_minkowski_sum_shape():
assert type(shape) is type(shape2) assert type(shape) is type(shape2)
assert shape.margin == shape2.margin assert shape.margin == shape2.margin
assert shape.name == shape2.name assert shape.name == shape2.name
assert shape.transform_a.compare_to(shape2.transform_a, True) == 0 assert shape.transform_a.mat.compare_to(shape2.transform_a.mat) == 0
assert shape.transform_b.compare_to(shape2.transform_b, True) == 0 assert shape.transform_b.mat.compare_to(shape2.transform_b.mat) == 0
assert type(shape.shape_a) == type(shape2.shape_a) assert type(shape.shape_a) == type(shape2.shape_a)
assert type(shape.shape_b) == type(shape2.shape_b) assert type(shape.shape_b) == type(shape2.shape_b)

View File

@ -1,5 +1,6 @@
import pytest import pytest
from panda3d import core from panda3d import core
import sys
# Fixtures for generating interesting datagrams (and verification functions) on # Fixtures for generating interesting datagrams (and verification functions) on
# the fly... # the fly...
@ -76,6 +77,17 @@ def datagram_large():
return dg, readback_function return dg, readback_function
@pytest.mark.skipif(sys.version_info < (3, 0), reason="Requires Python 3")
def test_datagram_bytes():
"""Tests that we can put and get a bytes object on Datagram."""
dg = core.Datagram(b'abc\x00')
dg.append_data(b'\xff123')
assert bytes(dg) == b'abc\x00\xff123'
dgi = core.DatagramIterator(dg)
dgi.get_remaining_bytes() == b'abc\x00\xff123'
def test_iterator(datagram_small): def test_iterator(datagram_small):
"""This tests Datagram/DatagramIterator, and sort of serves as a self-check """This tests Datagram/DatagramIterator, and sort of serves as a self-check
of the test fixtures too.""" of the test fixtures too."""