Use UTF8 paths in nearly all places, for OSG

We already request OSG to use UTF8 paths, so ensure whenever we pass
an SGPath to OSG, we use the correct conversion function.
This commit is contained in:
James Turner 2020-03-13 09:50:43 +00:00
parent f350bd31bd
commit f25c0c60a8
23 changed files with 75 additions and 50 deletions

View File

@ -31,7 +31,7 @@
// Constructor
SGEphemeris::SGEphemeris( const std::string &path ) {
SGEphemeris::SGEphemeris( const SGPath& path ) {
our_sun = new Star;
moon = new MoonPos;
mercury = new Mercury;
@ -44,7 +44,7 @@ SGEphemeris::SGEphemeris( const std::string &path ) {
nplanets = 7;
for ( int i = 0; i < nplanets; ++i )
planets[i] = SGVec3d::zeros();
stars = new SGStarData( SGPath(path) );
stars = new SGStarData(path);
}

View File

@ -97,7 +97,7 @@ public:
* calling the constructor you need to provide a path pointing to
* your star database file.
* @param path path to your star database */
SGEphemeris( const std::string &path );
SGEphemeris( const SGPath &path );
/** Destructor */
~SGEphemeris( void );

View File

@ -212,7 +212,7 @@ sg_ifstream::sg_ifstream(const SGPath& path, ios_openmode io_mode)
#if defined(SG_WINDOWS)
std::wstring ps = path.wstr();
#else
std::string ps = path.local8BitStr();
std::string ps = path.utf8Str();
#endif
std::ifstream::open(ps.c_str(), io_mode);
}
@ -222,7 +222,7 @@ void sg_ifstream::open( const SGPath& name, ios_openmode io_mode )
#if defined(SG_WINDOWS)
std::wstring ps = name.wstr();
#else
std::string ps = name.local8BitStr();
std::string ps = name.utf8Str();
#endif
std::ifstream::open(ps.c_str(), io_mode);
}
@ -232,7 +232,7 @@ sg_ofstream::sg_ofstream(const SGPath& path, ios_openmode io_mode)
#if defined(SG_WINDOWS)
std::wstring ps = path.wstr();
#else
std::string ps = path.local8BitStr();
std::string ps = path.utf8Str();
#endif
std::ofstream::open(ps.c_str(), io_mode);
}
@ -242,7 +242,7 @@ void sg_ofstream::open( const SGPath& name, ios_openmode io_mode )
#if defined(SG_WINDOWS)
std::wstring ps = name.wstr();
#else
std::string ps = name.local8BitStr();
std::string ps = name.utf8Str();
#endif
std::ofstream::open(ps.c_str(), io_mode);
}

7
simgear/misc/path_test.cxx Normal file → Executable file
View File

