Compare commits

...
Author SHA1 Message Date
Automatic Release Builder a9dddbcddc new version: 2020.3.10 2021-07-06 10:56:20 +01:00
James Turner fcd72581a1 Make out-of-memory in computeHash fatal 2021-07-06 02:53:28 +01:00
James Turner 0a6091eeeb Error reporting for animations / conditions
Don’t report errors for each condition parse failure, but do 
aggregate them at the animation level in ReaderWriterXML

Sentry-Id: FLIGHTGEAR-DD
2021-07-06 02:50:11 +01:00
James Turner d6400e3737 Add try/catch wrappers in SGSubsystemGroup
Attempt to narrow down the source of some fatal exceptions we see
on Senty, which occur during init/startup. All these blocks re-throw
so user behaviour is unchanged, but we’ll log the name of the subsytem.
2021-07-06 02:49:51 +01:00
James Turner 71e7050349 Attempt to fix realpath() recursion
Sentry-Id: FLIGHTGEAR-D6W
2021-06-15 17:31:33 +01:00
Automatic Release Builder e6f4936536 better STG error reporting 2021-06-15 02:33:31 +01:00
Automatic Release Builder b2ae7e9e63 Fix initial effect errors 2021-06-15 02:33:20 +01:00
Automatic Release Builder ee0b22fd52 Fix HTTP repo erros 2021-06-15 02:33:11 +01:00
James Turner 01233ba537 Error-reporting: improve reports for STGs and effects
When an effect defines no shader sources, special case this error to
avoid confusing result from SGProgram.

Add error-context for readNode STG loading, so failures inside an
STG can be attributed
2021-06-14 20:01:30 +01:00
James Turner ed29d9b75d Effects: better error reporting 2021-06-14 20:00:04 +01:00
James Turner 5d4201cdfa Shaders: report all shader file paths
When reporting a shader log error, include all the shader file
paths and the effect path in the detailed error information.
2021-06-14 19:59:36 +01:00
James Turner 2ef8c0d27b ReadWav: error reporting
Report errors from readWAV, and improve attribution for the
format error (include the file path). As a result, mark the individual
exceptions as dont-report, since we will report higher up.
2021-06-14 19:58:42 +01:00
James Turner 0fbfa3426f Catalogs: check for local IO failures writing to disk
Sentry.io shows some examples where we failed to write valid data
to disk; check for that if possible.
2021-06-14 19:58:18 +01:00
James Turner 57b4060eb3 Error-reporting: show XML path when 3D load fails 2021-06-14 19:57:16 +01:00
James Turner 84a569913d Report out-of-memory in some loading places
BTG can throw bad-alloc in the wild; catch this case and report it.
2021-06-14 19:56:53 +01:00
James Turner b585df04a5 TerraSync: report errors during downloading
Report various out-of-memory and IO failure conditions; especially,
failure to write downloaded to disk, which was previously not 
recorded.
2021-06-14 19:55:07 +01:00
James Turner ddba0c6731 Add osg::Program wrapper for error-reporting 2021-06-14 19:53:32 +01:00
James Turner 43d849232b ErrorReporting: set context for STG loading
Ensure the STG absolute path can be propagated to all files triggered
by STG loading, including the delayed files and proxied files. This
allows us to attribute errors to the correct scenery path.
2021-06-14 19:48:52 +01:00
James Turner 651460bbc8 Allow delayed setup of ErrorContext data
Permit no model data to be provided, when loading a model via the
modelLib API (d’oh)
2021-06-14 19:36:43 +01:00
James Turner 81a489d81d Error reporting: add SGModelData context support
Allow us to pass the current error-context from the main thread
into the osgDB loader thread. This is necessary so we can attribute
AIModel (etc) load problems to the correct source.
2021-06-14 19:36:25 +01:00
James Turner 7e76667af0 Error-reporting: add some errors for Effect shaders 2021-06-14 19:35:49 +01:00
James Turner 32f69df774 Error reporting for submodels
Also add some error codes I forgot for AI and traffic.
2021-06-14 19:34:55 +01:00
James Turner d8d64b2367 Add failure reporting / context to various places.
Not total coverage by far, but working through the list of common
failure points as seen on Sentry
2021-06-14 19:34:28 +01:00
James Turner 747d99450b Suppress reports on some common exception throws 2021-06-14 19:27:26 +01:00
James Turner b023c7c4f4 Add new error reporting function / callback 2021-06-14 19:23:54 +01:00
Erik Hofman c19cf094a7 Backport the code to be able to display the region name of the file that holds the selected material. 2021-05-27 15:55:02 +02:00
Automatic Release Builder 279179e88d new version: 2020.3.9 2021-05-27 11:09:42 +01:00
James Turner 0ddd3e7f2f Add sg_location to all exceptions, add report flag
Move sg_location member up to the base clase, since it’s potentially
useful in more types.

