Tool refactoring

This commit is contained in:
2023-03-22 18:54:22 -07:00
parent f267131d6b
commit 9e2f093527
41 changed files with 1871 additions and 1664 deletions

View File

@ -0,0 +1,17 @@
# Copyright (c) 2023 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
set(D ${CMAKE_CURRENT_LIST_DIR})
set(
DAWN_TOOL_SOURCES
${D}/DawnTool.cpp
${D}/File.cpp
${D}/Language.cpp
${D}/CodeGen.cpp
CACHE INTERNAL
${DAWN_CACHE_TARGET}
)

120
archive/tools/util/csv.cpp Normal file
View File

@ -0,0 +1,120 @@
/**
* Copyright (c) 2022 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "csv.hpp"
char * csvGetCell(csv_t *csv, int32_t row, int32_t cell) {
return csv->rows[(row * CSV_COLUMN_COUNT_MAX) + cell];
}
void csvParse(char *string, csv_t *csv) {
char c;
size_t i, j, length;
csvparsestate_t state;
int32_t rowCellCount;
length = strlen(string);
csv->buffer = (char *)malloc(sizeof(char) * (length+1) * CSV_COLUMN_COUNT_MAX * CSV_ROW_COUNT_MAX);
csv->cellCounts = (int32_t *)malloc(sizeof(int32_t) * CSV_ROW_COUNT_MAX);
csv->rows = (char**)malloc(sizeof(char*) * CSV_ROW_COUNT_MAX * CSV_COLUMN_COUNT_MAX);
i = 0;
j = 0;
rowCellCount = 0;
csv->rowCount = 0;
state = CSV_PARSE_STATE_FIND_CELL;
while(i < length) {
c = string[i++];
// What are we doing
switch(state) {
case CSV_PARSE_STATE_FIND_CELL:
if(c == '"') {
state = CSV_PARSE_STATE_PARSE_CELL_WITH_QUOTES;
csv->rows[(csv->rowCount * CSV_COLUMN_COUNT_MAX) + rowCellCount] = csv->buffer + j;
rowCellCount++;
continue;
} else if(c == '\r' || c == '\n') {
// Newline (todo: is this a blank line?)
state = CSV_PARSE_STATE_LINE_END;
continue;
} else if(c == ',') {
csv->rows[(csv->rowCount * CSV_COLUMN_COUNT_MAX) + rowCellCount] = csv->buffer + j;
csv->buffer[j++] = '\0';
rowCellCount++;
continue;
} else {
state = CSV_PARSE_STATE_PARSE_CELL;
csv->rows[(csv->rowCount * CSV_COLUMN_COUNT_MAX) + rowCellCount] = csv->buffer + j;
csv->buffer[j++] = c;
rowCellCount++;
continue;
}
case CSV_PARSE_STATE_PARSE_CELL:
if(c == '\r' || c == '\n') {
state = CSV_PARSE_STATE_LINE_END;
csv->buffer[j++] = '\0';
continue;
} else if(c == ',') {
state = CSV_PARSE_STATE_FIND_CELL;
csv->buffer[j++] = '\0';
continue;
}
csv->buffer[j++] = c;
continue;
case CSV_PARSE_STATE_PARSE_CELL_WITH_QUOTES:
if((c == '\\' && string[i] == '"') || (c == '"' && string[i] == '"')) {
// Handle escaped quotes. I normally see [\"] but excel does [""] in
// most cases
csv->buffer[j++] = '"';
i++;
continue;
} else if(c == '"') {
// Handle end of quoted string
state = CSV_PARSE_STATE_FIND_CELL;
csv->buffer[j++] = '\0';
// Because we tend to do [",] at the end of a quoted cell, we do this
// to prevent [,,] cases being treated the same
if(string[i] == ',') i++;
continue;
}
// Normal character.
csv->buffer[j++] = c;
continue;
case CSV_PARSE_STATE_LINE_END:
// Skip blanks
if(c == '\r' || c == '\n') continue;
csv->cellCounts[csv->rowCount] = rowCellCount;
csv->rowCount++;
rowCellCount = 0;
state = CSV_PARSE_STATE_FIND_CELL;
i--;
continue;
default:
printf("Error occured during parse operation.");
free(NULL);
}
}
csv->buffer[j++] = '\0';
if(rowCellCount != 0) {
csv->cellCounts[csv->rowCount] = rowCellCount;
csv->rowCount++;
}
}
void csvDispose(csv_t *csv) {
free(csv->buffer);
free(csv->cellCounts);
free(csv->rows);
}

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) 2022 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dawnsharedlibs.hpp"
#include "string.h"
#define CSV_ROW_COUNT_MAX 128
#define CSV_COLUMN_COUNT_MAX 16
typedef enum {
CSV_PARSE_STATE_FIND_CELL,//0
CSV_PARSE_STATE_PARSE_CELL_WITH_QUOTES,
CSV_PARSE_STATE_PARSE_CELL,//2
CSV_PARSE_STATE_LINE_END
} csvparsestate_t;
typedef struct {
char *buffer;
char **rows;
int32_t rowCount;
int32_t *cellCounts;
} csv_t;
char * csvGetCell(csv_t *csv, int32_t row, int32_t cell);
void csvParse(char *string, csv_t *csv);
void csvDispose(csv_t *csv);

View File

@ -0,0 +1,55 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "image.hpp"
#ifndef STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#endif
#ifndef STB_IMAGE_RESIZE_IMPLEMENTATION
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include <stb_image_resize.h>
#endif
#ifndef STB_IMAGE_WRITE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
#endif
void imageCopy(
uint8_t *source, int32_t sourceWidth, int32_t sourceHeight,
uint8_t *dest, int32_t destWidth, int32_t destHeight,
int32_t cropX, int32_t cropY, int32_t cropWidth, int32_t cropHeight,
int32_t pasteX, int32_t pasteY,
int32_t channels
) {
int32_t x, y, c;
int32_t absX, absY;
int32_t sourceIndex, targetIndex;
if(cropX == -1) cropX = 0;
if(cropY == -1) cropY = 0;
if(cropWidth == -1) cropWidth = sourceWidth;
if(cropHeight == -1) cropHeight = sourceHeight;
if(pasteX == -1) pasteX = 0;
if(pasteY == -1) pasteY = 0;
for(x = cropX; x < cropX + cropWidth; x++) {
for(y = cropY; y < cropY + cropHeight; y++) {
absX = x - cropX + pasteX;
absY = y - cropY + pasteY;
if(absX >= destWidth || absY >= destHeight || absX < 0 || absY < 0)continue;
targetIndex = absY * destWidth + absX;
sourceIndex = y * sourceWidth + x;
for(c = 0; c < channels; c++) {
dest[(targetIndex*channels) + c] = source[(sourceIndex*channels) + c];
}
}
}
}

View File

@ -0,0 +1,39 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dawnsharedlibs.hpp"
#include "file.hpp"
#include <stb_image.h>
#include <stb_image_resize.h>
#include <stb_image_write.h>
/**
* Unused currently.
*
* @param source
* @param sourceWidth
* @param sourceHeight
* @param dest
* @param destWidth
* @param destHeight
* @param cropX
* @param cropY
* @param cropWidth
* @param cropHeight
* @param pasteX
* @param pasteY
* @param channels
*/
void imageCopy(
uint8_t *source, int32_t sourceWidth, int32_t sourceHeight,
uint8_t *dest, int32_t destWidth, int32_t destHeight,
int32_t cropX, int32_t cropY, int32_t cropWidth, int32_t cropHeight,
int32_t pasteX, int32_t pasteY,
int32_t channels
);

