genx4r-fotopedia 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +43 -0
- data/LICENSE +22 -0
- data/README +31 -0
- data/TODO +6 -0
- data/ext/genx4r/MANIFEST +5 -0
- data/ext/genx4r/charProps.c +378 -0
- data/ext/genx4r/extconf.rb +5 -0
- data/ext/genx4r/genx.c +1940 -0
- data/ext/genx4r/genx.h +287 -0
- data/ext/genx4r/genx4r.c +570 -0
- data/genx4r-0.0.6.gem +0 -0
- data/genx4r-0.05.gem +0 -0
- data/genx4r.gemspec +33 -0
- data/lib/genx4r/builder.rb +123 -0
- data/setup.rb +1346 -0
- data/test/basics.rb +93 -0
- data/test/builder.rb +49 -0
- data/test/declare.rb +63 -0
- data/test/non-io.rb +41 -0
- metadata +89 -0
data/ext/genx4r/genx.h
ADDED
@@ -0,0 +1,287 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
* genx - C-callable library for generating XML documents
|
4
|
+
*/
|
5
|
+
|
6
|
+
/*
|
7
|
+
* Copyright (c) 2004 by Tim Bray and Sun Microsystems. For copying
|
8
|
+
* permission, see http://www.tbray.org/ongoing/genx/COPYING
|
9
|
+
*/
|
10
|
+
|
11
|
+
#include <stdio.h>
|
12
|
+
|
13
|
+
#ifdef __cplusplus
|
14
|
+
extern "C" {
|
15
|
+
#endif
|
16
|
+
|
17
|
+
/*
|
18
|
+
* Note on error handling: genx routines mostly return
|
19
|
+
* GENX_SUCCESS (guaranteed to be zero) in normal circumstances, one of
|
20
|
+
* these other GENX_ values on a memory allocation or I/O failure or if the
|
21
|
+
* call would result in non-well-formed output.
|
22
|
+
* You can associate an error message with one of these codes explicitly
|
23
|
+
* or with the most recent error using genxGetErrorMessage() and
|
24
|
+
* genxLastErrorMessage(); see below.
|
25
|
+
*/
|
26
|
+
typedef enum
|
27
|
+
{
|
28
|
+
GENX_SUCCESS = 0,
|
29
|
+
GENX_BAD_UTF8,
|
30
|
+
GENX_NON_XML_CHARACTER,
|
31
|
+
GENX_BAD_NAME,
|
32
|
+
GENX_ALLOC_FAILED,
|
33
|
+
GENX_BAD_NAMESPACE_NAME,
|
34
|
+
GENX_INTERNAL_ERROR,
|
35
|
+
GENX_DUPLICATE_PREFIX,
|
36
|
+
GENX_SEQUENCE_ERROR,
|
37
|
+
GENX_NO_START_TAG,
|
38
|
+
GENX_IO_ERROR,
|
39
|
+
GENX_MISSING_VALUE,
|
40
|
+
GENX_MALFORMED_COMMENT,
|
41
|
+
GENX_XML_PI_TARGET,
|
42
|
+
GENX_MALFORMED_PI,
|
43
|
+
GENX_DUPLICATE_ATTRIBUTE,
|
44
|
+
GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE,
|
45
|
+
GENX_DUPLICATE_NAMESPACE,
|
46
|
+
GENX_BAD_DEFAULT_DECLARATION
|
47
|
+
} genxStatus;
|
48
|
+
|
49
|
+
/* character types */
|
50
|
+
#define GENX_XML_CHAR 1
|
51
|
+
#define GENX_LETTER 2
|
52
|
+
#define GENX_NAMECHAR 4
|
53
|
+
|
54
|
+
/* a UTF-8 string */
|
55
|
+
typedef unsigned char * utf8;
|
56
|
+
typedef const unsigned char * constUtf8;
|
57
|
+
|
58
|
+
/*
|
59
|
+
* genx's own types
|
60
|
+
*/
|
61
|
+
typedef struct genxWriter_rec * genxWriter;
|
62
|
+
typedef struct genxNamespace_rec * genxNamespace;
|
63
|
+
typedef struct genxElement_rec * genxElement;
|
64
|
+
typedef struct genxAttribute_rec * genxAttribute;
|
65
|
+
|
66
|
+
/*
|
67
|
+
* Constructors, set/get
|
68
|
+
*/
|
69
|
+
|
70
|
+
/*
|
71
|
+
* Create a new writer. For generating multiple XML documents, it's most
|
72
|
+
* efficient to re-use the same genx object. However, you can only write
|
73
|
+
* one document at a time with a writer.
|
74
|
+
* Returns NULL if it fails, which can only be due to an allocation failure.
|
75
|
+
*/
|
76
|
+
genxWriter genxNew(void * (*alloc)(void * userData, int bytes),
|
77
|
+
void (* dealloc)(void * userData, void * data),
|
78
|
+
void * userData);
|
79
|
+
|
80
|
+
/*
|
81
|
+
* Dispose of a writer, freeing all associated memory
|
82
|
+
*/
|
83
|
+
void genxDispose(genxWriter w);
|
84
|
+
|
85
|
+
/*
|
86
|
+
* Set/get
|
87
|
+
*/
|
88
|
+
|
89
|
+
/*
|
90
|
+
* The userdata pointer will be passed to memory-allocation
|
91
|
+
* and I/O callbacks. If not set, genx will pass NULL
|
92
|
+
*/
|
93
|
+
void genxSetUserData(genxWriter w, void * userData);
|
94
|
+
void * genxGetUserData(genxWriter w);
|
95
|
+
|
96
|
+
/*
|
97
|
+
* User-provided memory allocator, if desired. For example, if you were
|
98
|
+
* in an Apache module, you could arrange for genx to use ap_palloc by
|
99
|
+
* making the pool accessible via the userData call.
|
100
|
+
* The "dealloc" is to be used to free memory allocated with "alloc". If
|
101
|
+
* alloc is provided but dealloc is NULL, genx will not attempt to free
|
102
|
+
* the memory; this would be appropriate in an Apache context.
|
103
|
+
* If "alloc" is not provided, genx routines use malloc() to allocate memory
|
104
|
+
*/
|
105
|
+
void genxSetAlloc(genxWriter w,
|
106
|
+
void * (* alloc)(void * userData, int bytes));
|
107
|
+
void genxSetDealloc(genxWriter w,
|
108
|
+
void (* dealloc)(void * userData, void * data));
|
109
|
+
void * (* genxGetAlloc(genxWriter w))(void * userData, int bytes);
|
110
|
+
void (* genxGetDealloc(genxWriter w))(void * userData, void * data);
|
111
|
+
|
112
|
+
/*
|
113
|
+
* Get the prefix associated with a namespace
|
114
|
+
*/
|
115
|
+
utf8 genxGetNamespacePrefix(genxNamespace ns);
|
116
|
+
|
117
|
+
/*
|
118
|
+
* Declaration functions
|
119
|
+
*/
|
120
|
+
|
121
|
+
/*
|
122
|
+
* Declare a namespace. The provided prefix is the default but can be
|
123
|
+
* overridden by genxAddNamespace. If no default prefiix is provided,
|
124
|
+
* genx will generate one of the form g-%d.
|
125
|
+
* On error, returns NULL and signals via statusp
|
126
|
+
*/
|
127
|
+
genxNamespace genxDeclareNamespace(genxWriter w,
|
128
|
+
constUtf8 uri, constUtf8 prefix,
|
129
|
+
genxStatus * statusP);
|
130
|
+
|
131
|
+
/*
|
132
|
+
* Declare an element
|
133
|
+
* If something failed, returns NULL and sets the status code via statusP
|
134
|
+
*/
|
135
|
+
genxElement genxDeclareElement(genxWriter w,
|
136
|
+
genxNamespace ns, constUtf8 type,
|
137
|
+
genxStatus * statusP);
|
138
|
+
|
139
|
+
/*
|
140
|
+
* Declare an attribute
|
141
|
+
*/
|
142
|
+
genxAttribute genxDeclareAttribute(genxWriter w,
|
143
|
+
genxNamespace ns,
|
144
|
+
constUtf8 name, genxStatus * statusP);
|
145
|
+
|
146
|
+
/*
|
147
|
+
* Writing XML
|
148
|
+
*/
|
149
|
+
|
150
|
+
/*
|
151
|
+
* Start a new document.
|
152
|
+
*/
|
153
|
+
genxStatus genxStartDocFile(genxWriter w, FILE * file);
|
154
|
+
|
155
|
+
/*
|
156
|
+
* Caller-provided I/O package.
|
157
|
+
* First form is for a null-terminated string.
|
158
|
+
* for second, if you have s="abcdef" and want to send "abc", you'd call
|
159
|
+
* sendBounded(userData, s, s + 3)
|
160
|
+
*/
|
161
|
+
typedef struct
|
162
|
+
{
|
163
|
+
genxStatus (* send)(void * userData, constUtf8 s);
|
164
|
+
genxStatus (* sendBounded)(void * userData, constUtf8 start, constUtf8 end);
|
165
|
+
genxStatus (* flush)(void * userData);
|
166
|
+
} genxSender;
|
167
|
+
|
168
|
+
genxStatus genxStartDocSender(genxWriter w, genxSender * sender);
|
169
|
+
|
170
|
+
/*
|
171
|
+
* End a document. Calls "flush"
|
172
|
+
*/
|
173
|
+
genxStatus genxEndDocument(genxWriter w);
|
174
|
+
|
175
|
+
/*
|
176
|
+
* Write a comment
|
177
|
+
*/
|
178
|
+
genxStatus genxComment(genxWriter w, constUtf8 text);
|
179
|
+
|
180
|
+
/*
|
181
|
+
* Write a PI
|
182
|
+
*/
|
183
|
+
genxStatus genxPI(genxWriter w, constUtf8 target, constUtf8 text);
|
184
|
+
|
185
|
+
/*
|
186
|
+
* Start an element
|
187
|
+
*/
|
188
|
+
genxStatus genxStartElementLiteral(genxWriter w,
|
189
|
+
constUtf8 xmlns, constUtf8 type);
|
190
|
+
|
191
|
+
/*
|
192
|
+
* Start a predeclared element
|
193
|
+
* - element must have been declared
|
194
|
+
*/
|
195
|
+
genxStatus genxStartElement(genxElement e);
|
196
|
+
|
197
|
+
/*
|
198
|
+
* Write an attribute
|
199
|
+
*/
|
200
|
+
genxStatus genxAddAttributeLiteral(genxWriter w, constUtf8 xmlns,
|
201
|
+
constUtf8 name, constUtf8 value);
|
202
|
+
|
203
|
+
/*
|
204
|
+
* Write a predeclared attribute
|
205
|
+
*/
|
206
|
+
genxStatus genxAddAttribute(genxAttribute a, constUtf8 value);
|
207
|
+
|
208
|
+
/*
|
209
|
+
* add a namespace declaration
|
210
|
+
*/
|
211
|
+
genxStatus genxAddNamespace(genxNamespace ns, utf8 prefix);
|
212
|
+
|
213
|
+
/*
|
214
|
+
* Clear default namespace declaration
|
215
|
+
*/
|
216
|
+
genxStatus genxUnsetDefaultNamespace(genxWriter w);
|
217
|
+
|
218
|
+
/*
|
219
|
+
* Write an end tag
|
220
|
+
*/
|
221
|
+
genxStatus genxEndElement(genxWriter w);
|
222
|
+
|
223
|
+
/*
|
224
|
+
* Write some text
|
225
|
+
* You can't write any text outside the root element, except with
|
226
|
+
* genxComment and genxPI
|
227
|
+
*/
|
228
|
+
genxStatus genxAddText(genxWriter w, constUtf8 start);
|
229
|
+
genxStatus genxAddCountedText(genxWriter w, constUtf8 start, int byteCount);
|
230
|
+
genxStatus genxAddBoundedText(genxWriter w, constUtf8 start, constUtf8 end);
|
231
|
+
|
232
|
+
/*
|
233
|
+
* Write one character. The integer value is the Unicode character
|
234
|
+
* value, as usually expressed in U+XXXX notation.
|
235
|
+
*/
|
236
|
+
genxStatus genxAddCharacter(genxWriter w, int c);
|
237
|
+
|
238
|
+
/*
|
239
|
+
* Utility routines
|
240
|
+
*/
|
241
|
+
|
242
|
+
/*
|
243
|
+
* Return the Unicode character encoded by the UTF-8 pointed-to by the
|
244
|
+
* argument, and advance the argument past the encoding of the character.
|
245
|
+
* Returns -1 if the UTF-8 is malformed, in which case advances the
|
246
|
+
* argument to point at the first byte past the point past the malformed
|
247
|
+
* ones.
|
248
|
+
*/
|
249
|
+
int genxNextUnicodeChar(constUtf8 * sp);
|
250
|
+
|
251
|
+
/*
|
252
|
+
* Scan a buffer allegedly full of UTF-8 encoded XML characters; return
|
253
|
+
* one of GENX_SUCCESS, GENX_BAD_UTF8, or GENX_NON_XML_CHARACTER
|
254
|
+
*/
|
255
|
+
genxStatus genxCheckText(genxWriter w, constUtf8 s);
|
256
|
+
|
257
|
+
/*
|
258
|
+
* return character status, the OR of GENX_XML_CHAR,
|
259
|
+
* GENX_LETTER, and GENX_NAMECHAR
|
260
|
+
*/
|
261
|
+
int genxCharClass(genxWriter w, int c);
|
262
|
+
|
263
|
+
/*
|
264
|
+
* Silently wipe any non-XML characters out of a chunk of text.
|
265
|
+
* If you call this on a string before you pass it addText or
|
266
|
+
* addAttribute, you will never get an error from genx unless
|
267
|
+
* (a) there's a bug in your software, e.g. a malformed element name, or
|
268
|
+
* (b) there's a memory allocation or I/O error
|
269
|
+
* The output can never be longer than the input.
|
270
|
+
* Returns true if any changes were made.
|
271
|
+
*/
|
272
|
+
int genxScrubText(genxWriter w, constUtf8 in, utf8 out);
|
273
|
+
|
274
|
+
/*
|
275
|
+
* return error messages
|
276
|
+
*/
|
277
|
+
char * genxGetErrorMessage(genxWriter w, genxStatus status);
|
278
|
+
char * genxLastErrorMessage(genxWriter w);
|
279
|
+
|
280
|
+
/*
|
281
|
+
* return version
|
282
|
+
*/
|
283
|
+
char * genxGetVersion();
|
284
|
+
|
285
|
+
#ifdef __cplusplus
|
286
|
+
}
|
287
|
+
#endif
|
data/ext/genx4r/genx4r.c
ADDED
@@ -0,0 +1,570 @@
|
|
1
|
+
/* Copyright (c) 2004 Garrett Rooney
|
2
|
+
*
|
3
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
* a copy of this software and associated documentation files (the
|
5
|
+
* "Software"), to deal in the Software without restriction, including
|
6
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
* the following conditions:
|
10
|
+
*
|
11
|
+
* The above copyright notice and this permission notice shall be included
|
12
|
+
* in all copies or substantial portions of the Software.
|
13
|
+
*
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
15
|
+
* KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
16
|
+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
21
|
+
|
22
|
+
/* $Id: genx4r.c 494 2004-11-25 15:21:41Z rooneg $ */
|
23
|
+
|
24
|
+
#include "ruby.h"
|
25
|
+
|
26
|
+
#include "genx.h"
|
27
|
+
|
28
|
+
static VALUE rb_mGenX;
|
29
|
+
static VALUE rb_cGenXWriter;
|
30
|
+
|
31
|
+
static VALUE rb_cGenXNamespace;
|
32
|
+
static VALUE rb_cGenXAttribute;
|
33
|
+
static VALUE rb_cGenXElement;
|
34
|
+
|
35
|
+
static VALUE rb_cGenXException;
|
36
|
+
|
37
|
+
static void
|
38
|
+
writer_mark (genxWriter w)
|
39
|
+
{}
|
40
|
+
|
41
|
+
static void
|
42
|
+
writer_free (genxWriter w)
|
43
|
+
{
|
44
|
+
genxDispose (w);
|
45
|
+
}
|
46
|
+
|
47
|
+
#define GENX4R_ERR(expr, w) \
|
48
|
+
do { \
|
49
|
+
genxStatus genx4r__status = (expr); \
|
50
|
+
if (genx4r__status) \
|
51
|
+
rb_raise (rb_cGenXException, "%s", genxLastErrorMessage (w)); \
|
52
|
+
} while (0)
|
53
|
+
|
54
|
+
static VALUE
|
55
|
+
call_write (VALUE ary)
|
56
|
+
{
|
57
|
+
rb_funcall (rb_ary_entry (ary, 0),
|
58
|
+
rb_intern ("<<"),
|
59
|
+
1,
|
60
|
+
rb_ary_entry (ary, 1));
|
61
|
+
|
62
|
+
return Qtrue;
|
63
|
+
}
|
64
|
+
|
65
|
+
static VALUE
|
66
|
+
call_flush (VALUE file)
|
67
|
+
{
|
68
|
+
rb_funcall (file, rb_intern ("flush"), 0);
|
69
|
+
|
70
|
+
return Qtrue;
|
71
|
+
}
|
72
|
+
|
73
|
+
static VALUE
|
74
|
+
handle_exception (VALUE unused)
|
75
|
+
{
|
76
|
+
return Qfalse;
|
77
|
+
}
|
78
|
+
|
79
|
+
static genxStatus
|
80
|
+
writer_send (void *baton, constUtf8 s)
|
81
|
+
{
|
82
|
+
VALUE file = (VALUE) baton;
|
83
|
+
VALUE ary;
|
84
|
+
|
85
|
+
if (! rb_respond_to (file, rb_intern ("<<")))
|
86
|
+
rb_raise (rb_eRuntimeError, "target must respond to '<<'");
|
87
|
+
|
88
|
+
ary = rb_ary_new2 (2);
|
89
|
+
|
90
|
+
rb_ary_store (ary, 0, file);
|
91
|
+
rb_ary_store (ary, 1, rb_str_new2 (s));
|
92
|
+
|
93
|
+
if (rb_rescue (call_write, ary, handle_exception, Qnil) == Qfalse)
|
94
|
+
return GENX_IO_ERROR;
|
95
|
+
else
|
96
|
+
return GENX_SUCCESS;
|
97
|
+
}
|
98
|
+
|
99
|
+
static genxStatus
|
100
|
+
writer_send_bounded (void *baton, constUtf8 start, constUtf8 end)
|
101
|
+
{
|
102
|
+
VALUE file = (VALUE) baton;
|
103
|
+
VALUE ary;
|
104
|
+
|
105
|
+
if (! rb_respond_to (file, rb_intern ("<<")))
|
106
|
+
rb_raise (rb_eRuntimeError, "target must respond to '<<'");
|
107
|
+
|
108
|
+
ary = rb_ary_new2 (2);
|
109
|
+
|
110
|
+
rb_ary_store (ary, 0, file);
|
111
|
+
rb_ary_store (ary, 1, rb_str_new (start, end - start));
|
112
|
+
|
113
|
+
if (rb_rescue (call_write, ary, handle_exception, Qnil) == Qfalse)
|
114
|
+
return GENX_IO_ERROR;
|
115
|
+
else
|
116
|
+
return GENX_SUCCESS;
|
117
|
+
}
|
118
|
+
|
119
|
+
static genxStatus
|
120
|
+
writer_flush (void *baton)
|
121
|
+
{
|
122
|
+
VALUE file = (VALUE) baton;
|
123
|
+
|
124
|
+
/* if we can't flush, just let it go... */
|
125
|
+
if (! rb_respond_to (file, rb_intern ("flush")))
|
126
|
+
return GENX_SUCCESS;
|
127
|
+
|
128
|
+
if (rb_rescue (call_flush, file, handle_exception, Qnil) == Qfalse)
|
129
|
+
return GENX_IO_ERROR;
|
130
|
+
else
|
131
|
+
return GENX_SUCCESS;
|
132
|
+
}
|
133
|
+
|
134
|
+
static genxSender writer_sender = { writer_send,
|
135
|
+
writer_send_bounded,
|
136
|
+
writer_flush };
|
137
|
+
|
138
|
+
static VALUE
|
139
|
+
writer_begin_document (VALUE self, VALUE file)
|
140
|
+
{
|
141
|
+
genxWriter w;
|
142
|
+
|
143
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
144
|
+
|
145
|
+
if (! rb_respond_to (file, rb_intern ("<<")))
|
146
|
+
rb_raise (rb_eRuntimeError, "target must respond to '<<'");
|
147
|
+
|
148
|
+
genxSetUserData(w, (void *) file);
|
149
|
+
|
150
|
+
GENX4R_ERR (genxStartDocSender (w, &writer_sender), w);
|
151
|
+
|
152
|
+
return Qnil;
|
153
|
+
}
|
154
|
+
|
155
|
+
static VALUE
|
156
|
+
writer_end_document (VALUE self)
|
157
|
+
{
|
158
|
+
genxWriter w;
|
159
|
+
|
160
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
161
|
+
|
162
|
+
GENX4R_ERR (genxEndDocument (w), w);
|
163
|
+
|
164
|
+
return Qnil;
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE
|
168
|
+
writer_document (VALUE self, VALUE file)
|
169
|
+
{
|
170
|
+
writer_begin_document (self, file);
|
171
|
+
|
172
|
+
if (rb_block_given_p ())
|
173
|
+
{
|
174
|
+
rb_yield (Qnil);
|
175
|
+
|
176
|
+
writer_end_document (self);
|
177
|
+
|
178
|
+
return Qnil;
|
179
|
+
}
|
180
|
+
else
|
181
|
+
rb_raise (rb_eRuntimeError, "must be called with a block");
|
182
|
+
}
|
183
|
+
|
184
|
+
static VALUE
|
185
|
+
writer_comment (VALUE self, VALUE arg)
|
186
|
+
{
|
187
|
+
genxWriter w;
|
188
|
+
|
189
|
+
Check_Type (arg, T_STRING);
|
190
|
+
|
191
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
192
|
+
|
193
|
+
GENX4R_ERR (genxComment (w, (constUtf8) RSTRING (arg)->ptr), w);
|
194
|
+
|
195
|
+
return Qnil;
|
196
|
+
}
|
197
|
+
|
198
|
+
static VALUE
|
199
|
+
writer_attribute (int argc, VALUE *argv, VALUE self)
|
200
|
+
{
|
201
|
+
genxAttribute attr = 0;
|
202
|
+
genxWriter w;
|
203
|
+
VALUE xmlns, name, value;
|
204
|
+
int nslen = 0;
|
205
|
+
|
206
|
+
switch (argc)
|
207
|
+
{
|
208
|
+
case 2:
|
209
|
+
xmlns = 0;
|
210
|
+
if (CLASS_OF (argv[0]) == rb_cGenXAttribute)
|
211
|
+
{
|
212
|
+
Data_Get_Struct (argv[0], struct genxAttribute_rec, attr);
|
213
|
+
name = 0;
|
214
|
+
}
|
215
|
+
else
|
216
|
+
name = argv[0];
|
217
|
+
|
218
|
+
value = argv[1];
|
219
|
+
break;
|
220
|
+
|
221
|
+
case 3:
|
222
|
+
xmlns = argv[0];
|
223
|
+
name = argv[1];
|
224
|
+
value = argv[2];
|
225
|
+
break;
|
226
|
+
|
227
|
+
default:
|
228
|
+
rb_raise (rb_eRuntimeError, "invalid arguments");
|
229
|
+
}
|
230
|
+
|
231
|
+
if (xmlns)
|
232
|
+
{
|
233
|
+
Check_Type (xmlns, T_STRING);
|
234
|
+
nslen = RSTRING (xmlns)->len;
|
235
|
+
}
|
236
|
+
|
237
|
+
if (name)
|
238
|
+
Check_Type (name, T_STRING);
|
239
|
+
|
240
|
+
Check_Type (value, T_STRING);
|
241
|
+
|
242
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
243
|
+
|
244
|
+
if (attr)
|
245
|
+
GENX4R_ERR (genxAddAttribute (attr, (constUtf8) RSTRING (value)->ptr), w);
|
246
|
+
else
|
247
|
+
GENX4R_ERR (genxAddAttributeLiteral
|
248
|
+
(w,
|
249
|
+
nslen ? (constUtf8) RSTRING (xmlns)->ptr : NULL,
|
250
|
+
(constUtf8) RSTRING (name)->ptr,
|
251
|
+
(constUtf8) RSTRING (value)->ptr), w);
|
252
|
+
|
253
|
+
return Qnil;
|
254
|
+
}
|
255
|
+
|
256
|
+
static VALUE
|
257
|
+
writer_begin_element (int argc, VALUE *argv, VALUE self)
|
258
|
+
{
|
259
|
+
genxWriter w;
|
260
|
+
genxElement elem = 0;
|
261
|
+
VALUE xmlns, name;
|
262
|
+
int nslen = 0;
|
263
|
+
|
264
|
+
switch (argc)
|
265
|
+
{
|
266
|
+
case 1:
|
267
|
+
xmlns = 0;
|
268
|
+
if (CLASS_OF (argv[0]) == rb_cGenXElement)
|
269
|
+
{
|
270
|
+
Data_Get_Struct (argv[0], struct genxElement_rec, elem);
|
271
|
+
name = 0;
|
272
|
+
}
|
273
|
+
else
|
274
|
+
name = argv[0];
|
275
|
+
break;
|
276
|
+
|
277
|
+
case 2:
|
278
|
+
xmlns = argv[0];
|
279
|
+
name = argv[1];
|
280
|
+
break;
|
281
|
+
|
282
|
+
default:
|
283
|
+
rb_raise (rb_eRuntimeError, "invalid arguments");
|
284
|
+
}
|
285
|
+
|
286
|
+
if (xmlns)
|
287
|
+
{
|
288
|
+
Check_Type (xmlns, T_STRING);
|
289
|
+
nslen = RSTRING (xmlns)->len;
|
290
|
+
}
|
291
|
+
|
292
|
+
if (name)
|
293
|
+
Check_Type (name, T_STRING);
|
294
|
+
|
295
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
296
|
+
|
297
|
+
if (elem)
|
298
|
+
GENX4R_ERR (genxStartElement (elem), w);
|
299
|
+
else
|
300
|
+
GENX4R_ERR (genxStartElementLiteral
|
301
|
+
(w,
|
302
|
+
nslen ? (constUtf8) RSTRING (xmlns)->ptr : NULL,
|
303
|
+
(constUtf8) RSTRING (name)->ptr), w);
|
304
|
+
|
305
|
+
return Qnil;
|
306
|
+
}
|
307
|
+
|
308
|
+
static VALUE
|
309
|
+
writer_end_element (VALUE self)
|
310
|
+
{
|
311
|
+
genxWriter w;
|
312
|
+
|
313
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
314
|
+
|
315
|
+
GENX4R_ERR (genxEndElement (w), w);
|
316
|
+
|
317
|
+
return Qnil;
|
318
|
+
}
|
319
|
+
|
320
|
+
static VALUE
|
321
|
+
writer_element (int argc, VALUE *argv, VALUE self)
|
322
|
+
{
|
323
|
+
writer_begin_element (argc, argv, self);
|
324
|
+
|
325
|
+
if (rb_block_given_p ())
|
326
|
+
{
|
327
|
+
rb_yield (Qnil);
|
328
|
+
|
329
|
+
writer_end_element (self);
|
330
|
+
|
331
|
+
return Qnil;
|
332
|
+
}
|
333
|
+
else
|
334
|
+
rb_raise (rb_eRuntimeError, "must be called with a block");
|
335
|
+
}
|
336
|
+
|
337
|
+
static VALUE
|
338
|
+
writer_pi (VALUE self, VALUE target, VALUE text)
|
339
|
+
{
|
340
|
+
genxWriter w;
|
341
|
+
|
342
|
+
Check_Type (target, T_STRING);
|
343
|
+
Check_Type (text, T_STRING);
|
344
|
+
|
345
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
346
|
+
|
347
|
+
GENX4R_ERR (genxPI (w,
|
348
|
+
(constUtf8) RSTRING (target)->ptr,
|
349
|
+
(constUtf8) RSTRING (text)->ptr), w);
|
350
|
+
|
351
|
+
return Qnil;
|
352
|
+
}
|
353
|
+
|
354
|
+
static VALUE
|
355
|
+
writer_text (VALUE self, VALUE text)
|
356
|
+
{
|
357
|
+
genxWriter w;
|
358
|
+
|
359
|
+
Check_Type (text, T_STRING);
|
360
|
+
|
361
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
362
|
+
|
363
|
+
GENX4R_ERR (genxAddText (w, (constUtf8) RSTRING (text)->ptr), w);
|
364
|
+
|
365
|
+
return Qnil;
|
366
|
+
}
|
367
|
+
|
368
|
+
static VALUE
|
369
|
+
writer_character (VALUE self, VALUE ch)
|
370
|
+
{
|
371
|
+
genxWriter w;
|
372
|
+
|
373
|
+
int c = NUM2INT (ch);
|
374
|
+
|
375
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
376
|
+
|
377
|
+
GENX4R_ERR (genxAddCharacter (w, c), w);
|
378
|
+
|
379
|
+
return Qnil;
|
380
|
+
}
|
381
|
+
|
382
|
+
#if RUBY_VERSION_MAJOR >= 1 && RUBY_VERSION_MINOR >= 8
|
383
|
+
static VALUE
|
384
|
+
writer_allocate (VALUE klass)
|
385
|
+
{
|
386
|
+
genxWriter writer = genxNew (NULL, NULL, NULL);
|
387
|
+
|
388
|
+
return Data_Wrap_Struct (klass, writer_mark, writer_free, writer);
|
389
|
+
}
|
390
|
+
#else
|
391
|
+
static VALUE
|
392
|
+
writer_new (VALUE klass)
|
393
|
+
{
|
394
|
+
genxWriter writer = genxNew (NULL, NULL, NULL);
|
395
|
+
|
396
|
+
return Data_Wrap_Struct (klass, writer_mark, writer_free, writer);
|
397
|
+
}
|
398
|
+
#endif
|
399
|
+
|
400
|
+
static VALUE
|
401
|
+
writer_declare_namespace (int argc, VALUE *argv, VALUE self)
|
402
|
+
{
|
403
|
+
VALUE uri, prefix = 0;
|
404
|
+
genxStatus st = 0;
|
405
|
+
genxNamespace ns;
|
406
|
+
genxWriter w;
|
407
|
+
|
408
|
+
rb_scan_args (argc, argv, "11", &uri, &prefix);
|
409
|
+
|
410
|
+
Check_Type (uri, T_STRING);
|
411
|
+
if (prefix)
|
412
|
+
Check_Type (prefix, T_STRING);
|
413
|
+
|
414
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
415
|
+
|
416
|
+
ns = genxDeclareNamespace (w,
|
417
|
+
(constUtf8) RSTRING (uri)->ptr,
|
418
|
+
prefix ? (constUtf8) RSTRING (prefix)->ptr : NULL,
|
419
|
+
&st);
|
420
|
+
|
421
|
+
if (st)
|
422
|
+
rb_raise (rb_cGenXException, "%s", genxGetErrorMessage (w, st));
|
423
|
+
|
424
|
+
return Data_Wrap_Struct (rb_cGenXNamespace, NULL, NULL, ns);
|
425
|
+
}
|
426
|
+
|
427
|
+
static VALUE
|
428
|
+
writer_declare_element (int argc, VALUE *argv, VALUE self)
|
429
|
+
{
|
430
|
+
genxNamespace ns = 0;
|
431
|
+
genxStatus st = 0;
|
432
|
+
genxElement elem;
|
433
|
+
genxWriter w;
|
434
|
+
VALUE name;
|
435
|
+
|
436
|
+
switch (argc)
|
437
|
+
{
|
438
|
+
case 1:
|
439
|
+
name = argv[0];
|
440
|
+
break;
|
441
|
+
|
442
|
+
case 2:
|
443
|
+
if (CLASS_OF (argv[0]) == rb_cGenXNamespace) {
|
444
|
+
Data_Get_Struct (argv[0], struct genxNamespace_rec, ns);
|
445
|
+
} else {
|
446
|
+
rb_raise (rb_eRuntimeError, "invalid arguments");
|
447
|
+
}
|
448
|
+
name = argv[1];
|
449
|
+
break;
|
450
|
+
|
451
|
+
default:
|
452
|
+
rb_raise (rb_eRuntimeError, "invalid arguments");
|
453
|
+
}
|
454
|
+
|
455
|
+
Check_Type (name, T_STRING);
|
456
|
+
|
457
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
458
|
+
|
459
|
+
elem = genxDeclareElement (w, ns, RSTRING (name)->ptr, &st);
|
460
|
+
if (st)
|
461
|
+
rb_raise (rb_cGenXException, "%s", genxGetErrorMessage (w, st));
|
462
|
+
|
463
|
+
return Data_Wrap_Struct (rb_cGenXElement, NULL, NULL, elem);
|
464
|
+
}
|
465
|
+
|
466
|
+
static VALUE
|
467
|
+
writer_declare_attribute (int argc, VALUE *argv, VALUE self)
|
468
|
+
{
|
469
|
+
genxNamespace ns = 0;
|
470
|
+
genxAttribute attr;
|
471
|
+
genxStatus st = 0;
|
472
|
+
genxWriter w;
|
473
|
+
VALUE name;
|
474
|
+
|
475
|
+
switch (argc)
|
476
|
+
{
|
477
|
+
case 1:
|
478
|
+
name = argv[0];
|
479
|
+
break;
|
480
|
+
|
481
|
+
case 2:
|
482
|
+
if (CLASS_OF (argv[0]) == rb_cGenXNamespace) {
|
483
|
+
Data_Get_Struct (argv[0], struct genxNamespace_rec, ns);
|
484
|
+
} else {
|
485
|
+
rb_raise (rb_eRuntimeError, "invalid arguments");
|
486
|
+
}
|
487
|
+
name = argv[1];
|
488
|
+
break;
|
489
|
+
|
490
|
+
default:
|
491
|
+
rb_raise (rb_eRuntimeError, "invalid arguments");
|
492
|
+
}
|
493
|
+
|
494
|
+
Check_Type (name, T_STRING);
|
495
|
+
|
496
|
+
Data_Get_Struct (self, struct genxWriter_rec, w);
|
497
|
+
|
498
|
+
attr = genxDeclareAttribute (w, ns, RSTRING (name)->ptr, &st);
|
499
|
+
if (st)
|
500
|
+
rb_raise (rb_cGenXException, "%s", genxGetErrorMessage (w, st));
|
501
|
+
|
502
|
+
return Data_Wrap_Struct (rb_cGenXAttribute, NULL, NULL, attr);
|
503
|
+
}
|
504
|
+
|
505
|
+
void
|
506
|
+
Init_genx4r ()
|
507
|
+
{
|
508
|
+
rb_mGenX = rb_define_module ("GenX");
|
509
|
+
|
510
|
+
rb_cGenXWriter = rb_define_class_under (rb_mGenX, "Writer", rb_cObject);
|
511
|
+
|
512
|
+
#if RUBY_VERSION_MAJOR >= 1 && RUBY_VERSION_MINOR >= 8
|
513
|
+
rb_define_alloc_func (rb_cGenXWriter, writer_allocate);
|
514
|
+
#else
|
515
|
+
rb_define_singleton_method(rb_cGenXWriter, "new", writer_new, 0);
|
516
|
+
#endif
|
517
|
+
|
518
|
+
rb_define_method (rb_cGenXWriter, "document", writer_document, 1);
|
519
|
+
|
520
|
+
rb_define_method (rb_cGenXWriter,
|
521
|
+
"begin_document",
|
522
|
+
writer_begin_document,
|
523
|
+
1);
|
524
|
+
|
525
|
+
rb_define_method (rb_cGenXWriter,
|
526
|
+
"end_document",
|
527
|
+
writer_end_document,
|
528
|
+
0);
|
529
|
+
|
530
|
+
rb_define_method (rb_cGenXWriter, "comment", writer_comment, 1);
|
531
|
+
rb_define_method (rb_cGenXWriter, "pi", writer_pi, 2);
|
532
|
+
|
533
|
+
rb_define_method (rb_cGenXWriter, "element", writer_element, -1);
|
534
|
+
|
535
|
+
rb_define_method (rb_cGenXWriter, "begin_element", writer_begin_element, -1);
|
536
|
+
rb_define_method (rb_cGenXWriter, "end_element", writer_end_element, 0);
|
537
|
+
|
538
|
+
rb_define_method (rb_cGenXWriter, "attribute", writer_attribute, -1);
|
539
|
+
rb_define_method (rb_cGenXWriter, "text", writer_text, 1);
|
540
|
+
rb_define_method (rb_cGenXWriter, "character", writer_character, 1);
|
541
|
+
|
542
|
+
rb_define_method (rb_cGenXWriter,
|
543
|
+
"declare_namespace",
|
544
|
+
writer_declare_namespace,
|
545
|
+
-1);
|
546
|
+
|
547
|
+
rb_define_method (rb_cGenXWriter,
|
548
|
+
"declare_element",
|
549
|
+
writer_declare_element,
|
550
|
+
-1);
|
551
|
+
|
552
|
+
rb_define_method (rb_cGenXWriter,
|
553
|
+
"declare_attribute",
|
554
|
+
writer_declare_attribute,
|
555
|
+
-1);
|
556
|
+
|
557
|
+
rb_cGenXNamespace = rb_define_class_under (rb_mGenX,
|
558
|
+
"Namespace",
|
559
|
+
rb_cObject);
|
560
|
+
|
561
|
+
rb_cGenXElement = rb_define_class_under (rb_mGenX, "Element", rb_cObject);
|
562
|
+
|
563
|
+
rb_cGenXAttribute = rb_define_class_under (rb_mGenX,
|
564
|
+
"Attribute",
|
565
|
+
rb_cObject);
|
566
|
+
|
567
|
+
rb_cGenXException = rb_define_class_under (rb_mGenX,
|
568
|
+
"Exception",
|
569
|
+
rb_eStandardError);
|
570
|
+
}
|