Allow suppression of the report callback when the exception is thrown
2021-05-05 15:00:23 +01:00
James Turner fe96298be5 Thread-safe error reporting in lowlevel.cxx
Use an exception rather than polling a flag, for checking errors
during BTG reading. This should allow us to give a correctly
identified error, at exactly the point the read fails.
2021-05-05 14:58:37 +01:00
James Turner c6351292dd TerraSync: add a warning file to the root dir.
Try to discourage users from adding custom content underneath the
Terrasync dir, since it can be over-written.
2021-04-23 12:15:34 +01:00
James Turner e2caad3b0b TerraSync: better reporting of permissions failures removing files
Log a ‘failed to remove orphan’ error as an error with the repository,
instead of failing the entire sync
2021-04-23 12:15:34 +01:00
James Turner a095ab684c ASan: fix a leak in GZ extraction 2021-04-23 11:55:02 +01:00
James Turner fe41a03180 Asan: fix leaks in Catalog code 2021-04-23 11:54:56 +01:00
Automatic Release Builder 332d9dfadb new version: 2020.3.8 2021-03-24 11:08:07 +00:00
Automatic Release Builder c05802a498 new version: 2020.3.8 2021-03-24 11:04:18 +00:00
James Turner 0970bb1be2 Fix for local particle update
See issue at:
https://sourceforge.net/p/flightgear/codetickets/2568/
2021-03-24 09:59:13 +00:00
43 changed files with 1424 additions and 839 deletions
+1 -1
View File
@@ -1 +1 @@
2020.3.7 2020.3.10
+73
View File
@@ -17,11 +17,15 @@
#include "ErrorReportingCallback.hxx" #include "ErrorReportingCallback.hxx"
#include <simgear/misc/sg_path.hxx>
using std::string; using std::string;
namespace simgear { namespace simgear {
static ErrorReportCallback static_callback; static ErrorReportCallback static_callback;
static ContextCallback static_contextCallback;
void setErrorReportCallback(ErrorReportCallback cb) void setErrorReportCallback(ErrorReportCallback cb)
{ {
@@ -44,4 +48,73 @@ void reportFatalError(const std::string& msg, const std::string& more)
static_callback(msg, more, true); static_callback(msg, more, true);
} }
static FailureCallback static_failureCallback;
void reportFailure(LoadFailure type, ErrorCode code, const std::string& details, sg_location loc)
{
if (!static_failureCallback) {
return;
}
static_failureCallback(type, code, details, loc);
}
void reportFailure(LoadFailure type, ErrorCode code, const std::string& details, const SGPath& path)
{
if (!static_failureCallback) {
return;
}
static_failureCallback(type, code, details, sg_location{path});
}
void setFailureCallback(FailureCallback cb)
{
static_failureCallback = cb;
}
void setErrorContextCallback(ContextCallback cb)
{
static_contextCallback = cb;
}
ErrorReportContext::ErrorReportContext(const std::string& key, const std::string& value)
{
add(key, value);
}
void ErrorReportContext::add(const std::string& key, const std::string& value)
{
if (static_contextCallback) {
_keys.push_back(key);
static_contextCallback(key, value);
}
}
ErrorReportContext::ErrorReportContext(const ContextMap& context)
{
addFromMap(context);
}
void ErrorReportContext::addFromMap(const ContextMap& context)
{
if (static_contextCallback) {
for (const auto& p : context) {
_keys.push_back(p.first);
static_contextCallback(p.first, p.second);
}
}
}
ErrorReportContext::~ErrorReportContext()
{
if (static_contextCallback) {
// pop all our keys
for (const auto& k : _keys) {
static_contextCallback(k, "POP");
}
}
}
} // namespace simgear } // namespace simgear
+97
View File
@@ -16,7 +16,14 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <map>
#include <string> #include <string>
#include <vector>
#include <simgear/structure/exception.hxx>
//forward decls
class SGPath;
namespace simgear { namespace simgear {
@@ -28,4 +35,94 @@ using ErrorReportCallback = std::function<void(const std::string& msg, const std
void setErrorReportCallback(ErrorReportCallback cb); void setErrorReportCallback(ErrorReportCallback cb);
/** kinds of failures we can report. This is *how* (or why) something failed. Extend
as necessary but update the correponsdings string translations if you do. More detail isn't
necessariyl useful here: better to provide that in the 'details' string
*/
enum class LoadFailure {
Unknown,
NotFound,
OutOfMemory,
BadHeader,
BadData,
Misconfigured,
IOError, // disk full, permissions error, etc
NetworkError
};
/**
@brief enum of the operations which can fail. This should be extended as necessary: it maps to
translated error messages for the user. This describes what failed, the enum above gives why/how. The
combination of what+why should be something at the user level: use details for debug-level information.
*/
enum class ErrorCode {
LoadEffectsShaders,
LoadingTexture,
XMLModelLoad,
ThreeDModelLoad, // AC3D, OBJ, etc
BTGLoad,
ScenarioLoad,
GUIDialog,
AudioFX,
XMLLoadCommand,
AircraftSystems, // autopilot, hydrualics, instruments
InputDeviceConfig,
AITrafficSchedule,
TerraSync
};
/**
@brief Define an error-reporting context value, for the duration of this
object's lifetime. The context value will be active for any errors occuring on the same thread, while
this object exists.
*/
class ErrorReportContext
{
public:
ErrorReportContext(const std::string& key, const std::string& value);
using ContextMap = std::map<std::string, std::string>;
/**
Allow establishing multiple context values in a single operation
*/
ErrorReportContext(const ContextMap& context = {});
void add(const std::string& key, const std::string& value);
/**
@brief allowed delayed add of values
*/
void addFromMap(const ContextMap& context);
~ErrorReportContext();
private:
std::vector<std::string> _keys;
};
/**
* @brief Report failure to load a resource, so they can be collated for reporting
* to the user.
*
* @param type - the reason for the failure, if it can be determined
* @param msg - an informational message about what caused the failure
* @param path - path on disk to the resource. In some cases this may be a relative path;
* especially in the case of a resource not found, we cannot report a file path.
*/
void reportFailure(LoadFailure type, ErrorCode code, const std::string& detailedMessage = {}, sg_location loc = {});
/**
overload taking a path as the location
*/
void reportFailure(LoadFailure type, ErrorCode code, const std::string& detailedMessage, const SGPath& p);
using FailureCallback = std::function<void(LoadFailure type, ErrorCode code, const std::string& details, const sg_location& location)>;
void setFailureCallback(FailureCallback cb);
using ContextCallback = std::function<void(const std::string& key, const std::string& value)>;
void setErrorContextCallback(ContextCallback cb);
} // namespace simgear } // namespace simgear
+67 -23
View File
@@ -35,11 +35,12 @@
#include "simgear/debug/logstream.hxx" #include "simgear/debug/logstream.hxx"
#include "simgear/misc/strutils.hxx" #include "simgear/misc/strutils.hxx"
#include <simgear/misc/sg_dir.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/io/HTTPClient.hxx> #include <simgear/io/HTTPClient.hxx>
#include <simgear/io/iostreams/sgstream.hxx>
#include <simgear/io/sg_file.hxx> #include <simgear/io/sg_file.hxx>
#include <simgear/io/untar.hxx> #include <simgear/io/untar.hxx>
#include <simgear/io/iostreams/sgstream.hxx> #include <simgear/misc/sg_dir.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/timing/timestamp.hxx> #include <simgear/timing/timestamp.hxx>
@@ -218,8 +219,7 @@ public:
return; return;
} }
char* buf = nullptr; std::vector<char> buf;
size_t bufSize = 0;
for (auto& child : children) { for (auto& child : children) {
if (child.type != HTTPRepository::FileType) if (child.type != HTTPRepository::FileType)
@@ -240,17 +240,34 @@ public:
src.open(SG_IO_IN); src.open(SG_IO_IN);
dst.open(SG_IO_OUT); dst.open(SG_IO_OUT);
if (bufSize < cp.sizeInBytes()) { const auto sizeToCopy = cp.sizeInBytes();
bufSize = cp.sizeInBytes(); if (buf.size() < sizeToCopy) {
free(buf); try {
buf = (char*)malloc(bufSize); buf.resize(sizeToCopy);
if (!buf) { } catch (std::bad_alloc) {
continue; simgear::reportFailure(simgear::LoadFailure::OutOfMemory, simgear::ErrorCode::TerraSync,
"copyInstalledChildren: couldn't allocation copy buffer of size:" + std::to_string(sizeToCopy),
child.path);
return;
} }
} }
src.read(buf, cp.sizeInBytes()); const auto r = src.read(buf.data(), sizeToCopy);
dst.write(buf, cp.sizeInBytes()); if (r != sizeToCopy) {
simgear::reportFailure(simgear::LoadFailure::IOError, simgear::ErrorCode::TerraSync,
"copyInstalledChildren: read underflow, got:" + std::to_string(r),
cp);
return;
}
const auto written = dst.write(buf.data(), sizeToCopy);
if (written != sizeToCopy) {
simgear::reportFailure(simgear::LoadFailure::IOError, simgear::ErrorCode::TerraSync,
"copyInstalledChildren: write underflow, wrote:" + std::to_string(r),
child.path);
return;
}
src.close(); src.close();
dst.close(); dst.close();
@@ -260,9 +277,7 @@ public:
std::string hash = computeHashForPath(child.path); std::string hash = computeHashForPath(child.path);
updatedFileContents(child.path, hash); updatedFileContents(child.path, hash);
} }
free(buf);
} }
/// helper to check and erase 'fooBar' from paths, if passed fooBar.zip, fooBar.tgz, etc. /// helper to check and erase 'fooBar' from paths, if passed fooBar.zip, fooBar.tgz, etc.
@@ -377,7 +392,12 @@ public:
// We now have a list of entries that need to be updated, and a list // We now have a list of entries that need to be updated, and a list
// of orphan files that should be removed. // of orphan files that should be removed.
removeOrphans(orphans); try {
removeOrphans(orphans);
} catch (sg_exception& e) {
_repository->failedToUpdateChild(_relativePath, HTTPRepository::ResultCode::REPO_ERROR_IO);
}
scheduleUpdates(toBeUpdated); scheduleUpdates(toBeUpdated);
} }
@@ -389,11 +409,10 @@ public:
void removeOrphans(const PathList orphans) void removeOrphans(const PathList orphans)
{ {
PathList::const_iterator it; for (const auto& o : orphans) {
for (it = orphans.begin(); it != orphans.end(); ++it) { if (o.file() == ".dirindex") continue;
if (it->file() == ".dirindex") continue; if (o.file() == ".hash") continue;
if (it->file() == ".hash") continue; removeChild(o);
removeChild(*it);
} }
} }
@@ -1015,13 +1034,20 @@ HTTPRepository::failure() const
if (!file.get()) { if (!file.get()) {
const bool ok = createOutputFile(); const bool ok = createOutputFile();
if (!ok) { if (!ok) {
ioFailureOccurred = true;
_directory->repository()->http->cancelRequest( _directory->repository()->http->cancelRequest(
this, "Unable to create output file:" + pathInRepo.utf8Str()); this, "Unable to create output file:" + pathInRepo.utf8Str());
} }
} }
sha1_write(&hashContext, s, n); sha1_write(&hashContext, s, n);
file->write(s, n); const auto written = file->write(s, n);
if (written != n) {
SG_LOG(SG_TERRASYNC, SG_WARN, "Underflow writing to " << pathInRepo);
ioFailureOccurred = true;
_directory->repository()->http->cancelRequest(
this, "Unable to write to output file:" + pathInRepo.utf8Str());
}
} }
bool createOutputFile() bool createOutputFile()
@@ -1078,8 +1104,15 @@ HTTPRepository::failure() const
void onFail() override { void onFail() override {
HTTPRepository::ResultCode code = HTTPRepository::REPO_ERROR_SOCKET; HTTPRepository::ResultCode code = HTTPRepository::REPO_ERROR_SOCKET;
// -1 means request cancelled locally
if (responseCode() == -1) { if (responseCode() == -1) {
code = HTTPRepository::REPO_ERROR_CANCELLED; if (ioFailureOccurred) {
// cancelled by code above due to IO error
code = HTTPRepository::REPO_ERROR_IO;
} else {
code = HTTPRepository::REPO_ERROR_CANCELLED;
}
} }
if (file) { if (file) {
@@ -1116,6 +1149,10 @@ HTTPRepository::failure() const
SGPath pathInRepo; SGPath pathInRepo;
simgear::sha1nfo hashContext; simgear::sha1nfo hashContext;
std::unique_ptr<SGBinaryFile> file; std::unique_ptr<SGBinaryFile> file;
/// becuase we cancel() in the case of an IO failure, we need to a way to distuinguish
/// user initated cancellation and IO-failure cancellation in onFail. This flag lets us do that
bool ioFailureOccurred = false;
}; };
class DirGetRequest : public HTTPRepoGetRequest class DirGetRequest : public HTTPRepoGetRequest
@@ -1369,6 +1406,9 @@ HTTPRepository::failure() const
if (st == HTTPRepository::REPO_ERROR_FILE_NOT_FOUND) { if (st == HTTPRepository::REPO_ERROR_FILE_NOT_FOUND) {
status = HTTPRepository::REPO_ERROR_NOT_FOUND; status = HTTPRepository::REPO_ERROR_NOT_FOUND;
} else { } else {
simgear::reportFailure(simgear::LoadFailure::NetworkError, simgear::ErrorCode::TerraSync,
"failed to get TerraSync repository root:" + innerResultCodeAsString(st),
sg_location{baseUrl});
SG_LOG(SG_TERRASYNC, SG_WARN, "Failed to get root of repo:" << baseUrl << " " << st); SG_LOG(SG_TERRASYNC, SG_WARN, "Failed to get root of repo:" << baseUrl << " " << st);
status = st; status = st;
} }
@@ -1385,6 +1425,10 @@ HTTPRepository::failure() const
"failed to update entry:" << relativePath << " status/code: " "failed to update entry:" << relativePath << " status/code: "
<< innerResultCodeAsString(fileStatus) << innerResultCodeAsString(fileStatus)
<< "/" << fileStatus); << "/" << fileStatus);
simgear::reportFailure(simgear::LoadFailure::NetworkError, simgear::ErrorCode::TerraSync,
"failed to update entry:" + innerResultCodeAsString(fileStatus),
sg_location{relativePath});
} }
HTTPRepository::Failure f; HTTPRepository::Failure f;
+70 -42
View File
@@ -23,28 +23,41 @@
// $Id$ // $Id$
#ifdef HAVE_CONFIG_H #include <simgear_config.h>
# include <simgear_config.h>
#endif
#include <string.h> // for memcpy() #include <string.h> // for memcpy()
#include <errno.h>
#include "lowlevel.hxx" #include <simgear/structure/exception.hxx>
#include <simgear/misc/strutils.hxx>
#include <simgear/misc/sg_path.hxx>
#include "lowlevel.hxx"
static int read_error = false ; thread_local SGPath thread_gzPath;
static int write_error = false ;
void sgClearReadError() { read_error = false; } void setThreadLocalSimgearReadPath(const SGPath& path)
void sgClearWriteError() { write_error = false; } {
int sgReadError() { return read_error ; } thread_gzPath = path;
int sgWriteError() { return write_error ; } }
static std::string gzErrorMessage(gzFile fd)
{
int errNum = 0;
const char *gzMsg = gzerror(fd, &errNum);
if (errNum == Z_ERRNO) {
return simgear::strutils::error_string(errno);
} else {
return {gzMsg};
}
}
void sgReadChar ( gzFile fd, char *var ) void sgReadChar ( gzFile fd, char *var )
{ {
if ( gzread ( fd, var, sizeof(char) ) != sizeof(char) ) { if ( gzread ( fd, var, sizeof(char) ) != sizeof(char) ) {
read_error = true ; throw sg_io_exception("sgReadChar: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
} }
@@ -52,7 +65,7 @@ void sgReadChar ( gzFile fd, char *var )
void sgWriteChar ( gzFile fd, const char var ) void sgWriteChar ( gzFile fd, const char var )
{ {
if ( gzwrite ( fd, (void *)(&var), sizeof(char) ) != sizeof(char) ) { if ( gzwrite ( fd, (void *)(&var), sizeof(char) ) != sizeof(char) ) {
write_error = true ; throw sg_io_exception("sgWriteChar: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -61,7 +74,8 @@ void sgReadFloat ( gzFile fd, float *var )
{ {
union { float v; uint32_t u; } buf; union { float v; uint32_t u; } buf;
if ( gzread ( fd, &buf.u, sizeof(float) ) != sizeof(float) ) { if ( gzread ( fd, &buf.u, sizeof(float) ) != sizeof(float) ) {
read_error = true ; throw sg_io_exception("sgReadFloat: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
sgEndianSwap( &buf.u ); sgEndianSwap( &buf.u );
@@ -78,7 +92,7 @@ void sgWriteFloat ( gzFile fd, const float var )
sgEndianSwap( &buf.u ); sgEndianSwap( &buf.u );
} }
if ( gzwrite ( fd, (void *)(&buf.u), sizeof(float) ) != sizeof(float) ) { if ( gzwrite ( fd, (void *)(&buf.u), sizeof(float) ) != sizeof(float) ) {
write_error = true ; throw sg_io_exception("sgWriteFloat: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -87,7 +101,8 @@ void sgReadDouble ( gzFile fd, double *var )
{ {
union { double v; uint64_t u; } buf; union { double v; uint64_t u; } buf;
if ( gzread ( fd, &buf.u, sizeof(double) ) != sizeof(double) ) { if ( gzread ( fd, &buf.u, sizeof(double) ) != sizeof(double) ) {
read_error = true ; throw sg_io_exception("sgReadDouble: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
sgEndianSwap( &buf.u ); sgEndianSwap( &buf.u );
@@ -104,7 +119,7 @@ void sgWriteDouble ( gzFile fd, const double var )
sgEndianSwap( &buf.u ); sgEndianSwap( &buf.u );
} }
if ( gzwrite ( fd, (void *)(&buf.u), sizeof(double) ) != sizeof(double) ) { if ( gzwrite ( fd, (void *)(&buf.u), sizeof(double) ) != sizeof(double) ) {
write_error = true ; throw sg_io_exception("sgWriteDouble: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -112,7 +127,8 @@ void sgWriteDouble ( gzFile fd, const double var )
void sgReadUInt ( gzFile fd, unsigned int *var ) void sgReadUInt ( gzFile fd, unsigned int *var )
{ {
if ( gzread ( fd, var, sizeof(unsigned int) ) != sizeof(unsigned int) ) { if ( gzread ( fd, var, sizeof(unsigned int) ) != sizeof(unsigned int) ) {
read_error = true ; throw sg_io_exception("sgReadUInt: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
sgEndianSwap( (uint32_t *)var); sgEndianSwap( (uint32_t *)var);
@@ -128,7 +144,7 @@ void sgWriteUInt ( gzFile fd, const unsigned int var )
if ( gzwrite ( fd, (void *)(&var), sizeof(unsigned int) ) if ( gzwrite ( fd, (void *)(&var), sizeof(unsigned int) )
!= sizeof(unsigned int) ) != sizeof(unsigned int) )
{ {
write_error = true ; throw sg_io_exception("sgWriteUInt: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -136,7 +152,8 @@ void sgWriteUInt ( gzFile fd, const unsigned int var )
void sgReadInt ( gzFile fd, int *var ) void sgReadInt ( gzFile fd, int *var )
{ {
if ( gzread ( fd, var, sizeof(int) ) != sizeof(int) ) { if ( gzread ( fd, var, sizeof(int) ) != sizeof(int) ) {
read_error = true ; throw sg_io_exception("sgReadInt: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
sgEndianSwap( (uint32_t *)var); sgEndianSwap( (uint32_t *)var);
@@ -150,7 +167,7 @@ void sgWriteInt ( gzFile fd, const int var )
sgEndianSwap( (uint32_t *)&var); sgEndianSwap( (uint32_t *)&var);
} }
if ( gzwrite ( fd, (void *)(&var), sizeof(int) ) != sizeof(int) ) { if ( gzwrite ( fd, (void *)(&var), sizeof(int) ) != sizeof(int) ) {
write_error = true ; throw sg_io_exception("sgWriteInt: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -158,7 +175,8 @@ void sgWriteInt ( gzFile fd, const int var )
void sgReadLong ( gzFile fd, int32_t *var ) void sgReadLong ( gzFile fd, int32_t *var )
{ {
if ( gzread ( fd, var, sizeof(int32_t) ) != sizeof(int32_t) ) { if ( gzread ( fd, var, sizeof(int32_t) ) != sizeof(int32_t) ) {
read_error = true ; throw sg_io_exception("sgReadLong: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
sgEndianSwap( (uint32_t *)var); sgEndianSwap( (uint32_t *)var);
@@ -174,7 +192,7 @@ void sgWriteLong ( gzFile fd, const int32_t var )
if ( gzwrite ( fd, (void *)(&var), sizeof(int32_t) ) if ( gzwrite ( fd, (void *)(&var), sizeof(int32_t) )
!= sizeof(int32_t) ) != sizeof(int32_t) )
{ {
write_error = true ; throw sg_io_exception("sgWriteLong: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -182,7 +200,8 @@ void sgWriteLong ( gzFile fd, const int32_t var )
void sgReadLongLong ( gzFile fd, int64_t *var ) void sgReadLongLong ( gzFile fd, int64_t *var )
{ {
if ( gzread ( fd, var, sizeof(int64_t) ) != sizeof(int64_t) ) { if ( gzread ( fd, var, sizeof(int64_t) ) != sizeof(int64_t) ) {
read_error = true ; throw sg_io_exception("sgReadLongLong: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
sgEndianSwap( (uint64_t *)var); sgEndianSwap( (uint64_t *)var);
@@ -198,7 +217,7 @@ void sgWriteLongLong ( gzFile fd, const int64_t var )
if ( gzwrite ( fd, (void *)(&var), sizeof(int64_t) ) if ( gzwrite ( fd, (void *)(&var), sizeof(int64_t) )
!= sizeof(int64_t) ) != sizeof(int64_t) )
{ {
write_error = true ; throw sg_io_exception("sgWriteLongLong: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -206,7 +225,8 @@ void sgWriteLongLong ( gzFile fd, const int64_t var )
void sgReadUShort ( gzFile fd, unsigned short *var ) void sgReadUShort ( gzFile fd, unsigned short *var )
{ {
if ( gzread ( fd, var, sizeof(unsigned short) ) != sizeof(unsigned short) ){ if ( gzread ( fd, var, sizeof(unsigned short) ) != sizeof(unsigned short) ){
read_error = true ; throw sg_io_exception("sgReadUShort: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
sgEndianSwap( (uint16_t *)var); sgEndianSwap( (uint16_t *)var);
@@ -222,7 +242,7 @@ void sgWriteUShort ( gzFile fd, const unsigned short var )
if ( gzwrite ( fd, (void *)(&var), sizeof(unsigned short) ) if ( gzwrite ( fd, (void *)(&var), sizeof(unsigned short) )
!= sizeof(unsigned short) ) != sizeof(unsigned short) )
{ {
write_error = true ; throw sg_io_exception("sgWriteUShort: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -230,7 +250,8 @@ void sgWriteUShort ( gzFile fd, const unsigned short var )
void sgReadShort ( gzFile fd, short *var ) void sgReadShort ( gzFile fd, short *var )
{ {
if ( gzread ( fd, var, sizeof(short) ) != sizeof(short) ) { if ( gzread ( fd, var, sizeof(short) ) != sizeof(short) ) {
read_error = true ; throw sg_io_exception("sgReadShort: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
sgEndianSwap( (uint16_t *)var); sgEndianSwap( (uint16_t *)var);
@@ -244,7 +265,7 @@ void sgWriteShort ( gzFile fd, const short var )
sgEndianSwap( (uint16_t *)&var); sgEndianSwap( (uint16_t *)&var);
} }
if ( gzwrite ( fd, (void *)(&var), sizeof(short) ) != sizeof(short) ) { if ( gzwrite ( fd, (void *)(&var), sizeof(short) ) != sizeof(short) ) {
write_error = true ; throw sg_io_exception("sgWriteShort: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -252,7 +273,8 @@ void sgWriteShort ( gzFile fd, const short var )
void sgReadFloat ( gzFile fd, const unsigned int n, float *var ) void sgReadFloat ( gzFile fd, const unsigned int n, float *var )
{ {
if ( gzread ( fd, var, sizeof(float) * n ) != (int)(sizeof(float) * n) ) { if ( gzread ( fd, var, sizeof(float) * n ) != (int)(sizeof(float) * n) ) {
read_error = true ; throw sg_io_exception("sgReadFloat array: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
for ( unsigned int i = 0; i < n; ++i ) { for ( unsigned int i = 0; i < n; ++i ) {
@@ -276,14 +298,15 @@ void sgWriteFloat ( gzFile fd, const unsigned int n, const float *var )
if ( gzwrite ( fd, (void *)var, sizeof(float) * n ) if ( gzwrite ( fd, (void *)var, sizeof(float) * n )
!= (int)(sizeof(float) * n) ) != (int)(sizeof(float) * n) )
{ {
write_error = true ; throw sg_io_exception("sgWriteFloat array: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
void sgReadDouble ( gzFile fd, const unsigned int n, double *var ) void sgReadDouble ( gzFile fd, const unsigned int n, double *var )
{ {
if ( gzread ( fd, var, sizeof(double) * n ) != (int)(sizeof(double) * n) ) { if ( gzread ( fd, var, sizeof(double) * n ) != (int)(sizeof(double) * n) ) {
read_error = true ; throw sg_io_exception("sgReadDouble array: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
for ( unsigned int i = 0; i < n; ++i ) { for ( unsigned int i = 0; i < n; ++i ) {
@@ -307,7 +330,7 @@ void sgWriteDouble ( gzFile fd, const unsigned int n, const double *var )
if ( gzwrite ( fd, (void *)var, sizeof(double) * n ) if ( gzwrite ( fd, (void *)var, sizeof(double) * n )
!= (int)(sizeof(double) * n) ) != (int)(sizeof(double) * n) )
{ {
write_error = true ; throw sg_io_exception("sgWriteDouble array: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -315,7 +338,8 @@ void sgReadBytes ( gzFile fd, const unsigned int n, void *var )
{ {
if ( n == 0) return; if ( n == 0) return;
if ( gzread ( fd, var, n ) != (int)n ) { if ( gzread ( fd, var, n ) != (int)n ) {
read_error = true ; throw sg_io_exception("sgReadBytes: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
} }
@@ -323,7 +347,7 @@ void sgWriteBytes ( gzFile fd, const unsigned int n, const void *var )
{ {
if ( n == 0) return; if ( n == 0) return;
if ( gzwrite ( fd, (void *)var, n ) != (int)n ) { if ( gzwrite ( fd, (void *)var, n ) != (int)n ) {
write_error = true ; throw sg_io_exception("sgWriteBytes: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -333,7 +357,8 @@ void sgReadUShort ( gzFile fd, const unsigned int n, unsigned short *var )
if ( gzread ( fd, var, sizeof(unsigned short) * n ) if ( gzread ( fd, var, sizeof(unsigned short) * n )
!= (int)(sizeof(unsigned short) * n) ) != (int)(sizeof(unsigned short) * n) )
{ {
read_error = true ; throw sg_io_exception("sgReadUShort array: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
for ( unsigned int i = 0; i < n; ++i ) { for ( unsigned int i = 0; i < n; ++i ) {
@@ -357,7 +382,7 @@ void sgWriteUShort ( gzFile fd, const unsigned int n, const unsigned short *var
if ( gzwrite ( fd, (void *)var, sizeof(unsigned short) * n ) if ( gzwrite ( fd, (void *)var, sizeof(unsigned short) * n )
!= (int)(sizeof(unsigned short) * n) ) != (int)(sizeof(unsigned short) * n) )
{ {
write_error = true ; throw sg_io_exception("sgWriteUShort array: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -368,7 +393,8 @@ void sgReadShort ( gzFile fd, const unsigned int n, short *var )
if ( gzread ( fd, var, sizeof(short) * n ) if ( gzread ( fd, var, sizeof(short) * n )
!= (int)(sizeof(short) * n) ) != (int)(sizeof(short) * n) )
{ {
read_error = true ; throw sg_io_exception("sgReadShort array: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
for ( unsigned int i = 0; i < n; ++i ) { for ( unsigned int i = 0; i < n; ++i ) {
@@ -392,7 +418,7 @@ void sgWriteShort ( gzFile fd, const unsigned int n, const short *var )
if ( gzwrite ( fd, (void *)var, sizeof(short) * n ) if ( gzwrite ( fd, (void *)var, sizeof(short) * n )
!= (int)(sizeof(short) * n) ) != (int)(sizeof(short) * n) )
{ {
write_error = true ; throw sg_io_exception("sgWriteShort array: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -402,7 +428,8 @@ void sgReadUInt ( gzFile fd, const unsigned int n, unsigned int *var )
if ( gzread ( fd, var, sizeof(unsigned int) * n ) if ( gzread ( fd, var, sizeof(unsigned int) * n )
!= (int)(sizeof(unsigned int) * n) ) != (int)(sizeof(unsigned int) * n) )
{ {
read_error = true ; throw sg_io_exception("sgReadUInt array: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
for ( unsigned int i = 0; i < n; ++i ) { for ( unsigned int i = 0; i < n; ++i ) {
@@ -426,7 +453,7 @@ void sgWriteUInt ( gzFile fd, const unsigned int n, const unsigned int *var )
if ( gzwrite ( fd, (void *)var, sizeof(unsigned int) * n ) if ( gzwrite ( fd, (void *)var, sizeof(unsigned int) * n )
!= (int)(sizeof(unsigned int) * n) ) != (int)(sizeof(unsigned int) * n) )
{ {
write_error = true ; throw sg_io_exception("sgWriteUInt array: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
@@ -437,7 +464,8 @@ void sgReadInt ( gzFile fd, const unsigned int n, int *var )
if ( gzread ( fd, var, sizeof(int) * n ) if ( gzread ( fd, var, sizeof(int) * n )
!= (int)(sizeof(int) * n) ) != (int)(sizeof(int) * n) )
{ {
read_error = true ; throw sg_io_exception("sgReadInt array: GZRead failed:" + gzErrorMessage(fd),
sg_location{thread_gzPath}, nullptr, false);
} }
if ( sgIsBigEndian() ) { if ( sgIsBigEndian() ) {
for ( unsigned int i = 0; i < n; ++i ) { for ( unsigned int i = 0; i < n; ++i ) {
@@ -461,7 +489,7 @@ void sgWriteInt ( gzFile fd, const unsigned int n, const int *var )
if ( gzwrite ( fd, (void *)var, sizeof(int) * n ) if ( gzwrite ( fd, (void *)var, sizeof(int) * n )
!= (int)(sizeof(int) * n) ) != (int)(sizeof(int) * n) )
{ {
write_error = true ; throw sg_io_exception("sgWriteInt array: gzwrite failed:" + gzErrorMessage(fd), {} /* origin */, false);
} }
} }
+8 -4
View File
@@ -35,6 +35,9 @@
#include <simgear/math/SGMath.hxx> #include <simgear/math/SGMath.hxx>
// forward decls
class SGPath;
// Note that output is written in little endian form (and converted as // Note that output is written in little endian form (and converted as
// necessary for big endian machines) // necessary for big endian machines)
@@ -121,9 +124,10 @@ inline void sgWriteGeod ( gzFile fd, const SGGeod& var ) {
sgWriteDouble( fd, var.getElevationM() ); sgWriteDouble( fd, var.getElevationM() );
} }
void sgClearReadError(); /**
void sgClearWriteError(); @ error aid: allow calling code to specify which file path we're reading from, so that erros we
int sgReadError(); throw from sgReadXXXX can have a valid location set.
int sgWriteError(); */
void setThreadLocalSimgearReadPath(const SGPath& path);
#endif // _SG_LOWLEVEL_HXX #endif // _SG_LOWLEVEL_HXX
+349 -363
View File
@@ -41,9 +41,10 @@
#include <bitset> #include <bitset>
#include <simgear/bucket/newbucket.hxx> #include <simgear/bucket/newbucket.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/misc/strutils.hxx> #include <simgear/misc/strutils.hxx>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include "lowlevel.hxx" #include "lowlevel.hxx"
@@ -454,10 +455,6 @@ void SGBinObject::read_object( gzFile fp,
} }
} }
if ( sgReadError() ) {
throw sg_exception("Error reading object properties");
}
size_t indexCount = std::bitset<32>((int)idx_mask).count(); size_t indexCount = std::bitset<32>((int)idx_mask).count();
if (indexCount == 0) { if (indexCount == 0) {
throw sg_exception("object index mask has no bits set"); throw sg_exception("object index mask has no bits set");
@@ -465,18 +462,10 @@ void SGBinObject::read_object( gzFile fp,
for ( j = 0; j < nelements; ++j ) { for ( j = 0; j < nelements; ++j ) {
sgReadUInt( fp, &nbytes ); sgReadUInt( fp, &nbytes );
if ( sgReadError() ) {
throw sg_exception("Error reading element size");
}
buf.resize( nbytes ); buf.resize( nbytes );
char *ptr = buf.get_ptr(); char *ptr = buf.get_ptr();
sgReadBytes( fp, nbytes, ptr ); sgReadBytes( fp, nbytes, ptr );
if ( sgReadError() ) {
throw sg_exception("Error reading element bytes");
}
int_list vs; int_list vs;
int_list ns; int_list ns;
int_list cs; int_list cs;
@@ -503,314 +492,311 @@ void SGBinObject::read_object( gzFile fp,
// read a binary file and populate the provided structures. // read a binary file and populate the provided structures.
bool SGBinObject::read_bin( const SGPath& file ) { bool SGBinObject::read_bin( const SGPath& file )
SGVec3d p; {
int i, k; gzFile fp = NULL;
size_t j;
unsigned int nbytes; try {
sgSimpleBuffer buf( 32768 ); // 32 Kb SGVec3d p;
int i, k;
size_t j;
unsigned int nbytes;
sgSimpleBuffer buf( 32768 ); // 32 Kb
// zero out structures simgear::ErrorReportContext ec("btg", file.utf8Str());
gbs_center = SGVec3d(0, 0, 0);
gbs_radius = 0.0;
wgs84_nodes.clear(); // zero out structures
normals.clear(); gbs_center = SGVec3d(0, 0, 0);
texcoords.clear(); gbs_radius = 0.0;
pts_v.clear(); wgs84_nodes.clear();
pts_n.clear(); normals.clear();
pts_c.clear(); texcoords.clear();
pts_tcs.clear();
pts_vas.clear();
pt_materials.clear();
tris_v.clear(); pts_v.clear();
tris_n.clear(); pts_n.clear();
tris_c.clear(); pts_c.clear();
tris_tcs.clear(); pts_tcs.clear();
tris_vas.clear(); pts_vas.clear();
tri_materials.clear(); pt_materials.clear();
strips_v.clear(); tris_v.clear();
strips_n.clear(); tris_n.clear();
strips_c.clear(); tris_c.clear();
strips_tcs.clear(); tris_tcs.clear();
strips_vas.clear(); tris_vas.clear();
strip_materials.clear(); tri_materials.clear();
fans_v.clear(); strips_v.clear();
fans_n.clear(); strips_n.clear();
fans_c.clear(); strips_c.clear();
fans_tcs.clear(); strips_tcs.clear();
fans_vas.clear(); strips_vas.clear();
fan_materials.clear(); strip_materials.clear();
gzFile fp = gzFileFromSGPath(file, "rb"); fans_v.clear();
if ( fp == NULL ) { fans_n.clear();
SGPath withGZ = file; fans_c.clear();
withGZ.concat(".gz"); fans_tcs.clear();
fp = gzFileFromSGPath(withGZ, "rb"); fans_vas.clear();
if (fp == nullptr) { fan_materials.clear();
SG_LOG( SG_EVENT, SG_ALERT,
"ERROR: opening " << file << " or " << withGZ << " for reading!");
throw sg_io_exception("Error opening for reading (and .gz)", sg_location(file)); gzFile fp = gzFileFromSGPath(file, "rb");
if ( fp == NULL ) {
SGPath withGZ = file;
withGZ.concat(".gz");
fp = gzFileFromSGPath(withGZ, "rb");
if (fp == nullptr) {
throw sg_io_exception("Error opening for reading (and .gz)", sg_location(file), {}, false);
}
} }
}
setThreadLocalSimgearReadPath(file);
sgClearReadError(); // read headers
unsigned int header;
sgReadUInt( fp, &header );
// read headers
unsigned int header;
sgReadUInt( fp, &header );
if (sgReadError()) { if ( ((header & 0xFF000000) >> 24) == 'S' &&
int code = 0; ((header & 0x00FF0000) >> 16) == 'G' ) {
const char* gzErrorString = gzerror(fp, &code);
gzclose(fp);
throw sg_io_exception("Unable to read BTG header: " + string{gzErrorString} + ", code =" + std::to_string(code), sg_location(file));
}
if ( ((header & 0xFF000000) >> 24) == 'S' && // read file version
((header & 0x00FF0000) >> 16) == 'G' ) { version = (header & 0x0000FFFF);
} else {
throw sg_io_exception("Bad BTG magic/version", sg_location(file), {}, false);
}
// read file version // read creation time
version = (header & 0x0000FFFF); unsigned int foo_calendar_time;
} else { sgReadUInt( fp, &foo_calendar_time );
// close the file before we return
gzclose(fp);
throw sg_io_exception("Bad BTG magic/version", sg_location(file));
}
// read creation time #if 0
unsigned int foo_calendar_time; time_t calendar_time = foo_calendar_time;
sgReadUInt( fp, &foo_calendar_time ); // The following code has a global effect on the host application
// and can screws up the time elsewhere. It should be avoided
// unless you need this for debugging in which case you should
// disable it again once the debugging task is finished.
struct tm *local_tm;
local_tm = localtime( &calendar_time );
char time_str[256];
strftime( time_str, 256, "%a %b %d %H:%M:%S %Z %Y", local_tm);
SG_LOG( SG_EVENT, SG_DEBUG, "File created on " << time_str);
#endif
#if 0 // read number of top level objects
time_t calendar_time = foo_calendar_time; int nobjects;
// The following code has a global effect on the host application if ( version >= 10) { // version 10 extends everything to be 32-bit
// and can screws up the time elsewhere. It should be avoided sgReadInt( fp, &nobjects );
// unless you need this for debugging in which case you should
// disable it again once the debugging task is finished.
struct tm *local_tm;
local_tm = localtime( &calendar_time );
char time_str[256];
strftime( time_str, 256, "%a %b %d %H:%M:%S %Z %Y", local_tm);
SG_LOG( SG_EVENT, SG_DEBUG, "File created on " << time_str);
#endif
// read number of top level objects
int nobjects;
if ( version >= 10) { // version 10 extends everything to be 32-bit
sgReadInt( fp, &nobjects );
} else if ( version >= 7 ) {
uint16_t v;
sgReadUShort( fp, &v );
nobjects = v;
} else {
int16_t v;
sgReadShort( fp, &v );
nobjects = v;
}
SG_LOG(SG_IO, SG_DEBUG, "SGBinObject::read_bin Total objects to read = " << nobjects);
if ( sgReadError() ) {
throw sg_io_exception("Error reading BTG file header", sg_location(file));
}
// read in objects
for ( i = 0; i < nobjects; ++i ) {
// read object header
char obj_type;
uint32_t nproperties, nelements;
sgReadChar( fp, &obj_type );
if ( version >= 10 ) {
sgReadUInt( fp, &nproperties );
sgReadUInt( fp, &nelements );
} else if ( version >= 7 ) { } else if ( version >= 7 ) {
uint16_t v; uint16_t v;
sgReadUShort( fp, &v ); sgReadUShort( fp, &v );
nproperties = v; nobjects = v;
sgReadUShort( fp, &v );
nelements = v;
} else { } else {
int16_t v; int16_t v;
sgReadShort( fp, &v ); sgReadShort( fp, &v );
nproperties = v; nobjects = v;
sgReadShort( fp, &v );
nelements = v;
} }
SG_LOG(SG_IO, SG_DEBUG, "SGBinObject::read_bin object " << i << SG_LOG(SG_IO, SG_DEBUG, "SGBinObject::read_bin Total objects to read = " << nobjects);
" = " << (int)obj_type << " props = " << nproperties <<
" elements = " << nelements);
if ( obj_type == SG_BOUNDING_SPHERE ) {
// read bounding sphere properties
read_properties( fp, nproperties );
// read bounding sphere elements // read in objects
for ( j = 0; j < nelements; ++j ) { for ( i = 0; i < nobjects; ++i ) {
sgReadUInt( fp, &nbytes ); // read object header
buf.resize( nbytes ); char obj_type;
buf.reset(); uint32_t nproperties, nelements;
char *ptr = buf.get_ptr(); sgReadChar( fp, &obj_type );
sgReadBytes( fp, nbytes, ptr ); if ( version >= 10 ) {
gbs_center = buf.readVec3d(); sgReadUInt( fp, &nproperties );
gbs_radius = buf.readFloat(); sgReadUInt( fp, &nelements );
} else if ( version >= 7 ) {
uint16_t v;
sgReadUShort( fp, &v );
nproperties = v;
sgReadUShort( fp, &v );
nelements = v;
} else {
int16_t v;
sgReadShort( fp, &v );
nproperties = v;
sgReadShort( fp, &v );
nelements = v;
} }
} else if ( obj_type == SG_VERTEX_LIST ) {
// read vertex list properties
read_properties( fp, nproperties );
// read vertex list elements SG_LOG(SG_IO, SG_DEBUG, "SGBinObject::read_bin object " << i <<
for ( j = 0; j < nelements; ++j ) { " = " << (int)obj_type << " props = " << nproperties <<
sgReadUInt( fp, &nbytes ); " elements = " << nelements);
buf.resize( nbytes );
buf.reset(); if ( obj_type == SG_BOUNDING_SPHERE ) {
char *ptr = buf.get_ptr(); // read bounding sphere properties
sgReadBytes( fp, nbytes, ptr ); read_properties( fp, nproperties );
int count = nbytes / (sizeof(float) * 3);
wgs84_nodes.reserve( count ); // read bounding sphere elements
for ( k = 0; k < count; ++k ) { for ( j = 0; j < nelements; ++j ) {
SGVec3f v = buf.readVec3f(); sgReadUInt( fp, &nbytes );
// extend from float to double, hmmm buf.resize( nbytes );
wgs84_nodes.push_back( SGVec3d(v[0], v[1], v[2]) ); buf.reset();
char *ptr = buf.get_ptr();
sgReadBytes( fp, nbytes, ptr );
gbs_center = buf.readVec3d();
gbs_radius = buf.readFloat();
} }
} } else if ( obj_type == SG_VERTEX_LIST ) {
} else if ( obj_type == SG_COLOR_LIST ) { // read vertex list properties
// read color list properties read_properties( fp, nproperties );
read_properties( fp, nproperties );
// read color list elements // read vertex list elements
for ( j = 0; j < nelements; ++j ) { for ( j = 0; j < nelements; ++j ) {
sgReadUInt( fp, &nbytes ); sgReadUInt( fp, &nbytes );
buf.resize( nbytes ); buf.resize( nbytes );
buf.reset(); buf.reset();
char *ptr = buf.get_ptr(); char *ptr = buf.get_ptr();
sgReadBytes( fp, nbytes, ptr ); sgReadBytes( fp, nbytes, ptr );
int count = nbytes / (sizeof(float) * 4); int count = nbytes / (sizeof(float) * 3);
colors.reserve(count); wgs84_nodes.reserve( count );
for ( k = 0; k < count; ++k ) { for ( k = 0; k < count; ++k ) {
colors.push_back( buf.readVec4f() ); SGVec3f v = buf.readVec3f();
// extend from float to double, hmmm
wgs84_nodes.push_back( SGVec3d(v[0], v[1], v[2]) );
}
} }
} } else if ( obj_type == SG_COLOR_LIST ) {
} else if ( obj_type == SG_NORMAL_LIST ) { // read color list properties
// read normal list properties read_properties( fp, nproperties );
read_properties( fp, nproperties );
// read normal list elements // read color list elements
for ( j = 0; j < nelements; ++j ) { for ( j = 0; j < nelements; ++j ) {
sgReadUInt( fp, &nbytes ); sgReadUInt( fp, &nbytes );
buf.resize( nbytes ); buf.resize( nbytes );
buf.reset(); buf.reset();
unsigned char *ptr = (unsigned char *)(buf.get_ptr()); char *ptr = buf.get_ptr();
sgReadBytes( fp, nbytes, ptr ); sgReadBytes( fp, nbytes, ptr );
int count = nbytes / 3; int count = nbytes / (sizeof(float) * 4);
normals.reserve( count ); colors.reserve(count);
for ( k = 0; k < count; ++k ) {
for ( k = 0; k < count; ++k ) { colors.push_back( buf.readVec4f() );
SGVec3f normal( (ptr[0]) / 127.5 - 1.0, }
(ptr[1]) / 127.5 - 1.0,
(ptr[2]) / 127.5 - 1.0);
normals.push_back(normalize(normal));
ptr += 3;
} }
} } else if ( obj_type == SG_NORMAL_LIST ) {
} else if ( obj_type == SG_TEXCOORD_LIST ) { // read normal list properties
// read texcoord list properties read_properties( fp, nproperties );
read_properties( fp, nproperties );
// read texcoord list elements // read normal list elements
for ( j = 0; j < nelements; ++j ) { for ( j = 0; j < nelements; ++j ) {
sgReadUInt( fp, &nbytes ); sgReadUInt( fp, &nbytes );
buf.resize( nbytes ); buf.resize( nbytes );
buf.reset(); buf.reset();
char *ptr = buf.get_ptr(); unsigned char *ptr = (unsigned char *)(buf.get_ptr());
sgReadBytes( fp, nbytes, ptr ); sgReadBytes( fp, nbytes, ptr );
int count = nbytes / (sizeof(float) * 2); int count = nbytes / 3;
texcoords.reserve(count); normals.reserve( count );
for ( k = 0; k < count; ++k ) {
texcoords.push_back( buf.readVec2f() ); for ( k = 0; k < count; ++k ) {
SGVec3f normal( (ptr[0]) / 127.5 - 1.0,
(ptr[1]) / 127.5 - 1.0,
(ptr[2]) / 127.5 - 1.0);
normals.push_back(normalize(normal));
ptr += 3;
}
} }
} } else if ( obj_type == SG_TEXCOORD_LIST ) {
} else if ( obj_type == SG_VA_FLOAT_LIST ) { // read texcoord list properties
// read vertex attribute (float) properties read_properties( fp, nproperties );
read_properties( fp, nproperties );
// read vertex attribute list elements // read texcoord list elements
for ( j = 0; j < nelements; ++j ) { for ( j = 0; j < nelements; ++j ) {
sgReadUInt( fp, &nbytes ); sgReadUInt( fp, &nbytes );
buf.resize( nbytes ); buf.resize( nbytes );
buf.reset(); buf.reset();
char *ptr = buf.get_ptr(); char *ptr = buf.get_ptr();
sgReadBytes( fp, nbytes, ptr ); sgReadBytes( fp, nbytes, ptr );
int count = nbytes / (sizeof(float)); int count = nbytes / (sizeof(float) * 2);
va_flt.reserve(count); texcoords.reserve(count);
for ( k = 0; k < count; ++k ) { for ( k = 0; k < count; ++k ) {
va_flt.push_back( buf.readFloat() ); texcoords.push_back( buf.readVec2f() );
}
} }
} } else if ( obj_type == SG_VA_FLOAT_LIST ) {
} else if ( obj_type == SG_VA_INTEGER_LIST ) { // read vertex attribute (float) properties
// read vertex attribute (integer) properties read_properties( fp, nproperties );
read_properties( fp, nproperties );
// read vertex attribute list elements // read vertex attribute list elements
for ( j = 0; j < nelements; ++j ) { for ( j = 0; j < nelements; ++j ) {
sgReadUInt( fp, &nbytes ); sgReadUInt( fp, &nbytes );
buf.resize( nbytes ); buf.resize( nbytes );
buf.reset(); buf.reset();
char *ptr = buf.get_ptr(); char *ptr = buf.get_ptr();
sgReadBytes( fp, nbytes, ptr ); sgReadBytes( fp, nbytes, ptr );
int count = nbytes / (sizeof(unsigned int)); int count = nbytes / (sizeof(float));
va_int.reserve(count); va_flt.reserve(count);
for ( k = 0; k < count; ++k ) { for ( k = 0; k < count; ++k ) {
va_int.push_back( buf.readInt() ); va_flt.push_back( buf.readFloat() );
}
} }
} } else if ( obj_type == SG_VA_INTEGER_LIST ) {
} else if ( obj_type == SG_POINTS ) { // read vertex attribute (integer) properties
// read point elements read_properties( fp, nproperties );
read_object( fp, SG_POINTS, nproperties, nelements,
pts_v, pts_n, pts_c, pts_tcs,
pts_vas, pt_materials );
} else if ( obj_type == SG_TRIANGLE_FACES ) {
// read triangle face properties
read_object( fp, SG_TRIANGLE_FACES, nproperties, nelements,
tris_v, tris_n, tris_c, tris_tcs,
tris_vas, tri_materials );
} else if ( obj_type == SG_TRIANGLE_STRIPS ) {
// read triangle strip properties
read_object( fp, SG_TRIANGLE_STRIPS, nproperties, nelements,
strips_v, strips_n, strips_c, strips_tcs,
strips_vas, strip_materials );
} else if ( obj_type == SG_TRIANGLE_FANS ) {
// read triangle fan properties
read_object( fp, SG_TRIANGLE_FANS, nproperties, nelements,
fans_v, fans_n, fans_c, fans_tcs,
fans_vas, fan_materials );
} else {
// unknown object type, just skip
read_properties( fp, nproperties );
// read elements // read vertex attribute list elements
for ( j = 0; j < nelements; ++j ) { for ( j = 0; j < nelements; ++j ) {
sgReadUInt( fp, &nbytes ); sgReadUInt( fp, &nbytes );
// cout << "element size = " << nbytes << endl; buf.resize( nbytes );
if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); } buf.reset();
char *ptr = buf.get_ptr(); char *ptr = buf.get_ptr();
sgReadBytes( fp, nbytes, ptr ); sgReadBytes( fp, nbytes, ptr );
int count = nbytes / (sizeof(unsigned int));
va_int.reserve(count);
for ( k = 0; k < count; ++k ) {
va_int.push_back( buf.readInt() );
}
}
} else if ( obj_type == SG_POINTS ) {
// read point elements
read_object( fp, SG_POINTS, nproperties, nelements,
pts_v, pts_n, pts_c, pts_tcs,
pts_vas, pt_materials );
} else if ( obj_type == SG_TRIANGLE_FACES ) {
// read triangle face properties
read_object( fp, SG_TRIANGLE_FACES, nproperties, nelements,
tris_v, tris_n, tris_c, tris_tcs,
tris_vas, tri_materials );
} else if ( obj_type == SG_TRIANGLE_STRIPS ) {
// read triangle strip properties
read_object( fp, SG_TRIANGLE_STRIPS, nproperties, nelements,
strips_v, strips_n, strips_c, strips_tcs,
strips_vas, strip_materials );
} else if ( obj_type == SG_TRIANGLE_FANS ) {
// read triangle fan properties
read_object( fp, SG_TRIANGLE_FANS, nproperties, nelements,
fans_v, fans_n, fans_c, fans_tcs,
fans_vas, fan_materials );
} else {
// unknown object type, just skip
read_properties( fp, nproperties );
// read elements
for ( j = 0; j < nelements; ++j ) {
sgReadUInt( fp, &nbytes );
// cout << "element size = " << nbytes << endl;
if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
char *ptr = buf.get_ptr();
sgReadBytes( fp, nbytes, ptr );
}
} }
} }
if ( sgReadError() ) { gzclose(fp);
throw sg_io_exception("Error while reading object", sg_location(file, i)); fp = NULL;
} catch (std::exception&) {
if (fp) {
// close the file
gzclose(fp);
} }
throw; // re-throw
} }
// close the file
gzclose(fp);
return true; return true;
} }
@@ -984,112 +970,112 @@ bool SGBinObject::write_bin_file(const SGPath& file)
return false; return false;
} }
sgClearWriteError(); try {
SG_LOG(SG_IO, SG_DEBUG, "points size = " << pts_v.size()
<< " pt_materials = " << pt_materials.size() );
SG_LOG(SG_IO, SG_DEBUG, "triangles size = " << tris_v.size()
<< " tri_materials = " << tri_materials.size() );
SG_LOG(SG_IO, SG_DEBUG, "strips size = " << strips_v.size()
<< " strip_materials = " << strip_materials.size() );
SG_LOG(SG_IO, SG_DEBUG, "fans size = " << fans_v.size()
<< " fan_materials = " << fan_materials.size() );
SG_LOG(SG_IO, SG_DEBUG, "points size = " << pts_v.size() SG_LOG(SG_IO, SG_DEBUG, "nodes = " << wgs84_nodes.size() );
<< " pt_materials = " << pt_materials.size() ); SG_LOG(SG_IO, SG_DEBUG, "colors = " << colors.size() );
SG_LOG(SG_IO, SG_DEBUG, "triangles size = " << tris_v.size() SG_LOG(SG_IO, SG_DEBUG, "normals = " << normals.size() );
<< " tri_materials = " << tri_materials.size() ); SG_LOG(SG_IO, SG_DEBUG, "tex coords = " << texcoords.size() );
SG_LOG(SG_IO, SG_DEBUG, "strips size = " << strips_v.size()
<< " strip_materials = " << strip_materials.size() );
SG_LOG(SG_IO, SG_DEBUG, "fans size = " << fans_v.size()
<< " fan_materials = " << fan_materials.size() );
SG_LOG(SG_IO, SG_DEBUG, "nodes = " << wgs84_nodes.size() ); version = 10;
SG_LOG(SG_IO, SG_DEBUG, "colors = " << colors.size() ); bool shortMaterialsRanges =
SG_LOG(SG_IO, SG_DEBUG, "normals = " << normals.size() ); (max_object_size(pt_materials) < VERSION_7_MATERIAL_LIMIT) &&
SG_LOG(SG_IO, SG_DEBUG, "tex coords = " << texcoords.size() ); (max_object_size(fan_materials) < VERSION_7_MATERIAL_LIMIT) &&
(max_object_size(strip_materials) < VERSION_7_MATERIAL_LIMIT) &&
(max_object_size(tri_materials) < VERSION_7_MATERIAL_LIMIT);
version = 10; if ((wgs84_nodes.size() < 0xffff) &&
bool shortMaterialsRanges = (normals.size() < 0xffff) &&
(max_object_size(pt_materials) < VERSION_7_MATERIAL_LIMIT) && (texcoords.size() < 0xffff) &&
(max_object_size(fan_materials) < VERSION_7_MATERIAL_LIMIT) && shortMaterialsRanges) {
(max_object_size(strip_materials) < VERSION_7_MATERIAL_LIMIT) && version = 7; // use smaller indices if possible
(max_object_size(tri_materials) < VERSION_7_MATERIAL_LIMIT); }
if ((wgs84_nodes.size() < 0xffff) && // write header magic
(normals.size() < 0xffff) &&
(texcoords.size() < 0xffff) &&
shortMaterialsRanges) {
version = 7; // use smaller indices if possible
}
// write header magic /** Magic Number for our file format */
#define SG_FILE_MAGIC_NUMBER ( ('S'<<24) + ('G'<<16) + version )
/** Magic Number for our file format */ sgWriteUInt( fp, SG_FILE_MAGIC_NUMBER );
#define SG_FILE_MAGIC_NUMBER ( ('S'<<24) + ('G'<<16) + version ) time_t calendar_time = time(NULL);
sgWriteLong( fp, (int32_t)calendar_time );
sgWriteUInt( fp, SG_FILE_MAGIC_NUMBER ); // calculate and write number of top level objects
time_t calendar_time = time(NULL); int nobjects = 5; // gbs, vertices, colors, normals, texcoords
sgWriteLong( fp, (int32_t)calendar_time ); nobjects += count_objects(pt_materials);
nobjects += count_objects(tri_materials);
nobjects += count_objects(strip_materials);
nobjects += count_objects(fan_materials);
// calculate and write number of top level objects SG_LOG(SG_IO, SG_DEBUG, "total top level objects = " << nobjects);
int nobjects = 5; // gbs, vertices, colors, normals, texcoords
nobjects += count_objects(pt_materials);
nobjects += count_objects(tri_materials);
nobjects += count_objects(strip_materials);
nobjects += count_objects(fan_materials);
SG_LOG(SG_IO, SG_DEBUG, "total top level objects = " << nobjects); if (version == 7) {
sgWriteUShort( fp, (uint16_t) nobjects );
} else {
sgWriteInt( fp, nobjects );
}
if (version == 7) { // write bounding sphere
sgWriteUShort( fp, (uint16_t) nobjects ); write_header( fp, SG_BOUNDING_SPHERE, 0, 1);
} else { sgWriteUInt( fp, sizeof(double) * 3 + sizeof(float) ); // nbytes
sgWriteInt( fp, nobjects ); sgWritedVec3( fp, gbs_center );
} sgWriteFloat( fp, gbs_radius );
// write bounding sphere // dump vertex list
write_header( fp, SG_BOUNDING_SPHERE, 0, 1); write_header( fp, SG_VERTEX_LIST, 0, 1);
sgWriteUInt( fp, sizeof(double) * 3 + sizeof(float) ); // nbytes sgWriteUInt( fp, wgs84_nodes.size() * sizeof(float) * 3 ); // nbytes
sgWritedVec3( fp, gbs_center ); for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
sgWriteFloat( fp, gbs_radius ); sgWriteVec3( fp, toVec3f(wgs84_nodes[i] - gbs_center));
}
// dump vertex list // dump vertex color list
write_header( fp, SG_VERTEX_LIST, 0, 1); write_header( fp, SG_COLOR_LIST, 0, 1);
sgWriteUInt( fp, wgs84_nodes.size() * sizeof(float) * 3 ); // nbytes sgWriteUInt( fp, colors.size() * sizeof(float) * 4 ); // nbytes
for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) { for ( i = 0; i < (int)colors.size(); ++i ) {
sgWriteVec3( fp, toVec3f(wgs84_nodes[i] - gbs_center)); sgWriteVec4( fp, colors[i]);
} }
// dump vertex color list // dump vertex normal list
write_header( fp, SG_COLOR_LIST, 0, 1); write_header( fp, SG_NORMAL_LIST, 0, 1);
sgWriteUInt( fp, colors.size() * sizeof(float) * 4 ); // nbytes sgWriteUInt( fp, normals.size() * 3 ); // nbytes
for ( i = 0; i < (int)colors.size(); ++i ) { char normal[3];
sgWriteVec4( fp, colors[i]); for ( i = 0; i < (int)normals.size(); ++i ) {
} SGVec3f p = normals[i];
normal[0] = (unsigned char)((p.x() + 1.0) * 127.5);
normal[1] = (unsigned char)((p.y() + 1.0) * 127.5);
normal[2] = (unsigned char)((p.z() + 1.0) * 127.5);
sgWriteBytes( fp, 3, normal );
}
// dump vertex normal list // dump texture coordinates
write_header( fp, SG_NORMAL_LIST, 0, 1); write_header( fp, SG_TEXCOORD_LIST, 0, 1);
sgWriteUInt( fp, normals.size() * 3 ); // nbytes sgWriteUInt( fp, texcoords.size() * sizeof(float) * 2 ); // nbytes
char normal[3]; for ( i = 0; i < (int)texcoords.size(); ++i ) {
for ( i = 0; i < (int)normals.size(); ++i ) { sgWriteVec2( fp, texcoords[i]);
SGVec3f p = normals[i]; }
normal[0] = (unsigned char)((p.x() + 1.0) * 127.5);
normal[1] = (unsigned char)((p.y() + 1.0) * 127.5);
normal[2] = (unsigned char)((p.z() + 1.0) * 127.5);
sgWriteBytes( fp, 3, normal );
}
// dump texture coordinates write_objects(fp, SG_POINTS, pts_v, pts_n, pts_c, pts_tcs, pts_vas, pt_materials);
write_header( fp, SG_TEXCOORD_LIST, 0, 1); write_objects(fp, SG_TRIANGLE_FACES, tris_v, tris_n, tris_c, tris_tcs, tris_vas, tri_materials);
sgWriteUInt( fp, texcoords.size() * sizeof(float) * 2 ); // nbytes write_objects(fp, SG_TRIANGLE_STRIPS, strips_v, strips_n, strips_c, strips_tcs, strips_vas, strip_materials);
for ( i = 0; i < (int)texcoords.size(); ++i ) { write_objects(fp, SG_TRIANGLE_FANS, fans_v, fans_n, fans_c, fans_tcs, fans_vas, fan_materials);
sgWriteVec2( fp, texcoords[i]);
}
write_objects(fp, SG_POINTS, pts_v, pts_n, pts_c, pts_tcs, pts_vas, pt_materials); // close the file
write_objects(fp, SG_TRIANGLE_FACES, tris_v, tris_n, tris_c, tris_tcs, tris_vas, tri_materials); gzclose(fp);
write_objects(fp, SG_TRIANGLE_STRIPS, strips_v, strips_n, strips_c, strips_tcs, strips_vas, strip_materials); fp = NULL;
write_objects(fp, SG_TRIANGLE_FANS, fans_v, fans_n, fans_c, fans_tcs, fans_vas, fan_materials); } catch (std::exception&) {
if (fp) {
// close the file gzclose(fp);
gzclose(fp); }
if ( sgWriteError() ) {
cout << "Error while writing file " << file << endl;
return false; return false;
} }
return true; return true;
} }
+1 -3
View File
@@ -82,9 +82,7 @@ std::string SGFile::computeHash()
[](char* p) { free(p); }}; [](char* p) { free(p); }};
if (!buf) { if (!buf) {
// @TODO report out of memory error throw sg_exception("Malloc of SHA buffer failed", {}, file_name);
SG_LOG(SG_IO, SG_ALERT, "Failed to malloc buffer for SHA1 check:" << file_name);
return {};
} }
size_t readLen; size_t readLen;
+3
View File
@@ -348,6 +348,9 @@ public:
~GZTarExtractor() ~GZTarExtractor()
{ {
if (haveInitedZLib) {
inflateEnd(&zlibStream);
}
free(zlibOutput); free(zlibOutput);
} }
+3 -1
View File
@@ -48,6 +48,7 @@
#endif #endif
#include "sg_path.hxx" #include "sg_path.hxx"
#include <simgear/misc/sg_dir.hxx>
using std::string; using std::string;
using simgear::strutils::starts_with; using simgear::strutils::starts_with;
@@ -995,8 +996,9 @@ SGPath SGPath::realpath() const
// (needed for fgValidatePath security) // (needed for fgValidatePath security)
{ {
if (path.empty()) { if (path.empty()) {
return SGPath(".").realpath(); // current directory return simgear::Dir::current().path();
} }
std::string this_dir = dir(); std::string this_dir = dir();
if (isAbsolute() && this_dir.empty()) { // top level if (isAbsolute() && this_dir.empty()) { // top level
this_dir = "/"; this_dir = "/";
+11 -3
View File
@@ -143,9 +143,15 @@ protected:
Dir d(m_owner->installRoot()); Dir d(m_owner->installRoot());
SGPath p = d.file("catalog.xml"); SGPath p = d.file("catalog.xml");
sg_ofstream f(p, std::ios::out | std::ios::trunc); sg_ofstream f(p, std::ios::out | std::ios::trunc);
f.write(m_buffer.data(), m_buffer.size()); const auto sz = m_buffer.size();
f.write(m_buffer.data(), sz);
f.close(); f.close();
if (f.fail()) {
m_owner->refreshComplete(Delegate::FAIL_FILESYSTEM);
return;
}
time(&m_owner->m_retrievedTime); time(&m_owner->m_retrievedTime);
m_owner->writeTimestamp(); m_owner->writeTimestamp();
m_owner->refreshComplete(Delegate::STATUS_REFRESHED); m_owner->refreshComplete(Delegate::STATUS_REFRESHED);
@@ -619,6 +625,8 @@ void Catalog::setUserEnabled(bool b)
void Catalog::processAlternate(SGPropertyNode_ptr alt) void Catalog::processAlternate(SGPropertyNode_ptr alt)
{ {
m_refreshRequest.reset();
std::string altId; std::string altId;
const auto idPtr = alt->getStringValue("id"); const auto idPtr = alt->getStringValue("id");
if (idPtr) { if (idPtr) {
@@ -694,8 +702,8 @@ void Catalog::processAlternate(SGPropertyNode_ptr alt)
SG_LOG(SG_GENERAL, SG_INFO, "Migrating catalog " << id() << " to new URL:" << altUrl); SG_LOG(SG_GENERAL, SG_INFO, "Migrating catalog " << id() << " to new URL:" << altUrl);
setUrl(altUrl); setUrl(altUrl);
Downloader* dl = new Downloader(this, altUrl); m_refreshRequest = new Downloader(this, altUrl);
root()->makeHTTPRequest(dl); root()->makeHTTPRequest(m_refreshRequest);
} }
int Catalog::markPackagesForInstallation(const string_list &packageIds) { int Catalog::markPackagesForInstallation(const string_list &packageIds) {
+11 -11
View File
@@ -166,7 +166,8 @@ int parseTest()
{ {
SGPath rootPath = simgear::Dir::current().path(); SGPath rootPath = simgear::Dir::current().path();
rootPath.append("testRoot"); rootPath.append("testRoot");
pkg::Root* root = new pkg::Root(rootPath, "8.1.12");
pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
root->setLocale("de"); root->setLocale("de");
pkg::CatalogRef cat = pkg::Catalog::createFromPath(root, SGPath(SRC_DIR "/catalogTest1")); pkg::CatalogRef cat = pkg::Catalog::createFromPath(root, SGPath(SRC_DIR "/catalogTest1"));
@@ -344,7 +345,6 @@ int parseTest()
SG_CHECK_EQUAL(urls.size(), 3); SG_CHECK_EQUAL(urls.size(), 3);
SG_CHECK_EQUAL(urls.at(1), "http://localhost:2000/mirrorB/b737.tar.gz"); SG_CHECK_EQUAL(urls.at(1), "http://localhost:2000/mirrorB/b737.tar.gz");
delete root;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@@ -953,7 +953,7 @@ int parseInvalidTest()
{ {
SGPath rootPath = simgear::Dir::current().path(); SGPath rootPath = simgear::Dir::current().path();
rootPath.append("testRoot"); rootPath.append("testRoot");
pkg::Root* root = new pkg::Root(rootPath, "8.1.12"); pkg::RootRef root(new pkg::Root(rootPath, "8.1.12"));
pkg::CatalogRef cat = pkg::Catalog::createFromPath(root, SGPath(SRC_DIR "/catalogTestInvalid")); pkg::CatalogRef cat = pkg::Catalog::createFromPath(root, SGPath(SRC_DIR "/catalogTestInvalid"));
SG_VERIFY(cat.valid()); SG_VERIFY(cat.valid());
@@ -1333,25 +1333,25 @@ int main(int argc, char* argv[])
testRefreshCatalog(&cl); testRefreshCatalog(&cl);
testInstallTarPackage(&cl); testInstallTarPackage(&cl);
testInstallArchiveType(&cl); testInstallArchiveType(&cl);
testDisableDueToVersion(&cl); testDisableDueToVersion(&cl);
testOfflineMode(&cl); testOfflineMode(&cl);
testVersionMigrate(&cl); testVersionMigrate(&cl);
updateInvalidToValid(&cl); updateInvalidToValid(&cl);
updateValidToInvalid(&cl); updateValidToInvalid(&cl);
updateInvalidToInvalid(&cl); updateInvalidToInvalid(&cl);
removeInvalidCatalog(&cl); removeInvalidCatalog(&cl);
testVersionMigrateToId(&cl); testVersionMigrateToId(&cl);
testInstallBadPackage(&cl); testInstallBadPackage(&cl);
testMirrorsFailure(&cl); testMirrorsFailure(&cl);
testMigrateInstalled(&cl); testMigrateInstalled(&cl);
+8 -4
View File
@@ -535,7 +535,8 @@ readComparison( SGPropertyNode *prop_root,
{ {
SGComparisonCondition * condition = new SGComparisonCondition(type, reverse); SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
if (node->nChildren() < 2 || node->nChildren() > 3 ) { if (node->nChildren() < 2 || node->nChildren() > 3 ) {
throw sg_exception("condition: comparison without two or three children"); throw sg_exception("condition: comparison without two or three children",
{}, {}, false);
} }
const SGPropertyNode* left = node->getChild(0), const SGPropertyNode* left = node->getChild(0),
@@ -551,7 +552,8 @@ readComparison( SGPropertyNode *prop_root,
SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0)); SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
condition->setLeftDExpression(exp); condition->setLeftDExpression(exp);
} else { } else {
throw sg_exception("Unknown condition comparison left child:" + leftName); throw sg_exception("Unknown condition comparison left child:" + leftName,
{}, {}, false);
} }
} }
@@ -565,7 +567,8 @@ readComparison( SGPropertyNode *prop_root,
SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0)); SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
condition->setRightDExpression(exp); condition->setRightDExpression(exp);
} else { } else {
throw sg_exception("Unknown condition comparison right child:" + rightName); throw sg_exception("Unknown condition comparison right child:" + rightName,
{}, {}, false);
} }
} }
@@ -580,7 +583,8 @@ readComparison( SGPropertyNode *prop_root,
SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0)); SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
condition->setPrecisionDExpression(exp); condition->setPrecisionDExpression(exp);
} else { } else {
throw sg_exception("Unknown condition comparison precision child:" + name ); throw sg_exception("Unknown condition comparison precision child:" + name,
{}, {}, false);
} }
} }
+65 -16
View File
@@ -67,9 +67,14 @@
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgDB/Registry> #include <osgDB/Registry>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/io/iostreams/sgstream.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/props/vectorPropTemplates.hxx>
#include <simgear/scene/tgdb/userdata.hxx> #include <simgear/scene/tgdb/userdata.hxx>
#include <simgear/scene/util/OsgMath.hxx> #include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/SGProgram.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx> #include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx> #include <simgear/scene/util/StateAttributeFactory.hxx>
#include <simgear/structure/OSGUtils.hxx> #include <simgear/structure/OSGUtils.hxx>
@@ -103,6 +108,7 @@ bool loadShaderFromUTF8File(osg::Shader* shader, const std::string& fileName)
if (!inStream.is_open()) if (!inStream.is_open())
return false; return false;
shader->setFileName(fileName);
shader->setShaderSource(inStream.read_all()); shader->setShaderSource(inStream.read_all());
return true; return true;
} }
@@ -221,8 +227,9 @@ Effect::Effect()
} }
Effect::Effect(const Effect& rhs, const CopyOp& copyop) Effect::Effect(const Effect& rhs, const CopyOp& copyop)
: osg::Object(rhs,copyop), root(rhs.root), parametersProp(rhs.parametersProp), _cache(0), : osg::Object(rhs, copyop), root(rhs.root), parametersProp(rhs.parametersProp), _cache(0),
_isRealized(rhs._isRealized) _isRealized(rhs._isRealized),
_effectFilePath(rhs._effectFilePath)
{ {
typedef vector<ref_ptr<Technique> > TechniqueList; typedef vector<ref_ptr<Technique> > TechniqueList;
for (TechniqueList::const_iterator itr = rhs.techniques.begin(), for (TechniqueList::const_iterator itr = rhs.techniques.begin(),
@@ -287,6 +294,8 @@ Effect::~Effect()
void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop, void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options)
{ {
simgear::ErrorReportContext ec("effect-pass", prop->getPath());
Pass* pass = new Pass; Pass* pass = new Pass;
tniq->passes.push_back(pass); tniq->passes.push_back(pass);
for (int i = 0; i < prop->nChildren(); ++i) { for (int i = 0; i < prop->nChildren(); ++i) {
@@ -837,10 +846,12 @@ void reload_shaders()
string fileName = SGModelLib::findDataFile(sitr->first.first); string fileName = SGModelLib::findDataFile(sitr->first.first);
if (!fileName.empty()) { if (!fileName.empty()) {
loadShaderFromUTF8File(shader, fileName); loadShaderFromUTF8File(shader, fileName);
} } else {
else
SG_LOG(SG_INPUT, SG_ALERT, "Could not locate shader: " << fileName); SG_LOG(SG_INPUT, SG_ALERT, "Could not locate shader: " << fileName);
simgear::reportFailure(simgear::LoadFailure::NotFound,
simgear::ErrorCode::LoadEffectsShaders,
"Reload: couldn't find shader:" + sitr->first.first);
}
} }
} }
@@ -936,10 +947,8 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
string fileName = SGModelLib::findDataFile(shaderName, options); string fileName = SGModelLib::findDataFile(shaderName, options);
if (fileName.empty()) if (fileName.empty())
{ {
SG_LOG(SG_INPUT, SG_ALERT, "Could not locate shader" << shaderName); simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadEffectsShaders,
if (!compositorEnabled) { "Couldn't locate shader:" + shaderName, sg_location{shaderName});
reportError("Missing shader", shaderName);
}
throw BuilderException(string("couldn't find shader ") + throw BuilderException(string("couldn't find shader ") +
shaderName); shaderName);
@@ -953,7 +962,11 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
pass->setAttributeAndModes(program); pass->setAttributeAndModes(program);
return; return;
} }
program = new Program;
auto sgprogram = new SGProgram;
program = sgprogram;
sgprogram->setEffectFilePath(effect->filePath());
for (const auto& skey : resolvedKey.shaders) { for (const auto& skey : resolvedKey.shaders) {
const string& fileName = skey.first; const string& fileName = skey.first;
Shader::Type stype = (Shader::Type)skey.second; Shader::Type stype = (Shader::Type)skey.second;
@@ -964,11 +977,30 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
ref_ptr<Shader> shader = new Shader(stype); ref_ptr<Shader> shader = new Shader(stype);
shader->setName(fileName); shader->setName(fileName);
if (loadShaderFromUTF8File(shader, fileName)) { if (loadShaderFromUTF8File(shader, fileName)) {
program->addShader(shader.get()); if (!program->addShader(shader.get())) {
simgear::reportFailure(simgear::LoadFailure::BadData,
simgear::ErrorCode::LoadEffectsShaders,
"Program::addShader failed",
SGPath::fromUtf8(fileName));
}
shaderMap.insert(ShaderMap::value_type(skey, shader)); shaderMap.insert(ShaderMap::value_type(skey, shader));
} else {
simgear::reportFailure(simgear::LoadFailure::BadData,
simgear::ErrorCode::LoadEffectsShaders,
"Failed to read shader source code",
SGPath::fromUtf8(fileName));
} }
} }
} }
if (sgprogram->getNumShaders() == 0) {
simgear::reportFailure(simgear::LoadFailure::BadData,
simgear::ErrorCode::LoadEffectsShaders,
"No shader source code defined for effect",
effect->filePath());
}
for (const auto& key : prgKey.attributes) { for (const auto& key : prgKey.attributes) {
program->addBindAttribLocation(key.first, key.second); program->addBindAttribLocation(key.first, key.second);
} }
@@ -1329,6 +1361,8 @@ InstallAttributeBuilder<DepthBuilder> installDepth("depth");
void buildTechnique(Effect* effect, const SGPropertyNode* prop, void buildTechnique(Effect* effect, const SGPropertyNode* prop,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options)
{ {
simgear::ErrorReportContext ec("effect-technique", prop->getPath());
Technique* tniq = new Technique; Technique* tniq = new Technique;
effect->techniques.push_back(tniq); effect->techniques.push_back(tniq);
tniq->setScheme(prop->getStringValue("scheme")); tniq->setScheme(prop->getStringValue("scheme"));
@@ -1486,16 +1520,19 @@ void mergeSchemesFallbacks(Effect *effect, const SGReaderWriterOptions *options)
// passes. // passes.
bool Effect::realizeTechniques(const SGReaderWriterOptions* options) bool Effect::realizeTechniques(const SGReaderWriterOptions* options)
{ {
simgear::ErrorReportContext ec{"effect", getName()};
if (getPropertyRoot()->getBoolValue("/sim/version/compositor-support", false)) if (getPropertyRoot()->getBoolValue("/sim/version/compositor-support", false))
mergeSchemesFallbacks(this, options); mergeSchemesFallbacks(this, options);
if (_isRealized) if (_isRealized)
return true; return true;
PropertyList tniqList = root->getChildren("technique"); PropertyList tniqList = root->getChildren("technique");
for (PropertyList::iterator itr = tniqList.begin(), e = tniqList.end(); for (const auto& tniq : tniqList) {
itr != e; buildTechnique(this, tniq, options);
++itr) }
buildTechnique(this, *itr, options);
_isRealized = true; _isRealized = true;
return true; return true;
} }
@@ -1631,3 +1668,15 @@ expression::ExpParserRegistrar propvalueRegistrar("float-property",
propertyExpressionParser<float>); propertyExpressionParser<float>);
} }
using namespace simgear;
void Effect::setFilePath(const SGPath& path)
{
_effectFilePath = path;
}
SGPath Effect::filePath() const
{
return _effectFilePath;
}
+12 -3
View File
@@ -29,10 +29,11 @@
#include <osg/observer_ptr> #include <osg/observer_ptr>
#include <osgDB/ReaderWriter> #include <osgDB/ReaderWriter>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/scene/util/UpdateOnceCallback.hxx> #include <simgear/scene/util/UpdateOnceCallback.hxx>
#include <simgear/threads/SGThread.hxx>
#include <simgear/structure/Singleton.hxx> #include <simgear/structure/Singleton.hxx>
#include <simgear/threads/SGThread.hxx>
namespace osg namespace osg
{ {
@@ -106,6 +107,10 @@ public:
std::string getName(){return _name;} std::string getName(){return _name;}
void setName(std::string name){_name = name;} void setName(std::string name){_name = name;}
void setFilePath(const SGPath& path);
SGPath filePath() const;
protected: protected:
~Effect(); ~Effect();
// Support for a cache of effects that inherit from this one, so // Support for a cache of effects that inherit from this one, so
@@ -142,10 +147,13 @@ protected:
Cache* _cache; Cache* _cache;
friend size_t hash_value(const Key& key); friend size_t hash_value(const Key& key);
friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques, friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
const SGReaderWriterOptions* options); const SGReaderWriterOptions* options,
const SGPath& path);
bool _isRealized; bool _isRealized;
std::string _name; std::string _name;
SGPath _effectFilePath;
}; };
// Automatic support for boost hash function // Automatic support for boost hash function
size_t hash_value(const Effect::Key&); size_t hash_value(const Effect::Key&);
@@ -156,7 +164,8 @@ Effect* makeEffect(const std::string& name,
Effect* makeEffect(SGPropertyNode* prop, Effect* makeEffect(SGPropertyNode* prop,
bool realizeTechniques, bool realizeTechniques,
const SGReaderWriterOptions* options); const SGReaderWriterOptions* options,
const SGPath& path = SGPath{});
bool makeParametersFromStateSet(SGPropertyNode* paramRoot, bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
const osg::StateSet* ss); const osg::StateSet* ss);
+2 -2
View File
@@ -75,13 +75,13 @@ BuilderException::BuilderException()
} }
BuilderException::BuilderException(const char* message, const char* origin) BuilderException::BuilderException(const char* message, const char* origin)
: sg_exception(message, origin) : sg_exception(message, origin, {}, false)
{ {
} }
BuilderException::BuilderException(const std::string& message, BuilderException::BuilderException(const std::string& message,
const std::string& origin) const std::string& origin)
: sg_exception(message, origin) : sg_exception(message, origin, {}, false)
{ {
} }
+16 -5
View File
@@ -39,12 +39,13 @@
#include <OpenThreads/Mutex> #include <OpenThreads/Mutex>
#include <OpenThreads/ScopedLock> #include <OpenThreads/ScopedLock>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/props/vectorPropTemplates.hxx>
#include <simgear/scene/util/OsgMath.hxx> #include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx> #include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx> #include <simgear/scene/util/StateAttributeFactory.hxx>
#include <simgear/structure/OSGUtils.hxx> #include <simgear/structure/OSGUtils.hxx>
#include <simgear/props/vectorPropTemplates.hxx>
namespace simgear namespace simgear
{ {
@@ -280,9 +281,10 @@ bool setAttrs(const TexTuple& attrs, Texture* tex,
#else #else
result = osgDB::readRefImageFile(imageName, options); result = osgDB::readRefImageFile(imageName, options);
#endif #endif
} catch (std::bad_alloc& ba) { } catch (std::exception& e) {
SG_LOG(SG_GL, SG_ALERT, "Bad allocation loading:" << imageName); simgear::reportFailure(simgear::LoadFailure::OutOfMemory, simgear::ErrorCode::LoadingTexture,
// todo: report low memory warning string{"osgDB::readRefImageFile failed:"} + e.what(),
SGPath::fromUtf8(imageName));
return false; return false;
} }
@@ -304,6 +306,9 @@ bool setAttrs(const TexTuple& attrs, Texture* tex,
tex->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter()); tex->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter());
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file " << imageName); SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file " << imageName);
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadingTexture,
"osgDB::readRefImageFile failed:" + result.message(),
SGPath::fromUtf8(imageName));
return false; return false;
} }
@@ -588,8 +593,8 @@ Texture* CubeMapBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*
const SGPropertyNode* texturesProp = getEffectPropertyChild(effect, props, "images"); const SGPropertyNode* texturesProp = getEffectPropertyChild(effect, props, "images");
const SGPropertyNode* crossProp = getEffectPropertyChild(effect, props, "image"); const SGPropertyNode* crossProp = getEffectPropertyChild(effect, props, "image");
if (!texturesProp && !crossProp) { if (!texturesProp && !crossProp) {
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadingTexture, "No images defined for cube map");
throw BuilderException("no images defined for cube map"); throw BuilderException("no images defined for cube map");
return NULL; // This is redundant
} }
// Using 6 separate images // Using 6 separate images
@@ -770,6 +775,9 @@ Texture* CubeMapBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*
return cubeTexture.release(); return cubeTexture.release();
} else { } else {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadingTexture,
"Could not load cube-map image:" + result.message(),
sg_location{texname});
throw BuilderException("Could not load cube cross"); throw BuilderException("Could not load cube cross");
} }
} }
@@ -850,6 +858,9 @@ Texture* Texture3DBuilder::build(Effect* effect, Pass* pass,
tex->setImage(image3d.get()); tex->setImage(image3d.get());
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file " << imageName); SG_LOG(SG_INPUT, SG_ALERT, "failed to load effect texture file " << imageName);
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadingTexture,
"osgDB::readRefImageFile failed:" + result.message(),
SGPath::fromUtf8(imageName));
return NULL; return NULL;
} }
+19 -14
View File
@@ -25,9 +25,11 @@
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgDB/Registry> #include <osgDB/Registry>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx> #include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/SplicingVisitor.hxx> #include <simgear/scene/util/SplicingVisitor.hxx>
#include <simgear/structure/SGExpression.hxx> #include <simgear/structure/SGExpression.hxx>
@@ -126,20 +128,20 @@ Effect* makeEffect(const string& name,
string absFileName string absFileName
= SGModelLib::findDataFile(effectFileName, options); = SGModelLib::findDataFile(effectFileName, options);
if (absFileName.empty()) { if (absFileName.empty()) {
SG_LOG(SG_INPUT, SG_ALERT, "can't find \"" << effectFileName << "\""); simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadEffectsShaders, "Couldn't find Effect:" + effectFileName);
return 0; return nullptr;
} }
SGPropertyNode_ptr effectProps = new SGPropertyNode(); SGPropertyNode_ptr effectProps = new SGPropertyNode();
try { try {
readProperties(absFileName, effectProps.ptr(), 0, true); readProperties(absFileName, effectProps.ptr(), 0, true);
} }
catch (sg_io_exception& e) { catch (sg_io_exception& e) {
SG_LOG(SG_INPUT, SG_ALERT, "error reading \"" << absFileName << "\": " simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadEffectsShaders, e.getFormattedMessage(),
<< e.getFormattedMessage()); e.getLocation());
return 0; return nullptr;
} }
ref_ptr<Effect> result = makeEffect(effectProps.ptr(), realizeTechniques, ref_ptr<Effect> result = makeEffect(effectProps.ptr(), realizeTechniques,
options); options, SGPath::fromUtf8(absFileName));
if (result.valid()) { if (result.valid()) {
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex); OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
pair<EffectMap::iterator, bool> irslt pair<EffectMap::iterator, bool> irslt
@@ -156,7 +158,8 @@ Effect* makeEffect(const string& name,
Effect* makeEffect(SGPropertyNode* prop, Effect* makeEffect(SGPropertyNode* prop,
bool realizeTechniques, bool realizeTechniques,
const SGReaderWriterOptions* options) const SGReaderWriterOptions* options,
const SGPath& filePath)
{ {
// Give default names to techniques and passes // Give default names to techniques and passes
vector<SGPropertyNode_ptr> techniques = prop->getChildren("technique"); vector<SGPropertyNode_ptr> techniques = prop->getChildren("technique");
@@ -217,6 +220,7 @@ Effect* makeEffect(SGPropertyNode* prop,
if (!effect.valid()) { if (!effect.valid()) {
effect = new Effect; effect = new Effect;
effect->setName(nameProp->getStringValue()); effect->setName(nameProp->getStringValue());
effect->setFilePath(filePath.isNull() ? parent->filePath() : filePath);
effect->root = new SGPropertyNode; effect->root = new SGPropertyNode;
mergePropertyTrees(effect->root, prop, parent->root); mergePropertyTrees(effect->root, prop, parent->root);
effect->parametersProp = effect->root->getChild("parameters"); effect->parametersProp = effect->root->getChild("parameters");
@@ -234,12 +238,13 @@ Effect* makeEffect(SGPropertyNode* prop,
effect->generator = parent->generator; // Copy the generators effect->generator = parent->generator; // Copy the generators
} }
} else { } else {
SG_LOG(SG_INPUT, SG_ALERT, "can't find base effect " << simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadEffectsShaders,
inheritProp->getStringValue()); string{"couldn't find base effect to inherit from:"} + inheritProp->getStringValue(), filePath);
return 0; return nullptr;
} }
} else { } else {
effect = new Effect; effect = new Effect;
effect->setFilePath(filePath);
effect->setName(nameProp->getStringValue()); effect->setName(nameProp->getStringValue());
effect->root = prop; effect->root = prop;
effect->parametersProp = effect->root->getChild("parameters"); effect->parametersProp = effect->root->getChild("parameters");
@@ -266,9 +271,9 @@ Effect* makeEffect(SGPropertyNode* prop,
effect->realizeTechniques(options); effect->realizeTechniques(options);
} }
catch (BuilderException& e) { catch (BuilderException& e) {
SG_LOG(SG_INPUT, SG_ALERT, "Error building technique: " simgear::reportFailure(simgear::LoadFailure::Misconfigured, simgear::ErrorCode::LoadEffectsShaders,
<< e.getFormattedMessage()); "Failed to build technique:" + e.getFormattedMessage(), filePath);
return 0; return nullptr;
} }
} }
return effect.release(); return effect.release();
+6 -2
View File
@@ -97,11 +97,13 @@ SGMaterial::SGMaterial( const SGReaderWriterOptions* options,
const SGPropertyNode *props, const SGPropertyNode *props,
SGPropertyNode *prop_root, SGPropertyNode *prop_root,
AreaList *a, AreaList *a,
SGSharedPtr<const SGCondition> c) SGSharedPtr<const SGCondition> c,
const std::string& n)
{ {
init(); init();
areas = a; areas = a;
condition = c; condition = c;
region = n;
read_properties( options, props, prop_root ); read_properties( options, props, prop_root );
buildEffectProperties(options); buildEffectProperties(options);
} }
@@ -110,12 +112,14 @@ SGMaterial::SGMaterial( const osgDB::Options* options,
const SGPropertyNode *props, const SGPropertyNode *props,
SGPropertyNode *prop_root, SGPropertyNode *prop_root,
AreaList *a, AreaList *a,
SGSharedPtr<const SGCondition> c) SGSharedPtr<const SGCondition> c,
const std::string& n)
{ {
osg::ref_ptr<SGReaderWriterOptions> opt; osg::ref_ptr<SGReaderWriterOptions> opt;
opt = SGReaderWriterOptions::copyOrCreate(options); opt = SGReaderWriterOptions::copyOrCreate(options);
areas = a; areas = a;
condition = c; condition = c;
region = n;
init(); init();
read_properties(opt.get(), props, prop_root); read_properties(opt.get(), props, prop_root);
buildEffectProperties(opt.get()); buildEffectProperties(opt.get());
+12 -2
View File
@@ -97,14 +97,16 @@ public:
const SGPropertyNode *props, const SGPropertyNode *props,
SGPropertyNode *prop_root, SGPropertyNode *prop_root,
AreaList *a, AreaList *a,
SGSharedPtr<const SGCondition> c); SGSharedPtr<const SGCondition> c,
const std::string& n);
SGMaterial(const simgear::SGReaderWriterOptions*, SGMaterial(const simgear::SGReaderWriterOptions*,
const SGPropertyNode *props, const SGPropertyNode *props,
SGPropertyNode *prop_root, SGPropertyNode *prop_root,
AreaList *a, AreaList *a,
SGSharedPtr<const SGCondition> c); SGSharedPtr<const SGCondition> c,
const std::string& n);
/** /**
* Destructor. * Destructor.
@@ -123,6 +125,11 @@ public:
simgear::Effect* get_one_effect(int texIndex); simgear::Effect* get_one_effect(int texIndex);
simgear::Effect* get_effect(); simgear::Effect* get_effect();
/**
* Get the region Name.
*/
const std::string get_region_name() const { return region; }
/** /**
* Get the Effect Name. * Get the Effect Name.
*/ */
@@ -487,6 +494,9 @@ private:
SGVec4f ambient, diffuse, specular, emission; SGVec4f ambient, diffuse, specular, emission;
double shininess; double shininess;
// region of this material
std::string region;
// effect for this material // effect for this material
std::string effect; std::string effect;
+2 -1
View File
@@ -128,12 +128,13 @@ bool SGMaterialLib::load( const SGPath &fg_root, const SGPath& mpath,
// Now build all the materials for this set of areas and conditions // Now build all the materials for this set of areas and conditions
const std::string region = node->getStringValue("name");
const simgear::PropertyList materials = node->getChildren("material"); const simgear::PropertyList materials = node->getChildren("material");
simgear::PropertyList::const_iterator materials_iter = materials.begin(); simgear::PropertyList::const_iterator materials_iter = materials.begin();
for (; materials_iter != materials.end(); materials_iter++) { for (; materials_iter != materials.end(); materials_iter++) {
const SGPropertyNode *node = materials_iter->get(); const SGPropertyNode *node = materials_iter->get();
SGSharedPtr<SGMaterial> m = SGSharedPtr<SGMaterial> m =
new SGMaterial(options.get(), node, prop_root, arealist, condition); new SGMaterial(options.get(), node, prop_root, arealist, condition, region);
std::vector<SGPropertyNode_ptr>names = node->getChildren("name"); std::vector<SGPropertyNode_ptr>names = node->getChildren("name");
for ( unsigned int j = 0; j < names.size(); j++ ) { for ( unsigned int j = 0; j < names.size(); j++ ) {
+35 -6
View File
@@ -56,12 +56,15 @@
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/NodeAndDrawableVisitor.hxx> #include <simgear/scene/util/NodeAndDrawableVisitor.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/props/props.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/io/sg_file.hxx> #include <simgear/io/sg_file.hxx>
#include <simgear/misc/lru_cache.hxx> #include <simgear/misc/lru_cache.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/structure/exception.hxx>
#include "BoundingVolumeBuildVisitor.hxx" #include "BoundingVolumeBuildVisitor.hxx"
#include "model.hxx" #include "model.hxx"
@@ -289,6 +292,11 @@ ModelRegistry::readImage(const string& fileName,
const SGReaderWriterOptions* sgoptC = dynamic_cast<const SGReaderWriterOptions*>(opt); const SGReaderWriterOptions* sgoptC = dynamic_cast<const SGReaderWriterOptions*>(opt);
simgear::ErrorReportContext ec;
if (sgoptC && sgoptC->getModelData()) {
ec.addFromMap(sgoptC->getModelData()->getErrorContext());
}
if (cache_active && (!sgoptC || sgoptC->getLoadOriginHint() != SGReaderWriterOptions::LoadOriginHint::ORIGIN_SPLASH_SCREEN)) { if (cache_active && (!sgoptC || sgoptC->getLoadOriginHint() != SGReaderWriterOptions::LoadOriginHint::ORIGIN_SPLASH_SCREEN)) {
if (fileExtension != "dds" && fileExtension != "gz") { if (fileExtension != "dds" && fileExtension != "gz") {
@@ -549,7 +557,13 @@ ModelRegistry::readImage(const string& fileName,
} }
} }
res = registry->readImageImplementation(absFileName, opt); try {
res = registry->readImageImplementation(absFileName, opt);
} catch (std::bad_alloc&) {
simgear::reportFailure(simgear::LoadFailure::OutOfMemory, simgear::ErrorCode::ThreeDModelLoad,
"Out of memory loading texture", sg_location{absFileName});
return ReaderWriter::ReadResult::INSUFFICIENT_MEMORY_TO_LOAD;
}
if (!res.success()) { if (!res.success()) {
SG_LOG(SG_IO, SG_DEV_WARN, "Image loading failed:" << res.message()); SG_LOG(SG_IO, SG_DEV_WARN, "Image loading failed:" << res.message());
@@ -714,7 +728,17 @@ ReaderWriter::ReadResult
ModelRegistry::readNode(const string& fileName, ModelRegistry::readNode(const string& fileName,
const Options* opt) const Options* opt)
{ {
ReaderWriter::ReadResult res; // propogate error context from the caller
simgear::ErrorReportContext ec;
auto sgopt = dynamic_cast<const SGReaderWriterOptions*>(opt);
if (sgopt) {
if (sgopt->getModelData()) {
ec.addFromMap(sgopt->getModelData()->getErrorContext());
}
ec.addFromMap(sgopt->getErrorContext());
}
CallbackMap::iterator iter CallbackMap::iterator iter
= nodeCallbackMap.find(getFileExtension(fileName)); = nodeCallbackMap.find(getFileExtension(fileName));
ReaderWriter::ReadResult result; ReaderWriter::ReadResult result;
@@ -723,6 +747,11 @@ ModelRegistry::readNode(const string& fileName,
else else
result = _defaultCallback->readNode(fileName, opt); result = _defaultCallback->readNode(fileName, opt);
if (!result.validNode()) {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::ThreeDModelLoad,
"Failed to load 3D model:" + result.message(), sg_location{fileName});
}
return result; return result;
} }
+45 -15
View File
@@ -35,12 +35,13 @@
#include <osgDB/FileNameUtils> #include <osgDB/FileNameUtils>
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/structure/exception.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx> #include <simgear/scene/util/SGNodeMasks.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/structure/exception.hxx>
#include "modellib.hxx" #include "modellib.hxx"
#include "SGReaderWriterXML.hxx" #include "SGReaderWriterXML.hxx"
@@ -81,6 +82,7 @@ SGReaderWriterXML::readNode(const std::string& name,
const osgDB::Options* options) const const osgDB::Options* options) const
{ {
std::string fileName = osgDB::findDataFile(name, options); std::string fileName = osgDB::findDataFile(name, options);
simgear::ErrorReportContext ec{"model-xml", fileName};
osg::Node *result=0; osg::Node *result=0;
try { try {
@@ -262,8 +264,10 @@ sgLoad3DModel_internal(const SGPath& path,
SGPropertyNode *overlay) SGPropertyNode *overlay)
{ {
if (!path.exists()) { if (!path.exists()) {
SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << path << "\""); simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::XMLModelLoad,
return std::make_tuple(0, (osg::Node *) NULL); "Failed to load model XML: not found", path);
SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << path << "\"");
return std::make_tuple(0, (osg::Node*)NULL);
} }
osg::ref_ptr<SGReaderWriterOptions> options; osg::ref_ptr<SGReaderWriterOptions> options;
@@ -291,6 +295,8 @@ sgLoad3DModel_internal(const SGPath& path,
try { try {
readProperties(modelpath, props); readProperties(modelpath, props);
} catch (const sg_exception &t) { } catch (const sg_exception &t) {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::XMLModelLoad,
"Failed to load model XML:" + t.getFormattedMessage(), t.getLocation());
SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load xml: " SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load xml: "
<< t.getFormattedMessage()); << t.getFormattedMessage());
throw; throw;
@@ -305,18 +311,24 @@ sgLoad3DModel_internal(const SGPath& path,
if (props->hasValue("/path")) { if (props->hasValue("/path")) {
string modelPathStr = props->getStringValue("/path"); string modelPathStr = props->getStringValue("/path");
modelpath = SGModelLib::findDataFile(modelPathStr, NULL, modelDir); modelpath = SGModelLib::findDataFile(modelPathStr, NULL, modelDir);
if (modelpath.isNull()) if (modelpath.isNull()) {
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::ThreeDModelLoad,
"Model not found:" + modelPathStr, path);
throw sg_io_exception("Model file not found: '" + modelPathStr + "'", throw sg_io_exception("Model file not found: '" + modelPathStr + "'",
path); path, {}, false);
}
if (props->hasValue("/texture-path")) { if (props->hasValue("/texture-path")) {
string texturePathStr = props->getStringValue("/texture-path"); string texturePathStr = props->getStringValue("/texture-path");
if (!texturePathStr.empty()) if (!texturePathStr.empty())
{ {
texturepath = SGModelLib::findDataFile(texturePathStr, NULL, modelDir); texturepath = SGModelLib::findDataFile(texturePathStr, NULL, modelDir);
if (texturepath.isNull()) if (texturepath.isNull()) {
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadingTexture,
"Texture file not found:" + texturePathStr, path);
throw sg_io_exception("Texture file not found: '" + texturePathStr + "'", throw sg_io_exception("Texture file not found: '" + texturePathStr + "'",
path); path);
}
} }
} }
} else { } else {
@@ -343,9 +355,13 @@ sgLoad3DModel_internal(const SGPath& path,
#else #else
modelResult = osgDB::readRefNodeFile(modelpath.utf8Str(), options.get()); modelResult = osgDB::readRefNodeFile(modelpath.utf8Str(), options.get());
#endif #endif
if (!modelResult.validNode()) if (!modelResult.validNode()) {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::XMLModelLoad,
"Failed to load 3D model:" + modelResult.message(), modelpath);
throw sg_io_exception("Failed to load 3D model:" + modelResult.message(), throw sg_io_exception("Failed to load 3D model:" + modelResult.message(),
modelpath); modelpath, {}, false);
}
model = copyModel(modelResult.getNode()); model = copyModel(modelResult.getNode());
// Add an extra reference to the model stored in the database. // Add an extra reference to the model stored in the database.
// That is to avoid expiring the object from the cache even if // That is to avoid expiring the object from the cache even if
@@ -413,6 +429,9 @@ sgLoad3DModel_internal(const SGPath& path,
if (submodelPath.isNull()) { if (submodelPath.isNull()) {
SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << subPathStr << "\""); SG_LOG(SG_IO, SG_DEV_ALERT, "Failed to load file: \"" << subPathStr << "\"");
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::XMLModelLoad,
"Couldn't find file for submodel:" + subPathStr,
SGPath::fromUtf8(subPathStr));
continue; continue;
} }
@@ -425,6 +444,8 @@ sgLoad3DModel_internal(const SGPath& path,
} }
} }
simgear::ErrorReportContext("submodel", submodelPath.utf8Str());
try { try {
int num_anims; int num_anims;
std::tie(num_anims, submodel) = sgLoad3DModel_internal(submodelPath, options.get(), std::tie(num_anims, submodel) = sgLoad3DModel_internal(submodelPath, options.get(),
@@ -553,13 +574,22 @@ sgLoad3DModel_internal(const SGPath& path,
} // of object-names in the animation } // of object-names in the animation
continue; continue;
} }
/*
* Setup the model data for the node currently being animated. try {
*/ /*
modelData.LoadAnimationValuesForElement(animation_nodes[i], i); * Setup the model data for the node currently being animated.
*/
modelData.LoadAnimationValuesForElement(animation_nodes[i], i);
/// OSGFIXME: duh, why not only model????? /// OSGFIXME: duh, why not only model?????
SGAnimation::animate(modelData); SGAnimation::animate(modelData);
} catch (sg_exception& e) {
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::XMLModelLoad,
"Couldn't load animation " + animation_nodes[i]->getNameString()
+ ":" + e.getFormattedMessage(),
modelpath);
throw;
}
} }
animationcount += animation_nodes.size(); animationcount += animation_nodes.size();
+11
View File
@@ -39,9 +39,11 @@
#include <simgear/bvh/BVHGroup.hxx> #include <simgear/bvh/BVHGroup.hxx>
#include <simgear/bvh/BVHLineGeometry.hxx> #include <simgear/bvh/BVHLineGeometry.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/math/interpolater.hxx> #include <simgear/math/interpolater.hxx>
#include <simgear/props/condition.hxx> #include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/scene/material/EffectGeode.hxx> #include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/EffectCullVisitor.hxx> #include <simgear/scene/material/EffectCullVisitor.hxx>
#include <simgear/scene/util/DeletionManager.hxx> #include <simgear/scene/util/DeletionManager.hxx>
@@ -455,6 +457,9 @@ SGAnimation::~SGAnimation()
} }
if (!info.empty()) if (!info.empty())
{ {
reportFailure(LoadFailure::Misconfigured, ErrorCode::XMLModelLoad,
"Could not find at least one of the following object for animation:" + info,
SGPath::fromUtf8(_modelData.getPath()));
SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find at least one of the following" SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find at least one of the following"
" objects for animation: " << info << " in file: " << _modelData.getPath()); " objects for animation: " << info << " in file: " << _modelData.getPath());
} }
@@ -773,10 +778,16 @@ bool SGAnimation::setCenterAndAxisFromObject(osg::Node *rootNode, SGVec3d& cente
object_group->setNodeMask(0); object_group->setNodeMask(0);
} }
else { else {
reportFailure(LoadFailure::Misconfigured, ErrorCode::XMLModelLoad,
"Could not find valid line segment for axis animation:" + axis_object_name,
SGPath::fromUtf8(_modelData.getPath()));
SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find a valid line segment for animation: " << axis_object_name << " in file: " << _modelData.getPath()); SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find a valid line segment for animation: " << axis_object_name << " in file: " << _modelData.getPath());
} }
} }
else if (can_warn) { else if (can_warn) {
reportFailure(LoadFailure::Misconfigured, ErrorCode::XMLModelLoad,
"Could not find object for axis animation:" + axis_object_name,
SGPath::fromUtf8(_modelData.getPath()));
SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find at least one of the following objects for axis animation: " << axis_object_name << " in file: " << _modelData.getPath()); SG_LOG(SG_IO, SG_DEV_ALERT, "Could not find at least one of the following objects for axis animation: " << axis_object_name << " in file: " << _modelData.getPath());
} }
} }
+6 -3
View File
@@ -24,11 +24,12 @@
#include <simgear/scene/util/SplicingVisitor.hxx> #include <simgear/scene/util/SplicingVisitor.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/structure/Singleton.hxx> #include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx> #include <simgear/structure/Singleton.hxx>
#include <simgear/structure/exception.hxx>
#include "model.hxx" #include "model.hxx"
@@ -380,6 +381,8 @@ ref_ptr<Node> instantiateMaterialEffects(osg::Node* modelGroup,
} else { } else {
effect = DefaultEffect::instance()->getEffect(); effect = DefaultEffect::instance()->getEffect();
SG_LOG( SG_TERRAIN, SG_ALERT, "Unable to get effect for " << options->getMaterialName()); SG_LOG( SG_TERRAIN, SG_ALERT, "Unable to get effect for " << options->getMaterialName());
simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::LoadEffectsShaders,
"Unable to get effect for material:" + options->getMaterialName());
} }
} else { } else {
effect = DefaultEffect::instance()->getEffect(); effect = DefaultEffect::instance()->getEffect();
+3 -3
View File
@@ -29,12 +29,13 @@
#include <osgDB/Registry> #include <osgDB/Registry>
#include <simgear/constants.h> #include <simgear/constants.h>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/misc/ResourceManager.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/scene/model/model.hxx>
#include <simgear/scene/model/ModelRegistry.hxx> #include <simgear/scene/model/ModelRegistry.hxx>
#include <simgear/scene/model/model.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/misc/ResourceManager.hxx>
#include "SGReaderWriterXML.hxx" #include "SGReaderWriterXML.hxx"
@@ -159,7 +160,6 @@ SGModelLib::loadDeferredModel(const string &path, SGPropertyNode *prop_root,
proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER); proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
proxyNode->setFileName(0, path); proxyNode->setFileName(0, path);
osg::ref_ptr<SGReaderWriterOptions> opt; osg::ref_ptr<SGReaderWriterOptions> opt;
opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions()); opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
opt->getDatabasePathList().push_front( osgDB::getFilePath(path) ); opt->getDatabasePathList().push_front( osgDB::getFilePath(path) );
+5 -4
View File
@@ -18,12 +18,9 @@
#ifndef _SG_MODEL_LIB_HXX #ifndef _SG_MODEL_LIB_HXX
#define _SG_MODEL_LIB_HXX 1 #define _SG_MODEL_LIB_HXX 1
#ifndef __cplusplus
# error This library requires C++
#endif
#include <simgear/compiler.h> // for SG_USING_STD #include <simgear/compiler.h> // for SG_USING_STD
#include <map>
#include <string> #include <string>
#include <osg/Node> #include <osg/Node>
@@ -112,6 +109,10 @@ public:
virtual void modelLoaded(const std::string& path, SGPropertyNode *prop, virtual void modelLoaded(const std::string& path, SGPropertyNode *prop,
osg::Node* branch) = 0; osg::Node* branch) = 0;
virtual SGModelData* clone() const = 0; virtual SGModelData* clone() const = 0;
using ErrorContext = std::map<std::string, std::string>;
virtual ErrorContext getErrorContext() const = 0;
}; };
/* /*
+1
View File
@@ -187,6 +187,7 @@ void ParticlesGlobalManager::initFromMainThread()
std::lock_guard<std::mutex> g(d->_lock); std::lock_guard<std::mutex> g(d->_lock);
d->internalGetCommonRoot(); d->internalGetCommonRoot();
d->_commonRoot->addUpdateCallback(d.get()); d->_commonRoot->addUpdateCallback(d.get());
d->_commonRoot->setCullingActive(false);
d->_commonRoot->addCullCallback(d->_cullCallback); d->_commonRoot->addCullCallback(d->_cullCallback);
} }
+32 -18
View File
@@ -38,10 +38,12 @@
#include <osgDB/ReaderWriter> #include <osgDB/ReaderWriter>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <simgear/math/sg_random.h>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/bucket/newbucket.hxx> #include <simgear/bucket/newbucket.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/io/iostreams/sgstream.hxx> #include <simgear/io/iostreams/sgstream.hxx>
#include <simgear/scene/util/OptionsReadFileCallback.hxx> #include <simgear/scene/util/OptionsReadFileCallback.hxx>
#include <simgear/scene/util/OsgMath.hxx> #include <simgear/scene/util/OsgMath.hxx>
@@ -154,7 +156,7 @@ struct ReaderWriterSTG::_ModelBin {
proxy->setName("proxyNode"); proxy->setName("proxyNode");
proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER); proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
proxy->setFileName(0, o._name); proxy->setFileName(0, o._name);
proxy->setDatabaseOptions(o._options.get()); proxy->setDatabaseOptions(o._options);
// Give the node some values so the Quadtree builder has // Give the node some values so the Quadtree builder has
// a BoundingBox to work with prior to the model being loaded. // a BoundingBox to work with prior to the model being loaded.
@@ -163,6 +165,7 @@ struct ReaderWriterSTG::_ModelBin {
proxy->setCenterMode(osg::ProxyNode::UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED); proxy->setCenterMode(osg::ProxyNode::UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED);
node = proxy; node = proxy;
} else { } else {
ErrorReportContext ec("terrain-stg", o._errorLocation.utf8Str());
#if OSG_VERSION_LESS_THAN(3,4,0) #if OSG_VERSION_LESS_THAN(3,4,0)
node = osgDB::readNodeFile(o._name, o._options.get()); node = osgDB::readNodeFile(o._name, o._options.get());
#else #else
@@ -209,6 +212,8 @@ struct ReaderWriterSTG::_ModelBin {
virtual osgDB::ReaderWriter::ReadResult virtual osgDB::ReaderWriter::ReadResult
readNode(const std::string&, const osgDB::Options*) readNode(const std::string&, const osgDB::Options*)
{ {
ErrorReportContext ec("terrain-bucket", _bucket.gen_index_str());
STGObjectsQuadtree quadtree((GetModelLODCoord()), (AddModelLOD())); STGObjectsQuadtree quadtree((GetModelLODCoord()), (AddModelLOD()));
quadtree.buildQuadTree(_objectStaticList.begin(), _objectStaticList.end()); quadtree.buildQuadTree(_objectStaticList.begin(), _objectStaticList.end());
osg::ref_ptr<osg::Group> group = quadtree.getRoot(); osg::ref_ptr<osg::Group> group = quadtree.getRoot();
@@ -465,15 +470,15 @@ struct ReaderWriterSTG::_ModelBin {
else else
opt->setInstantiateEffects(false); opt->setInstantiateEffects(false);
_ObjectStatic obj; _ObjectStatic obj;
opt->addErrorContext("terrain-stg", absoluteFileName.utf8Str());
obj._errorLocation = absoluteFileName; obj._errorLocation = absoluteFileName;
obj._token = token; obj._token = token;
obj._name = name; obj._name = name;
obj._agl = (token == "OBJECT_STATIC_AGL"); obj._agl = (token == "OBJECT_STATIC_AGL");
obj._proxy = true; obj._proxy = true;
in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll; in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
obj._range = range; obj._range = range;
obj._options = opt; obj._options = opt;
checkInsideBucket(absoluteFileName, obj._lon, obj._lat); checkInsideBucket(absoluteFileName, obj._lon, obj._lat);
_objectStaticList.push_back(obj); _objectStaticList.push_back(obj);
} else if (token == "OBJECT_SHARED" || token == "OBJECT_SHARED_AGL") { } else if (token == "OBJECT_SHARED" || token == "OBJECT_SHARED_AGL") {
@@ -509,6 +514,8 @@ struct ReaderWriterSTG::_ModelBin {
_ObjectStatic obj; _ObjectStatic obj;
opt->setInstantiateEffects(false); opt->setInstantiateEffects(false);
opt->addErrorContext("terrain-stg", absoluteFileName.utf8Str());
if (SGPath(name).lower_extension() == "ac") { if (SGPath(name).lower_extension() == "ac") {
// Generate material/Effects lookups for raw models, i.e. // Generate material/Effects lookups for raw models, i.e.
// those not wrapped in an XML while will include Effects // those not wrapped in an XML while will include Effects
@@ -573,7 +580,9 @@ struct ReaderWriterSTG::_ModelBin {
} }
callback(token,name, SGGeod::fromDegM(obj._lon, obj._lat, obj._elev), obj._hdg,restofline); callback(token,name, SGGeod::fromDegM(obj._lon, obj._lat, obj._elev), obj._hdg,restofline);
} else { } else {
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName << ": Unknown token '" << token << "'" ); // SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName << ": Unknown token '" << token << "'" );
simgear::reportFailure(simgear::LoadFailure::Misconfigured, simgear::ErrorCode::BTGLoad,
"Unknown STG token:" + token, absoluteFileName);
} }
} }
} }
@@ -594,9 +603,13 @@ struct ReaderWriterSTG::_ModelBin {
std::string terrain_name = string("terrain ").append(bucket.gen_index_str()); std::string terrain_name = string("terrain ").append(bucket.gen_index_str());
terrainGroup->setName(terrain_name); terrainGroup->setName(terrain_name);
simgear::ErrorReportContext ec{"terrain-bucket", bucket.gen_index_str()};
if (_foundBase) { if (_foundBase) {
for (auto stgObject : _objectList) { for (auto stgObject : _objectList) {
osg::ref_ptr<osg::Node> node; osg::ref_ptr<osg::Node> node;
simgear::ErrorReportContext ec("terrain-stg", stgObject._errorLocation.utf8Str());
#if OSG_VERSION_LESS_THAN(3,4,0) #if OSG_VERSION_LESS_THAN(3,4,0)
node = osgDB::readNodeFile(stgObject._name, stgObject._options.get()); node = osgDB::readNodeFile(stgObject._name, stgObject._options.get());
#else #else
@@ -621,7 +634,6 @@ struct ReaderWriterSTG::_ModelBin {
"Warning: failed to generate ocean tile!" ); "Warning: failed to generate ocean tile!" );
} }
} }
for (std::list<_ObjectStatic>::iterator i = _objectStaticList.begin(); i != _objectStaticList.end(); ++i) { for (std::list<_ObjectStatic>::iterator i = _objectStaticList.begin(); i != _objectStaticList.end(); ++i) {
if (!i->_agl) if (!i->_agl)
continue; continue;
@@ -701,6 +713,7 @@ ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* opt
{ {
_ModelBin modelBin; _ModelBin modelBin;
SGBucket bucket(bucketIndexFromFileName(fileName)); SGBucket bucket(bucketIndexFromFileName(fileName));
simgear::ErrorReportContext ec("terrain-bucket", bucket.gen_index_str());
// We treat 123.stg different than ./123.stg. // We treat 123.stg different than ./123.stg.
// The difference is that ./123.stg as well as any absolute path // The difference is that ./123.stg as well as any absolute path
@@ -708,6 +721,7 @@ ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* opt
// In contrast 123.stg uses the search paths to load a set of stg // In contrast 123.stg uses the search paths to load a set of stg
// files spread across the scenery directories. // files spread across the scenery directories.
if (osgDB::getSimpleFileName(fileName) != fileName) { if (osgDB::getSimpleFileName(fileName) != fileName) {
simgear::ErrorReportContext ec("terrain-stg", fileName);
if (!modelBin.read(fileName, options)) if (!modelBin.read(fileName, options))
return ReadResult::FILE_NOT_FOUND; return ReadResult::FILE_NOT_FOUND;
} }
@@ -717,11 +731,10 @@ ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* opt
return ReadResult::FILE_NOT_FOUND; return ReadResult::FILE_NOT_FOUND;
} }
osg::ref_ptr<SGReaderWriterOptions> sgOpts(SGReaderWriterOptions::copyOrCreate(options)); const auto sgOpts = dynamic_cast<const SGReaderWriterOptions*>(options);
if (sgOpts->getSceneryPathSuffixes().empty()) { if (!sgOpts || sgOpts->getSceneryPathSuffixes().empty()) {
SG_LOG(SG_TERRAIN, SG_ALERT, "Loading tile " << fileName << ", no scenery path suffixes were configured so giving up"); SG_LOG(SG_TERRAIN, SG_ALERT, "Loading tile " << fileName << ", no scenery path suffixes were configured so giving up");
return ReadResult::FILE_NOT_FOUND; return ReadResult::FILE_NOT_FOUND;
} }
SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName); SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName);
@@ -746,7 +759,8 @@ ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* opt
} }
for (auto suffix : sgOpts->getSceneryPathSuffixes()) { for (auto suffix : sgOpts->getSceneryPathSuffixes()) {
SGPath p = base / suffix / basePath / fileName; const auto p = base / suffix / basePath / fileName;
simgear::ErrorReportContext ec("terrain-stg", p.utf8Str());
modelBin.read(p, options); modelBin.read(p, options);
} }
} }
+10 -3
View File
@@ -22,6 +22,7 @@
#include <osgDB/FileNameUtils> #include <osgDB/FileNameUtils>
#include <osgDB/Registry> #include <osgDB/Registry>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/scene/model/ModelRegistry.hxx> #include <simgear/scene/model/ModelRegistry.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx> #include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
@@ -62,16 +63,22 @@ SGReaderWriterBTG::readNode(const std::string& fileName,
const SGReaderWriterOptions* sgOptions; const SGReaderWriterOptions* sgOptions;
sgOptions = dynamic_cast<const SGReaderWriterOptions*>(options); sgOptions = dynamic_cast<const SGReaderWriterOptions*>(options);
osg::Node* result = NULL; osg::Node* result = NULL;
simgear::ErrorReportContext ec{"btg", fileName};
try { try {
result = SGLoadBTG(fileName, sgOptions); result = SGLoadBTG(fileName, sgOptions);
if (!result) if (!result)
return ReadResult::FILE_NOT_HANDLED; return ReadResult::FILE_NOT_HANDLED;
} catch (sg_exception& e) { } catch (sg_exception& e) {
SG_LOG(SG_IO, SG_WARN, "error reading:" << fileName << ":" << simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::BTGLoad,
e.getFormattedMessage()); "Failed to load BTG file:" + e.getFormattedMessage(),
e.getLocation());
return ReadResult::ERROR_IN_READING_FILE;
} catch (std::bad_alloc&) {
simgear::reportFailure(simgear::LoadFailure::OutOfMemory, simgear::ErrorCode::BTGLoad,
"Out of memory loading BTG:" + fileName, sg_location{fileName});
return ReadResult::ERROR_IN_READING_FILE; return ReadResult::ERROR_IN_READING_FILE;
} }
return result; return result;
} }
+20
View File
@@ -1124,6 +1124,9 @@ void SGTerraSync::reinit()
SGPath sceneryRoot{_terraRoot->getStringValue("scenery-dir", "")}; SGPath sceneryRoot{_terraRoot->getStringValue("scenery-dir", "")};
_workerThread->setLocalDir(sceneryRoot.utf8Str()); _workerThread->setLocalDir(sceneryRoot.utf8Str());
if (sceneryRoot.exists()) {
writeWarningFile(sceneryRoot);
}
SGPath installPath(_terraRoot->getStringValue("installation-dir")); SGPath installPath(_terraRoot->getStringValue("installation-dir"));
_workerThread->setInstalledDir(installPath); _workerThread->setInstalledDir(installPath);
@@ -1362,6 +1365,23 @@ void SGTerraSync::reposition()
// stub, remove // stub, remove
} }
void SGTerraSync::writeWarningFile(const SGPath& sceneryDir)
{
SGPath p = sceneryDir / "TerraSync-WARNING.txt";
if (p.exists())
return;
sg_ofstream os(p, std::ios::out | std::ios::trunc);
os << "This folder is managed by FlightGear's download system.\n";
os << "Any changes you make here or in sub-folders will be overwritten when TerraSync\n";
os << "downloads updates.\n";
os << "\n";
os << "To use custom scenery or data with FlightGear, put it in a differnet location\n";
os << "on your computer, then add the location using either the launcher 'Add-ons' page, or by\n";
os << "passing '--fg-scenery=<location>' on the command line.";
os << endl;
}
// Register the subsystem. // Register the subsystem.
SGSubsystemMgr::Registrant<SGTerraSync> registrantSGTerraSync( SGSubsystemMgr::Registrant<SGTerraSync> registrantSGTerraSync(
+3
View File
@@ -90,6 +90,9 @@ protected:
class WorkerThread; class WorkerThread;
private:
void writeWarningFile(const SGPath& sceneryDir);
private: private:
WorkerThread* _workerThread; WorkerThread* _workerThread;
SGPropertyNode_ptr _terraRoot; SGPropertyNode_ptr _terraRoot;
+2
View File
@@ -31,6 +31,7 @@ set(HEADERS
UpdateOnceCallback.hxx UpdateOnceCallback.hxx
VectorArrayAdapter.hxx VectorArrayAdapter.hxx
project.hxx project.hxx
SGProgram.hxx
) )
set(SOURCES set(SOURCES
@@ -55,6 +56,7 @@ set(SOURCES
StateAttributeFactory.cxx StateAttributeFactory.cxx
UpdateOnceCallback.cxx UpdateOnceCallback.cxx
project.cxx project.cxx
SGProgram.cxx
) )
simgear_scene_component(util scene/util "${SOURCES}" "${HEADERS}") simgear_scene_component(util scene/util "${SOURCES}" "${HEADERS}")
+83
View File
@@ -0,0 +1,83 @@
////
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301, USA.
#include "simgear_config.h"
#include "SGProgram.hxx"
#include <osg/State>
#include <sstream>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include <simgear/debug/logstream.hxx>
SGProgram::SGProgram()
{
}
SGProgram::SGProgram(const SGProgram& rhs, const osg::CopyOp& copyop) : osg::Program(rhs, copyop),
_effectFilePath(rhs._effectFilePath)
{
}
void SGProgram::setEffectFilePath(const SGPath& p)
{
_effectFilePath = p;
}
void SGProgram::apply(osg::State& state) const
{
osg::Program::apply(state);
if (_checkState != NotApplied) {
return; // already done
}
auto pcp = state.getLastAppliedProgramObject();
if (!pcp) {
std::string infoLog;
_checkState = FailedToApply;
getPCP(state)->getInfoLog(infoLog);
if (!infoLog.empty()) {
// log all the shader source file names, to help in debugging link errors
std::ostringstream os;
for (int i = 0; i < getNumShaders(); ++i) {
const auto shader = getShader(i);
os << "\t" << shader->getFileName() << "\n";
}
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadEffectsShaders,
"Shader program errors: " + infoLog +
"\n\nShader sources:\n" + os.str(),
_effectFilePath);
}
for (int i = 0; i < getNumShaders(); ++i) {
const auto shader = getShader(i);
auto pcs = shader->getPCS(state);
std::string shaderLog;
pcs->getInfoLog(shaderLog);
if (!shaderLog.empty()) {
simgear::reportFailure(simgear::LoadFailure::BadData, simgear::ErrorCode::LoadEffectsShaders,
"Shader source errors: " + shaderLog, sg_location(shader->getFileName()));
}
}
} else {
_checkState = AppliedOk;
}
}
+50
View File
@@ -0,0 +1,50 @@
////
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301, USA.
#pragma once
#include <osg/Program>
#include <simgear/misc/sg_path.hxx>
/**
* @brief wrapper around osg::Program to allow detecting shader/link
* errors in the GLSL code at runtime, and reporting of them
*
*/
class SGProgram : public osg::Program
{
public:
SGProgram();
SGProgram(const SGProgram& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
META_StateAttribute(simgear, SGProgram, PROGRAM);
void apply(osg::State& state) const override;
enum ErrorCheckState {
NotApplied,
AppliedOk,
FailedToApply
};
void setEffectFilePath(const SGPath& p);
private:
SGPath _effectFilePath;
mutable ErrorCheckState _checkState = NotApplied;
};
+7 -3
View File
@@ -17,9 +17,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// //
#ifdef HAVE_CONFIG_H #include <simgear_config.h>
# include <simgear_config.h>
#endif
#include <simgear/scene/util/OsgMath.hxx> #include <simgear/scene/util/OsgMath.hxx>
@@ -54,4 +52,10 @@ SGReaderWriterOptions::fromPath(const SGPath& path)
return options; return options;
} }
void SGReaderWriterOptions::addErrorContext(const std::string& key, const std::string& value)
{
_errorContext[key] = value;
} }
} // namespace simgear
+17 -7
View File
@@ -76,12 +76,11 @@ public:
_LoadOriginHint(ORIGIN_MODEL) _LoadOriginHint(ORIGIN_MODEL)
{ } { }
SGReaderWriterOptions(const SGReaderWriterOptions& options, SGReaderWriterOptions(const SGReaderWriterOptions& options,
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) : const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) : osgDB::Options(options, copyop),
osgDB::Options(options, copyop), _propertyNode(options._propertyNode),
_propertyNode(options._propertyNode), _materialLib(options._materialLib),
_materialLib(options._materialLib),
#ifdef ENABLE_GDAL #ifdef ENABLE_GDAL
_dem(options._dem), _dem(options._dem),
#endif #endif
_load_panel(options._load_panel), _load_panel(options._load_panel),
_model_data(options._model_data), _model_data(options._model_data),
@@ -89,7 +88,8 @@ public:
_instantiateMaterialEffects(options._instantiateMaterialEffects), _instantiateMaterialEffects(options._instantiateMaterialEffects),
_materialName(options._materialName), _materialName(options._materialName),
_sceneryPathSuffixes(options._sceneryPathSuffixes), _sceneryPathSuffixes(options._sceneryPathSuffixes),
_LoadOriginHint(ORIGIN_MODEL) _LoadOriginHint(ORIGIN_MODEL),
_errorContext(options._errorContext)
{ } { }
META_Object(simgear, SGReaderWriterOptions); META_Object(simgear, SGReaderWriterOptions);
@@ -158,7 +158,16 @@ public:
// any texture that is used in a shader, as these often have special values // any texture that is used in a shader, as these often have special values
// encoded into the channels that aren't suitable for conversion. // encoded into the channels that aren't suitable for conversion.
void setLoadOriginHint(LoadOriginHint _v) const { _LoadOriginHint = _v; } void setLoadOriginHint(LoadOriginHint _v) const { _LoadOriginHint = _v; }
LoadOriginHint getLoadOriginHint() const { return _LoadOriginHint; } LoadOriginHint getLoadOriginHint() const { return _LoadOriginHint; }
using ErrorContext = std::map<std::string, std::string>;
void addErrorContext(const std::string& key, const std::string& value);
ErrorContext getErrorContext() const
{
return _errorContext;
}
protected: protected:
virtual ~SGReaderWriterOptions(); virtual ~SGReaderWriterOptions();
@@ -179,6 +188,7 @@ private:
string_list _sceneryPathSuffixes; string_list _sceneryPathSuffixes;
SGGeod _geod; SGGeod _geod;
mutable LoadOriginHint _LoadOriginHint; mutable LoadOriginHint _LoadOriginHint;
ErrorContext _errorContext;
}; };
} }
+22 -20
View File
@@ -32,6 +32,7 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/misc/stdint.hxx> #include <simgear/misc/stdint.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/debug/ErrorReportingCallback.hxx>
#include "sample.hxx" #include "sample.hxx"
@@ -56,7 +57,7 @@ namespace
} }
}; };
unsigned int formatConstruct(ALint numChannels, ALint bitsPerSample, bool compressed) unsigned int formatConstruct(ALint numChannels, ALint bitsPerSample, bool compressed, const SGPath& path)
{ {
unsigned int rv = 0; unsigned int rv = 0;
if (!compressed) { if (!compressed) {
@@ -67,7 +68,7 @@ namespace
else { else {
char msg[81]; char msg[81];
snprintf(msg, 80, "Unsupported audio format: tracks: %i, bits/sample: %i", numChannels, bitsPerSample); snprintf(msg, 80, "Unsupported audio format: tracks: %i, bits/sample: %i", numChannels, bitsPerSample);
throw sg_exception(msg); throw sg_exception(msg, {}, path, false);
} }
} else { } else {
if (numChannels == 1 && bitsPerSample == 4) rv = SG_SAMPLE_ADPCM; if (numChannels == 1 && bitsPerSample == 4) rv = SG_SAMPLE_ADPCM;
@@ -75,7 +76,7 @@ namespace
else { else {
char msg[81]; char msg[81];
snprintf(msg, 80, "Unsupported compressed audio format: tracks: %i, bits/sample: %i", numChannels, bitsPerSample); snprintf(msg, 80, "Unsupported compressed audio format: tracks: %i, bits/sample: %i", numChannels, bitsPerSample);
throw sg_exception(msg); throw sg_exception(msg, {}, path, false);
} }
} }
return rv; return rv;
@@ -275,29 +276,29 @@ namespace
Codec *codec = codecLinear; Codec *codec = codecLinear;
if (!wavReadBE(fd, magic)) if (!wavReadBE(fd, magic))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
if (magic != WAV_RIFF_4CC) { if (magic != WAV_RIFF_4CC) {
throw sg_io_exception("not a .wav file", b->path); throw sg_io_exception("not a .wav file", b->path, {}, false);
} }
if (!wavReadLE(fd, chunkLength) || !wavReadBE(fd, magic)) if (!wavReadLE(fd, chunkLength) || !wavReadBE(fd, magic))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
if (magic != WAV_WAVE_4CC) /* "WAVE" */ if (magic != WAV_WAVE_4CC) /* "WAVE" */
{ {
throw sg_io_exception("unrecognized WAV magic", b->path); throw sg_io_exception("unrecognized WAV magic", b->path, {}, false);
} }
while (1) { while (1) {
if (!wavReadBE(fd, magic) || !wavReadLE(fd, chunkLength)) if (!wavReadBE(fd, magic) || !wavReadLE(fd, chunkLength))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
if (magic == WAV_FORMAT_4CC) /* "fmt " */ if (magic == WAV_FORMAT_4CC) /* "fmt " */
{ {
found_header = true; found_header = true;
if (chunkLength < 16) { if (chunkLength < 16) {
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} }
if (!wavReadLE (fd, audioFormat) || if (!wavReadLE (fd, audioFormat) ||
@@ -307,11 +308,11 @@ namespace
!wavReadLE (fd, blockAlign) || !wavReadLE (fd, blockAlign) ||
!wavReadLE (fd, bitsPerSample)) !wavReadLE (fd, bitsPerSample))
{ {
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} }
if (!gzSkip(fd, chunkLength - 16)) if (!gzSkip(fd, chunkLength - 16))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
switch (audioFormat) switch (audioFormat)
{ {
@@ -340,33 +341,33 @@ namespace
} }
break; break;
default: default:
throw sg_io_exception("unsupported WAV encoding", b->path); throw sg_io_exception("unsupported WAV encoding:" + std::to_string(audioFormat), b->path, {}, false);
} }
b->block_align = blockAlign; b->block_align = blockAlign;
b->frequency = samplesPerSecond; b->frequency = samplesPerSecond;
b->format = formatConstruct(numChannels, bitsPerSample, compressed); b->format = formatConstruct(numChannels, bitsPerSample, compressed, b->path);
} else if (magic == WAV_DATA_4CC) { } else if (magic == WAV_DATA_4CC) {
if (!found_header) { if (!found_header) {
/* ToDo: A bit wrong to check here, fmt chunk could come later... */ /* ToDo: A bit wrong to check here, fmt chunk could come later... */
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} }
b->data = malloc(chunkLength); b->data = malloc(chunkLength);
b->length = chunkLength; b->length = chunkLength;
size_t read = gzread(fd, b->data, chunkLength); size_t read = gzread(fd, b->data, chunkLength);
if (read != chunkLength) { if (read != chunkLength) {
throw sg_io_exception("insufficent data reading WAV file", b->path); throw sg_io_exception("insufficent data reading WAV file", b->path, {}, false);
} }
break; break;
} else { } else {
if (!gzSkip(fd, chunkLength)) if (!gzSkip(fd, chunkLength))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} }
if ((chunkLength & 1) && !gzeof(fd) && !gzSkip(fd, 1)) if ((chunkLength & 1) && !gzeof(fd) && !gzSkip(fd, 1))
throw sg_io_exception("corrupt or truncated WAV data", b->path); throw sg_io_exception("corrupt or truncated WAV data", b->path, {}, false);
} // of file chunk parser loop } // of file chunk parser loop
codec(b); // might throw if something really bad occurs codec(b); // might throw if something really bad occurs
@@ -380,7 +381,7 @@ namespace simgear
ALvoid* loadWAVFromFile(const SGPath& path, unsigned int& format, ALsizei& size, ALfloat& freqf, unsigned int& block_align) ALvoid* loadWAVFromFile(const SGPath& path, unsigned int& format, ALsizei& size, ALfloat& freqf, unsigned int& block_align)
{ {
if (!path.exists()) { if (!path.exists()) {
SG_LOG(SG_IO, SG_DEV_ALERT, "loadWAVFromFile: file not found:" << path); simgear::reportFailure(simgear::LoadFailure::NotFound, simgear::ErrorCode::AudioFX, "loadWAVFromFile: not found", path);
return nullptr; return nullptr;
} }
@@ -396,14 +397,15 @@ ALvoid* loadWAVFromFile(const SGPath& path, unsigned int& format, ALsizei& size,
fd = gzopen(ps.c_str(), "rb"); fd = gzopen(ps.c_str(), "rb");
#endif #endif
if (!fd) { if (!fd) {
SG_LOG(SG_IO, SG_DEV_ALERT, "loadWAVFromFile: unable to open file:" << path); simgear::reportFailure(simgear::LoadFailure::IOError, simgear::ErrorCode::AudioFX, "loadWAVFromFile: unable to open file", path);
return nullptr; return nullptr;
} }
try { try {
loadWavFile(fd, &b); loadWavFile(fd, &b);
} catch (sg_exception& e) { } catch (sg_exception& e) {
SG_LOG(SG_IO, SG_DEV_ALERT, "loadWAVFromFile:" << e.getFormattedMessage() << "\nfor: " << path); simgear::reportFailure(simgear::LoadFailure::IOError, simgear::ErrorCode::AudioFX, "loadWAVFromFile: unable to read file:"
+ e.getFormattedMessage(), e.getLocation());
return nullptr; return nullptr;
} }
+110 -157
View File
@@ -19,66 +19,65 @@ static ThrowCallback static_callback;
// Implementation of sg_location class. // Implementation of sg_location class.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_location::sg_location () sg_location::sg_location() noexcept
: _line(-1), : _line(-1),
_column(-1), _column(-1),
_byte(-1) _byte(-1)
{ {
_path[0] = '\0'; _path[0] = '\0';
} }
sg_location::sg_location (const std::string& path, int line, int column) sg_location::sg_location(const std::string& path, int line, int column) noexcept
: _line(line), : _line(line),
_column(column), _column(column),
_byte(-1) _byte(-1)
{ {
setPath(path.c_str()); setPath(path.c_str());
} }
sg_location::sg_location (const SGPath& path, int line, int column) sg_location::sg_location(const SGPath& path, int line, int column) noexcept
: _line(line), : _line(line),
_column(column), _column(column),
_byte(-1) _byte(-1)
{ {
setPath(path.utf8Str().c_str()); setPath(path.utf8Str().c_str());
} }
sg_location::sg_location (const char* path, int line, int column) sg_location::sg_location(const char* path, int line, int column) noexcept
: _line(line), : _line(line),
_column(column), _column(column),
_byte(-1) _byte(-1)
{ {
setPath(path); setPath(path);
} }
void sg_location::setPath(const char *path) { void sg_location::setPath(const char* path) noexcept
if (path) { {
strncpy(_path, path, max_path); if (path) {
_path[max_path -1] = '\0'; strncpy(_path, path, max_path);
} else { _path[max_path - 1] = '\0';
_path[0] = '\0'; } else {
} _path[0] = '\0';
}
} }
const char *sg_location::getPath() const { return _path; } const char* sg_location::getPath() const noexcept { return _path; }
int sg_location::getLine() const { return _line; } int sg_location::getLine() const noexcept { return _line; }
int int sg_location::getColumn() const noexcept
sg_location::getColumn () const
{ {
return _column; return _column;
} }
int int sg_location::getByte() const noexcept
sg_location::getByte () const
{ {
return _byte; return _byte;
} }
std::string std::string
sg_location::asString () const sg_location::asString() const noexcept
{ {
std::ostringstream out; std::ostringstream out;
if (_path[0]) { if (_path[0]) {
@@ -97,46 +96,48 @@ sg_location::asString () const
return out.str(); return out.str();
} }
bool sg_location::isValid() const { return strlen(_path) > 0; } bool sg_location::isValid() const noexcept { return strlen(_path) > 0; }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Implementation of sg_throwable class. // Implementation of sg_throwable class.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_throwable::sg_throwable () sg_throwable::sg_throwable() noexcept
{ {
_message[0] = '\0'; _message[0] = '\0';
_origin[0] = '\0'; _origin[0] = '\0';
} }
sg_throwable::sg_throwable(const char *message, const char *origin, sg_throwable::sg_throwable(const char* message, const char* origin,
const sg_location &loc) { const sg_location& loc, bool report) noexcept : _location(loc)
setMessage(message);
setOrigin(origin);
if (static_callback) {
static_callback(_message, _origin, loc);
}
}
sg_throwable::~sg_throwable ()
{ {
setMessage(message);
setOrigin(origin);
if (static_callback && report) {
static_callback(_message, _origin, loc);
}
} }
const char* const char*
sg_throwable::getMessage () const sg_throwable::getMessage() const noexcept
{ {
return _message; return _message;
} }
const std::string std::string
sg_throwable::getFormattedMessage () const sg_throwable::getFormattedMessage() const noexcept
{ {
return std::string(getMessage()); std::string ret = getMessage();
const std::string loc = getLocation().asString();
if (loc.length()) {
ret += "\n at ";
ret += loc;
}
return ret;
} }
void void sg_throwable::setMessage(const char* message) noexcept
sg_throwable::setMessage (const char* message)
{ {
strncpy(_message, message, MAX_TEXT_LEN); strncpy(_message, message, MAX_TEXT_LEN);
_message[MAX_TEXT_LEN - 1] = '\0'; _message[MAX_TEXT_LEN - 1] = '\0';
@@ -144,13 +145,12 @@ sg_throwable::setMessage (const char* message)
} }
const char* const char*
sg_throwable::getOrigin () const sg_throwable::getOrigin() const noexcept
{ {
return _origin; return _origin;
} }
void void sg_throwable::setOrigin(const char* origin) noexcept
sg_throwable::setOrigin (const char* origin)
{ {
if (origin) { if (origin) {
strncpy(_origin, origin, MAX_TEXT_LEN); strncpy(_origin, origin, MAX_TEXT_LEN);
@@ -170,27 +170,27 @@ const char* sg_throwable::what() const noexcept
} }
} }
sg_location sg_throwable::getLocation() const noexcept
{
return _location;
}
void sg_throwable::setLocation(const sg_location& location) noexcept
{
_location = location;
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Implementation of sg_error class. // Implementation of sg_error class.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_error::sg_error () sg_error::sg_error(const char* message, const char* origin, bool report) noexcept
: sg_throwable () : sg_throwable(message, origin, {}, report)
{ {
} }
sg_error::sg_error (const char* message, const char *origin) sg_error::sg_error(const std::string& message, const std::string& origin, bool report) noexcept
: sg_throwable(message, origin) : sg_throwable(message.c_str(), origin.c_str(), {}, report)
{
}
sg_error::sg_error(const std::string& message, const std::string& origin)
: sg_throwable(message.c_str(), origin.c_str())
{
}
sg_error::~sg_error ()
{ {
} }
@@ -198,121 +198,81 @@ sg_error::~sg_error ()
// Implementation of sg_exception class. // Implementation of sg_exception class.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_exception::sg_exception () sg_exception::sg_exception(const char* message, const char* origin,
: sg_throwable () const sg_location& loc, bool report) noexcept
{ : sg_throwable(message, origin, loc, report) {}
}
sg_exception::sg_exception(const char *message, const char *origin, sg_exception::sg_exception(const std::string& message,
const sg_location &loc) const std::string& origin, const sg_location& loc,
: sg_throwable(message, origin, loc) {} bool report) noexcept
: sg_throwable(message.c_str(), origin.c_str(), loc, report) {}
sg_exception::sg_exception(const std::string &message,
const std::string &origin, const sg_location &loc)
: sg_throwable(message.c_str(), origin.c_str(), loc) {}
sg_exception::~sg_exception ()
{
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Implementation of sg_io_exception. // Implementation of sg_io_exception.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_io_exception::sg_io_exception () sg_io_exception::sg_io_exception(const char* message, const char* origin, bool report)
: sg_exception() : sg_exception(message, origin, {}, report)
{ {
} }
sg_io_exception::sg_io_exception (const char* message, const char* origin) sg_io_exception::sg_io_exception(const char* message,
: sg_exception(message, origin) const sg_location& location,
const char* origin,
bool report)
: sg_exception(message, origin, location, report) {}
sg_io_exception::sg_io_exception(const std::string& message,
const std::string& origin,
bool report)
: sg_exception(message, origin, {}, report)
{ {
} }
sg_io_exception::sg_io_exception(const char *message, sg_io_exception::sg_io_exception(const std::string& message,
const sg_location &location, const sg_location& location,
const char *origin) const std::string& origin,
: sg_exception(message, origin, location), _location(location) {} bool report)
: sg_exception(message, origin, location, report) {}
sg_io_exception::sg_io_exception( const std::string& message,
const std::string& origin )
: sg_exception(message, origin)
{
}
sg_io_exception::sg_io_exception(const std::string &message,
const sg_location &location,
const std::string &origin)
: sg_exception(message, origin, location), _location(location) {}
sg_io_exception::~sg_io_exception ()
{
}
const std::string
sg_io_exception::getFormattedMessage () const
{
std::string ret = getMessage();
std::string loc = getLocation().asString();
if (loc.length()) {
ret += "\n at ";
ret += loc;
}
return ret;
}
const sg_location &
sg_io_exception::getLocation () const
{
return _location;
}
void
sg_io_exception::setLocation (const sg_location &location)
{
_location = location;
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Implementation of sg_format_exception. // Implementation of sg_format_exception.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_format_exception::sg_format_exception () sg_format_exception::sg_format_exception() noexcept
: sg_exception() : sg_exception()
{ {
_text[0] = '\0'; _text[0] = '\0';
} }
sg_format_exception::sg_format_exception (const char* message, sg_format_exception::sg_format_exception(const char* message,
const char* text, const char* text,
const char* origin) const char* origin,
: sg_exception(message, origin) bool report)
: sg_exception(message, origin, {}, report)
{ {
setText(text); setText(text);
} }
sg_format_exception::sg_format_exception( const std::string& message, sg_format_exception::sg_format_exception(const std::string& message,
const std::string& text, const std::string& text,
const std::string& origin ) const std::string& origin,
: sg_exception(message, origin) bool report)
: sg_exception(message, origin, {}, report)
{ {
setText(text.c_str()); setText(text.c_str());
} }
sg_format_exception::~sg_format_exception ()
{
}
const char* const char*
sg_format_exception::getText () const sg_format_exception::getText() const noexcept
{ {
return _text; return _text;
} }
void void sg_format_exception::setText(const char* text) noexcept
sg_format_exception::setText (const char* text)
{ {
if (text) { if (text) {
strncpy(_text, text, MAX_TEXT_LEN); strncpy(_text, text, MAX_TEXT_LEN);
@@ -328,26 +288,19 @@ sg_format_exception::setText (const char* text)
// Implementation of sg_range_exception. // Implementation of sg_range_exception.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
sg_range_exception::sg_range_exception () sg_range_exception::sg_range_exception(const char* message,
: sg_exception() const char* origin, bool report)
{ : sg_exception(message, origin, {}, report)
}
sg_range_exception::sg_range_exception (const char* message,
const char* origin)
: sg_exception(message, origin)
{ {
} }
sg_range_exception::sg_range_exception(const std::string& message, sg_range_exception::sg_range_exception(const std::string& message,
const std::string& origin) const std::string& origin,
: sg_exception(message, origin) bool report)
: sg_exception(message, origin, {}, report)
{ {
} }
sg_range_exception::~sg_range_exception ()
{
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
+63 -59
View File
@@ -28,23 +28,23 @@ class sg_location
{ {
public: public:
enum {max_path = 1024}; enum {max_path = 1024};
sg_location (); sg_location() noexcept;
sg_location(const std::string& path, int line = -1, int column = -1); sg_location(const std::string& path, int line = -1, int column = -1) noexcept;
sg_location(const SGPath& path, int line = -1, int column = -1); sg_location(const SGPath& path, int line = -1, int column = -1) noexcept;
explicit sg_location(const char* path, int line = -1, int column = -1); explicit sg_location(const char* path, int line = -1, int column = -1) noexcept;
~sg_location() = default; ~sg_location() = default;
const char *getPath() const; const char* getPath() const noexcept;
int getLine() const; int getLine() const noexcept;
int getColumn() const; int getColumn() const noexcept;
int getByte() const; int getByte() const noexcept;
std::string asString() const; std::string asString() const noexcept;
bool isValid() const; bool isValid() const noexcept;
private: private:
void setPath(const char *p); void setPath(const char* p) noexcept;
char _path[max_path]; char _path[max_path];
int _line; int _line;
@@ -60,20 +60,26 @@ class sg_throwable : public std::exception
{ {
public: public:
enum {MAX_TEXT_LEN = 1024}; enum {MAX_TEXT_LEN = 1024};
sg_throwable (); sg_throwable() noexcept;
sg_throwable(const char *message, const char *origin = 0, sg_throwable(const char* message, const char* origin = 0,
const sg_location &loc = {}); const sg_location& loc = {}, bool report = true) noexcept;
virtual ~sg_throwable (); virtual ~sg_throwable() noexcept = default;
virtual const char* getMessage () const;
virtual const std::string getFormattedMessage () const; virtual const char* getMessage() const noexcept;
virtual void setMessage (const char* message); std::string getFormattedMessage() const noexcept;
virtual const char* getOrigin () const; virtual void setMessage(const char* message) noexcept;
virtual void setOrigin (const char *origin); virtual const char* getOrigin() const noexcept;
virtual void setOrigin(const char* origin) noexcept;
virtual const char* what() const noexcept; virtual const char* what() const noexcept;
private:
sg_location getLocation() const noexcept;
void setLocation(const sg_location& location) noexcept;
private:
char _message[MAX_TEXT_LEN]; char _message[MAX_TEXT_LEN];
char _origin[MAX_TEXT_LEN]; char _origin[MAX_TEXT_LEN];
sg_location _location;
}; };
@@ -90,10 +96,10 @@ private:
class sg_error : public sg_throwable class sg_error : public sg_throwable
{ {
public: public:
sg_error (); sg_error() noexcept = default;
sg_error (const char* message, const char* origin = 0); sg_error(const char* message, const char* origin = 0, bool report = true) noexcept;
sg_error(const std::string &message, const std::string &origin = {}); sg_error(const std::string& message, const std::string& origin = {}, bool report = true) noexcept;
virtual ~sg_error (); virtual ~sg_error() noexcept = default;
}; };
@@ -114,12 +120,12 @@ public:
class sg_exception : public sg_throwable class sg_exception : public sg_throwable
{ {
public: public:
sg_exception (); sg_exception() noexcept = default;
sg_exception(const char *message, const char *origin = 0, sg_exception(const char* message, const char* origin = 0,
const sg_location &loc = {}); const sg_location& loc = {}, bool report = true) noexcept;
sg_exception(const std::string &message, const std::string & = {}, sg_exception(const std::string& message, const std::string& = {},
const sg_location &loc = {}); const sg_location& loc = {}, bool report = true) noexcept;
virtual ~sg_exception (); virtual ~sg_exception() noexcept = default;
}; };
@@ -137,20 +143,15 @@ public:
class sg_io_exception : public sg_exception class sg_io_exception : public sg_exception
{ {
public: public:
sg_io_exception (); sg_io_exception() noexcept = default;
sg_io_exception (const char* message, const char* origin = 0); sg_io_exception(const char* message, const char* origin = 0, bool report = true);
sg_io_exception (const char* message, const sg_location &location, sg_io_exception(const char* message, const sg_location& location,
const char* origin = 0); const char* origin = 0, bool report = true);
sg_io_exception (const std::string &message, const std::string &origin = ""); sg_io_exception(const std::string& message, const std::string& origin = {}, bool report = true);
sg_io_exception (const std::string &message, const sg_location &location, sg_io_exception(const std::string& message, const sg_location& location,
const std::string &origin = ""); const std::string& origin = {}, bool report = true);
virtual ~sg_io_exception (); virtual ~sg_io_exception() noexcept = default;
virtual const std::string getFormattedMessage () const;
virtual const sg_location &getLocation () const;
virtual void setLocation (const sg_location &location);
private:
sg_location _location;
}; };
@@ -168,14 +169,15 @@ private:
class sg_format_exception : public sg_exception class sg_format_exception : public sg_exception
{ {
public: public:
sg_format_exception (); sg_format_exception() noexcept;
sg_format_exception (const char* message, const char* text, sg_format_exception(const char* message, const char* text,
const char* origin = 0); const char* origin = 0, bool report = true);
sg_format_exception (const std::string& message, const std::string& text, sg_format_exception(const std::string& message, const std::string& text,
const std::string& origin = ""); const std::string& origin = {}, bool report = true);
virtual ~sg_format_exception ();
virtual const char* getText () const; const char* getText() const noexcept;
virtual void setText (const char* text); void setText(const char* text) noexcept;
private: private:
char _text[MAX_TEXT_LEN]; char _text[MAX_TEXT_LEN];
}; };
@@ -193,12 +195,14 @@ private:
class sg_range_exception : public sg_exception class sg_range_exception : public sg_exception
{ {
public: public:
sg_range_exception (); sg_range_exception() noexcept = default;
sg_range_exception (const char* message, sg_range_exception(const char* message,
const char* origin = 0); const char* origin = 0,
sg_range_exception (const std::string& message, bool report = true);
const std::string& origin = ""); sg_range_exception(const std::string& message,
virtual ~sg_range_exception (); const std::string& origin = {},
bool report = true);
virtual ~sg_range_exception() noexcept = default;
}; };
using ThrowCallback = std::function<void( using ThrowCallback = std::function<void(
+27 -9
View File
@@ -250,10 +250,15 @@ void
SGSubsystemGroup::init () SGSubsystemGroup::init ()
{ {
assert(_state == State::BIND); assert(_state == State::BIND);
forEach([this](SGSubsystem* s){ forEach([this](SGSubsystem* s) {
this->notifyWillChange(s, State::INIT); try {
s->init(); this->notifyWillChange(s, State::INIT);
this->notifyDidChange(s, State::INIT); s->init();
this->notifyDidChange(s, State::INIT);
} catch (std::exception& e) {
simgear::reportError("Caught exception init-ing subsystem " + s->subsystemId() + "\n\t" + e.what());
throw;
}
}); });
_state = State::INIT; _state = State::INIT;
} }
@@ -283,7 +288,15 @@ SGSubsystemGroup::incrementalInit()
const auto m = _members[_initPosition]; const auto m = _members[_initPosition];
SGTimeStamp st; SGTimeStamp st;
st.stamp(); st.stamp();
const InitStatus memberStatus = m->subsystem->incrementalInit(); InitStatus memberStatus;
try {
memberStatus = m->subsystem->incrementalInit();
} catch (std::exception& e) {
simgear::reportError("Caught exception init-ing subsystem " + m->subsystem->subsystemId() + "\n\t" + e.what());
throw;
}
m->initTime += st.elapsedMSec(); m->initTime += st.elapsedMSec();
if (memberStatus == INIT_DONE) { if (memberStatus == INIT_DONE) {
@@ -351,10 +364,15 @@ SGSubsystemGroup::shutdown ()
void void
SGSubsystemGroup::bind () SGSubsystemGroup::bind ()
{ {
forEach([this](SGSubsystem* s){ forEach([this](SGSubsystem* s) {
this->notifyWillChange(s, State::BIND); try {
s->bind(); this->notifyWillChange(s, State::BIND);
this->notifyDidChange(s, State::BIND); s->bind();
this->notifyDidChange(s, State::BIND);
} catch (std::exception& e) {
simgear::reportError("Caught exception binding subsystem " + s->subsystemId() + "\n\t" + e.what());
throw;
}
}); });
_state = State::BIND; _state = State::BIND;
} }
+35 -31
View File
@@ -244,40 +244,43 @@ readXML (istream &input, XMLVisitor &visitor, const string &path)
// FIXME: get proper error string from system // FIXME: get proper error string from system
if (!input.good()) { if (!input.good()) {
sg_io_exception ex ("Problem reading file", sg_io_exception ex("Problem reading file",
sg_location(path, sg_location(path,
XML_GetCurrentLineNumber(parser), XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser)), XML_GetCurrentColumnNumber(parser)),
"SimGear XML Parser"); "SimGear XML Parser",
visitor.setParser(0); false /* don't report */);
XML_ParserFree(parser); visitor.setParser(0);
throw ex; XML_ParserFree(parser);
throw ex;
} }
input.read(buf,16384); input.read(buf,16384);
if (!XML_Parse(parser, buf, input.gcount(), false)) { if (!XML_Parse(parser, buf, input.gcount(), false)) {
sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)), sg_io_exception ex(XML_ErrorString(XML_GetErrorCode(parser)),
sg_location(path, sg_location(path,
XML_GetCurrentLineNumber(parser), XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser)), XML_GetCurrentColumnNumber(parser)),
"SimGear XML Parser"); "SimGear XML Parser",
visitor.setParser(0); false /* don't report */);
XML_ParserFree(parser); visitor.setParser(0);
throw ex; XML_ParserFree(parser);
throw ex;
} }
} }
// Verify end of document. // Verify end of document.
if (!XML_Parse(parser, buf, 0, true)) { if (!XML_Parse(parser, buf, 0, true)) {
sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)), sg_io_exception ex(XML_ErrorString(XML_GetErrorCode(parser)),
sg_location(path, sg_location(path,
XML_GetCurrentLineNumber(parser), XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser)), XML_GetCurrentColumnNumber(parser)),
"SimGear XML Parser"); "SimGear XML Parser",
visitor.setParser(0); false /* don't report */);
XML_ParserFree(parser); visitor.setParser(0);
throw ex; XML_ParserFree(parser);
throw ex;
} }
visitor.setParser(0); visitor.setParser(0);
@@ -300,8 +303,8 @@ readXML (const SGPath &path, XMLVisitor &visitor)
throw; throw;
} }
} else { } else {
throw sg_io_exception("Failed to open file", sg_location(path), throw sg_io_exception("Failed to open file", sg_location(path),
"SimGear XML Parser"); "SimGear XML Parser", false /* don't report */);
} }
input.close(); input.close();
} }
@@ -318,11 +321,12 @@ readXML (const char *buf, const int size, XMLVisitor &visitor)
visitor.startXML(); visitor.startXML();
if (!XML_Parse(parser, buf, size, false)) { if (!XML_Parse(parser, buf, size, false)) {
sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)), sg_io_exception ex(XML_ErrorString(XML_GetErrorCode(parser)),
sg_location("In-memory XML buffer", sg_location("In-memory XML buffer",
XML_GetCurrentLineNumber(parser), XML_GetCurrentLineNumber(parser),
XML_GetCurrentColumnNumber(parser)), XML_GetCurrentColumnNumber(parser)),
"SimGear XML Parser"); "SimGear XML Parser",
false /* don't report */);
XML_ParserFree(parser); XML_ParserFree(parser);
throw ex; throw ex;
} }
+1 -1
View File
@@ -1 +1 @@
2020.3.7 2020.3.8