View File

@ -0,0 +1,36 @@
/**
* Copyright (c) 2023 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dawnsharedlibs.hpp"
/**
* Remove all instances of a character from a C-Styled string.
*
* @param string String to remove characters from.
* @param remove Character to remove.
*/
static inline void stringRemoveAll(char *string, char remove) {
size_t len = strlen(string);
size_t i, j;
i = 0;
while(i < len) {
char c = string[i];
if(c != remove) {
i++;
continue;
}
j = i + 1;
while(j < len) {
string[j-1] = string[j];
j++;
}
len--;
}
}

231
archive/tools/util/xml.cpp Normal file
View File

@ -0,0 +1,231 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "xml.hpp"
int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i) {
char c;
int32_t level = 0;
uint8_t doing = XML_DOING_NOTHING;
uint8_t doingBeforeComment;
bool insideTag = false;
char* buffer = (char *)malloc(sizeof(char) * XML_TEXT_BUFFER_MAX);
int32_t bufferLength = 0;
xml->value = NULL;
xml->attributeCount = 0;
xml->children = (xml_t *)malloc(sizeof(xml_t) * XML_CHILD_COUNT_MAX);
xml->childrenCount = 0;
while(c = data[i++]) {
switch(doing) {
case XML_DOING_NOTHING:
// Look for either an opening tag (<) or a word for a value.
if(c == '>') continue;
if(c == '<') {
if(data[i] == '!' && data[i+1] == '-' && data[i+2] == '-') {
doingBeforeComment = doing;
doing = XML_PARSING_COMMENT;
i += 3;
} else if(insideTag) {
i = xmlLoadChild(xml->children + xml->childrenCount++, data, i-1);
doing = XML_PARSING_CHILD;
} else {
doing = XML_PARSING_TAG_NAME;
level++;
insideTag = true;
}
continue;
}
if(xmlIsWhitespace(c)) continue;
doing = XML_PARSING_VALUE;
buffer[bufferLength++] = c;
break;
case XML_PARSING_TAG_NAME:
// Just keep reading until we either hit a space (end of the tag name)
// or a closing tag value, either / or >
if(xmlIsWhitespace(c) || c == '>' || c == '/') {
buffer[bufferLength] = '\0';
xml->node = buffer;
buffer = (char *)malloc(sizeof(char) * XML_TEXT_BUFFER_MAX);
bufferLength = 0;
if(c == '/') {
level--;
insideTag = false;
doing = XML_PARSING_CLOSE;
} else {
doing = c == '>' ? XML_DOING_NOTHING : XML_LOOKING_FOR_ATTRIBUTE;
}
continue;
}
buffer[bufferLength++] = c;
break;
case XML_LOOKING_FOR_ATTRIBUTE:
// Look until we hit either the end of a tag, or the attribute itself
if(xmlIsWhitespace(c) || c == '>' || c == '/' || c == '=') {
if(c == '>' || c == '/') {
doing = XML_DOING_NOTHING;
if(c == '/') {
level--;
insideTag = false;
doing = XML_PARSING_CLOSE;
}
} else if(c == '=') {
doing = XML_LOOKING_FOR_ATTRIBUTE_VALUE;
} else {
doing = XML_LOOKING_FOR_ATTRIBUTE;
}
if(bufferLength > 0) {
buffer[bufferLength] = '\0';
xml->attributeNames[xml->attributeCount++] = buffer;
xml->attributeDatas[xml->attributeCount] = NULL;
buffer = (char *)malloc(sizeof(char) * XML_TEXT_BUFFER_MAX);
bufferLength = 0;
}
continue;
}
buffer[bufferLength++] = c;
break;
case XML_LOOKING_FOR_ATTRIBUTE_VALUE:
// Keep looking until we find a quote mark
if(xmlIsWhitespace(c)) continue;
if(c == '>' || c == '/') {
doing = XML_DOING_NOTHING;
insideTag = false;
continue;
}
if(c != '"') continue;
doing = XML_PARSING_ATTRIBUTE_VALUE;
break;
case XML_PARSING_ATTRIBUTE_VALUE:
// Parse the attribute value until we find a quote mark.
if(c == '"') {
doing = XML_LOOKING_FOR_ATTRIBUTE;
buffer[bufferLength] = '\0';
xml->attributeDatas[xml->attributeCount - 1] = buffer;
buffer = (char *)malloc(sizeof(char) * XML_TEXT_BUFFER_MAX);
bufferLength = 0;
continue;
}
buffer[bufferLength++] = c;
break;
case XML_PARSING_VALUE:
// Keep parsing child until we find a < for an opening/closing tag.
if(c == '<') {
// In HTML Spec there could be a child here but not in XML spec.
doing = XML_PARSING_CLOSE;
buffer[bufferLength] = '\0';
bufferLength = 0;
xml->value = buffer;
buffer = (char *)malloc(sizeof(char) * XML_TEXT_BUFFER_MAX);
continue;
}
buffer[bufferLength++] = c;
break;
case XML_PARSING_CHILD:
if(c == '<') {
// Read ahead and confirm this is a close or not
if(data[i] == '/') {
doing = XML_PARSING_CLOSE;
continue;
}
if(data[i] == '!' && data[i+1] == '-' && data[i+2] == '-') {
doingBeforeComment = doing;
doing = XML_PARSING_COMMENT;
i += 3;
continue;
}
// Likely another child.
i = xmlLoadChild(xml->children + xml->childrenCount++, data, i-1);
}
if(xmlIsWhitespace(c)) continue;
// In HTML Spec there's a chance for there to be a value here, but not
// in the XML spec.
break;
case XML_PARSING_CLOSE:
// Just keep parsing until the tag closer finishes.
if(c != '>') continue;
doing = XML_DOING_NOTHING;
//TODO: Return index or something?
free(buffer);
return i;
case XML_PARSING_COMMENT:
if(c != '-') continue;
if(data[i] != '-') continue;
if(data[i+1] != '>') continue;
i += 2;
doing = doingBeforeComment;
break;
default:
break;
}
}
free(buffer);
return i;
}
void xmlLoad(xml_t *xml, char *data) {
xmlLoadChild(xml, data, 0);
}
void xmlDispose(xml_t *xml) {
uint8_t i;
// Dispose children recursively
for(i = 0; i < xml->childrenCount; i++) {
xmlDispose(xml->children + i);
}
// Free children array.
free(xml->children);
// Dispose attributes
for(i = 0; i < xml->attributeCount; i++) {
free(xml->attributeNames[i]);
if((xml->attributeDatas + i) != NULL) {
free(xml->attributeDatas[i]);
}
}
free(xml->node);
if(xml-> value != NULL) free(xml->value);
}
int16_t xmlGetAttributeByName(xml_t *xml, char *name) {
int16_t i;
for(i = 0; i < xml->attributeCount; i++) {
if(strcmp(xml->attributeNames[i], name) == 0) return i;
}
return -1;
}
bool xmlIsWhitespace(char c) {
return c == ' ' || c == '\r' || c == '\n' || c == '\t';
}

