Added friend list parser

This commit is contained in:
Magmus 2013-06-30 17:59:08 -07:00
parent 2e0c3bb593
commit 4b6929bcc8
4 changed files with 332 additions and 0 deletions

162
core/XML_Parser/asm-xml.h.h Normal file
View File

@ -0,0 +1,162 @@
/****************************************************************************
* *
* asm-xml.h *
* *
* Copyright (C) 2007-08 Marc Kerbiquet *
* *
****************************************************************************/
#ifdef WIN32
#define ACC __cdecl
#else
#define ACC
#endif
#ifdef __cplusplus
extern "C" {
#endif
//-----------------------------------------------------------------------------
// Error Codes
//-----------------------------------------------------------------------------
#define RC_OK 0 // everything is ok
#define RC_MEMORY 1 // out of memory
#define RC_EMPTY_NAME 10 // name empty or not defined
#define RC_ATTR_DEFINED 11 // attribute already defined
#define RC_ELEM_DEFINED 12 // element already defined
#define RC_SCHEMA_EMPTY 13 // schema does not contains a document
#define RC_DOCUMENT_DEFINED 14 // schema contains more than one document
#define RC_UNDEFINED_CLASS 15 // can't find collection in reference
#define RC_UNDEFINED_GROUP 16 // can't find a group in include
#define RC_INVALID_ID 17 // id is not a valid number
#define RC_INVALID_IGNORE 18 // ignore is not 'yes' or 'no'
#define RC_INVALID_ENTITY_REFERENCE 20 // must be amp, quot, lt, gt, or apos
#define RC_UNEXPECTED_END 21 // found last char too early
#define RC_INVALID_CHAR 22 // wrong char
#define RC_OVERFLOW 23 // number to big in char reference
#define RC_NO_START_TAG 24 // xml does not start with a tag
#define RC_TAG_MISMATCH 25 // invalid close tag
#define RC_INVALID_TAG 26 // invalid root element
#define RC_INVALID_ATTRIBUTE 27 // unknown attribute
#define RC_INVALID_PI 28 // invalid processing instruction (<?xml)
#define RC_INVALID_DOCTYPE 29 // duplicate doctype or after main element
#define RC_VERSION_EXPECTED 30 // version is missing in xml declaration
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
typedef struct AXElement AXElement ;
typedef struct AXAttribute AXAttribute ;
typedef struct AXElementClass AXElementClass ;
typedef struct AXParseContext AXParseContext ;
typedef struct AXClassContext AXClassContext ;
struct AXElementClass
{
int offset ; // Offset of the element in attribute list
char* name ; // Name of the element (not zero terminated)
char* nameLimit ; // End of the name of the element
unsigned int size ; // size in bytes of an element of this class
unsigned int id ; // container, text or mixed
unsigned int type ; // container, text or mixed
unsigned int propertyCount ; // number of attributes and text elements
unsigned int childCount ; // number of child classes
int* attributes ; // (internal) attribute map
int* elements ; // (internal) element map
AXElementClass** children ; // The list of child classes.
// The order is the one defined in the class
// definition file.
int reserved ;
void* reserved2 ;
};
struct AXClassContext
{
void* base ;
void* limit ;
void* chunks ;
int chunkSize ;
int errorCode ;
int line ;
int column ;
AXElementClass** classes ; // all global classes
AXElementClass* rootClass ; // the root class
AXElement* rootElement ;
};
struct AXAttribute
{
const char* begin ; // the value (not zero terminated)
// This slot can also contain an element if
// a <element> has been defined in schema;
// use ax_getElement() to retrieve it.
const char* limit ; // the end of the value
};
struct AXElement
{
int id ; // the class of the element
AXElement* nextSibling ; // the next sibling element
AXElement* firstChild ; // the first child element
AXElement* lastChild ; // the last child element
AXAttribute reserved ; // do not use
AXAttribute attributes[1] ; // the array of attributes - there is
// no bound checking in C
};
struct AXParseContext
{
void* base ;
void* limit ;
void* chunks ;
int chunkSize ;
int errorCode ;
const char* source ;
const char* current ;
int line ;
int column ;
AXElement* root ;
AXAttribute version ;
AXAttribute encoding ;
int strict ;
int reserved1 ;
AXElement reserved2 ;
};
//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------
extern
void ACC ax_initialize (void* mallocFun,
void* freeFun);
extern
int ACC ax_initializeParser (AXParseContext* context,
unsigned int chunkSize);
extern
int ACC ax_releaseParser (AXParseContext* context);
extern
AXElement* ACC ax_parse (AXParseContext* context,
const char* source,
AXElementClass* type,
int strict);
extern
int ACC ax_initializeClassParser (AXClassContext* context);
extern
int ACC ax_releaseClassParser (AXClassContext* context);
extern
AXElementClass* ACC ax_classFromElement (AXElement* e,
AXClassContext* context);
extern
AXElementClass* ACC ax_classFromString (const char* source,
AXClassContext* context);
#define ax_getElement(element, index) ((AXElement*)element->attributes[index].begin)
#define ax_getAttribute(element, index) (&element->attributes[index])
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- List of friends -->
<friends>
<friend id="001">
<name>Senator Herpies</name>
<userID>12341241251</userID>
</friend>
</friends>

160
core/XML_Parser/main.c Normal file
View File

@ -0,0 +1,160 @@
///////////////////////////////////////////////////////////////////////////////
//
// Friend List Parser
//
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm-xml.h"
static const int chunkSize = 16*1024*1024; // 16Mk
static const char schemaFilename[] = "schema.xml";
static const char xmlFilename[] = "friends.xml";
char buffer[65536];
///////////////////////////////////////////////////////////////////////////////
// Print an attribute / text value
///////////////////////////////////////////////////////////////////////////////
const char* asString(AXAttribute* attr)
{
const char* start = attr->begin;
const char* limit = attr->limit;
size_t size = limit - start;
memcpy(buffer, start, size);
buffer[size] = 0;
return buffer;
}
///////////////////////////////////////////////////////////////////////////////
// Print an error code from the parser
///////////////////////////////////////////////////////////////////////////////
void printAsmXmlError(AXParseContext* context)
{
fprintf(stderr, "Error (%d,%d): %d\n", context->line, context->column, context->errorCode);
}
///////////////////////////////////////////////////////////////////////////////
// Read Schema Definition
///////////////////////////////////////////////////////////////////////////////
AXElementClass* readClass(const char* filename, AXClassContext* classContext)
{
FILE* f;
size_t size;
f = fopen(filename, "rb");
if( f == NULL )
{
fprintf(stderr, "can't open schema '%s'\n", filename);
return NULL;
}
size = fread(buffer, 1, 65535, f);
buffer[size] = 0;
fclose(f);
// Parse the string and build the class
return ax_classFromString(buffer, classContext);
}
///////////////////////////////////////////////////////////////////////////////
// Read Document
///////////////////////////////////////////////////////////////////////////////
AXElement* readDocument(const char* filename,
AXParseContext* parseContext,
AXElementClass* clazz)
{
FILE* f;
size_t size;
f = fopen(filename, "rb");
if( f == NULL )
{
fprintf(stderr, "can't open file '%s'\n", filename);
return NULL;
}
size = fread(buffer, 1, 65535, f);
buffer[size] = 0;
fclose(f);
// Parse the string and build the class
return ax_parse(parseContext, buffer, clazz, 1);
}
///////////////////////////////////////////////////////////////////////////////
// main
///////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
int res;
AXClassContext classContext;
AXParseContext parseContext;
AXElementClass* friendClass;
AXElement* friends;
AXElement* friend;
// Initialize the AsmXml library
//
// Pass the malloc() and free() functions
//
ax_initialize(malloc, free);
// Initialize the class context
//
// It can store one or more classes. Classes read with this
// context are kept in memory as long as it is not released.
//
res = ax_initializeClassParser(&classContext);
// An error while initialization means that allocation failed.
// It should never happen since it allocates only 4K.
if( res != 0 )
return 1;
// Read the schema and compile it
//
friendClass = readClass(schemaFilename, &classContext);
if( friendClass == NULL )
return 1;
// Initialize the parser
//
// Documents read with this parser will stay in memory as long as
// the parser is not released.
//
// The choice of the chunk size is very important since the
// performance can be affected by this value. The parser allocates
// memory by chunks to reduce calls to malloc that can be very slow.
// The ideal value is around 50% of the source XML to process.
//
res = ax_initializeParser(&parseContext, chunkSize);
// An error while initialization means that initial allocation failed.
if( res != 0 )
return 1;
// Read the file and parse it
//
friends = readDocument(xmlFilename, &parseContext, friendClass);
if( friends == NULL )
{
printAsmXmlError(&parseContext);
return 1;
}
// Enumerate child elements
friend = friends->firstChild;
while( friend )
{
printf("================================\n");
printf("Friend ID: %s\n", asString(&friend->attributes[0]));
printf("Name: %s\n", asString(&friend->attributes[1]));
printf("UserID: %s\n", asString(&friend->attributes[2]));
friend = friend->nextSibling;
printf("================================\n");
}
// Release the document and its class
ax_releaseParser(&parseContext);
ax_releaseClassParser(&classContext);
return 0;
}

BIN
core/XML_Parser/parser.obj Normal file

Binary file not shown.