From 4a38917e08a83314ca9d2cb8af3c0562acd29fb2 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Tue, 30 Jul 2019 10:27:31 +0300 Subject: [PATCH] Split parser.* into hash.*, value.* and parser.* --- src/celengine/CMakeLists.txt | 4 + src/celengine/asterism.cpp | 1 + src/celengine/dsodb.cpp | 1 + src/celengine/hash.cpp | 660 +++++++++++++++++++++++++ src/celengine/hash.h | 84 ++++ src/celengine/meshmanager.cpp | 1 + src/celengine/parser.cpp | 760 +---------------------------- src/celengine/parser.h | 118 +---- src/celengine/solarsys.cpp | 1 + src/celengine/stardb.cpp | 1 + src/celengine/value.cpp | 36 ++ src/celengine/value.h | 112 +++++ src/celengine/virtualtex.cpp | 1 + src/celestia/configfile.cpp | 1 + src/celestia/destination.cpp | 1 + src/celestia/favorites.cpp | 1 + src/celscript/legacy/cmdparser.cpp | 1 + 17 files changed, 920 insertions(+), 864 deletions(-) create mode 100644 src/celengine/hash.cpp create mode 100644 src/celengine/hash.h create mode 100644 src/celengine/value.cpp create mode 100644 src/celengine/value.h diff --git a/src/celengine/CMakeLists.txt b/src/celengine/CMakeLists.txt index 31d95f79a..e65d88ba1 100644 --- a/src/celengine/CMakeLists.txt +++ b/src/celengine/CMakeLists.txt @@ -51,6 +51,8 @@ set(CELENGINE_SOURCES globular.h glshader.cpp glshader.h + hash.cpp + hash.h #hdrfuncrender.cpp image.cpp image.h @@ -152,6 +154,8 @@ set(CELENGINE_SOURCES univcoord.h universe.cpp universe.h + value.cpp + value.h vecgl.h vertexobject.cpp vertexobject.h diff --git a/src/celengine/asterism.cpp b/src/celengine/asterism.cpp index 3b69ba361..89e3fbf24 100644 --- a/src/celengine/asterism.cpp +++ b/src/celengine/asterism.cpp @@ -14,6 +14,7 @@ #include "stardb.h" #include "asterism.h" #include "parser.h" +#include "tokenizer.h" using namespace std; diff --git a/src/celengine/dsodb.cpp b/src/celengine/dsodb.cpp index b0f68e771..cfeb466e9 100644 --- a/src/celengine/dsodb.cpp +++ b/src/celengine/dsodb.cpp @@ -26,6 +26,7 @@ #include "parseobject.h" #include "multitexture.h" #include "meshmanager.h" +#include "tokenizer.h" #include #include diff --git a/src/celengine/hash.cpp b/src/celengine/hash.cpp new file mode 100644 index 000000000..6cabab541 --- /dev/null +++ b/src/celengine/hash.cpp @@ -0,0 +1,660 @@ +// hash.cpp +// +// Copyright (C) 2001-2019, the Celestia Development Team +// Original version by Chris Laurel +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +#include +#include +#include +#include +#include "astro.h" +#include "hash.h" +#include "value.h" + +using namespace Eigen; +using namespace std; +using namespace celmath; + + +AssociativeArray::~AssociativeArray() +{ + for (const auto &iter : assoc) + delete iter.second; +} + + +Value* AssociativeArray::getValue(const string& key) const +{ + map::const_iterator iter = assoc.find(key); + if (iter == assoc.end()) + return nullptr; + + return iter->second; +} + + +void AssociativeArray::addValue(const string& key, Value& val) +{ + assoc.insert(map::value_type(key, &val)); +} + + +bool AssociativeArray::getNumber(const string& key, double& val) const +{ + Value* v = getValue(key); + if (v == nullptr || v->getType() != Value::NumberType) + return false; + + val = v->getNumber(); + return true; +} + + +bool AssociativeArray::getNumber(const string& key, float& val) const +{ + double dval; + + if (!getNumber(key, dval)) + return false; + + val = (float) dval; + return true; +} + + +bool AssociativeArray::getNumber(const string& key, int& val) const +{ + double ival; + + if (!getNumber(key, ival)) + return false; + + val = (int) ival; + return true; +} + + +bool AssociativeArray::getNumber(const string& key, uint32_t& val) const +{ + double ival; + + if (!getNumber(key, ival)) + return false; + + val = (uint32_t) ival; + return true; +} + + +bool AssociativeArray::getString(const string& key, string& val) const +{ + Value* v = getValue(key); + if (v == nullptr || v->getType() != Value::StringType) + return false; + + val = v->getString(); + return true; +} + + +bool AssociativeArray::getPath(const string& key, fs::path& val) const +{ + string v; + if (getString(key, v)) + { + val = PathExp(v); + return true; + } + return false; +} + + +bool AssociativeArray::getBoolean(const string& key, bool& val) const +{ + Value* v = getValue(key); + if (v == nullptr || v->getType() != Value::BooleanType) + return false; + + val = v->getBoolean(); + return true; +} + + +bool AssociativeArray::getVector(const string& key, Vector3d& val) const +{ + Value* v = getValue(key); + if (v == nullptr || v->getType() != Value::ArrayType) + return false; + + ValueArray* arr = v->getArray(); + if (arr->size() != 3) + return false; + + Value* x = (*arr)[0]; + Value* y = (*arr)[1]; + Value* z = (*arr)[2]; + + if (x->getType() != Value::NumberType || + y->getType() != Value::NumberType || + z->getType() != Value::NumberType) + return false; + + val = Vector3d(x->getNumber(), y->getNumber(), z->getNumber()); + return true; +} + + +bool AssociativeArray::getVector(const string& key, Vector3f& val) const +{ + Vector3d vecVal; + + if (!getVector(key, vecVal)) + return false; + + val = vecVal.cast(); + return true; +} + + +bool AssociativeArray::getVector(const string& key, Vector4d& val) const +{ + Value* v = getValue(key); + if (v == nullptr || v->getType() != Value::ArrayType) + return false; + + ValueArray* arr = v->getArray(); + if (arr->size() != 4) + return false; + + Value* x = (*arr)[0]; + Value* y = (*arr)[1]; + Value* z = (*arr)[2]; + Value* w = (*arr)[3]; + + if (x->getType() != Value::NumberType || + y->getType() != Value::NumberType || + z->getType() != Value::NumberType || + w->getType() != Value::NumberType) + return false; + + val = Vector4d(x->getNumber(), y->getNumber(), z->getNumber(), w->getNumber()); + return true; +} + + +bool AssociativeArray::getVector(const string& key, Vector4f& val) const +{ + Vector4d vecVal; + + if (!getVector(key, vecVal)) + return false; + + val = vecVal.cast(); + return true; +} + + +/** + * Retrieves a quaternion, scaled to an associated angle unit. + * + * The quaternion is specified in the catalog file in axis-angle format as follows: + * \verbatim {PropertyName} [ angle axisX axisY axisZ ] \endverbatim + * + * @param[in] key Hash key for the rotation. + * @param[out] val A quaternion representing the value if present, unaffected if not. + * @return True if the key exists in the hash, false otherwise. + */ +bool AssociativeArray::getRotation(const string& key, Eigen::Quaternionf& val) const +{ + Value* v = getValue(key); + if (v == nullptr || v->getType() != Value::ArrayType) + return false; + + ValueArray* arr = v->getArray(); + if (arr->size() != 4) + return false; + + Value* w = (*arr)[0]; + Value* x = (*arr)[1]; + Value* y = (*arr)[2]; + Value* z = (*arr)[3]; + + if (w->getType() != Value::NumberType || + x->getType() != Value::NumberType || + y->getType() != Value::NumberType || + z->getType() != Value::NumberType) + return false; + + Vector3f axis((float) x->getNumber(), + (float) y->getNumber(), + (float) z->getNumber()); + + double ang = w->getNumber(); + double angScale = 1.0; + getAngleScale(key, angScale); + float angle = degToRad((float) (ang * angScale)); + + val = Quaternionf(AngleAxisf(angle, axis.normalized())); + + return true; +} + + +bool AssociativeArray::getColor(const string& key, Color& val) const +{ + Vector4d vec4; + if (getVector(key, vec4)) + { + Vector4f vec4f = vec4.cast(); + val = Color(vec4f); + return true; + } + + Vector3d vec3; + if (getVector(key, vec3)) + { + Vector3f vec3f = vec3.cast(); + val = Color(vec3f); + return true; + } + + string rgba; + if (getString(key, rgba)) + { + int r, g, b, a; + int ret = sscanf(rgba.c_str(), "#%2x%2x%2x%2x", &r, &g, &b, &a); + switch (ret) + { + case 3: + a = 0xFF; + case 4: + val = Color((char unsigned)r, (char unsigned)g, (unsigned char)b, (unsigned char)a); + return true; + default: + return false; + } + } + + return false; +} + + +/** + * Retrieves a numeric quantity scaled to an associated angle unit. + * @param[in] key Hash key for the quantity. + * @param[out] val The returned quantity if present, unaffected if not. + * @param[in] outputScale Returned value is scaled to this value. + * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. + * @return True if the key exists in the hash, false otherwise. + */ +bool +AssociativeArray::getAngle(const string& key, double& val, double outputScale, double defaultScale) const +{ + if (!getNumber(key, val)) + return false; + + double angleScale; + if(getAngleScale(key, angleScale)) + { + angleScale /= outputScale; + } + else + { + angleScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; + } + + val *= angleScale; + + return true; +} + + +/** @copydoc AssociativeArray::getAngle() */ +bool +AssociativeArray::getAngle(const string& key, float& val, double outputScale, double defaultScale) const +{ + double dval; + + if (!getAngle(key, dval, outputScale, defaultScale)) + return false; + + val = ((float) dval); + + return true; +} + + +/** + * Retrieves a numeric quantity scaled to an associated length unit. + * @param[in] key Hash key for the quantity. + * @param[out] val The returned quantity if present, unaffected if not. + * @param[in] outputScale Returned value is scaled to this value. + * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. + * @return True if the key exists in the hash, false otherwise. + */ +bool +AssociativeArray::getLength(const string& key, double& val, double outputScale, double defaultScale) const +{ + if(!getNumber(key, val)) + return false; + + double lengthScale; + if(getLengthScale(key, lengthScale)) + { + lengthScale /= outputScale; + } + else + { + lengthScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; + } + + val *= lengthScale; + + return true; +} + + +/** @copydoc AssociativeArray::getLength() */ +bool AssociativeArray::getLength(const string& key, float& val, double outputScale, double defaultScale) const +{ + double dval; + + if (!getLength(key, dval, outputScale, defaultScale)) + return false; + + val = ((float) dval); + + return true; +} + + +/** + * Retrieves a numeric quantity scaled to an associated time unit. + * @param[in] key Hash key for the quantity. + * @param[out] val The returned quantity if present, unaffected if not. + * @param[in] outputScale Returned value is scaled to this value. + * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. + * @return True if the key exists in the hash, false otherwise. + */ +bool AssociativeArray::getTime(const string& key, double& val, double outputScale, double defaultScale) const +{ + if(!getNumber(key, val)) + return false; + + double timeScale; + if(getTimeScale(key, timeScale)) + { + timeScale /= outputScale; + } + else + { + timeScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; + } + + val *= timeScale; + + return true; +} + + +/** @copydoc AssociativeArray::getTime() */ +bool AssociativeArray::getTime(const string& key, float& val, double outputScale, double defaultScale) const +{ + double dval; + + if(!getTime(key, dval, outputScale, defaultScale)) + return false; + + val = ((float) dval); + + return true; +} + + +/** + * Retrieves a numeric quantity scaled to an associated mass unit. + * @param[in] key Hash key for the quantity. + * @param[out] val The returned quantity if present, unaffected if not. + * @param[in] outputScale Returned value is scaled to this value. + * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. + * @return True if the key exists in the hash, false otherwise. + */ +bool AssociativeArray::getMass(const string& key, double& val, double outputScale, double defaultScale) const +{ + if(!getNumber(key, val)) + return false; + + double massScale; + if(getMassScale(key, massScale)) + { + massScale /= outputScale; + } + else + { + massScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; + } + + val *= massScale; + + return true; +} + + +/** @copydoc AssociativeArray::getMass() */ +bool AssociativeArray::getMass(const string& key, float& val, double outputScale, double defaultScale) const +{ + double dval; + + if(!getMass(key, dval, outputScale, defaultScale)) + return false; + + val = ((float) dval); + + return true; +} + + +/** + * Retrieves a vector quantity scaled to an associated length unit. + * @param[in] key Hash key for the quantity. + * @param[out] val The returned vector if present, unaffected if not. + * @param[in] outputScale Returned value is scaled to this value. + * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. + * @return True if the key exists in the hash, false otherwise. + */ +bool AssociativeArray::getLengthVector(const string& key, Eigen::Vector3d& val, double outputScale, double defaultScale) const +{ + if(!getVector(key, val)) + return false; + + double lengthScale; + if(getLengthScale(key, lengthScale)) + { + lengthScale /= outputScale; + } + else + { + lengthScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; + } + + val *= lengthScale; + + return true; +} + + +/** @copydoc AssociativeArray::getLengthVector() */ +bool AssociativeArray::getLengthVector(const string& key, Eigen::Vector3f& val, double outputScale, double defaultScale) const +{ + Vector3d vecVal; + + if(!getLengthVector(key, vecVal, outputScale, defaultScale)) + return false; + + val = vecVal.cast(); + return true; +} + + +/** + * Retrieves a spherical tuple \verbatim [longitude, latitude, altitude] \endverbatim scaled to associated angle and length units. + * @param[in] key Hash key for the quantity. + * @param[out] val The returned tuple in units of degrees and kilometers if present, unaffected if not. + * @return True if the key exists in the hash, false otherwise. + */ +bool AssociativeArray::getSphericalTuple(const string& key, Vector3d& val) const +{ + if(!getVector(key, val)) + return false; + + double angleScale; + if(getAngleScale(key, angleScale)) + { + val[0] *= angleScale; + val[1] *= angleScale; + } + + double lengthScale = 1.0; + getLengthScale(key, lengthScale); + val[2] *= lengthScale; + + return true; +} + + +/** @copydoc AssociativeArray::getSphericalTuple */ +bool AssociativeArray::getSphericalTuple(const string& key, Vector3f& val) const +{ + Vector3d vecVal; + + if(!getSphericalTuple(key, vecVal)) + return false; + + val = vecVal.cast(); + return true; +} + + +/** + * Retrieves the angle unit associated with a given property. + * @param[in] key Hash key for the property. + * @param[out] scale The returned angle unit scaled to degrees if present, unaffected if not. + * @return True if an angle unit has been specified for the property, false otherwise. + */ +bool AssociativeArray::getAngleScale(const string& key, double& scale) const +{ + string unitKey(key + "%Angle"); + string unit; + + if (!getString(unitKey, unit)) + return false; + + return astro::getAngleScale(unit, scale); +} + + +/** @copydoc AssociativeArray::getAngleScale() */ +bool AssociativeArray::getAngleScale(const string& key, float& scale) const +{ + double dscale; + if (!getAngleScale(key, dscale)) + return false; + + scale = ((float) dscale); + return true; +} + + +/** + * Retrieves the length unit associated with a given property. + * @param[in] key Hash key for the property. + * @param[out] scale The returned length unit scaled to kilometers if present, unaffected if not. + * @return True if a length unit has been specified for the property, false otherwise. + */ +bool AssociativeArray::getLengthScale(const string& key, double& scale) const +{ + string unitKey(key + "%Length"); + string unit; + + if (!getString(unitKey, unit)) + return false; + + return astro::getLengthScale(unit, scale); +} + + +/** @copydoc AssociativeArray::getLengthScale() */ +bool AssociativeArray::getLengthScale(const string& key, float& scale) const +{ + double dscale; + if (!getLengthScale(key, dscale)) + return false; + + scale = ((float) dscale); + return true; +} + + +/** + * Retrieves the time unit associated with a given property. + * @param[in] key Hash key for the property. + * @param[out] scale The returned time unit scaled to days if present, unaffected if not. + * @return True if a time unit has been specified for the property, false otherwise. + */ +bool AssociativeArray::getTimeScale(const string& key, double& scale) const +{ + string unitKey(key + "%Time"); + string unit; + + if (!getString(unitKey, unit)) + return false; + + return astro::getTimeScale(unit, scale); +} + + +/** @copydoc AssociativeArray::getTimeScale() */ +bool AssociativeArray::getTimeScale(const string& key, float& scale) const +{ + double dscale; + if (!getTimeScale(key, dscale)) + return false; + + scale = ((float) dscale); + return true; +} + + +/** + * Retrieves the mass unit associated with a given property. + * @param[in] key Hash key for the property. + * @param[out] scale The returned mass unit scaled to Earth mass if present, unaffected if not. + * @return True if a mass unit has been specified for the property, false otherwise. + */ +bool AssociativeArray::getMassScale(const string& key, double& scale) const +{ + string unitKey(key + "%Mass"); + string unit; + + if (!getString(unitKey, unit)) + return false; + + return astro::getMassScale(unit, scale); +} + + +/** @copydoc AssociativeArray::getMassScale() */ +bool AssociativeArray::getMassScale(const string& key, float& scale) const +{ + double dscale; + if (!getMassScale(key, dscale)) + return false; + + scale = ((float) dscale); + return true; +} diff --git a/src/celengine/hash.h b/src/celengine/hash.h new file mode 100644 index 000000000..6afca60e2 --- /dev/null +++ b/src/celengine/hash.h @@ -0,0 +1,84 @@ +// hash.h +// +// Copyright (C) 2001-2019, the Celestia Development Team +// Original version by Chris Laurel +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +#pragma once + +#include +#include +#include +#include + + +class Color; +class Value; + +using HashIterator = std::map::const_iterator; + +class AssociativeArray +{ + public: + AssociativeArray() = default; + ~AssociativeArray(); + AssociativeArray(AssociativeArray&&) = default; + AssociativeArray(const AssociativeArray&) = delete; + AssociativeArray& operator=(AssociativeArray&&) = default; + AssociativeArray& operator=(AssociativeArray&) = delete; + + Value* getValue(const std::string&) const; + void addValue(const std::string&, Value&); + + bool getNumber(const std::string&, double&) const; + bool getNumber(const std::string&, float&) const; + bool getNumber(const std::string&, int&) const; + bool getNumber(const std::string&, uint32_t&) const; + bool getString(const std::string&, std::string&) const; + bool getPath(const std::string&, fs::path&) const; + bool getBoolean(const std::string&, bool&) const; + bool getVector(const std::string&, Eigen::Vector3d&) const; + bool getVector(const std::string&, Eigen::Vector3f&) const; + bool getVector(const std::string&, Eigen::Vector4d&) const; + bool getVector(const std::string&, Eigen::Vector4f&) const; + bool getRotation(const std::string&, Eigen::Quaternionf&) const; + bool getColor(const std::string&, Color&) const; + bool getAngle(const std::string&, double&, double = 1.0, double = 0.0) const; + bool getAngle(const std::string&, float&, double = 1.0, double = 0.0) const; + bool getLength(const std::string&, double&, double = 1.0, double = 0.0) const; + bool getLength(const std::string&, float&, double = 1.0, double = 0.0) const; + bool getTime(const std::string&, double&, double = 1.0, double = 0.0) const; + bool getTime(const std::string&, float&, double = 1.0, double = 0.0) const; + bool getMass(const std::string&, double&, double = 1.0, double = 0.0) const; + bool getMass(const std::string&, float&, double = 1.0, double = 0.0) const; + bool getLengthVector(const std::string&, Eigen::Vector3d&, double = 1.0, double = 0.0) const; + bool getLengthVector(const std::string&, Eigen::Vector3f&, double = 1.0, double = 0.0) const; + bool getSphericalTuple(const std::string&, Eigen::Vector3d&) const; + bool getSphericalTuple(const std::string&, Eigen::Vector3f&) const; + bool getAngleScale(const std::string&, double&) const; + bool getAngleScale(const std::string&, float&) const; + bool getLengthScale(const std::string&, double&) const; + bool getLengthScale(const std::string&, float&) const; + bool getTimeScale(const std::string&, double&) const; + bool getTimeScale(const std::string&, float&) const; + bool getMassScale(const std::string&, double&) const; + bool getMassScale(const std::string&, float&) const; + + HashIterator begin() const + { + return assoc.begin(); + } + HashIterator end() const + { + return assoc.end(); + } + + private: + std::map assoc; +}; + +using Hash = AssociativeArray; diff --git a/src/celengine/meshmanager.cpp b/src/celengine/meshmanager.cpp index 7e9158d44..3ea2a11ef 100644 --- a/src/celengine/meshmanager.cpp +++ b/src/celengine/meshmanager.cpp @@ -21,6 +21,7 @@ #include "texmanager.h" #include "meshmanager.h" #include "modelgeometry.h" +#include "tokenizer.h" #include #include diff --git a/src/celengine/parser.cpp b/src/celengine/parser.cpp index 57c732a52..ea6646ad9 100644 --- a/src/celengine/parser.cpp +++ b/src/celengine/parser.cpp @@ -1,6 +1,6 @@ // parser.cpp // -// Copyright (C) 2001-2009, the Celestia Development Team +// Copyright (C) 2001-2019, the Celestia Development Team // Original version by Chris Laurel // // This program is free software; you can redistribute it and/or @@ -8,114 +8,15 @@ // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. -#include "parser.h" #include "astro.h" -#include +#include "parser.h" +#include "tokenizer.h" +#include "value.h" using namespace Eigen; using namespace celmath; -/****** Value method implementations *******/ - -Value::Value(double d) -{ - type = NumberType; - data.d = d; -} - -Value::Value(const string& s) -{ - type = StringType; - data.s = new string(s); -} - -Value::Value(ValueArray* a) -{ - type = ArrayType; - data.a = a; -} - -Value::Value(Hash* h) -{ - type = HashType; - data.h = h; -} - -Value::Value(bool b) -{ - type = BooleanType; - data.d = b ? 1.0 : 0.0; -} - -Value::~Value() -{ - if (type == StringType) - { - delete data.s; - } - else if (type == ArrayType) - { - if (data.a != nullptr) - { - for (unsigned int i = 0; i < data.a->size(); i++) - delete (*data.a)[i]; - delete data.a; - } - } - else if (type == HashType) - { - if (data.h != nullptr) - { -#if 0 - Hash::iterator iter = data.h->begin(); - while (iter != data.h->end()) - { - delete iter->second; - iter++; - } -#endif - delete data.h; - } - } -} - -Value::ValueType Value::getType() const -{ - return type; -} - -double Value::getNumber() const -{ - // ASSERT(type == NumberType); - return data.d; -} - -string Value::getString() const -{ - // ASSERT(type == StringType); - return *data.s; -} - -ValueArray* Value::getArray() const -{ - // ASSERT(type == ArrayType); - return data.a; -} - -Hash* Value::getHash() const -{ - // ASSERT(type == HashType); - return data.h; -} - -bool Value::getBoolean() const -{ - // ASSERT(type == BooleanType); - return (data.d != 0.0); -} - - /****** Parser method implementation ******/ Parser::Parser(Tokenizer* _tokenizer) : @@ -133,7 +34,7 @@ ValueArray* Parser::readArray() return nullptr; } - auto* array = new ValueArray(); + ValueArray* array = new ValueArray(); Value* v = readValue(); while (v != nullptr) @@ -285,7 +186,7 @@ Value* Parser::readValue() case Tokenizer::TokenBeginArray: tokenizer->pushBack(); { - ValueArray* array = readArray(); + auto* array = readArray(); if (array == nullptr) return nullptr; else @@ -307,652 +208,3 @@ Value* Parser::readValue() return nullptr; } } - - -AssociativeArray::~AssociativeArray() -{ -#if 0 - Hash::iterator iter = data.h->begin(); - while (iter != data.h->end()) - { - delete iter->second; - iter++; - } -#endif - for (const auto &iter : assoc) - delete iter.second; -} - -Value* AssociativeArray::getValue(const string& key) const -{ - map::const_iterator iter = assoc.find(key); - if (iter == assoc.end()) - return nullptr; - - return iter->second; -} - -void AssociativeArray::addValue(const string& key, Value& val) -{ - assoc.insert(map::value_type(key, &val)); -} - -bool AssociativeArray::getNumber(const string& key, double& val) const -{ - Value* v = getValue(key); - if (v == nullptr || v->getType() != Value::NumberType) - return false; - - val = v->getNumber(); - return true; -} - -bool AssociativeArray::getNumber(const string& key, float& val) const -{ - double dval; - - if (!getNumber(key, dval)) - return false; - - val = (float) dval; - return true; -} - -bool AssociativeArray::getNumber(const string& key, int& val) const -{ - double ival; - - if (!getNumber(key, ival)) - return false; - - val = (int) ival; - return true; -} - -bool AssociativeArray::getNumber(const string& key, uint32_t& val) const -{ - double ival; - - if (!getNumber(key, ival)) - return false; - - val = (uint32_t) ival; - return true; -} - -bool AssociativeArray::getString(const string& key, string& val) const -{ - Value* v = getValue(key); - if (v == nullptr || v->getType() != Value::StringType) - return false; - - val = v->getString(); - return true; -} - -bool AssociativeArray::getPath(const string& key, fs::path& val) const -{ - string v; - if (getString(key, v)) - { - val = PathExp(v); - return true; - } - return false; -} - -bool AssociativeArray::getBoolean(const string& key, bool& val) const -{ - Value* v = getValue(key); - if (v == nullptr || v->getType() != Value::BooleanType) - return false; - - val = v->getBoolean(); - return true; -} - -bool AssociativeArray::getVector(const string& key, Vector3d& val) const -{ - Value* v = getValue(key); - if (v == nullptr || v->getType() != Value::ArrayType) - return false; - - ValueArray* arr = v->getArray(); - if (arr->size() != 3) - return false; - - Value* x = (*arr)[0]; - Value* y = (*arr)[1]; - Value* z = (*arr)[2]; - - if (x->getType() != Value::NumberType || - y->getType() != Value::NumberType || - z->getType() != Value::NumberType) - return false; - - val = Vector3d(x->getNumber(), y->getNumber(), z->getNumber()); - return true; -} - - -bool AssociativeArray::getVector(const string& key, Vector3f& val) const -{ - Vector3d vecVal; - - if (!getVector(key, vecVal)) - return false; - - val = vecVal.cast(); - return true; -} - - -bool AssociativeArray::getVector(const string& key, Vector4d& val) const -{ - Value* v = getValue(key); - if (v == nullptr || v->getType() != Value::ArrayType) - return false; - - ValueArray* arr = v->getArray(); - if (arr->size() != 4) - return false; - - Value* x = (*arr)[0]; - Value* y = (*arr)[1]; - Value* z = (*arr)[2]; - Value* w = (*arr)[3]; - - if (x->getType() != Value::NumberType || - y->getType() != Value::NumberType || - z->getType() != Value::NumberType || - w->getType() != Value::NumberType) - return false; - - val = Vector4d(x->getNumber(), y->getNumber(), z->getNumber(), w->getNumber()); - return true; -} - - -bool AssociativeArray::getVector(const string& key, Vector4f& val) const -{ - Vector4d vecVal; - - if (!getVector(key, vecVal)) - return false; - - val = vecVal.cast(); - return true; -} - - -/** - * Retrieves a quaternion, scaled to an associated angle unit. - * - * The quaternion is specified in the catalog file in axis-angle format as follows: - * \verbatim {PropertyName} [ angle axisX axisY axisZ ] \endverbatim - * - * @param[in] key Hash key for the rotation. - * @param[out] val A quaternion representing the value if present, unaffected if not. - * @return True if the key exists in the hash, false otherwise. - */ -bool AssociativeArray::getRotation(const string& key, Eigen::Quaternionf& val) const -{ - Value* v = getValue(key); - if (v == nullptr || v->getType() != Value::ArrayType) - return false; - - ValueArray* arr = v->getArray(); - if (arr->size() != 4) - return false; - - Value* w = (*arr)[0]; - Value* x = (*arr)[1]; - Value* y = (*arr)[2]; - Value* z = (*arr)[3]; - - if (w->getType() != Value::NumberType || - x->getType() != Value::NumberType || - y->getType() != Value::NumberType || - z->getType() != Value::NumberType) - return false; - - Vector3f axis((float) x->getNumber(), - (float) y->getNumber(), - (float) z->getNumber()); - - double ang = w->getNumber(); - double angScale = 1.0; - getAngleScale(key, angScale); - float angle = degToRad((float) (ang * angScale)); - - val = Quaternionf(AngleAxisf(angle, axis.normalized())); - - return true; -} - - -bool AssociativeArray::getColor(const string& key, Color& val) const -{ - Vector4d vec4; - if (getVector(key, vec4)) - { - Vector4f vec4f = vec4.cast(); - val = Color(vec4f); - return true; - } - - Vector3d vec3; - if (getVector(key, vec3)) - { - Vector3f vec3f = vec3.cast(); - val = Color(vec3f); - return true; - } - - string rgba; - if (getString(key, rgba)) - { - int r, g, b, a; - int ret = sscanf(rgba.c_str(), "#%2x%2x%2x%2x", &r, &g, &b, &a); - switch (ret) - { - case 3: - a = 0xFF; - case 4: - val = Color((char unsigned)r, (char unsigned)g, (unsigned char)b, (unsigned char)a); - return true; - default: - return false; - } - } - - return false; -} - - -/** - * Retrieves a numeric quantity scaled to an associated angle unit. - * @param[in] key Hash key for the quantity. - * @param[out] val The returned quantity if present, unaffected if not. - * @param[in] outputScale Returned value is scaled to this value. - * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. - * @return True if the key exists in the hash, false otherwise. - */ -bool -AssociativeArray::getAngle(const string& key, double& val, double outputScale, double defaultScale) const -{ - if (!getNumber(key, val)) - return false; - - double angleScale; - if(getAngleScale(key, angleScale)) - { - angleScale /= outputScale; - } - else - { - angleScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; - } - - val *= angleScale; - - return true; -} - - -/** @copydoc AssociativeArray::getAngle() */ -bool -AssociativeArray::getAngle(const string& key, float& val, double outputScale, double defaultScale) const -{ - double dval; - - if (!getAngle(key, dval, outputScale, defaultScale)) - return false; - - val = ((float) dval); - - return true; -} - - -/** - * Retrieves a numeric quantity scaled to an associated length unit. - * @param[in] key Hash key for the quantity. - * @param[out] val The returned quantity if present, unaffected if not. - * @param[in] outputScale Returned value is scaled to this value. - * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. - * @return True if the key exists in the hash, false otherwise. - */ -bool -AssociativeArray::getLength(const string& key, double& val, double outputScale, double defaultScale) const -{ - if(!getNumber(key, val)) - return false; - - double lengthScale; - if(getLengthScale(key, lengthScale)) - { - lengthScale /= outputScale; - } - else - { - lengthScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; - } - - val *= lengthScale; - - return true; -} - - -/** @copydoc AssociativeArray::getLength() */ -bool AssociativeArray::getLength(const string& key, float& val, double outputScale, double defaultScale) const -{ - double dval; - - if (!getLength(key, dval, outputScale, defaultScale)) - return false; - - val = ((float) dval); - - return true; -} - - -/** - * Retrieves a numeric quantity scaled to an associated time unit. - * @param[in] key Hash key for the quantity. - * @param[out] val The returned quantity if present, unaffected if not. - * @param[in] outputScale Returned value is scaled to this value. - * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. - * @return True if the key exists in the hash, false otherwise. - */ -bool AssociativeArray::getTime(const string& key, double& val, double outputScale, double defaultScale) const -{ - if(!getNumber(key, val)) - return false; - - double timeScale; - if(getTimeScale(key, timeScale)) - { - timeScale /= outputScale; - } - else - { - timeScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; - } - - val *= timeScale; - - return true; -} - - -/** @copydoc AssociativeArray::getTime() */ -bool AssociativeArray::getTime(const string& key, float& val, double outputScale, double defaultScale) const -{ - double dval; - - if(!getTime(key, dval, outputScale, defaultScale)) - return false; - - val = ((float) dval); - - return true; -} - - -/** - * Retrieves a numeric quantity scaled to an associated mass unit. - * @param[in] key Hash key for the quantity. - * @param[out] val The returned quantity if present, unaffected if not. - * @param[in] outputScale Returned value is scaled to this value. - * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. - * @return True if the key exists in the hash, false otherwise. - */ -bool AssociativeArray::getMass(const string& key, double& val, double outputScale, double defaultScale) const -{ - if(!getNumber(key, val)) - return false; - - double massScale; - if(getMassScale(key, massScale)) - { - massScale /= outputScale; - } - else - { - massScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; - } - - val *= massScale; - - return true; -} - -/** @copydoc AssociativeArray::getMass() */ -bool AssociativeArray::getMass(const string& key, float& val, double outputScale, double defaultScale) const -{ - double dval; - - if(!getMass(key, dval, outputScale, defaultScale)) - return false; - - val = ((float) dval); - - return true; -} - - -/** - * Retrieves a vector quantity scaled to an associated length unit. - * @param[in] key Hash key for the quantity. - * @param[out] val The returned vector if present, unaffected if not. - * @param[in] outputScale Returned value is scaled to this value. - * @param[in] defaultScale If no units are specified, use this scale. Defaults to outputScale. - * @return True if the key exists in the hash, false otherwise. - */ -bool AssociativeArray::getLengthVector(const string& key, Eigen::Vector3d& val, double outputScale, double defaultScale) const -{ - if(!getVector(key, val)) - return false; - - double lengthScale; - if(getLengthScale(key, lengthScale)) - { - lengthScale /= outputScale; - } - else - { - lengthScale = (defaultScale == 0.0) ? 1.0 : defaultScale / outputScale; - } - - val *= lengthScale; - - return true; -} - - -/** @copydoc AssociativeArray::getLengthVector() */ -bool AssociativeArray::getLengthVector(const string& key, Eigen::Vector3f& val, double outputScale, double defaultScale) const -{ - Vector3d vecVal; - - if(!getLengthVector(key, vecVal, outputScale, defaultScale)) - return false; - - val = vecVal.cast(); - return true; -} - - -/** - * Retrieves a spherical tuple \verbatim [longitude, latitude, altitude] \endverbatim scaled to associated angle and length units. - * @param[in] key Hash key for the quantity. - * @param[out] val The returned tuple in units of degrees and kilometers if present, unaffected if not. - * @return True if the key exists in the hash, false otherwise. - */ -bool AssociativeArray::getSphericalTuple(const string& key, Vector3d& val) const -{ - if(!getVector(key, val)) - return false; - - double angleScale; - if(getAngleScale(key, angleScale)) - { - val[0] *= angleScale; - val[1] *= angleScale; - } - - double lengthScale = 1.0; - getLengthScale(key, lengthScale); - val[2] *= lengthScale; - - return true; -} - - -/** @copydoc AssociativeArray::getSphericalTuple */ -bool AssociativeArray::getSphericalTuple(const string& key, Vector3f& val) const -{ - Vector3d vecVal; - - if(!getSphericalTuple(key, vecVal)) - return false; - - val = vecVal.cast(); - return true; -} - - -/** - * Retrieves the angle unit associated with a given property. - * @param[in] key Hash key for the property. - * @param[out] scale The returned angle unit scaled to degrees if present, unaffected if not. - * @return True if an angle unit has been specified for the property, false otherwise. - */ -bool AssociativeArray::getAngleScale(const string& key, double& scale) const -{ - string unitKey(key + "%Angle"); - string unit; - - if (!getString(unitKey, unit)) - return false; - - return astro::getAngleScale(unit, scale); -} - - -/** @copydoc AssociativeArray::getAngleScale() */ -bool AssociativeArray::getAngleScale(const string& key, float& scale) const -{ - double dscale; - if (!getAngleScale(key, dscale)) - return false; - - scale = ((float) dscale); - return true; -} - - -/** - * Retrieves the length unit associated with a given property. - * @param[in] key Hash key for the property. - * @param[out] scale The returned length unit scaled to kilometers if present, unaffected if not. - * @return True if a length unit has been specified for the property, false otherwise. - */ -bool AssociativeArray::getLengthScale(const string& key, double& scale) const -{ - string unitKey(key + "%Length"); - string unit; - - if (!getString(unitKey, unit)) - return false; - - return astro::getLengthScale(unit, scale); -} - - -/** @copydoc AssociativeArray::getLengthScale() */ -bool AssociativeArray::getLengthScale(const string& key, float& scale) const -{ - double dscale; - if (!getLengthScale(key, dscale)) - return false; - - scale = ((float) dscale); - return true; -} - - -/** - * Retrieves the time unit associated with a given property. - * @param[in] key Hash key for the property. - * @param[out] scale The returned time unit scaled to days if present, unaffected if not. - * @return True if a time unit has been specified for the property, false otherwise. - */ -bool AssociativeArray::getTimeScale(const string& key, double& scale) const -{ - string unitKey(key + "%Time"); - string unit; - - if (!getString(unitKey, unit)) - return false; - - return astro::getTimeScale(unit, scale); -} - - -/** @copydoc AssociativeArray::getTimeScale() */ -bool AssociativeArray::getTimeScale(const string& key, float& scale) const -{ - double dscale; - if (!getTimeScale(key, dscale)) - return false; - - scale = ((float) dscale); - return true; -} - - -/** - * Retrieves the mass unit associated with a given property. - * @param[in] key Hash key for the property. - * @param[out] scale The returned mass unit scaled to Earth mass if present, unaffected if not. - * @return True if a mass unit has been specified for the property, false otherwise. - */ -bool AssociativeArray::getMassScale(const string& key, double& scale) const -{ - string unitKey(key + "%Mass"); - string unit; - - if (!getString(unitKey, unit)) - return false; - - return astro::getMassScale(unit, scale); -} - - -/** @copydoc AssociativeArray::getMassScale() */ -bool AssociativeArray::getMassScale(const string& key, float& scale) const -{ - double dscale; - if (!getMassScale(key, dscale)) - return false; - - scale = ((float) dscale); - return true; -} - -HashIterator -AssociativeArray::begin() -{ - return assoc.begin(); -} - - -HashIterator -AssociativeArray::end() -{ - return assoc.end(); -} diff --git a/src/celengine/parser.h b/src/celengine/parser.h index 57a8fcdf2..2b627d54f 100644 --- a/src/celengine/parser.h +++ b/src/celengine/parser.h @@ -1,6 +1,6 @@ // parser.h // -// Copyright (C) 2001-2009, the Celestia Development Team +// Copyright (C) 2001-2019, the Celestia Development Team // Original version by Chris Laurel // // This program is free software; you can redistribute it and/or @@ -8,127 +8,25 @@ // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. -#ifndef _PARSER_H_ -#define _PARSER_H_ +#pragma once -#include -#include -#include -#include -#include -#include -#include -#include +#include "hash.h" +#include "value.h" +class Tokenizer; class Value; -typedef map::const_iterator HashIterator; - -class AssociativeArray -{ - public: - AssociativeArray() = default; - ~AssociativeArray(); - - Value* getValue(const std::string&) const; - void addValue(const std::string&, Value&); - - bool getNumber(const std::string&, double&) const; - bool getNumber(const std::string&, float&) const; - bool getNumber(const std::string&, int&) const; - bool getNumber(const std::string&, uint32_t&) const; - bool getString(const std::string&, std::string&) const; - bool getPath(const std::string&, fs::path&) const; - bool getBoolean(const std::string&, bool&) const; - bool getVector(const std::string&, Eigen::Vector3d&) const; - bool getVector(const std::string&, Eigen::Vector3f&) const; - bool getVector(const std::string&, Eigen::Vector4d&) const; - bool getVector(const std::string&, Eigen::Vector4f&) const; - bool getRotation(const std::string&, Eigen::Quaternionf&) const; - bool getColor(const std::string&, Color&) const; - bool getAngle(const std::string&, double&, double = 1.0, double = 0.0) const; - bool getAngle(const std::string&, float&, double = 1.0, double = 0.0) const; - bool getLength(const std::string&, double&, double = 1.0, double = 0.0) const; - bool getLength(const std::string&, float&, double = 1.0, double = 0.0) const; - bool getTime(const std::string&, double&, double = 1.0, double = 0.0) const; - bool getTime(const std::string&, float&, double = 1.0, double = 0.0) const; - bool getMass(const std::string&, double&, double = 1.0, double = 0.0) const; - bool getMass(const std::string&, float&, double = 1.0, double = 0.0) const; - bool getLengthVector(const std::string&, Eigen::Vector3d&, double = 1.0, double = 0.0) const; - bool getLengthVector(const std::string&, Eigen::Vector3f&, double = 1.0, double = 0.0) const; - bool getSphericalTuple(const std::string&, Eigen::Vector3d&) const; - bool getSphericalTuple(const std::string&, Eigen::Vector3f&) const; - bool getAngleScale(const std::string&, double&) const; - bool getAngleScale(const std::string&, float&) const; - bool getLengthScale(const std::string&, double&) const; - bool getLengthScale(const std::string&, float&) const; - bool getTimeScale(const std::string&, double&) const; - bool getTimeScale(const std::string&, float&) const; - bool getMassScale(const string&, double&) const; - bool getMassScale(const string&, float&) const; - - HashIterator begin(); - HashIterator end(); - - private: - map assoc; -}; - -typedef vector Array; -typedef vector ValueArray; -typedef AssociativeArray Hash; - -class Value -{ -public: - enum ValueType { - NumberType = 0, - StringType = 1, - ArrayType = 2, - HashType = 3, - BooleanType = 4 - }; - - Value(double); - Value(const string&); - Value(ValueArray*); - Value(Hash*); - Value(bool); - ~Value(); - - ValueType getType() const; - - double getNumber() const; - string getString() const; - ValueArray* getArray() const; - Hash* getHash() const; - bool getBoolean() const; - -private: - ValueType type; - - union { - string* s; - double d; - ValueArray* a; - Hash* h; - } data; -}; - - class Parser { -public: + public: Parser(Tokenizer*); Value* readValue(); -private: + private: Tokenizer* tokenizer; bool readUnits(const std::string&, Hash*); - ValueArray* readArray(); + Array* readArray(); Hash* readHash(); }; - -#endif // _PARSER_H_ diff --git a/src/celengine/solarsys.cpp b/src/celengine/solarsys.cpp index e3b206262..ff2d6f266 100644 --- a/src/celengine/solarsys.cpp +++ b/src/celengine/solarsys.cpp @@ -19,6 +19,7 @@ #include #include "astro.h" #include "parser.h" +#include "tokenizer.h" #include "texmanager.h" #include "meshmanager.h" #include "universe.h" diff --git a/src/celengine/stardb.cpp b/src/celengine/stardb.cpp index 581e0ab24..d77e55b9e 100644 --- a/src/celengine/stardb.cpp +++ b/src/celengine/stardb.cpp @@ -24,6 +24,7 @@ #include "parseobject.h" #include "multitexture.h" #include "meshmanager.h" +#include "tokenizer.h" #include using namespace Eigen; diff --git a/src/celengine/value.cpp b/src/celengine/value.cpp new file mode 100644 index 000000000..9eb2f6530 --- /dev/null +++ b/src/celengine/value.cpp @@ -0,0 +1,36 @@ +// value.cpp +// +// Copyright (C) 2001-2019, the Celestia Development Team +// Original version by Chris Laurel +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +#include "value.h" + +/****** Value method implementations *******/ + +Value::~Value() +{ + switch (type) + { + case StringType: + delete data.s; + break; + case ArrayType: + if (data.a != nullptr) + { + for (auto *p : *data.a) + delete p; + delete data.a; + } + break; + case HashType: + delete data.h; + break; + default: + break; + } +} diff --git a/src/celengine/value.h b/src/celengine/value.h new file mode 100644 index 000000000..dfc45c5e0 --- /dev/null +++ b/src/celengine/value.h @@ -0,0 +1,112 @@ +// value.h +// +// Copyright (C) 2001-2019, the Celestia Development Team +// Original version by Chris Laurel +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. + +#pragma once + +#include +#include +#include +#include "hash.h" + +class Value; +using Array = std::vector; +using ValueArray = Array; + +class Value +{ + public: + enum ValueType + { + NullType = 0, + NumberType = 1, + StringType = 2, + ArrayType = 3, + HashType = 4, + BooleanType = 5 + }; + + Value() = default; + ~Value(); + Value(const Value&) = delete; + Value(Value&&) = default; + Value& operator=(const Value&) = delete; + Value& operator=(Value&&) = default; + + Value(double d) : type(NumberType) + { + data.d = d; + } + Value(const char *s) : type(StringType) + { + data.s = new std::string(s); + } + explicit Value(const std::string &s) : type(StringType) + { + data.s = new std::string(s); + } + Value(Array *a) : type(ArrayType) + { + data.a = a; + } + Value(Hash *h) : type(HashType) + { + data.h = h; + } + Value(bool b) : type(BooleanType) + { + data.d = b ? 1.0 : 0.0; + } + + ValueType getType() const + { + return type; + } + bool isNull() const + { + return type == NullType; + } + double getNumber() const + { + assert(type == NumberType); + return data.d; + } + std::string getString() const + { + assert(type == StringType); + return *data.s; + } + Array* getArray() const + { + assert(type == ArrayType); + return data.a; + } + Hash* getHash() const + { + assert(type == HashType); + return data.h; + } + bool getBoolean() const + { + assert(type == BooleanType); + return (data.d != 0.0); + } + + private: + union Data + { + std::string *s; + double d; + Array *a; + Hash *h; + }; + + ValueType type { NullType }; + Data data; +}; diff --git a/src/celengine/virtualtex.cpp b/src/celengine/virtualtex.cpp index b7c5907cd..9889cbf7b 100644 --- a/src/celengine/virtualtex.cpp +++ b/src/celengine/virtualtex.cpp @@ -20,6 +20,7 @@ #include #include #include "parser.h" +#include "tokenizer.h" #include "virtualtex.h" diff --git a/src/celestia/configfile.cpp b/src/celestia/configfile.cpp index ab68c1e04..041e750be 100644 --- a/src/celestia/configfile.cpp +++ b/src/celestia/configfile.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "configfile.h" using namespace std; diff --git a/src/celestia/destination.cpp b/src/celestia/destination.cpp index b5b044e3c..d83a9e1ee 100644 --- a/src/celestia/destination.cpp +++ b/src/celestia/destination.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "destination.h" using namespace std; diff --git a/src/celestia/favorites.cpp b/src/celestia/favorites.cpp index 20890e8a1..e32bfd16d 100644 --- a/src/celestia/favorites.cpp +++ b/src/celestia/favorites.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "favorites.h" diff --git a/src/celscript/legacy/cmdparser.cpp b/src/celscript/legacy/cmdparser.cpp index 71d5088ae..6b5ef733d 100644 --- a/src/celscript/legacy/cmdparser.cpp +++ b/src/celscript/legacy/cmdparser.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef USE_GLCONTEXT #include #endif