1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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[] = "friends_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;
}
|