Skip to content
Permalink
Browse files

Now LSP plugins do not need expat library to generate resources

  • Loading branch information
sadko4u committed Oct 30, 2019
1 parent 120ba4e commit d444686924312c798c65d2a39a8c37c000527c50
Showing with 121 additions and 190 deletions.
  1. +119 −183 include/utils/resource_gen/xml.h
  2. +2 −7 src/utils/resource_gen.cpp
@@ -12,11 +12,7 @@
#include <data/cvector.h>
#include <core/stdlib/stdio.h>

#if defined(PLATFORM_WINDOWS)
#include <msxml.h>
#else
#include <expat.h>
#endif /* PLATFORM_WINDOWS */
#include <core/files/xml/PushParser.h>

#include <utils/resource_gen/resource.h>
#include <utils/resource_gen/wdict.h>
@@ -27,210 +23,150 @@ namespace lsp
namespace resgen
{

typedef struct xml_parser_t
class XMLPreparser: public xml::IXMLHandler
{
FILE *out;
size_t pad_left;
bool new_line;
cvector<xml_word_t> *dict;
} xml_parser_t;
private:
XMLPreparser & operator = (const XMLPreparser &);

static void xml_pre_start_element_handler(void *userData, const XML_Char *name, const XML_Char **atts)
{
xml_parser_t *parser = reinterpret_cast<xml_parser_t *>(userData);
private:
cvector<xml_word_t> *pDict;

// Preprocess name
res_dict_add(parser->dict, name);
public:
explicit XMLPreparser(cvector<xml_word_t> *dict): pDict(dict) {}
virtual ~XMLPreparser() { pDict = NULL; }

// Preprocess parameters
for (const XML_Char **p = atts; *p != NULL; p++)
res_dict_add(parser->dict, *p);
}
public:
virtual status_t start_element(const LSPString *name, const LSPString * const *atts)
{
// Preprocess element name
const char *s = name->get_utf8();
if ((s == NULL) || (!res_dict_add(pDict, s)))
return STATUS_NO_MEM;

// Preprocess parameters
for ( ; *atts != NULL; ++atts)
{
s = (*atts)->get_utf8();
if ((s == NULL) || (!res_dict_add(pDict, s)))
return STATUS_NO_MEM;
}
return STATUS_OK;
}
};

static void xml_pre_end_element_handler(void *userData, const XML_Char *name)
class XMLTranslator: public xml::IXMLHandler
{
xml_parser_t *parser = reinterpret_cast<xml_parser_t *>(userData);
private:
XMLTranslator & operator = (const XMLTranslator &);

// Preprocess name
res_dict_add(parser->dict, name);
}

static void xml_padding(const xml_parser_t *parser)
{
for (size_t i=0; i<parser->pad_left; ++i)
fputc('\t', parser->out);
}
private:
FILE *pOut;
cvector<xml_word_t> *pDict;
size_t nPadLeft;
bool bNewLine;

static void xml_start_element_handler(void *userData, const XML_Char *name, const XML_Char **atts)
{
xml_parser_t *parser = reinterpret_cast<xml_parser_t *>(userData);

// Calculate number of parameters
size_t count = 0;
for (const XML_Char **p = atts; *p != NULL; p++)
{
if (*(++p) == NULL)
break;
count++;
}

// Output tag header
fputc('\n', parser->out);
xml_padding(parser);
fprintf(parser->out, "O(");
encode_word(parser->out, parser->dict, name);
fprintf(parser->out, ", \"\\x%02x\")", int(count));

// Now output parameters
while (*atts != NULL)
{
const XML_Char *k = *atts++;
const XML_Char *v = *atts++;
if ((k != NULL) && (v != NULL))
private:
void xml_padding()
{
fprintf(parser->out, " P(");
encode_word(parser->out, parser->dict, k);
fprintf(parser->out, ", ");
encode_word(parser->out, parser->dict, v);
fprintf(parser->out, ")");
for (size_t i=0; i<nPadLeft; ++i)
fputc('\t', pOut);
}
}
parser->pad_left ++;
parser->new_line = false;
}

static void xml_end_element_handler(void *userData, const XML_Char *name)
{
xml_parser_t *parser = reinterpret_cast<xml_parser_t *>(userData);

parser->pad_left --;

if (parser->new_line)
{
fputc('\n', parser->out);
xml_padding(parser);
}
else
fputc(' ', parser->out);
fprintf(parser->out, "C(");
encode_word(parser->out, parser->dict, name);
fprintf(parser->out, ")");

parser->new_line = true;
}