@ -333,6 +333,12 @@ void test_hash_function()
SG_CHECK_NE(std::hash<SGPath>{}(p), std::hash<SGPath>{}(p / "foobar"));
}
void test_null_path()
{
const SGPath nullPath;
SG_VERIFY(!nullPath.exists());
}
int main(int argc, char* argv[])
{
SGPath pa;
@ -441,6 +447,7 @@ int main(int argc, char* argv[])
test_update_dir();
test_comparisons();
test_hash_function();
test_null_path();
cout << "all tests passed OK" << endl;
return 0; // passed

View File

@ -115,7 +115,7 @@ Dir Dir::tempDir(const std::string& templ)
// Mac OS-X / BSD manual says any number of 'X's, but GLibc manual
// says exactly six, so that's what I'm going with
p.concat("-XXXXXX");
std::string s = p.local8BitStr();
std::string s = p.utf8Str();
::snprintf(buf, 1024, "%s", s.c_str());
if (!mkdtemp(buf)) {
SG_LOG(SG_IO, SG_WARN,
@ -206,7 +206,7 @@ PathList Dir::children(int types, const std::string& nameFilter) const
FindClose(find);
#else
std::string ps = _path.local8BitStr();
std::string ps = _path.utf8Str();
DIR* dp = opendir(ps.c_str());
if (!dp) {
SG_LOG(SG_GENERAL, SG_WARN, "Dir::children: opendir failed:" << _path);
@ -290,7 +290,7 @@ bool Dir::isEmpty() const
std::wstring ps = _path.wstr();
return PathIsDirectoryEmptyW( ps.c_str() );
#else
std::string ps = _path.local8BitStr();
std::string ps = _path.utf8Str();
DIR* dp = opendir( ps.c_str() );
if (!dp) return true;
@ -339,7 +339,7 @@ bool Dir::create(mode_t mode)
std::wstring ps = _path.wstr();
int err = _wmkdir(ps.c_str());
#else
std::string ps = _path.local8BitStr();
std::string ps = _path.utf8Str();
int err = mkdir(ps.c_str(), mode);
#endif
if (err) {
@ -394,7 +394,7 @@ bool Dir::remove(bool recursive)
std::wstring ps = _path.wstr();
int err = _wrmdir(ps.c_str());
#else
std::string ps = _path.local8BitStr();
std::string ps = _path.utf8Str();
int err = rmdir(ps.c_str());
#endif
if (err) {

View File

@ -786,8 +786,8 @@ bool SGPath::rename(const SGPath& newName)
std::wstring np = newName.wstr();
if (_wrename(p.c_str(), np.c_str()) != 0)
#else
std::string p = local8BitStr();
std::string np = newName.local8BitStr();
std::string p = utf8Str();
std::string np = newName.utf8Str();
if( ::rename(p.c_str(), np.c_str()) != 0 )
#endif

View File

@ -149,7 +149,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
SGPath tpath("Textures");
tpath.append(tname);
std::string fullTexPath = SGModelLib::findDataFile(tpath.local8BitStr(), options);
std::string fullTexPath = SGModelLib::findDataFile(tpath, options);
if (fullTexPath.empty()) {
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \""
<< tname << "\" in Textures folders.");
@ -181,7 +181,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
SGPath tpath("Textures");
tpath.append(tname);
std::string fullTexPath = SGModelLib::findDataFile(tpath.local8BitStr(), options);
std::string fullTexPath = SGModelLib::findDataFile(tpath, options);
if (fullTexPath.empty()) {
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \""
<< tname << "\" in Textures folders.");
@ -207,7 +207,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
SGPath tpath("Textures");
tpath.append("Terrain");
tpath.append("unknown.rgb");
_internal_state st( NULL, tpath.local8BitStr(), true, options );
_internal_state st( NULL, tpath.utf8Str(), true, options );
_status.push_back( st );
}
@ -219,7 +219,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
if (! omname.empty()) {
SGPath ompath("Textures");
ompath.append(omname);
std::string fullMaskPath = SGModelLib::findDataFile(ompath.local8BitStr(), options);
std::string fullMaskPath = SGModelLib::findDataFile(ompath, options);
if (fullMaskPath.empty()) {
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \""
@ -358,7 +358,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
if (! treeTexPath.empty()) {
SGPath treePath("Textures");
treePath.append(treeTexPath);
tree_texture = SGModelLib::findDataFile(treePath.local8BitStr(), options);
tree_texture = SGModelLib::findDataFile(treePath, options);
if (tree_texture.empty()) {
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \""

View File

@ -65,7 +65,7 @@ SGMaterialLib::SGMaterialLib ( void ) :
}
// Load a library of material properties
bool SGMaterialLib::load( const string &fg_root, const string& mpath,
bool SGMaterialLib::load( const SGPath &fg_root, const SGPath& mpath,
SGPropertyNode *prop_root )
{
SGPropertyNode materialblocks;
@ -81,7 +81,7 @@ bool SGMaterialLib::load( const string &fg_root, const string& mpath,
osg::ref_ptr<osgDB::Options> options
= new osgDB::Options;
options->setObjectCacheHint(osgDB::Options::CACHE_ALL);
options->setDatabasePath(fg_root);
options->setDatabasePath(fg_root.utf8Str());
simgear::PropertyList blocks = materialblocks.getChildren("region");
simgear::PropertyList::const_iterator block_iter = blocks.begin();

View File

@ -38,6 +38,7 @@
class SGMaterial;
class SGPropertyNode;
class SGPath;
namespace simgear { class Effect; }
namespace osg { class Geode; }
@ -87,7 +88,7 @@ public:
SGMaterialLib ( void );
// Load a library of material properties
bool load( const std::string &fg_root, const std::string& mpath,
bool load( const SGPath &fg_root, const SGPath& mpath,
SGPropertyNode *prop_root );
// find a material record by material name
SGMaterial *find( const std::string& material, SGVec2f center ) const;

View File

@ -338,12 +338,12 @@ sgLoad3DModel_internal(const SGPath& path,
if (!texturepath.extension().empty())
texturepath = texturepath.dir();
options->setDatabasePath(texturepath.local8BitStr());
options->setDatabasePath(texturepath.utf8Str());
osgDB::ReaderWriter::ReadResult modelResult;
#if OSG_VERSION_LESS_THAN(3,4,1)
modelResult = osgDB::readNodeFile(modelpath.local8BitStr(), options.get());
modelResult = osgDB::readNodeFile(modelpath.utf8Str(), options.get());
#else
modelResult = osgDB::readRefNodeFile(modelpath.local8BitStr(), options.get());
modelResult = osgDB::readRefNodeFile(modelpath.utf8Str(), options.get());
#endif
if (!modelResult.validNode())
throw sg_io_exception("Failed to load 3D model:" + modelResult.message(),
@ -503,7 +503,7 @@ sgLoad3DModel_internal(const SGPath& path,
if (!texturepath.extension().empty())
texturepath = texturepath.dir();
options2->setDatabasePath(texturepath.local8BitStr());
options2->setDatabasePath(texturepath.utf8Str());
}
group->addChild(Particles::appendParticles(particle_nodes[i],
prop_root,
@ -544,7 +544,7 @@ sgLoad3DModel_internal(const SGPath& path,
group = static_cast<Group*>(modelWithEffects.get());
}
simgear::SGTransientModelData modelData(group.get(), prop_root, options.get(), path.local8BitStr());
simgear::SGTransientModelData modelData(group.get(), prop_root, options.get(), path.utf8Str());
for (unsigned i = 0; i < animation_nodes.size(); ++i) {
if (previewMode && animation_nodes[i]->hasChild("nopreview")) {

View File

@ -97,7 +97,7 @@ osg::Node * SGText::appendText(const SGPropertyNode* configNode,
SGPath path("Fonts" );
path.append( configNode->getStringValue( "font", "Helvetica" ));
text->setFont( path.local8BitStr() );
text->setFont( path.utf8Str() );
text->setCharacterSize(configNode->getDoubleValue("character-size", 1.0 ),
configNode->getDoubleValue("character-aspect-ratio", 1.0 ));

View File

@ -47,7 +47,7 @@ SGLoadTexture2D(const SGPath& path,
bool wrapu = true, bool wrapv = true,
int mipmaplevels = -1)
{
return SGLoadTexture2D(true, path.local8BitStr(), options, wrapu, wrapv,
return SGLoadTexture2D(true, path.utf8Str(), options, wrapu, wrapv,
mipmaplevels);
}
@ -57,7 +57,7 @@ SGLoadTexture2D(bool staticTexture, const SGPath& path,
bool wrapu = true, bool wrapv = true,
int mipmaplevels = -1)
{
return SGLoadTexture2D(staticTexture, path.local8BitStr(), options, wrapu, wrapv,
return SGLoadTexture2D(staticTexture, path.utf8Str(), options, wrapu, wrapv,
mipmaplevels);
}

View File

@ -77,13 +77,27 @@ std::string SGModelLib::findDataFile(const std::string& file,
return file;
SGPath p = ResourceManager::instance()->findPath(file, currentPath);
if (p.exists()) {
return p.local8BitStr();
return p.utf8Str();
}
// finally hand on to standard OSG behaviour
return osgDB::findDataFile(file, opts);
}
std::string SGModelLib::findDataFile(const SGPath& file,
const osgDB::Options* opts,
SGPath currentPath)
{
SGPath p = ResourceManager::instance()->findPath(file.utf8Str(), currentPath);
if (p.exists()) {
return p.utf8Str();
}
// finally hand on to standard OSG behaviour
return osgDB::findDataFile(file.utf8Str(), opts);
}
SGModelLib::SGModelLib()
{
}

View File

@ -85,7 +85,11 @@ public:
SGModelData *data=0);
static std::string findDataFile(const std::string& file,
const osgDB::Options* opts = NULL,
const osgDB::Options* opts = nullptr,
SGPath currentDir = SGPath());
static std::string findDataFile(const SGPath& file,
const osgDB::Options* opts = nullptr,
SGPath currentDir = SGPath());
protected:
SGModelLib();

View File

@ -78,7 +78,7 @@ SGMakeState(const SGPath &path, const char* colorTexture,
osg::StateSet *stateSet = new osg::StateSet;
osg::ref_ptr<SGReaderWriterOptions> options;
options = SGReaderWriterOptions::fromPath(path.local8BitStr());
options = SGReaderWriterOptions::fromPath(path);
stateSet->setTextureAttribute(0, SGLoadTexture2D(colorTexture,
options.get()));
stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);

View File

@ -76,7 +76,7 @@ SGMoon::build( SGPath path, double moon_size ) {
// set up the orb state
osg::ref_ptr<SGReaderWriterOptions> options;
options = SGReaderWriterOptions::fromPath(path.local8BitStr());
options = SGReaderWriterOptions::fromPath(path);
osg::Texture2D* texture = SGLoadTexture2D("moon.png", options.get());
stateSet->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);

View File

@ -118,7 +118,7 @@ SGNewCloud::SGNewCloud(const SGPath &texture_root, const SGPropertyNode *cld_def
"image"),
texture);
ref_ptr<SGReaderWriterOptions> options;
options = SGReaderWriterOptions::fromPath(texture_root.local8BitStr());
options = SGReaderWriterOptions::fromPath(texture_root);
effect = makeEffect(pcloudEffect, true, options.get());
if (effect.valid())
{

View File

@ -70,7 +70,7 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
env_node = property_tree_Node;
osg::ref_ptr<SGReaderWriterOptions> options;
options = SGReaderWriterOptions::fromPath(path.local8BitStr());
options = SGReaderWriterOptions::fromPath(path);
// build the ssg scene graph sub tree for the sky and connected
// into the provide scene graph branch
sun_transform = new osg::MatrixTransform;

View File

@ -276,7 +276,7 @@ struct ReaderWriterSTG::_ModelBin {
SGPath path = filePath;
path.append(".."); path.append(".."); path.append("..");
sharedOptions->getDatabasePathList().push_back(path.local8BitStr());
sharedOptions->getDatabasePathList().push_back(path.utf8Str());
// ensure Models directory synced via TerraSync is searched before the copy in
// FG_ROOT, so that updated models can be used.
@ -372,7 +372,7 @@ struct ReaderWriterSTG::_ModelBin {
SG_LOG(SG_TERRAIN, SG_INFO, "Loading stg file " << absoluteFileName);
std::string filePath = osgDB::getFilePath(absoluteFileName.local8BitStr());
std::string filePath = osgDB::getFilePath(absoluteFileName.utf8Str());
// Bucket provides a consistent seed
// so we have consistent set of pseudo-random numbers for each STG file
@ -420,7 +420,7 @@ struct ReaderWriterSTG::_ModelBin {
_Object obj;
obj._errorLocation = absoluteFileName;
obj._token = token;
obj._name = path.local8BitStr();
obj._name = path.utf8Str();
obj._options = staticOptions(filePath, options);
_objectList.push_back(obj);
}
@ -430,7 +430,7 @@ struct ReaderWriterSTG::_ModelBin {
_Object obj;
obj._errorLocation = absoluteFileName;
obj._token = token;
obj._name = path.local8BitStr();
obj._name = path.utf8Str();
obj._options = staticOptions(filePath, options);
_objectList.push_back(obj);
}
@ -537,7 +537,7 @@ struct ReaderWriterSTG::_ModelBin {
_objectStaticList.push_back(obj);
} else if (token == BUILDING_LIST) {
_BuildingList buildinglist;
buildinglist._filename = path.local8BitStr();
buildinglist._filename = path.utf8Str();
in >> buildinglist._material_name >> buildinglist._lon >> buildinglist._lat >> buildinglist._elev;
checkInsideBucket(absoluteFileName, buildinglist._lon, buildinglist._lat);
_buildingListList.push_back(buildinglist);

View File

@ -47,10 +47,10 @@ SGReaderWriterOptions::copyOrCreate(const osgDB::Options* options)
}
SGReaderWriterOptions*
SGReaderWriterOptions::fromPath(const std::string& path)
SGReaderWriterOptions::fromPath(const SGPath& path)
{
SGReaderWriterOptions* options = copyOrCreate(0);
options->setDatabasePath(path);
SGReaderWriterOptions* options = copyOrCreate(nullptr);
options->setDatabasePath(path.utf8Str());
return options;
}

View File

@ -31,6 +31,8 @@
#endif
class SGPropertyNode;
class SGPath;
typedef std::vector < std::string > string_list;
namespace simgear
@ -50,7 +52,6 @@ public:
SGReaderWriterOptions() :
_materialLib(0),
_load_panel(0),
_model_data(0),
_instantiateEffects(false),
_instantiateMaterialEffects(false),
_LoadOriginHint(ORIGIN_MODEL)
@ -59,7 +60,6 @@ public:
osgDB::Options(str),
_materialLib(0),
_load_panel(0),
_model_data(0),
_instantiateEffects(false),
_instantiateMaterialEffects(false),
_LoadOriginHint(ORIGIN_MODEL)
@ -69,7 +69,6 @@ public:
osgDB::Options(options, copyop),
_materialLib(0),
_load_panel(0),
_model_data(0),
_instantiateEffects(false),
_instantiateMaterialEffects(false),
_LoadOriginHint(ORIGIN_MODEL)
@ -144,7 +143,7 @@ public:
{ _sceneryPathSuffixes = suffixes; }
static SGReaderWriterOptions* copyOrCreate(const osgDB::Options* options);
static SGReaderWriterOptions* fromPath(const std::string& path);
static SGReaderWriterOptions* fromPath(const SGPath& path);
void setLocation(double lon, double lat)
{ _geod = SGGeod::fromDeg(lon, lat); }

View File

@ -222,7 +222,7 @@ void SGTime::update( const SGGeod& location, time_t ct, long int warp )
// Given lon/lat, update timezone information and local_offset
void SGTime::updateLocal( const SGGeod& aLocation, const string& root ) {
void SGTime::updateLocal( const SGGeod& aLocation, const SGPath& root ) {
SGGeod location(aLocation);
if (!aLocation.isValid()) {
location = SGGeod();

View File

@ -162,7 +162,7 @@ public:
* @param location Current geodetic location
* @param root Bbase path containing time zone directory
*/
void updateLocal( const SGGeod& location, const std::string& root );
void updateLocal( const SGGeod& location, const SGPath& root );
/** @return current system/unix time in seconds */
inline time_t get_cur_time() const { return cur_time; };