Adding struct to hold parsed Profile

This commit is contained in:
Alexander Bock
2020-06-16 16:39:51 +02:00
parent 9d922f2634
commit 809ee9c753
2 changed files with 318 additions and 22 deletions
+91 -3
View File
@@ -29,8 +29,12 @@
#include <istream>
#include <fstream>
#include <functional>
#include <optional>
#include <variant>
#include <vector>
#include <ghoul/systemcapabilities/version.h>
namespace ghoul { class Dictionary; }
namespace ghoul::opengl { class ProgramObject; }
@@ -83,6 +87,90 @@ const size_t cameraGeoFieldAltitude = 4;
class ProfileFile {
public:
struct ProfileStruct {
// Version
struct Version {
int major = 0;
int minor = 0;
int patch = 0;
};
Version version;
struct Module {
std::string name;
std::string loadedInstruction;
std::string notLoadedInstruction;
};
std::vector<Module> modules;
struct Asset {
enum class Type {
Require,
Request
};
std::string path;
Type type;
};
std::vector<Asset> assets;
struct Property {
enum class SetType {
SetPropertyValue,
SetPropertyValueSingle
};
SetType setType;
std::string name;
std::string value;
};
std::vector<Property> properties;
struct Keybinding {
std::string key; // @TODO (abock, 2020-06-16) change to key+action
std::string documentation;
std::string name;
std::string guiPath;
bool isLocal;
std::string script;
};
std::vector<Keybinding> keybindings;
struct Time {
enum class Type {
Absolute,
Relative
};
Type type;
std::string time;
};
Time time;
struct CameraNavState {
std::string anchor;
std::string aim;
std::string referenceFrame;
std::string position;
std::string up;
std::string yaw;
std::string pitch;
};
struct CameraGoToGeo {
std::string anchor;
double latitude;
double longitude;
std::optional<double> altitude;
};
std::variant<CameraNavState, CameraGoToGeo> camera;
std::vector<std::string> markNodes;
};
ProfileStruct profile;
using Lines = std::vector<std::string>;
/**
@@ -233,7 +321,7 @@ private:
void verifyRequiredFields(std::string sectionName, std::vector<std::string> fields,
std::vector<std::string> standard, unsigned int nFields);
void processIndividualLine(bool& insideSection, std::string line);
bool determineSection(std::string line);
void determineSection(std::string line);
void (ProfileFile::* parseCurrentSection)(std::string);
void parseVersion(std::string line);
void parseModule(std::string line);
@@ -246,8 +334,8 @@ private:
size_t _lineNum = 1;
size_t _numLinesVersion = 0;
size_t _numLinesTime = 0;
size_t _numLinesCamera = 0;
size_t _numLinesTime = 0;
size_t _numLinesCamera = 0;
std::string _version;
std::string _time;
+227 -19
View File
@@ -89,7 +89,7 @@ ProfileFile::ProfileFile(std::string filename) {
throw ProfileError(
_lineNum,
fmt::format("Read error using getline in: {} ({})", filename, e.what()
));
));
}
}
@@ -105,9 +105,8 @@ void ProfileFile::processIndividualLine(bool& insideSection, std::string line) {
}
}
else if (line.substr(0, 1) == "#") {
if (determineSection(line)) {
insideSection = true;
}
determineSection(line);
insideSection = true;
}
}
@@ -203,33 +202,33 @@ void ProfileFile::clearAllFields() {
_properties.clear();
_keybindings.clear();
_markNodes.clear();
profile = ProfileStruct();
}
bool ProfileFile::determineSection(std::string line) {
bool foundSection = true;
if (line.compare(headerVersion) == 0) {
void ProfileFile::determineSection(std::string line) {
if (line == headerVersion) {
parseCurrentSection = &ProfileFile::parseVersion;
}
else if (line.compare(headerModule) == 0) {
else if (line == headerModule) {
parseCurrentSection = &ProfileFile::parseModule;
}
else if (line.compare(headerAsset) == 0) {
else if (line == headerAsset) {
parseCurrentSection = &ProfileFile::parseAsset;
}
else if (line.compare(headerProperty) == 0) {
else if (line == headerProperty) {
parseCurrentSection = &ProfileFile::parseProperty;
}
else if (line.compare(headerKeybinding) == 0) {
else if (line == headerKeybinding) {
parseCurrentSection = &ProfileFile::parseKeybinding;
}
else if (line.compare(headerTime) == 0) {
else if (line == headerTime) {
parseCurrentSection = &ProfileFile::parseTime;
}
else if (line.compare(headerCamera) == 0) {
else if (line == headerCamera) {
parseCurrentSection = &ProfileFile::parseCamera;
}
else if (line.compare(headerMarkNodes) == 0) {
else if (line == headerMarkNodes) {
parseCurrentSection = &ProfileFile::parseMarkNodes;
}
else {
@@ -237,9 +236,7 @@ bool ProfileFile::determineSection(std::string line) {
_lineNum,
fmt::format("Invalid section header '{}'", line)
);
foundSection = false;
}
return foundSection;
}
std::string ProfileFile::time() const {
@@ -278,9 +275,29 @@ void ProfileFile::parseVersion(std::string line) {
if (fields.size() > versionFieldsExpected) {
throw ProfileError(_lineNum, "No tabs allowed in Version entry");
}
else {
_version = line;
_version = line;
//
// New
//
std::vector<std::string> parts = ghoul::tokenizeString(line, '.');
if (parts.empty() || parts.size() > 3) {
throw ProfileError(
_lineNum,
fmt::format("Expected 1-3 version components, got {}", parts.size())
);
}
ProfileStruct::Version version;
version.major = std::stoi(parts[0]);
if (parts.size() > 1) {
version.minor = std::stoi(parts[1]);
}
if (parts.size() > 2) {
version.patch = std::stoi(parts[2]);
}
profile.version = std::move(version);
}
void ProfileFile::parseModule(std::string line) {
@@ -299,6 +316,22 @@ void ProfileFile::parseModule(std::string line) {
};
verifyRequiredFields("Module", fields, standard, moduleFieldsExpected);
_modules.push_back(line);
//
// New
//
if (fields.size() != 3) {
throw ProfileError(
_lineNum,
fmt::format("Expected 3 fields in a Module entry, got {}", fields.size())
);
}
ProfileStruct::Module m;
m.name = fields[0];
m.loadedInstruction = fields[1];
m.notLoadedInstruction = fields[2];
profile.modules.push_back(std::move(m));
}
void ProfileFile::parseAsset(std::string line) {
@@ -315,6 +348,33 @@ void ProfileFile::parseAsset(std::string line) {
};
verifyRequiredFields("Asset", fields, standard, assetFieldsExpected);
_assets.push_back(line);
//
// New
//
if (fields.size() != 2) {
throw ProfileError(
_lineNum,
fmt::format("Expected 2 fields in an Asset entry, got {}", fields.size())
);
}
ProfileStruct::Asset a;
a.path = fields[0];
a.type = [&](const std::string& type) -> ProfileStruct::Asset::Type {
if (type == "required") {
return ProfileStruct::Asset::Type::Require;
}
if (type == "request") {
return ProfileStruct::Asset::Type::Request;
}
throw ProfileError(
_lineNum,
fmt::format("Expected asset type 'required' or 'request', got {}", type)
);
}(fields[1]);
profile.assets.push_back(std::move(a));
}
void ProfileFile::parseProperty(std::string line) {
@@ -333,6 +393,37 @@ void ProfileFile::parseProperty(std::string line) {
};
verifyRequiredFields("Property", fields, standard, propertyFieldsExpected);
_properties.push_back(line);
//
// New
//
if (fields.size() != 3) {
throw ProfileError(
_lineNum,
fmt::format("Expected 3 fields in Property entry, got {}", fields.size())
);
}
ProfileStruct::Property p;
p.setType = [&](const std::string& type) -> ProfileStruct::Property::SetType {
if (type == "setPropertyValue") {
return ProfileStruct::Property::SetType::SetPropertyValue;
}
if (type == "setPropertyValueSingle") {
return ProfileStruct::Property::SetType::SetPropertyValueSingle;
}
throw ProfileError(
_lineNum,
fmt::format(
"Expected property set type 'setPropertyValue' or "
"'setPropertyValueSingle', got {}",
type
)
);
}(fields[0]);
p.name = fields[1];
p.value = fields[2];
profile.properties.push_back(std::move(p));
}
void ProfileFile::parseKeybinding(std::string line) {
@@ -354,6 +445,36 @@ void ProfileFile::parseKeybinding(std::string line) {
};
verifyRequiredFields("Keybinding", fields, standard, keybindingFieldsExpected);
_keybindings.push_back(line);
//
// New
//
if (fields.size() != 6) {
throw ProfileError(
_lineNum,
fmt::format("Expected 6 fields in Keybinding entry, got {}", fields.size())
);
}
ProfileStruct::Keybinding kb;
kb.key = fields[0];
kb.documentation = fields[1];
kb.name = fields[2];
kb.guiPath = fields[3];
kb.isLocal = [&](const std::string& local) -> bool {
if (local == "false") {
return false;
}
if (local == "true") {
return true;
}
throw ProfileError(
_lineNum,
fmt::format("Expected 'false' or 'true' for the local path, got {}", local)
);
}(fields[4]);
kb.script = fields[5];
profile.keybindings.push_back(std::move(kb));
}
void ProfileFile::parseTime(std::string line) {
@@ -374,6 +495,32 @@ void ProfileFile::parseTime(std::string line) {
};
verifyRequiredFields("Time", fields, standard, timeFieldsExpected);
_time = line;
//
// New
//
if (fields.size() != 2) {
throw ProfileError(
_lineNum,
fmt::format("Expected 2 fields in Time entry, got {}", fields.size())
);
}
ProfileStruct::Time time;
time.type = [&](const std::string& type) -> ProfileStruct::Time::Type {
if (type == "absolute") {
return ProfileStruct::Time::Type::Absolute;
}
if (type == "relative") {
return ProfileStruct::Time::Type::Relative;
}
throw ProfileError(
_lineNum,
fmt::format("Expected 'absolute' or 'relative' for the type, got {}", type)
);
}(fields[0]);
time.time = fields[1];
profile.time = std::move(time);
}
void ProfileFile::parseCamera(std::string line) {
@@ -418,6 +565,61 @@ void ProfileFile::parseCamera(std::string line) {
);
}
_camera = line;
//
// New
//
if (fields.empty()) {
throw ProfileError(_lineNum, "No values specified for Camera location");
}
if (fields[0] == "setNavigationState") {
if (fields.size() != 8) {
throw ProfileError(
_lineNum,
fmt::format(
"Expected 8 fields in the Camera entry, got {}", fields.size()
)
);
}
ProfileStruct::CameraNavState camera;
camera.anchor = fields[1];
camera.aim = fields[2];
camera.referenceFrame = fields[3];
camera.position = fields[4];
camera.up = fields[5];
camera.yaw = fields[6];
camera.pitch = fields[7];
profile.camera = std::move(camera);
return;
}
if (fields[0] == "goToGeo") {
if (fields.size() != 5) {
throw ProfileError(
_lineNum,
fmt::format(
"Expected 5 fields in the Camera entry, got {}", fields.size()
)
);
}
ProfileStruct::CameraGoToGeo camera;
camera.anchor = fields[1];
camera.latitude = std::stod(fields[2]);
camera.longitude = std::stod(fields[3]);
if (!fields[4].empty()) {
camera.altitude = std::stod(fields[4]);
}
profile.camera = std::move(camera);
return;
}
throw ProfileError(
_lineNum,
fmt::format(
"Expected 'setNavigationState' or 'goToGeo' for the type, got {}", fields[0]
)
);
}
void ProfileFile::parseMarkNodes(std::string line) {
@@ -433,6 +635,12 @@ void ProfileFile::parseMarkNodes(std::string line) {
verifyRequiredFields("Mark Interesting Nodes", fields, standard,
markNodesFieldsExpected);
_markNodes.push_back(line);
//
// New
//
profile.markNodes.push_back(line);
}
void ProfileFile::verifyRequiredFields(std::string sectionName,