static int preprocess_xml_resource(const scan_resource_t *resource, cvector<xml_word_t> *dict)
{
// Initialize context
xml_parser_t context;
context.out = NULL;
context.pad_left = 2;
context.new_line = false;
context.dict = dict;

// Create XML parser
XML_Parser parser = XML_ParserCreate(NULL);
if (parser == NULL)
return -2;

// Initialize parser
XML_SetUserData(parser, &context);
XML_SetElementHandler(parser, xml_pre_start_element_handler, xml_pre_end_element_handler);

// Open input file
FILE *in = fopen(resource->path, "r");
if (in == NULL)
{
fprintf(stderr, "Could not open file %s\n", resource->path);
XML_ParserFree(parser);
return -3;
}

// Parse file
char buf[4096];
while (true)
{
size_t to_read = sizeof(buf)/sizeof(char);
size_t count = fread(buf, sizeof(char), to_read, in);
bool final = count < to_read;

if (!XML_Parse(parser, buf, count, final))
public:
explicit XMLTranslator(FILE *out, cvector<xml_word_t> *dict)
{
XML_Error code = XML_GetErrorCode(parser);
fprintf(stderr, "XML parsing error: %s\n", XML_ErrorString(code));
XML_ParserFree(parser);
return -4;
pOut = out;
pDict = dict;
nPadLeft = 2;
bNewLine = false;
}
virtual ~XMLTranslator() { pDict = NULL; }

if (final)
break;
}
public:
virtual status_t start_element(const LSPString *name, const LSPString * const *atts)
{
// Calculate number of parameters
size_t count = 0;
for (const LSPString * const *p = atts; *p != NULL; p += 2, ++count) {}

// Output tag header
fputc('\n', pOut);
xml_padding();
fputs("O(", pOut);
const char *s = name->get_utf8();
if (s == NULL)
return STATUS_NO_MEM;
encode_word(pOut, pDict, s);
fprintf(pOut, ", \"\\x%02x\")", int(count));

// Now output parameters
for ( ; *atts != NULL; atts += 2)
{
const char *k = atts[0]->get_utf8();
const char *v = atts[1]->get_utf8();

if ((k != NULL) && (v != NULL))
{
fputs(" P(", pOut);
encode_word(pOut, pDict, k);
fputs(", ", pOut);
encode_word(pOut, pDict, v);
fputc(')', pOut);
}
}

nPadLeft ++;
bNewLine = false;

return STATUS_OK;
}

// Free parser and close file
XML_ParserFree(parser);
fclose(in);
virtual status_t end_element(const LSPString *name)
{
nPadLeft --;

if (bNewLine)
{
fputc('\n', pOut);
xml_padding();
}
else
fputc(' ', pOut);

const char *s = name->get_utf8();
if (s == NULL)
return STATUS_NO_MEM;

fputs("C(", pOut);
encode_word(pOut, pDict, s);
fputc(')', pOut);
bNewLine = true;
return STATUS_OK;
}
};

return 0;
static int preprocess_xml_resource(const scan_resource_t *resource, cvector<xml_word_t> *dict)
{
// Create XML parser
xml::PushParser parser;
XMLPreparser h(dict);
return parser.parse_file(&h, resource->path);
}

static int serialize_xml_resource(FILE *out, const scan_resource_t *resource, cvector<xml_word_t> *dict)
{
// Initialize context
xml_parser_t context;
context.out = out;
context.pad_left = 2;
context.new_line = false;
context.dict = dict;

// Output resource descriptor
fprintf(out, "\t// Contents of file %s\n", resource->id);
fprintf(out, "\tstatic const char *builtin_resource%s =", resource->hex);

// Create XML parser
XML_Parser parser = XML_ParserCreate(NULL);
if (parser == NULL)
return -2;

// Initialize parser
XML_SetUserData(parser, &context);
XML_SetElementHandler(parser, xml_start_element_handler, xml_end_element_handler);

// Open input file
FILE *in = fopen(resource->path, "r");
if (in == NULL)
{
fprintf(stderr, "Could not open file %s\n", resource->path);
XML_ParserFree(parser);
return -3;
}

// Parse file
char buf[4096];
while (true)
{
size_t to_read = sizeof(buf)/sizeof(char);
size_t count = fread(buf, sizeof(char), to_read, in);
bool final = count < to_read;

if (!XML_Parse(parser, buf, count, final))
{
XML_Error code = XML_GetErrorCode(parser);
fprintf(stderr, "XML parsing error: %s\n", XML_ErrorString(code));
XML_ParserFree(parser);
return -4;
}

if (final)
break;
}

// Free parser and close file
XML_ParserFree(parser);
fclose(in);

fprintf(out, "\n\t\t;\n\n");
xml::PushParser parser;
XMLTranslator h(out, dict);
status_t res = parser.parse_file(&h, resource->path);

return 0;
// Trailing characters
fputs("\n\t\t;\n\n", out);
return res;
}
}
}
@@ -268,15 +268,10 @@ namespace lsp

fprintf(out, "#include <core/resource.h>\n\n");

fprintf(out, "// Control characters\n");
// fprintf(out, "#define X_TAG_OPEN \"\\x55\"\n");
fprintf(out, "#define X_TAG_CLOSE \"\\xff\"\n\n");
fprintf(out, "#define X_SEPARATOR \"\\0\"\n\n");

fprintf(out, "// String encoders\n");
fprintf(out, "#define K(k) k X_SEPARATOR\n");
fprintf(out, "#define K(k) k \"\\0\"\n");
fprintf(out, "#define O(x, count) count x\n");
fprintf(out, "#define C(x) X_TAG_CLOSE \n");
fprintf(out, "#define C(x) \"\\xff\" \n");
fprintf(out, "#define P(k, v) k v \n\n");

fprintf(out, "// Resource definition\n");

0 comments on commit d444686

Please sign in to comment.
You can’t perform that action at this time.