/** * 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 tags std::vector 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> 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 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 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> *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())); } (*strings)[attrLang->second].push_back(str); return 0; } int32_t LanguageGen::parseGroup( Xml *groupNode, std::string key, std::map> *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; }