genx4r 0.04

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
@@ -0,0 +1,584 @@
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 278 2004-07-26 13:09:20Z 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;
404
+ genxNamespace ns;
405
+ genxStatus st;
406
+ genxWriter w;
407
+
408
+ switch (argc)
409
+ {
410
+ case 1:
411
+ uri = argv[0];
412
+ prefix = 0;
413
+ break;
414
+
415
+ case 2:
416
+ uri = argv[0];
417
+ prefix = argv[1];
418
+ break;
419
+
420
+ default:
421
+ rb_raise (rb_eRuntimeError, "invalid arguments");
422
+ }
423
+
424
+ Check_Type (uri, T_STRING);
425
+ if (prefix)
426
+ Check_Type (prefix, T_STRING);
427
+
428
+ Data_Get_Struct (self, struct genxWriter_rec, w);
429
+
430
+ ns = genxDeclareNamespace (w,
431
+ (constUtf8) RSTRING (uri)->ptr,
432
+ prefix ? (constUtf8) RSTRING (prefix)->ptr : NULL,
433
+ &st);
434
+
435
+ if (st)
436
+ rb_raise (rb_cGenXException, "%s", genxLastErrorMessage (w));
437
+
438
+ return Data_Wrap_Struct (rb_cGenXNamespace, NULL, NULL, ns);
439
+ }
440
+
441
+ static VALUE
442
+ writer_declare_element (int argc, VALUE *argv, VALUE self)
443
+ {
444
+ genxNamespace ns = 0;
445
+ genxElement elem;
446
+ genxStatus st;
447
+ genxWriter w;
448
+ VALUE name;
449
+
450
+ switch (argc)
451
+ {
452
+ case 1:
453
+ name = argv[0];
454
+ break;
455
+
456
+ case 2:
457
+ if (CLASS_OF (argv[0]) == rb_cGenXNamespace) {
458
+ Data_Get_Struct (argv[0], struct genxNamespace_rec, ns);
459
+ } else {
460
+ rb_raise (rb_eRuntimeError, "invalid arguments");
461
+ }
462
+ name = argv[1];
463
+ break;
464
+
465
+ default:
466
+ rb_raise (rb_eRuntimeError, "invalid arguments");
467
+ }
468
+
469
+ Check_Type (name, T_STRING);
470
+
471
+ Data_Get_Struct (self, struct genxWriter_rec, w);
472
+
473
+ elem = genxDeclareElement (w, ns, RSTRING (name)->ptr, &st);
474
+ if (st)
475
+ rb_raise (rb_cGenXException, "%s", genxLastErrorMessage (w));
476
+
477
+ return Data_Wrap_Struct (rb_cGenXElement, NULL, NULL, elem);
478
+ }
479
+
480
+ static VALUE
481
+ writer_declare_attribute (int argc, VALUE *argv, VALUE self)
482
+ {
483
+ genxNamespace ns = 0;
484
+ genxAttribute attr;
485
+ genxStatus st;
486
+ genxWriter w;
487
+ VALUE name;
488
+
489
+ switch (argc)
490
+ {
491
+ case 1:
492
+ name = argv[0];
493
+ break;
494
+
495
+ case 2:
496
+ if (CLASS_OF (argv[0]) == rb_cGenXNamespace) {
497
+ Data_Get_Struct (argv[0], struct genxNamespace_rec, ns);
498
+ } else {
499
+ rb_raise (rb_eRuntimeError, "invalid arguments");
500
+ }
501
+ name = argv[1];
502
+ break;
503
+
504
+ default:
505
+ rb_raise (rb_eRuntimeError, "invalid arguments");
506
+ }
507
+
508
+ Check_Type (name, T_STRING);
509
+
510
+ Data_Get_Struct (self, struct genxWriter_rec, w);
511
+
512
+ attr = genxDeclareAttribute (w, ns, RSTRING (name)->ptr, &st);
513
+ if (st)
514
+ rb_raise (rb_cGenXException, "%s", genxLastErrorMessage (w));
515
+
516
+ return Data_Wrap_Struct (rb_cGenXAttribute, NULL, NULL, attr);
517
+ }
518
+
519
+ void
520
+ Init_genx4r ()
521
+ {
522
+ rb_mGenX = rb_define_module ("GenX");
523
+
524
+ rb_cGenXWriter = rb_define_class_under (rb_mGenX, "Writer", rb_cObject);
525
+
526
+ #if RUBY_VERSION_MAJOR >= 1 && RUBY_VERSION_MINOR >= 8
527
+ rb_define_alloc_func (rb_cGenXWriter, writer_allocate);
528
+ #else
529
+ rb_define_singleton_method(rb_cGenXWriter, "new", writer_new, 0);
530
+ #endif
531
+
532
+ rb_define_method (rb_cGenXWriter, "document", writer_document, 1);
533
+
534
+ rb_define_method (rb_cGenXWriter,
535
+ "begin_document",
536
+ writer_begin_document,
537
+ 1);
538
+
539
+ rb_define_method (rb_cGenXWriter,
540
+ "end_document",
541
+ writer_end_document,
542
+ 0);
543
+
544
+ rb_define_method (rb_cGenXWriter, "comment", writer_comment, 1);
545
+ rb_define_method (rb_cGenXWriter, "pi", writer_pi, 2);
546
+
547
+ rb_define_method (rb_cGenXWriter, "element", writer_element, -1);
548
+
549
+ rb_define_method (rb_cGenXWriter, "begin_element", writer_begin_element, -1);
550
+ rb_define_method (rb_cGenXWriter, "end_element", writer_end_element, 0);
551
+
552
+ rb_define_method (rb_cGenXWriter, "attribute", writer_attribute, -1);
553
+ rb_define_method (rb_cGenXWriter, "text", writer_text, 1);
554
+ rb_define_method (rb_cGenXWriter, "character", writer_character, 1);
555
+
556
+ rb_define_method (rb_cGenXWriter,
557
+ "declare_namespace",
558
+ writer_declare_namespace,
559
+ -1);
560
+
561
+ rb_define_method (rb_cGenXWriter,
562
+ "declare_element",
563
+ writer_declare_element,
564
+ -1);
565
+
566
+ rb_define_method (rb_cGenXWriter,
567
+ "declare_attribute",
568
+ writer_declare_attribute,
569
+ -1);
570
+
571
+ rb_cGenXNamespace = rb_define_class_under (rb_mGenX,
572
+ "Namespace",
573
+ rb_cObject);
574
+
575
+ rb_cGenXElement = rb_define_class_under (rb_mGenX, "Element", rb_cObject);
576
+
577
+ rb_cGenXAttribute = rb_define_class_under (rb_mGenX,
578
+ "Attribute",
579
+ rb_cObject);
580
+
581
+ rb_cGenXException = rb_define_class_under (rb_mGenX,
582
+ "Exception",
583
+ rb_eStandardError);
584
+ }