170 lines
4.7 KiB
C++
170 lines
4.7 KiB
C++
/**
|
|
* Copyright (c) 2021 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "LanguageGen.hpp"
|
|
|
|
using namespace Dawn;
|
|
|
|
int32_t LanguageGen::start() {
|
|
if(this->args.size() != 3) {
|
|
std::cout << "Invalid number of arguments provided to language gen!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
auto fileIn = File(this->args[1]);
|
|
std::string buffer;
|
|
if(!fileIn.readString(&buffer)) {
|
|
std::cout << "Failed to open/read input file " << fileIn.filename << std::endl;
|
|
return 1;
|
|
}
|
|
auto xml = Xml::load(buffer);
|
|
|
|
// Begin parsing. Start by looking for the <language> tags
|
|
std::vector<std::string> languages;
|
|
auto itChildren = xml.children.begin();
|
|
while(itChildren != xml.children.end()) {
|
|
auto child = *itChildren;
|
|
if(child->node == "language") {
|
|
auto attrName = child->attributes.find("name");
|
|
if(attrName == child->attributes.end()) {
|
|
std::cout << "Missing name param on language node" << std::endl;
|
|
return 1;
|
|
}
|
|
languages.push_back(attrName->second);
|
|
}
|
|
++itChildren;
|
|
}
|
|
|
|
// Now begin actually parsing
|
|
std::map<std::string, std::vector<struct LanguageString>> strings;
|
|
itChildren = xml.children.begin();
|
|
while(itChildren != xml.children.end()) {
|
|
auto child = *itChildren;
|
|
if(child->node == "group") {
|
|
auto ret = this->parseGroup(child, "", &strings);
|
|
if(ret != 0) return ret;
|
|
} else if(child->node == "string") {
|
|
std::cout << "String cannot be a root node" << std::endl;
|
|
return 1;
|
|
}
|
|
++itChildren;
|
|
}
|
|
|
|
// Now we validate each lang has each key.
|
|
std::vector<std::string> keys;
|
|
auto it = strings.begin();
|
|
while(it != strings.end()) {
|
|
auto it2 = it->second.begin();
|
|
while(it2 != it->second.end()) {
|
|
auto key = it2->key;
|
|
auto exist = std::find(keys.begin(), keys.end(), key);
|
|
if(exist == keys.end()) {
|
|
keys.push_back(key);
|
|
}
|
|
it2++;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
// Now we actually parse each string, validating as we go.
|
|
it = strings.begin();
|
|
while(it != strings.end()) {
|
|
std::vector<std::string> itKeys;
|
|
|
|
std::string bufferOut;
|
|
|
|
auto it2 = it->second.begin();
|
|
while(it2 != it->second.end()) {
|
|
auto l = *it2;
|
|
itKeys.push_back(l.key);
|
|
bufferOut += l.key + "|" + l.value + "|";
|
|
it2++;
|
|
}
|
|
|
|
File fileOut(this->args[2] + "/language_" + it->first + ".language");
|
|
if(!fileOut.mkdirp()) {
|
|
std::cout << "Failed to create output folder" << std::endl;
|
|
}
|
|
if(!fileOut.writeString(bufferOut)) {
|
|
std::cout << "Failed to write to output file " << fileOut.filename << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
auto it3 = keys.begin();
|
|
while(it3 != keys.end()) {
|
|
auto key = *it3;
|
|
auto inIt = std::find(itKeys.begin(), itKeys.end(), key);
|
|
if(inIt == itKeys.end()) {
|
|
std::cout << "Locale " << it->first << " missing key " << key << std::endl;
|
|
}
|
|
it3++;
|
|
}
|
|
|
|
if(itKeys.size() != keys.size()) {
|
|
std::cout << "Locale is missing some keys, see above" << std::endl;
|
|
return 1;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t LanguageGen::parseString(
|
|
Xml *stringNode,
|
|
std::string key,
|
|
std::map<std::string,std::vector<struct LanguageString>> *strings
|
|
) {
|
|
auto attrLang = stringNode->attributes.find("lang");
|
|
if(attrLang == stringNode->attributes.end()) {
|
|
std::cout << "String is missing lang parameter." << std::endl;
|
|
return -1;
|
|
}
|
|
|
|
struct LanguageString str;
|
|
str.key = key;
|
|
str.value = stringNode->value;
|
|
|
|
auto existing = (*strings).find(attrLang->second);
|
|
if(existing == (*strings).end()) {
|
|
(*strings).insert(std::make_pair(attrLang->second, std::vector<struct LanguageString>()));
|
|
}
|
|
(*strings)[attrLang->second].push_back(str);
|
|
return 0;
|
|
}
|
|
|
|
int32_t LanguageGen::parseGroup(
|
|
Xml *groupNode,
|
|
std::string key,
|
|
std::map<std::string, std::vector<struct LanguageString>> *strings
|
|
) {
|
|
int32_t ret;
|
|
|
|
auto attrKey = groupNode->attributes.find("key");
|
|
if(attrKey == groupNode->attributes.end()) {
|
|
std::cout << "Group node is missing key" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
if(key.size() > 0) key += ".";
|
|
key += attrKey->second;
|
|
|
|
auto itChildren = groupNode->children.begin();
|
|
while(itChildren != groupNode->children.end()) {
|
|
auto child = *itChildren;
|
|
if(child->node == "string") {
|
|
ret = this->parseString(child, key, strings);
|
|
if(ret != 0) return ret;
|
|
} else if(child->node == "group") {
|
|
ret = this->parseGroup(child, key, strings);
|
|
if(ret != 0) return ret;
|
|
}
|
|
++itChildren;
|
|
}
|
|
|
|
return 0;
|
|
} |