Finished Language Generation Tool
This commit is contained in:
@ -26,6 +26,8 @@ void Xml::load(Xml *xml, std::string data, size_t *j) {
|
||||
bool_t insideTag = false;
|
||||
std::string buffer = "";
|
||||
std::string attrKey = "";
|
||||
std::string bufferWhitespaces;
|
||||
bool_t valueIsInWhitespace = false;
|
||||
size_t i = *j;
|
||||
|
||||
while(c = data[i++]) {
|
||||
@ -131,10 +133,29 @@ void Xml::load(Xml *xml, std::string data, size_t *j) {
|
||||
// In HTML Spec there could be a child here but not in XML spec.
|
||||
doing = XML_PARSE_STATE_PARSING_CLOSE;
|
||||
xml->value = buffer;
|
||||
buffer = "";
|
||||
buffer.clear();
|
||||
valueIsInWhitespace = false;
|
||||
bufferWhitespaces.clear();
|
||||
continue;
|
||||
}
|
||||
buffer += c;
|
||||
|
||||
if(Xml::isWhitespace(c)) {
|
||||
if(!valueIsInWhitespace) {
|
||||
bufferWhitespaces.clear();
|
||||
bufferWhitespaces += c;
|
||||
valueIsInWhitespace = true;
|
||||
} else {
|
||||
if(c != ' ') bufferWhitespaces += c;
|
||||
}
|
||||
// TODO: I can maybe consider indentation here
|
||||
} else {
|
||||
if(valueIsInWhitespace) {
|
||||
buffer += bufferWhitespaces;
|
||||
valueIsInWhitespace = false;
|
||||
}
|
||||
buffer += c;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case XML_PARSE_STATE_PARSING_CHILD:
|
||||
|
@ -25,7 +25,86 @@ int32_t GeneratedLanguages::start() {
|
||||
}
|
||||
|
||||
// Now process each language file
|
||||
|
||||
std::map<std::string, std::map<std::string, std::string>> strings;
|
||||
std::vector<std::string> knownKeys;
|
||||
auto itFiles = files.begin();
|
||||
while(itFiles != files.end()) {
|
||||
File file(*itFiles);
|
||||
file.open(FILE_MODE_READ);
|
||||
std::string buffer;
|
||||
size_t n = 0;
|
||||
|
||||
while(n < file.length) {
|
||||
char lang[32];
|
||||
char key[128];
|
||||
char string[32178];
|
||||
|
||||
// Read lang
|
||||
if(n != 0) file.setPosition(n);
|
||||
auto langSize = file.readAhead(lang, 32, '|');
|
||||
lang[langSize] = '\0';
|
||||
n += langSize + 1;
|
||||
if(langSize <= 0) {
|
||||
std::cout << "Error reading language name: " << langSize << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read Key
|
||||
file.setPosition(n);
|
||||
auto keySize = file.readAhead(key, 128, '|');
|
||||
key[keySize] = '\0';
|
||||
n += keySize + 1;
|
||||
if(keySize <= 0) {
|
||||
std::cout << "Error reading language key: " << keySize << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read String
|
||||
file.setPosition(n);
|
||||
auto stringSize = file.readAhead(string, 32178, '|');
|
||||
string[stringSize] = '\0';
|
||||
n += stringSize + 1;
|
||||
if(stringSize <= 0) {
|
||||
std::cout << "Error reading language string: " << stringSize << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
strings[lang][key] = string;
|
||||
auto exist = std::find(knownKeys.begin(), knownKeys.end(), key);
|
||||
if(exist == knownKeys.end()) knownKeys.push_back(key);
|
||||
}
|
||||
|
||||
++itFiles;
|
||||
}
|
||||
|
||||
// Now prepare output file
|
||||
auto itLang = strings.begin();
|
||||
std::string bufferOut = "";
|
||||
while(itLang != strings.end()) {
|
||||
File langOut(flags["output"] + FILE_PATH_SEP + "language_" + itLang->first + ".language");
|
||||
bufferOut.clear();
|
||||
|
||||
auto itKeys = knownKeys.begin();
|
||||
while(itKeys != knownKeys.end()) {
|
||||
auto key = *itKeys;
|
||||
auto exist = itLang->second.find(key);
|
||||
if(exist == itLang->second.end()) {
|
||||
std::cout << "Language " << itLang->first << " is missing key " << key << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::cout << "bruh " << exist->second << std::endl;
|
||||
bufferOut += exist->first + "|" + exist->second + "|";
|
||||
++itKeys;
|
||||
}
|
||||
|
||||
// Write out.
|
||||
if(!langOut.writeString(bufferOut)) {
|
||||
std::cout << "Failed to create output file \"" + langOut.filename + "\"" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
++itLang;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -126,6 +126,46 @@ bool_t File::readString(std::string *out) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t File::readAhead(char *buffer, size_t max, char needle) {
|
||||
assertNotNull(buffer);
|
||||
assertTrue(max > 0);
|
||||
|
||||
if(!this->isOpen()) {
|
||||
if(!this->open(FILE_MODE_READ)) return 0;
|
||||
}
|
||||
assertTrue(this->mode == FILE_MODE_READ);
|
||||
|
||||
// Buffer
|
||||
size_t pos = ftell(this->file);
|
||||
size_t amountLeftToRead = mathMin<size_t>(max, this->length - pos);
|
||||
char temporary[FILE_BUFFER_SIZE];
|
||||
size_t n = 0;
|
||||
|
||||
while(amountLeftToRead > 0) {
|
||||
size_t toRead = mathMin<size_t>(amountLeftToRead, FILE_BUFFER_SIZE);
|
||||
amountLeftToRead -= toRead;
|
||||
// Read bytes
|
||||
size_t read = fread(temporary, sizeof(char), toRead, this->file);
|
||||
|
||||
// Read error?
|
||||
if(toRead != read) return 0;
|
||||
|
||||
// Did we read the needle?
|
||||
size_t i = 0;
|
||||
while(i < read) {
|
||||
char c = temporary[i++];
|
||||
if(c == needle) {
|
||||
return n;
|
||||
} else {
|
||||
buffer[n++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Needle was not found.
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool_t File::writeString(std::string in) {
|
||||
if(!this->isOpen()) {
|
||||
if(!this->open(FILE_MODE_WRITE)) return false;
|
||||
@ -143,6 +183,11 @@ bool_t File::writeRaw(char *data, size_t len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void File::setPosition(size_t n) {
|
||||
fseek(this->file, 0, SEEK_SET);
|
||||
fseek(this->file, n, SEEK_CUR);
|
||||
}
|
||||
|
||||
File::~File() {
|
||||
if(this->file != nullptr) this->close();
|
||||
}
|
@ -33,14 +33,14 @@ namespace Dawn {
|
||||
class File {
|
||||
private:
|
||||
enum FileMode mode;
|
||||
size_t length;
|
||||
|
||||
public:
|
||||
FILE *file = nullptr;
|
||||
static std::string normalizeSlashes(std::string str);
|
||||
static void mkdirp(std::string path);
|
||||
|
||||
std::string filename;
|
||||
size_t length;
|
||||
FILE *file = nullptr;
|
||||
|
||||
/**
|
||||
* Constructs a new File interface class.
|
||||
@ -95,6 +95,20 @@ namespace Dawn {
|
||||
*/
|
||||
bool_t readString(std::string *out);
|
||||
|
||||
/**
|
||||
* Reads ahead from the current position to a specific needle (character).
|
||||
*
|
||||
* @param buffer Buffer to output read chars to.
|
||||
* @param max Max length of the buffer / amount of chars to read ahead.
|
||||
* @param needle The character (needle) to look for.
|
||||
* @return Amount of chars read, or <= 0 on error.
|
||||
*/
|
||||
size_t readAhead(
|
||||
char *buffer,
|
||||
size_t max,
|
||||
char needle
|
||||
);
|
||||
|
||||
/**
|
||||
* Writes the entire contents of a string to a file.
|
||||
*
|
||||
@ -111,6 +125,8 @@ namespace Dawn {
|
||||
*/
|
||||
bool_t writeRaw(char *data, size_t );
|
||||
|
||||
void setPosition(size_t pos);
|
||||
|
||||
~File();
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user