View File

@ -0,0 +1,81 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dawnsharedlibs.hpp"
#include "file.hpp"
#define XML_DOING_NOTHING 0x00
#define XML_PARSING_TAG_NAME 0x01
#define XML_LOOKING_FOR_ATTRIBUTE 0x02
#define XML_PARSING_ATTRIBUTE_NAME 0x03
#define XML_LOOKING_FOR_ATTRIBUTE_VALUE 0x04
#define XML_PARSING_ATTRIBUTE_VALUE 0x05
#define XML_PARSING_VALUE 0x06
#define XML_PARSING_CHILD 0x07
#define XML_PARSING_CLOSE 0x08
#define XML_PARSING_COMMENT 0x09
#define XML_TEXT_BUFFER_MAX 2048
#define XML_CHILD_COUNT_MAX 128
#define XML_ATTRIBUTE_MAX 128
typedef struct _xml_t xml_t;
typedef struct _xml_t {
char *node;
char *value;
char *attributeNames[XML_ATTRIBUTE_MAX];
char *attributeDatas[XML_ATTRIBUTE_MAX];
uint8_t attributeCount;
xml_t *children;
uint8_t childrenCount;
} xml_t;
/**
* Load an XML child from a string buffer.
*
* @param xml XML to load.
* @param data Data to parse
* @param i Character index within the data
* @return The index in the data string this XML node ends.
*/
int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i);
/**
* Load an XML String into an XML memory.
*
* @param xml XML to load into.
* @param data XML string.
*/
void xmlLoad(xml_t *xml, char *data);
/**
* Dispose a previously loaded XML.
*
* @param xml XML to dispose.
*/
void xmlDispose(xml_t *xml);
/**
* Find an attribute index by its name.
*
* @param xml Xml node to get the attribute from.
* @param name The name of the attribute you're trying to find.
* @return -1 if not found, otherwise the index of the attribute within array.
*/
int16_t xmlGetAttributeByName(xml_t *xml, char *name);
/**
* Checks if a given character is a whitespace character or not.
*
* @param c Character to check if a whitespace.
* @return True if whitespace, otherwise false.
*/
bool xmlIsWhitespace(char c);