Converted tooling to C.
This commit is contained in:
@ -1,12 +0,0 @@
|
||||
const args = process.argv.splice(2).reduce((x,y) => {
|
||||
const bits = y.split('=');
|
||||
const name = bits[0].replace('--', '');
|
||||
const val = bits[1];
|
||||
|
||||
x[name] = val;
|
||||
return x;
|
||||
}, {});
|
||||
|
||||
module.exports = {
|
||||
args
|
||||
};
|
@ -10,4 +10,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stb_image.h>
|
||||
#include <stb_image_resize.h>
|
||||
#include <stb_image_write.h>
|
||||
|
@ -55,4 +55,67 @@ void assetReadString(FILE *file, char *buffer) {
|
||||
length = ftell(file);// Get our current position (the end)
|
||||
fseek(file, 0, SEEK_SET);// Reset the seek
|
||||
fread(buffer, 1, length, file);// Read all the bytes
|
||||
}
|
||||
|
||||
void fileGetDirectory(char *file, char* buffer) {
|
||||
char *c, *p;
|
||||
int32_t i;
|
||||
p = strrchr(file, FILE_PATH_SEP);
|
||||
c = file;
|
||||
i = 0;
|
||||
do {
|
||||
buffer[i++] = *c;
|
||||
} while(++c < p);
|
||||
buffer[i] = '\0';
|
||||
}
|
||||
|
||||
bool fileListChildren(
|
||||
char *directory,
|
||||
char *buffer,
|
||||
int32_t *count,
|
||||
uint8_t *types,
|
||||
char **children
|
||||
) {
|
||||
#if defined(_MSC_VER)
|
||||
WIN32_FIND_DATA fdFile;
|
||||
HANDLE hFind = NULL;
|
||||
char sPath[2048];
|
||||
int32_t i;
|
||||
|
||||
// Append wildcard
|
||||
sprintf(sPath, "%s\\*.*", directory);
|
||||
|
||||
// Scan first
|
||||
if((hFind = FindFirstFile(sPath, &fdFile)) == INVALID_HANDLE_VALUE) {
|
||||
printf("Path not found: [%s]\n", directory);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Iterate
|
||||
i = 0;
|
||||
do {
|
||||
if(
|
||||
strcmp(fdFile.cFileName, ".") == 0 ||
|
||||
strcmp(fdFile.cFileName, "..") == 0
|
||||
) continue;
|
||||
|
||||
// Get Full path.
|
||||
sprintf(sPath, "%s\\%s", directory, fdFile.cFileName);
|
||||
|
||||
//Is the entity a File or Folder?
|
||||
if(fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
types[i] = FILE_CHILD_TYPE_DIR;
|
||||
} else {
|
||||
types[i] = FILE_CHILD_TYPE_FILE;
|
||||
}
|
||||
|
||||
children[i] = buffer + (i * FILE_CHILD_NAME_MAX);
|
||||
strcpy(children[i], fdFile.cFileName);
|
||||
i++;
|
||||
} while(FindNextFile(hFind, &fdFile));
|
||||
|
||||
*count = i;
|
||||
return true;
|
||||
#else
|
||||
#endif
|
||||
}
|
@ -8,8 +8,14 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
#define FILE_CHILD_TYPE_DIR 0x00
|
||||
#define FILE_CHILD_TYPE_FILE 0x01
|
||||
#define FILE_CHILD_NAME_MAX 512
|
||||
#define FILE_CHILD_COUNT_MAX 64
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#define getcwd _getcwd
|
||||
#define FILE_PATH_SEP '\\'
|
||||
#elif defined(__GNUC__)
|
||||
@ -21,4 +27,14 @@ void fileNormalizeSlashes(char *string);
|
||||
|
||||
void fileMkdirp(char *path);
|
||||
|
||||
void assetReadString(FILE *file, char *buffer);
|
||||
void assetReadString(FILE *file, char *buffer);
|
||||
|
||||
void fileGetDirectory(char *file, char* buffer);
|
||||
|
||||
bool fileListChildren(
|
||||
char *directory,
|
||||
char *buffer,
|
||||
int32_t *count,
|
||||
uint8_t *types,
|
||||
char **children
|
||||
);
|
@ -1,19 +0,0 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const mkdirp = dir => {
|
||||
const resolved = path.resolve(dir);
|
||||
const resolvedDir = path.dirname(resolved);
|
||||
const bits = resolvedDir.split(path.sep);
|
||||
let running = '';
|
||||
|
||||
bits.forEach(bit => {
|
||||
running += bit;
|
||||
if(!fs.existsSync(running)) fs.mkdirSync(running);
|
||||
running += path.sep;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mkdirp
|
||||
}
|
55
tools/utils/image.c
Normal file
55
tools/utils/image.c
Normal 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.h"
|
||||
|
||||
#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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,3 +6,13 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include "file.h"
|
||||
|
||||
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
|
||||
);
|
@ -1,103 +0,0 @@
|
||||
const { PNG } = require("pngjs");
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
/**
|
||||
* Loads an image into memory.
|
||||
* @param image Image to load
|
||||
* @returns A promise that resolves to the loaded image.
|
||||
*/
|
||||
const imageLoad = (image) => new Promise(resolve => {
|
||||
fs.createReadStream(image)
|
||||
.pipe(new PNG({ filterType: 4 }))
|
||||
.on("parsed", function () {
|
||||
// Normalize
|
||||
const pixels = [];
|
||||
for(let y = 0; y < this.height; y++) {
|
||||
for(let x = 0; x < this.width; x++) {
|
||||
const idx = (this.width * y + x) << 2;
|
||||
const r = this.data[idx];
|
||||
const g = this.data[idx + 1];
|
||||
const b = this.data[idx + 2];
|
||||
const a = this.data[idx + 3];
|
||||
|
||||
pixels.push({ r, g, b, a });
|
||||
}
|
||||
}
|
||||
resolve({ pixels, width: this.width, height: this.height });
|
||||
})
|
||||
;
|
||||
});
|
||||
|
||||
/**
|
||||
* Writes an image to an output file.
|
||||
* @param image Image to write.
|
||||
* @param file File to write to.
|
||||
* @returns A promise that, when resolved, has saved the image.
|
||||
*/
|
||||
const imageWrite = (image, file) => new Promise(resolve => {
|
||||
const png = new PNG({ width: image.width, height: image.height });
|
||||
png.width = image.width;
|
||||
png.height = image.height;
|
||||
|
||||
for(let y = 0; y < image.height; y++) {
|
||||
for(let x = 0; x < image.width; x++) {
|
||||
const i = (image.width * y + x);
|
||||
const idx = i << 2;
|
||||
|
||||
const pixel = image.pixels[i];
|
||||
png.data[idx] = pixel.r;
|
||||
png.data[idx + 1] = pixel.g;
|
||||
png.data[idx + 2] = pixel.b;
|
||||
png.data[idx + 3] = pixel.a;
|
||||
}
|
||||
}
|
||||
|
||||
png.pack().pipe(fs.createWriteStream(file))
|
||||
.on('close', () => resolve(true))
|
||||
;
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a blank image
|
||||
* @param width Width of the image.
|
||||
* @param height Height of the image.
|
||||
* @param fill Optional pixel to fill with, defaults to 0,0,0,0
|
||||
* @returns The newly created image.
|
||||
*/
|
||||
const imageCreate = (width, height, pixel) => {
|
||||
if(!pixel || !pixel.r) pixel = { r:0, g:0, b:0, a:0 };
|
||||
const pixels = [];
|
||||
for(let i = 0; i < width * height; i++) pixels.push({ ...pixel });
|
||||
return { pixels, width, height };
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies an area of a source image into a target image.
|
||||
* @param target Target image to copy into.
|
||||
* @param source Source image to copy from.
|
||||
* @param tx Target X position to copy into
|
||||
* @param ty Target Y position to copy into
|
||||
* @param sub Optional source area to use, defined as { x, y, width, height }.
|
||||
*/
|
||||
const imageCopy = (target, source, tx, ty, sub) => {
|
||||
if(!sub) sub = { x: 0, y: 0, width: source.width, height: source.height };
|
||||
|
||||
for(let x = sub.x; x < sub.x+sub.width; x++) {
|
||||
for(let y = sub.y; y < sub.y+sub.height; y++) {
|
||||
let absX = x - sub.x + tx;
|
||||
let absY = y - sub.y + ty;
|
||||
if(absX > target.width || absY > target.height) continue;
|
||||
let ti = absY * target.width + absX;
|
||||
let si = y * source.width + x;
|
||||
target.pixels[ti] = { ...source.pixels[si] };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
imageWrite,
|
||||
imageCreate,
|
||||
imageLoad,
|
||||
imageCopy
|
||||
}
|
@ -7,88 +7,204 @@
|
||||
|
||||
#include "xml.h"
|
||||
|
||||
void xmlParseElement(xmlnode_t *node, char *string) {
|
||||
int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i) {
|
||||
char c;
|
||||
int32_t i, j;
|
||||
uint8_t state;
|
||||
int32_t level = 0;
|
||||
uint8_t doing = XML_DOING_NOTHING;
|
||||
bool insideTag = false;
|
||||
char* buffer = malloc(sizeof(char) * XML_TEXT_BUFFER_MAX);
|
||||
int32_t bufferLength = 0;
|
||||
|
||||
node->attributeCount = 0;
|
||||
xml->value = NULL;
|
||||
xml->attributeCount = 0;
|
||||
|
||||
i = 0;
|
||||
state = XML_STATE_NOTHING;
|
||||
while(c = string[i++]) {
|
||||
switch(state) {
|
||||
case XML_STATE_NOTHING:
|
||||
if(c != '<') continue;
|
||||
node->start = string + (i - 1);
|
||||
state = XML_STATE_PARSING_NAME;
|
||||
break;
|
||||
xml->children = malloc(sizeof(xml_t) * XML_CHILD_COUNT_MAX);
|
||||
xml->childrenCount = 0;
|
||||
|
||||
case XML_STATE_PARSING_NAME:
|
||||
if(c == ' ' || c == '\n' || c == '\r') continue;
|
||||
|
||||
j = i - 1;
|
||||
while(c = string[j++]) {
|
||||
if(c == ' ') break;
|
||||
node->name[j] = c;
|
||||
}
|
||||
i = j;
|
||||
state = XML_STATE_PARSING_ATTRIBUTES;
|
||||
break;
|
||||
|
||||
case XML_STATE_PARSING_ATTRIBUTES:
|
||||
if(c == ' ' || c == '\n' || c == '\r') continue;
|
||||
if(c == '>') {
|
||||
node->internal = string + i;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse Name
|
||||
node->attributeNames[node->attributeCount] = string + (i - 1);
|
||||
node->attributeNameLengths[node->attributeCount] = 0;
|
||||
while(c == ' ' && c == '\n' && c == '\r' && c != '>' && c != '=' && c != '\0') {
|
||||
c = string[i++];
|
||||
node->attributeNameLengths[node->attributeCount]++;
|
||||
}
|
||||
|
||||
if(c == '>') {
|
||||
i--;
|
||||
node->attributeValues[node->attributeCount] = NULL;
|
||||
node->attributeValueLengths[node->attributeCount] = 0;
|
||||
node->attributeCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait for = sign
|
||||
while(c == ' ' || c == '\n' || c == '\r') c = string[i++];
|
||||
|
||||
// Handle booleans
|
||||
if(c != '=') {
|
||||
node->attributeValues[node->attributeCount] = NULL;
|
||||
node->attributeValueLengths[node->attributeCount] = 0;
|
||||
node->attributeCount++;
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
node->attributeValues[node->attributeCount] = string + i;
|
||||
node->attributeValueLengths[node->attributeCount] = 0;
|
||||
do {
|
||||
c = string[i++];
|
||||
node->attributeNameLengths[node->attributeCount]++;
|
||||
if(c == '\0' || c == '"') break;
|
||||
if(c == '\\') {
|
||||
i++;
|
||||
node->attributeNameLengths[node->attributeCount]++;
|
||||
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(insideTag) {
|
||||
i = xmlLoadChild(xml->children + xml->childrenCount++, data, i-1);
|
||||
doing = XML_PARSING_CHILD;
|
||||
} else {
|
||||
doing = XML_PARSING_TAG_NAME;
|
||||
level++;
|
||||
insideTag = true;
|
||||
}
|
||||
} while(c);
|
||||
|
||||
node->attributeCount++;
|
||||
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 = 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 = 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 = 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 = 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
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';
|
||||
}
|
@ -9,26 +9,59 @@
|
||||
#include "common.h"
|
||||
#include "file.h"
|
||||
|
||||
#define XML_NODE_CHILD_MAX 32
|
||||
#define XML_NODE_NAME_MAX 32
|
||||
#define XML_NODE_ATTRIBUTES_MAX 32
|
||||
#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_STATE_NOTHING 0x00
|
||||
#define XML_STATE_PARSING_NAME 0x01
|
||||
#define XML_STATE_PARSING_ATTRIBUTES 0x02
|
||||
#define XML_TEXT_BUFFER_MAX 256
|
||||
#define XML_CHILD_COUNT_MAX 16
|
||||
#define XML_ATTRIBUTE_MAX 16
|
||||
|
||||
typedef struct {
|
||||
char *start;
|
||||
char *internal;
|
||||
char name[XML_NODE_NAME_MAX];
|
||||
typedef struct _xml_t xml_t;
|
||||
|
||||
char *attributeNames[XML_NODE_ATTRIBUTES_MAX];
|
||||
uint8_t attributeNameLengths[XML_NODE_ATTRIBUTES_MAX];
|
||||
char *attributeValues[XML_NODE_ATTRIBUTES_MAX];
|
||||
uint8_t attributeValueLengths[XML_NODE_ATTRIBUTES_MAX];
|
||||
typedef struct _xml_t {
|
||||
char *node;
|
||||
char *value;
|
||||
|
||||
char *attributeNames[XML_ATTRIBUTE_MAX];
|
||||
char *attributeDatas[XML_ATTRIBUTE_MAX];
|
||||
uint8_t attributeCount;
|
||||
} xmlnode_t;
|
||||
|
||||
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);
|
||||
|
||||
void xmlParseElement(xmlnode_t *node, char *string);
|
||||
/**
|
||||
* 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);
|
||||
|
||||
int16_t xmlGetAttributeByName(xml_t *xml, char *name);
|
||||
|
||||
bool xmlIsWhitespace(char c);
|
Reference in New Issue
Block a user