~vaifrax/inkscape/bugfix170049

« back to all changes in this revision

Viewing changes to src/libcroco/cr-input.c

  • Committer: mental
  • Date: 2006-01-16 02:36:01 UTC
  • Revision ID: mental@users.sourceforge.net-20060116023601-wkr0h7edl5veyudq
moving trunk for module inkscape

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8-*- */
 
2
 
 
3
/*
 
4
 * This file is part of The Croco Library
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of version 2.1 of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
18
 * USA
 
19
 *
 
20
 * Author: Dodji Seketeli
 
21
 * See COPYRIGHTS file for copyright information.
 
22
 */
 
23
 
 
24
#include "stdio.h"
 
25
#include <string.h>
 
26
#include "cr-input.h"
 
27
#include "cr-enc-handler.h"
 
28
 
 
29
/**
 
30
 *@file
 
31
 *The definition of the #CRInput class.
 
32
 */
 
33
 
 
34
/*******************
 
35
 *Private type defs
 
36
 *******************/
 
37
 
 
38
/**
 
39
 *The private attributes of
 
40
 *the #CRInputPriv class.
 
41
 */
 
42
struct _CRInputPriv {
 
43
        /*
 
44
         *The input buffer
 
45
         */
 
46
        guchar *in_buf;
 
47
        gulong in_buf_size;
 
48
 
 
49
        gulong nb_bytes;
 
50
 
 
51
        /*
 
52
         *The index of the next byte
 
53
         *to be read.
 
54
         */
 
55
        gulong next_byte_index;
 
56
 
 
57
        /*
 
58
         *The current line number
 
59
         */
 
60
        gulong line;
 
61
 
 
62
        /*
 
63
         *The current col number
 
64
         */
 
65
        gulong col;
 
66
 
 
67
        gboolean end_of_line;
 
68
        gboolean end_of_input;
 
69
 
 
70
        /*
 
71
         *the reference count of this
 
72
         *instance.
 
73
         */
 
74
        guint ref_count;
 
75
        gboolean free_in_buf;
 
76
};
 
77
 
 
78
#define PRIVATE(object) (object)->priv
 
79
 
 
80
/***************************
 
81
 *private constants
 
82
 **************************/
 
83
#define CR_INPUT_MEM_CHUNK_SIZE 1024 * 4
 
84
 
 
85
static CRInput *cr_input_new_real (void);
 
86
 
 
87
static CRInput *
 
88
cr_input_new_real (void)
 
89
{
 
90
        CRInput *result = NULL;
 
91
 
 
92
        result = g_try_malloc (sizeof (CRInput));
 
93
        if (!result) {
 
94
                cr_utils_trace_info ("Out of memory");
 
95
                return NULL;
 
96
        }
 
97
        memset (result, 0, sizeof (CRInput));
 
98
 
 
99
        PRIVATE (result) = g_try_malloc (sizeof (CRInputPriv));
 
100
        if (!PRIVATE (result)) {
 
101
                cr_utils_trace_info ("Out of memory");
 
102
                g_free (result);
 
103
                return NULL;
 
104
        }
 
105
        memset (PRIVATE (result), 0, sizeof (CRInputPriv));
 
106
        PRIVATE (result)->free_in_buf = TRUE;
 
107
        return result;
 
108
}
 
109
 
 
110
/****************
 
111
 *Public methods
 
112
 ***************/
 
113
 
 
114
/**
 
115
 *Creates a new input stream from a memory buffer.
 
116
 *@param a_buf the memory buffer to create the input stream from.
 
117
 *The #CRInput keeps this pointer so user should not free it !.
 
118
 *@param a_len the size of the input buffer.
 
119
 *@param a_enc the buffer's encoding.
 
120
 *@param a_free_buf if set to TRUE, this a_buf will be freed
 
121
 *at the destruction of this instance. If set to false, it is up
 
122
 *to the caller to free it.
 
123
 *@return the newly built instance of #CRInput.
 
124
 */
 
125
CRInput *
 
126
cr_input_new_from_buf (guchar * a_buf,
 
127
                       gulong a_len,
 
128
                       enum CREncoding a_enc,
 
129
                       gboolean a_free_buf)
 
130
{
 
131
        CRInput *result = NULL;
 
132
        enum CRStatus status = CR_OK;
 
133
        CREncHandler *enc_handler = NULL;
 
134
        gulong len = a_len;
 
135
 
 
136
        g_return_val_if_fail (a_buf, NULL);
 
137
 
 
138
        result = cr_input_new_real ();
 
139
        g_return_val_if_fail (result, NULL);
 
140
 
 
141
        /*transform the encoding in utf8 */
 
142
        if (a_enc != CR_UTF_8) {
 
143
                enc_handler = cr_enc_handler_get_instance (a_enc);
 
144
                if (!enc_handler) {
 
145
                        goto error;
 
146
                }
 
147
 
 
148
                status = cr_enc_handler_convert_input
 
149
                        (enc_handler, a_buf, &len,
 
150
                         &PRIVATE (result)->in_buf,
 
151
                         &PRIVATE (result)->in_buf_size);
 
152
                if (status != CR_OK)
 
153
                        goto error;
 
154
                PRIVATE (result)->free_in_buf = TRUE;
 
155
                if (a_free_buf == TRUE && a_buf) {
 
156
                        g_free (a_buf) ;
 
157
                        a_buf = NULL ;
 
158
                }                
 
159
                PRIVATE (result)->nb_bytes = PRIVATE (result)->in_buf_size;
 
160
        } else {
 
161
                PRIVATE (result)->in_buf = (guchar *) a_buf;
 
162
                PRIVATE (result)->in_buf_size = a_len;
 
163
                PRIVATE (result)->nb_bytes = a_len;
 
164
                PRIVATE (result)->free_in_buf = a_free_buf;
 
165
        }
 
166
        PRIVATE (result)->line = 1;
 
167
        PRIVATE (result)->col =  0;
 
168
        return result;
 
169
 
 
170
 error:
 
171
        if (result) {
 
172
                cr_input_destroy (result);
 
173
                result = NULL;
 
174
        }
 
175
 
 
176
        return NULL;
 
177
}
 
178
 
 
179
/**
 
180
 *Creates a new input stream from
 
181
 *a file.
 
182
 *@param a_file_uri the file to create
 
183
 *the input stream from.
 
184
 *@param a_enc the encoding of the file
 
185
 *to create the input from
 
186
 *@return the newly created input stream if
 
187
 *this method could read the file and create it,
 
188
 *NULL otherwise.
 
189
 */
 
190
 
 
191
CRInput *
 
192
cr_input_new_from_uri (const gchar * a_file_uri, enum CREncoding a_enc)
 
193
{
 
194
        CRInput *result = NULL;
 
195
        enum CRStatus status = CR_OK;
 
196
        FILE *file_ptr = NULL;
 
197
        guchar tmp_buf[CR_INPUT_MEM_CHUNK_SIZE] = { 0 };
 
198
        gulong nb_read = 0,
 
199
                len = 0,
 
200
                buf_size = 0;
 
201
        gboolean loop = TRUE;
 
202
        guchar *buf = NULL;
 
203
 
 
204
        g_return_val_if_fail (a_file_uri, NULL);
 
205
 
 
206
        file_ptr = fopen (a_file_uri, "r");
 
207
 
 
208
        if (file_ptr == NULL) {
 
209
 
 
210
#ifdef CR_DEBUG
 
211
                cr_utils_trace_debug ("could not open file");
 
212
#endif
 
213
                g_warning ("Could not open file %s\n", a_file_uri);
 
214
 
 
215
                return NULL;
 
216
        }
 
217
 
 
218
        /*load the file */
 
219
        while (loop) {
 
220
                nb_read = fread (tmp_buf, 1 /*read bytes */ ,
 
221
                                 CR_INPUT_MEM_CHUNK_SIZE /*nb of bytes */ ,
 
222
                                 file_ptr);
 
223
 
 
224
                if (nb_read != CR_INPUT_MEM_CHUNK_SIZE) {
 
225
                        /*we read less chars than we wanted */
 
226
                        if (feof (file_ptr)) {
 
227
                                /*we reached eof */
 
228
                                loop = FALSE;
 
229
                        } else {
 
230
                                /*a pb occured !! */
 
231
                                cr_utils_trace_debug ("an io error occured");
 
232
                                status = CR_ERROR;
 
233
                                goto cleanup;
 
234
                        }
 
235
                }
 
236
 
 
237
                if (status == CR_OK) {
 
238
                        /*read went well */
 
239
                        buf = g_realloc (buf, len + CR_INPUT_MEM_CHUNK_SIZE);
 
240
                        memcpy (buf + len, tmp_buf, nb_read);
 
241
                        len += nb_read;
 
242
                        buf_size += CR_INPUT_MEM_CHUNK_SIZE;
 
243
                }
 
244
        }
 
245
 
 
246
        if (status == CR_OK) {
 
247
                result = cr_input_new_from_buf (buf, len, a_enc, TRUE);
 
248
                if (!result) {
 
249
                        goto cleanup;
 
250
                }
 
251
                /*
 
252
                 *we should  free buf here because it's own by CRInput.
 
253
                 *(see the last parameter of cr_input_new_from_buf().
 
254
                 */
 
255
                buf = NULL ;
 
256
        }
 
257
 
 
258
 cleanup:
 
259
        if (file_ptr) {
 
260
                fclose (file_ptr);
 
261
                file_ptr = NULL;
 
262
        }
 
263
 
 
264
        if (buf) {
 
265
                g_free (buf);
 
266
                buf = NULL;
 
267
        }
 
268
 
 
269
        return result;
 
270
}
 
271
 
 
272
/**
 
273
 *The destructor of the #CRInput class.
 
274
 *@param a_this the current instance of #CRInput.
 
275
 */
 
276
void
 
277
cr_input_destroy (CRInput * a_this)
 
278
{
 
279
        if (a_this == NULL)
 
280
                return;
 
281
 
 
282
        if (PRIVATE (a_this)) {
 
283
                if (PRIVATE (a_this)->in_buf && PRIVATE (a_this)->free_in_buf) {
 
284
                        g_free (PRIVATE (a_this)->in_buf);
 
285
                        PRIVATE (a_this)->in_buf = NULL;
 
286
                }
 
287
 
 
288
                g_free (PRIVATE (a_this));
 
289
                PRIVATE (a_this) = NULL;
 
290
        }
 
291
 
 
292
        g_free (a_this);
 
293
}
 
294
 
 
295
/**
 
296
 *Increments the reference count of the current
 
297
 *instance of #CRInput.
 
298
 *@param a_this the current instance of #CRInput.
 
299
 */
 
300
void
 
301
cr_input_ref (CRInput * a_this)
 
302
{
 
303
        g_return_if_fail (a_this && PRIVATE (a_this));
 
304
 
 
305
        PRIVATE (a_this)->ref_count++;
 
306
}
 
307
 
 
308
/**
 
309
 *Decrements the reference count of this instance
 
310
 *of #CRInput. If the reference count goes down to
 
311
 *zero, this instance is destroyed.
 
312
 *@param a_this the current instance of #CRInput.
 
313
 *
 
314
 */
 
315
gboolean
 
316
cr_input_unref (CRInput * a_this)
 
317
{
 
318
        g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
 
319
 
 
320
        if (PRIVATE (a_this)->ref_count) {
 
321
                PRIVATE (a_this)->ref_count--;
 
322
        }
 
323
 
 
324
        if (PRIVATE (a_this)->ref_count == 0) {
 
325
                cr_input_destroy (a_this);
 
326
                return TRUE;
 
327
        }
 
328
        return FALSE;
 
329
}
 
330
 
 
331
/**
 
332
 *Tests wether the current instance of
 
333
 *#CRInput has reached its input buffer.
 
334
 *@param a_this the current instance of #CRInput.
 
335
 *@param a_end_of_input out parameter. Is set to TRUE if
 
336
 *the current instance has reached the end of its input buffer,
 
337
 *FALSE otherwise.
 
338
 *@param CR_OK upon successful completion, an error code otherwise.
 
339
 *Note that all the out parameters of this method are valid if
 
340
 *and only if this method returns CR_OK.
 
341
 */
 
342
enum CRStatus
 
343
cr_input_end_of_input (CRInput * a_this, gboolean * a_end_of_input)
 
344
{
 
345
        g_return_val_if_fail (a_this && PRIVATE (a_this)
 
346
                              && a_end_of_input, CR_BAD_PARAM_ERROR);
 
347
 
 
348
        *a_end_of_input = (PRIVATE (a_this)->next_byte_index
 
349
                           >= PRIVATE (a_this)->in_buf_size) ? TRUE : FALSE;
 
350
 
 
351
        return CR_OK;
 
352
}
 
353
 
 
354
/**
 
355
 *Returns the number of bytes left in the input stream
 
356
 *before the end.
 
357
 *@param a_this the current instance of #CRInput.
 
358
 *@return the number of characters left or -1 in case of error.
 
359
 */
 
360
glong
 
361
cr_input_get_nb_bytes_left (CRInput * a_this)
 
362
{
 
363
        g_return_val_if_fail (a_this && PRIVATE (a_this), -1);
 
364
        g_return_val_if_fail (PRIVATE (a_this)->nb_bytes
 
365
                              <= PRIVATE (a_this)->in_buf_size, -1);
 
366
        g_return_val_if_fail (PRIVATE (a_this)->next_byte_index
 
367
                              <= PRIVATE (a_this)->nb_bytes, -1);
 
368
 
 
369
        if (PRIVATE (a_this)->end_of_input)
 
370
                return 0;
 
371
 
 
372
        return PRIVATE (a_this)->nb_bytes - PRIVATE (a_this)->next_byte_index;
 
373
}
 
374
 
 
375
/**
 
376
 *Returns the next byte of the input.
 
377
 *Update the state of the input so that
 
378
 *the next invocation of this method  returns
 
379
 *the next coming byte.
 
380
 *
 
381
 *@param a_this the current instance of #CRInput.
 
382
 *@param a_byte out parameter the returned byte.
 
383
 *@return CR_OK upon successful completion, an error code
 
384
 *otherwise. All the out parameters of this method are valid if
 
385
 *and only if this method returns CR_OK.
 
386
 */
 
387
enum CRStatus
 
388
cr_input_read_byte (CRInput * a_this, guchar * a_byte)
 
389
{
 
390
        g_return_val_if_fail (a_this && PRIVATE (a_this)
 
391
                              && a_byte, CR_BAD_PARAM_ERROR);
 
392
 
 
393
        g_return_val_if_fail (PRIVATE (a_this)->next_byte_index <=
 
394
                              PRIVATE (a_this)->nb_bytes, CR_BAD_PARAM_ERROR);
 
395
 
 
396
        if (PRIVATE (a_this)->end_of_input == TRUE)
 
397
                return CR_END_OF_INPUT_ERROR;
 
398
 
 
399
        *a_byte = PRIVATE (a_this)->in_buf[PRIVATE (a_this)->next_byte_index];
 
400
 
 
401
        if (PRIVATE (a_this)->nb_bytes -
 
402
            PRIVATE (a_this)->next_byte_index < 2) {
 
403
                PRIVATE (a_this)->end_of_input = TRUE;
 
404
        } else {
 
405
                PRIVATE (a_this)->next_byte_index++;
 
406
        }
 
407
 
 
408
        return CR_OK;
 
409
}
 
410
 
 
411
/**
 
412
 *Reads an unicode character from the current instance of
 
413
 *#CRInput.
 
414
 *@param a_this the current instance of CRInput.
 
415
 *@param a_char out parameter. The read character.
 
416
 *@return CR_OK upon successful completion, an error code
 
417
 *otherwise.
 
418
 */
 
419
enum CRStatus
 
420
cr_input_read_char (CRInput * a_this, guint32 * a_char)
 
421
{
 
422
        enum CRStatus status = CR_OK;
 
423
        gulong consumed = 0,
 
424
                nb_bytes_left = 0;
 
425
 
 
426
        g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
 
427
                              CR_BAD_PARAM_ERROR);
 
428
 
 
429
        if (PRIVATE (a_this)->end_of_input == TRUE)
 
430
                return CR_END_OF_INPUT_ERROR;
 
431
 
 
432
        nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
 
433
 
 
434
        if (nb_bytes_left < 1) {
 
435
                return CR_END_OF_INPUT_ERROR;
 
436
        }
 
437
 
 
438
        status = cr_utils_read_char_from_utf8_buf
 
439
                (PRIVATE (a_this)->in_buf
 
440
                 +
 
441
                 PRIVATE (a_this)->next_byte_index,
 
442
                 nb_bytes_left, a_char, &consumed);
 
443
 
 
444
        if (status == CR_OK) {
 
445
                /*update next byte index */
 
446
                PRIVATE (a_this)->next_byte_index += consumed;
 
447
 
 
448
                /*update line and column number */
 
449
                if (PRIVATE (a_this)->end_of_line == TRUE) {
 
450
                        PRIVATE (a_this)->col = 1;
 
451
                        PRIVATE (a_this)->line++;
 
452
                        PRIVATE (a_this)->end_of_line = FALSE;
 
453
                } else if (*a_char != '\n') {
 
454
                        PRIVATE (a_this)->col++;
 
455
                }
 
456
 
 
457
                if (*a_char == '\n') {
 
458
                        PRIVATE (a_this)->end_of_line = TRUE;
 
459
                }
 
460
 
 
461
        }
 
462
 
 
463
        return status;
 
464
}
 
465
 
 
466
/**
 
467
 *Setter of the current line number.
 
468
 *@param a_this the "this pointer" of the current instance of
 
469
 *#CRInput.
 
470
 *@param a_line_num the new line number.
 
471
 *@return CR_OK upon successful completion, an error code otherwise.
 
472
 */
 
473
enum CRStatus
 
474
cr_input_set_line_num (CRInput * a_this, glong a_line_num)
 
475
{
 
476
        g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
 
477
 
 
478
        PRIVATE (a_this)->line = a_line_num;
 
479
 
 
480
        return CR_OK;
 
481
}
 
482
 
 
483
/**
 
484
 *Getter of the current line number.
 
485
 *@param a_this the "this pointer" of the current instance of
 
486
 *#CRInput.
 
487
 *@param a_line_num the returned line number.
 
488
 *@return CR_OK upon successful completion, an error code otherwise.
 
489
 */
 
490
enum CRStatus
 
491
cr_input_get_line_num (CRInput * a_this, glong * a_line_num)
 
492
{
 
493
        g_return_val_if_fail (a_this && PRIVATE (a_this)
 
494
                              && a_line_num, CR_BAD_PARAM_ERROR);
 
495
 
 
496
        *a_line_num = PRIVATE (a_this)->line;
 
497
 
 
498
        return CR_OK;
 
499
}
 
500
 
 
501
/**
 
502
 *Setter of the current column number.
 
503
 *@param a_this the "this pointer" of the current instance of
 
504
 *#CRInput.
 
505
 *@param a_col the new column number.
 
506
 *@return CR_OK upon successful completion, an error code otherwise.
 
507
 */
 
508
enum CRStatus
 
509
cr_input_set_column_num (CRInput * a_this, glong a_col)
 
510
{
 
511
        g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
 
512
 
 
513
        PRIVATE (a_this)->col = a_col;
 
514
 
 
515
        return CR_OK;
 
516
}
 
517
 
 
518
/**
 
519
 *Getter of the current column number.
 
520
 *@param a_this the "this pointer" of the current instance of
 
521
 *#CRInput.
 
522
 *@param a_col out parameter
 
523
 *@return CR_OK upon successful completion, an error code otherwise.
 
524
 */
 
525
enum CRStatus
 
526
cr_input_get_column_num (CRInput * a_this, glong * a_col)
 
527
{
 
528
        g_return_val_if_fail (a_this && PRIVATE (a_this) && a_col,
 
529
                              CR_BAD_PARAM_ERROR);
 
530
 
 
531
        *a_col = PRIVATE (a_this)->col;
 
532
 
 
533
        return CR_OK;
 
534
}
 
535
 
 
536
/**
 
537
 *Increments the current line number.
 
538
 *@param a_this the "this pointer" of the current instance of
 
539
 *#CRInput.
 
540
 *@return CR_OK upon successful completion, an error code otherwise.
 
541
 */
 
542
enum CRStatus
 
543
cr_input_increment_line_num (CRInput * a_this, glong a_increment)
 
544
{
 
545
        g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
 
546
 
 
547
        PRIVATE (a_this)->line += a_increment;
 
548
 
 
549
        return CR_OK;
 
550
}
 
551
 
 
552
/**
 
553
 *Increments the current column number.
 
554
 *@param a_this the "this pointer" of the current instance of
 
555
 *#CRInput.
 
556
 *@return CR_OK upon successful completion, an error code otherwise.
 
557
 */
 
558
enum CRStatus
 
559
cr_input_increment_col_num (CRInput * a_this, glong a_increment)
 
560
{
 
561
        g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
 
562
 
 
563
        PRIVATE (a_this)->col += a_increment;
 
564
 
 
565
        return CR_OK;
 
566
}
 
567
 
 
568
/**
 
569
 *Consumes the next character of the input stream if
 
570
 *and only if that character equals a_char.
 
571
 *
 
572
 *@param a_this the this pointer.
 
573
 *@param a_char the character to consume. If set to zero,
 
574
 *consumes any character.
 
575
 *@return CR_OK upon successful completion, CR_PARSING_ERROR if
 
576
 *next char is different from a_char, an other error code otherwise
 
577
 */
 
578
enum CRStatus
 
579
cr_input_consume_char (CRInput * a_this, guint32 a_char)
 
580
{
 
581
        guint32 c;
 
582
        enum CRStatus status;
 
583
 
 
584
        g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
 
585
 
 
586
        if ((status = cr_input_peek_char (a_this, &c)) != CR_OK) {
 
587
                return status;
 
588
        }
 
589
 
 
590
        if (c == a_char || a_char == 0) {
 
591
                status = cr_input_read_char (a_this, &c);
 
592
        } else {
 
593
                return CR_PARSING_ERROR;
 
594
        }
 
595
 
 
596
        return status;
 
597
}
 
598
 
 
599
/**
 
600
 *Consumes up to a_nb_char occurences of the next contiguous characters 
 
601
 *which equal a_char. Note that the next character of the input stream
 
602
 **MUST* equal a_char to trigger the consumption, or else, the error
 
603
 *code CR_PARSING_ERROR is returned.
 
604
 *If the number of contiguous characters that equals a_char is less than
 
605
 *a_nb_char, then this function consumes all the characters it can consume.
 
606
 *
 
607
 *@param a_this the this pointer of the current instance of #CRInput.
 
608
 *@param a_char the character to consume.
 
609
 *@param a_nb_char in/out parameter. The number of characters to consume.
 
610
 *If set to a negative value, the function will consume all the occurences
 
611
 *of a_char found.
 
612
 *After return, if the return value equals CR_OK, this variable contains 
 
613
 *the number of characters actually consumed.
 
614
 *@return CR_OK if at least one character has been consumed, an error code
 
615
 *otherwise.
 
616
 */
 
617
enum CRStatus
 
618
cr_input_consume_chars (CRInput * a_this, guint32 a_char, gulong * a_nb_char)
 
619
{
 
620
        enum CRStatus status = CR_OK;
 
621
        gulong nb_consumed = 0;
 
622
 
 
623
        g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_char,
 
624
                              CR_BAD_PARAM_ERROR);
 
625
 
 
626
        g_return_val_if_fail (a_char != 0 || a_nb_char != NULL,
 
627
                              CR_BAD_PARAM_ERROR);
 
628
 
 
629
        for (nb_consumed = 0; ((status == CR_OK)
 
630
                               && (*a_nb_char > 0
 
631
                                   && nb_consumed < *a_nb_char));
 
632
             nb_consumed++) {
 
633
                status = cr_input_consume_char (a_this, a_char);
 
634
        }
 
635
 
 
636
        *a_nb_char = nb_consumed;
 
637
 
 
638
        if ((nb_consumed > 0)
 
639
            && ((status == CR_PARSING_ERROR)
 
640
                || (status == CR_END_OF_INPUT_ERROR))) {
 
641
                status = CR_OK;
 
642
        }
 
643
 
 
644
        return status;
 
645
}
 
646
 
 
647
/**
 
648
 *Same as cr_input_consume_chars() but this one consumes white
 
649
 *spaces.
 
650
 *
 
651
 *@param a_this the "this pointer" of the current instance of #CRInput.
 
652
 *@param a_nb_chars in/out parameter. The number of white spaces to
 
653
 *consume. After return, holds the number of white spaces actually consumed.
 
654
 *@return CR_OK upon successful completion, an error code otherwise.
 
655
 */
 
656
enum CRStatus
 
657
cr_input_consume_white_spaces (CRInput * a_this, gulong * a_nb_chars)
 
658
{
 
659
        enum CRStatus status = CR_OK;
 
660
        guint32 cur_char = 0,
 
661
                nb_consumed = 0;
 
662
 
 
663
        g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_chars,
 
664
                              CR_BAD_PARAM_ERROR);
 
665
 
 
666
        for (nb_consumed = 0;
 
667
             ((*a_nb_chars > 0) && (nb_consumed < *a_nb_chars));
 
668
             nb_consumed++) {
 
669
                status = cr_input_peek_char (a_this, &cur_char);
 
670
                if (status != CR_OK)
 
671
                        break;
 
672
 
 
673
                /*if the next char is a white space, consume it ! */
 
674
                if (cr_utils_is_white_space (cur_char) == TRUE) {
 
675
                        status = cr_input_read_char (a_this, &cur_char);
 
676
                        if (status != CR_OK)
 
677
                                break;
 
678
                        continue;
 
679
                }
 
680
 
 
681
                break;
 
682
 
 
683
        }
 
684
 
 
685
        if (nb_consumed && status == CR_END_OF_INPUT_ERROR) {
 
686
                status = CR_OK;
 
687
        }
 
688
 
 
689
        return status;
 
690
}
 
691
 
 
692
/**
 
693
 *Same as cr_input_read_char() but does not update the
 
694
 *internal state of the input stream. The next call
 
695
 *to cr_input_peek_char() or cr_input_read_char() will thus
 
696
 *return the same character as the current one.
 
697
 *@param a_this the current instance of #CRInput.
 
698
 *@param a_char out parameter. The returned character.
 
699
 *@return CR_OK upon successful completion, an error code
 
700
 *otherwise.
 
701
 */
 
702
enum CRStatus
 
703
cr_input_peek_char (CRInput * a_this, guint32 * a_char)
 
704
{
 
705
        enum CRStatus status = CR_OK;
 
706
        glong consumed = 0,
 
707
                nb_bytes_left = 0;
 
708
 
 
709
        g_return_val_if_fail (a_this && PRIVATE (a_this)
 
710
                              && a_char, CR_BAD_PARAM_ERROR);
 
711
 
 
712
        if (PRIVATE (a_this)->next_byte_index >=
 
713
            PRIVATE (a_this)->in_buf_size) {
 
714
                return CR_END_OF_INPUT_ERROR;
 
715
        }
 
716
 
 
717
        nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
 
718
 
 
719
        if (nb_bytes_left < 1) {
 
720
                return CR_END_OF_INPUT_ERROR;
 
721
        }
 
722
 
 
723
        status = cr_utils_read_char_from_utf8_buf
 
724
                (PRIVATE (a_this)->in_buf +
 
725
                 PRIVATE (a_this)->next_byte_index,
 
726
                 nb_bytes_left, a_char, &consumed);
 
727
 
 
728
        return status;
 
729
}
 
730
 
 
731
/**
 
732
 *Gets a byte from the input stream,
 
733
 *starting from the current position in the input stream.
 
734
 *Unlike cr_input_peek_next_byte() this method
 
735
 *does not update the state of the current input stream.
 
736
 *Subsequent calls to cr_input_peek_byte with the same arguments
 
737
 *will return the same byte.
 
738
 *
 
739
 *@param a_this the current instance of #CRInput.
 
740
 *@param a_origin the origin to consider in the calculation
 
741
 *of the position of the byte to peek.
 
742
 *@param a_offset the offset of the byte to peek, starting from
 
743
 *the origin specified by a_origin.
 
744
 *@param a_byte out parameter the peeked byte.
 
745
 *@return CR_OK upon successful completion or,
 
746
 *
 
747
 *<ul>
 
748
 *<li>CR_BAD_PARAM_ERROR if at least one of the parameters is invalid</li>
 
749
 *<li>CR_OUT_OF_BOUNDS_ERROR if the indexed byte is out of bounds</li>
 
750
 *</ul>
 
751
 */
 
752
enum CRStatus
 
753
cr_input_peek_byte (CRInput * a_this, enum CRSeekPos a_origin,
 
754
                    gulong a_offset, guchar * a_byte)
 
755
{
 
756
        gulong abs_offset = 0;
 
757
 
 
758
        g_return_val_if_fail (a_this && PRIVATE (a_this)
 
759
                              && a_byte, CR_BAD_PARAM_ERROR);
 
760
 
 
761
        switch (a_origin) {
 
762
 
 
763
        case CR_SEEK_CUR:
 
764
                abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_offset;
 
765
                break;
 
766
 
 
767
        case CR_SEEK_BEGIN:
 
768
                abs_offset = a_offset;
 
769
                break;
 
770
 
 
771
        case CR_SEEK_END:
 
772
                abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_offset;
 
773
                break;
 
774
 
 
775
        default:
 
776
                return CR_BAD_PARAM_ERROR;
 
777
        }
 
778
 
 
779
        if (abs_offset < PRIVATE (a_this)->in_buf_size) {
 
780
 
 
781
                *a_byte = PRIVATE (a_this)->in_buf[abs_offset];
 
782
 
 
783
                return CR_OK;
 
784
 
 
785
        } else {
 
786
                return CR_END_OF_INPUT_ERROR;
 
787
        }
 
788
}
 
789
 
 
790
/**
 
791
 *Same as cr_input_peek_byte() but with a simplified
 
792
 *interface.
 
793
 *@param a_this the current byte input stream.
 
794
 *@param a_offset the offset of the byte to peek, starting
 
795
 *from the current input position pointer.
 
796
 *@param a_eof out parameter. Is set to true is we reach end of
 
797
 *stream. If set to NULL by the caller, this parameter is not taken
 
798
 *in account.
 
799
 *@return the read byte or 0 if something bad happened.
 
800
 */
 
801
guchar
 
802
cr_input_peek_byte2 (CRInput * a_this, gulong a_offset, gboolean * a_eof)
 
803
{
 
804
        guchar result = 0;
 
805
        enum CRStatus status = CR_ERROR;
 
806
 
 
807
        g_return_val_if_fail (a_this && PRIVATE (a_this), 0);
 
808
 
 
809
        if (a_eof)
 
810
                *a_eof = FALSE;
 
811
 
 
812
        status = cr_input_peek_byte (a_this, CR_SEEK_CUR, a_offset, &result);
 
813
 
 
814
        if ((status == CR_END_OF_INPUT_ERROR)
 
815
            && a_eof)
 
816
                *a_eof = TRUE;
 
817
 
 
818
        return result;
 
819
}
 
820
 
 
821
/**
 
822
 *Returns the memory address of the byte located at a given offset
 
823
 *in the input stream.
 
824
 *@param a_this the current instance of #CRInput.
 
825
 *@param a_offset the offset of the byte in the input stream starting
 
826
 *from the beginning of the stream.
 
827
 *@return the address, otherwise NULL if an error occured.
 
828
 */
 
829
guchar *
 
830
cr_input_get_byte_addr (CRInput * a_this, gulong a_offset)
 
831
{
 
832
        g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
 
833
 
 
834
        if (a_offset >= PRIVATE (a_this)->nb_bytes) {
 
835
                return NULL;
 
836
        }
 
837
 
 
838
        return &PRIVATE (a_this)->in_buf[a_offset];
 
839
}
 
840
 
 
841
/**
 
842
 *Returns the address of the current character pointer.
 
843
 *@param a_this the current input stream
 
844
 *@param a_offset out parameter. The returned address.
 
845
 *@return CR_OK upon successful completion, an error code otherwise.
 
846
 */
 
847
enum CRStatus
 
848
cr_input_get_cur_byte_addr (CRInput * a_this, guchar ** a_offset)
 
849
{
 
850
        g_return_val_if_fail (a_this && PRIVATE (a_this) && a_offset,
 
851
                              CR_BAD_PARAM_ERROR);
 
852
 
 
853
        if (!PRIVATE (a_this)->next_byte_index) {
 
854
                return CR_START_OF_INPUT_ERROR;
 
855
        }
 
856
 
 
857
        *a_offset = cr_input_get_byte_addr
 
858
                (a_this, PRIVATE (a_this)->next_byte_index - 1);
 
859
 
 
860
        return CR_OK;
 
861
}
 
862
 
 
863
/**
 
864
 *Sets the "current byte index" of the current instance
 
865
 *of #CRInput. Next call to cr_input_get_byte() will return
 
866
 *the byte next after the new "current byte index".
 
867
 *
 
868
 *@param a_this the current instance of #CRInput.
 
869
 *
 
870
 *@param a_origin the origin to consider during the calculation
 
871
 *of the absolute position of the new "current byte index".
 
872
 *
 
873
 *@param a_pos the relative offset of the new "current byte index."
 
874
 *This offset is relative to the origin a_origin.
 
875
 *
 
876
 *@return CR_OK upon successful completion otherwise returns
 
877
 *<ul>
 
878
 *<li>CR_BAD_PARAM_ERROR if at least one of the parameters is not valid</li>
 
879
 *<li>CR_OUT_BOUNDS_ERROR</li>
 
880
 *</ul>
 
881
 */
 
882
enum CRStatus
 
883
cr_input_seek_index (CRInput * a_this, enum CRSeekPos a_origin, gint a_pos)
 
884
{
 
885
 
 
886
        glong abs_offset = 0;
 
887
 
 
888
        g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
 
889
 
 
890
        switch (a_origin) {
 
891
 
 
892
        case CR_SEEK_CUR:
 
893
                abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_pos;
 
894
                break;
 
895
 
 
896
        case CR_SEEK_BEGIN:
 
897
                abs_offset = a_pos;
 
898
                break;
 
899
 
 
900
        case CR_SEEK_END:
 
901
                abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_pos;
 
902
                break;
 
903
 
 
904
        default:
 
905
                return CR_BAD_PARAM_ERROR;
 
906
        }
 
907
 
 
908
        if ((abs_offset > 0)
 
909
            && (gulong) abs_offset < PRIVATE (a_this)->nb_bytes) {
 
910
 
 
911
                /*update the input stream's internal state */
 
912
                PRIVATE (a_this)->next_byte_index = abs_offset + 1;
 
913
 
 
914
                return CR_OK;
 
915
        }
 
916
 
 
917
        return CR_OUT_OF_BOUNDS_ERROR;
 
918
}
 
919
 
 
920
/**
 
921
 *Gets the position of the "current byte index" which
 
922
 *is basically the position of the last returned byte in the
 
923
 *input stream.
 
924
 *
 
925
 *@param a_this the current instance of #CRInput.
 
926
 *
 
927
 *@param a_pos out parameter. The returned position.
 
928
 *
 
929
 *@return CR_OK upon successful completion. Otherwise,
 
930
 *<ul>
 
931
 *<li>CR_BAD_PARAMETER_ERROR if at least one of the arguments is invalid.</li>
 
932
 *<li>CR_START_OF_INPUT if no call to either cr_input_read_byte()
 
933
 *or cr_input_seek_index() have been issued before calling 
 
934
 *cr_input_get_cur_pos()</li>
 
935
 *</ul>
 
936
 *Note that the out parameters of this function are valid if and only if this
 
937
 *function returns CR_OK.
 
938
 */
 
939
enum CRStatus
 
940
cr_input_get_cur_pos (CRInput * a_this, CRInputPos * a_pos)
 
941
{
 
942
        g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
 
943
                              CR_BAD_PARAM_ERROR);
 
944
 
 
945
        a_pos->next_byte_index = PRIVATE (a_this)->next_byte_index;
 
946
        a_pos->line = PRIVATE (a_this)->line;
 
947
        a_pos->col = PRIVATE (a_this)->col;
 
948
        a_pos->end_of_line = PRIVATE (a_this)->end_of_line;
 
949
        a_pos->end_of_file = PRIVATE (a_this)->end_of_input;
 
950
 
 
951
        return CR_OK;
 
952
}
 
953
 
 
954
/**
 
955
 *Gets the current parsing location.
 
956
 *The Parsing location is a public datastructure that
 
957
 *represents the current line/column/byte offset/ in the input
 
958
 *stream.
 
959
 *@param a_this the current instance of #CRInput
 
960
 *@param a_loc the set parsing location.
 
961
 *@return CR_OK upon successful completion, an error
 
962
 *code otherwise.
 
963
 */
 
964
enum CRStatus
 
965
cr_input_get_parsing_location (CRInput *a_this,
 
966
                               CRParsingLocation *a_loc)
 
967
{
 
968
        g_return_val_if_fail (a_this 
 
969
                              && PRIVATE (a_this)
 
970
                              && a_loc, 
 
971
                              CR_BAD_PARAM_ERROR) ;
 
972
 
 
973
        a_loc->line = PRIVATE (a_this)->line ;
 
974
        a_loc->column = PRIVATE (a_this)->col ;
 
975
        if (PRIVATE (a_this)->next_byte_index) {
 
976
                a_loc->byte_offset = PRIVATE (a_this)->next_byte_index - 1 ;
 
977
        } else {
 
978
                a_loc->byte_offset = PRIVATE (a_this)->next_byte_index  ;
 
979
        }
 
980
        return CR_OK ;
 
981
}
 
982
 
 
983
/**
 
984
 *Getter of the next byte index. 
 
985
 *It actually returns the index of the
 
986
 *next byte to be read.
 
987
 *@param a_this the "this pointer" of the current instance of
 
988
 *#CRInput
 
989
 *@param a_index out parameter. The returned index.
 
990
 *@return CR_OK upon successful completion, an error code
 
991
 *otherwise.
 
992
 */
 
993
enum CRStatus
 
994
cr_input_get_cur_index (CRInput * a_this, glong * a_index)
 
995
{
 
996
        g_return_val_if_fail (a_this && PRIVATE (a_this)
 
997
                              && a_index, CR_BAD_PARAM_ERROR);
 
998
 
 
999
        *a_index = PRIVATE (a_this)->next_byte_index;
 
1000
 
 
1001
        return CR_OK;
 
1002
}
 
1003
 
 
1004
/**
 
1005
 *Setter of the next byte index.
 
1006
 *It sets the index of the next byte to be read.
 
1007
 *@param a_this the "this pointer" of the current instance
 
1008
 *of #CRInput .
 
1009
 *@param a_index the new index to set.
 
1010
 *@return CR_OK upon successful completion, an error code otherwise.
 
1011
 */
 
1012
enum CRStatus
 
1013
cr_input_set_cur_index (CRInput * a_this, glong a_index)
 
1014
{
 
1015
        g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
 
1016
 
 
1017
        PRIVATE (a_this)->next_byte_index = a_index;
 
1018
 
 
1019
        return CR_OK;
 
1020
}
 
1021
 
 
1022
/**
 
1023
 *Sets the end of file flag.
 
1024
 *@param a_this the current instance of #CRInput.
 
1025
 *@param a_eof the new end of file flag.
 
1026
 *@return CR_OK upon successful completion, an error code otherwise.
 
1027
 */
 
1028
enum CRStatus
 
1029
cr_input_set_end_of_file (CRInput * a_this, gboolean a_eof)
 
1030
{
 
1031
        g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
 
1032
 
 
1033
        PRIVATE (a_this)->end_of_input = a_eof;
 
1034
 
 
1035
        return CR_OK;
 
1036
}
 
1037
 
 
1038
/**
 
1039
 *Gets the end of file flag.
 
1040
 *@param a_this the current instance of #CRInput.
 
1041
 *@param a_eof out parameter the place to put the end of
 
1042
 *file flag.
 
1043
 *@return CR_OK upon successful completion, an error code otherwise.
 
1044
 */
 
1045
enum CRStatus
 
1046
cr_input_get_end_of_file (CRInput * a_this, gboolean * a_eof)
 
1047
{
 
1048
        g_return_val_if_fail (a_this && PRIVATE (a_this)
 
1049
                              && a_eof, CR_BAD_PARAM_ERROR);
 
1050
 
 
1051
        *a_eof = PRIVATE (a_this)->end_of_input;
 
1052
 
 
1053
        return CR_OK;
 
1054
}
 
1055
 
 
1056
/**
 
1057
 *Sets the end of line flag.
 
1058
 *@param a_this the current instance of #CRInput.
 
1059
 *@param a_eol the new end of line flag.
 
1060
 *@return CR_OK upon successful completion, an error code
 
1061
 *otherwise.
 
1062
 */
 
1063
enum CRStatus
 
1064
cr_input_set_end_of_line (CRInput * a_this, gboolean a_eol)
 
1065
{
 
1066
        g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
 
1067
 
 
1068
        PRIVATE (a_this)->end_of_line = a_eol;
 
1069
 
 
1070
        return CR_OK;
 
1071
}
 
1072
 
 
1073
/**
 
1074
 *Gets the end of line flag of the current input.
 
1075
 *@param a_this the current instance of #CRInput
 
1076
 *@param a_eol out parameter. The place to put
 
1077
 *the returned flag
 
1078
 *@return CR_OK upon successful completion, an error code
 
1079
 *otherwise.
 
1080
 */
 
1081
enum CRStatus
 
1082
cr_input_get_end_of_line (CRInput * a_this, gboolean * a_eol)
 
1083
{
 
1084
        g_return_val_if_fail (a_this && PRIVATE (a_this)
 
1085
                              && a_eol, CR_BAD_PARAM_ERROR);
 
1086
 
 
1087
        *a_eol = PRIVATE (a_this)->end_of_line;
 
1088
 
 
1089
        return CR_OK;
 
1090
}
 
1091
 
 
1092
/**
 
1093
 *Sets the current position in the input stream.
 
1094
 *
 
1095
 *@param a_this the "this pointer" of the current instance of
 
1096
 *#CRInput.
 
1097
 *@param a_pos the new position.
 
1098
 */
 
1099
enum CRStatus
 
1100
cr_input_set_cur_pos (CRInput * a_this, CRInputPos * a_pos)
 
1101
{
 
1102
        g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
 
1103
                              CR_BAD_PARAM_ERROR);
 
1104
 
 
1105
        cr_input_set_column_num (a_this, a_pos->col);
 
1106
        cr_input_set_line_num (a_this, a_pos->line);
 
1107
        cr_input_set_cur_index (a_this, a_pos->next_byte_index);
 
1108
        cr_input_set_end_of_line (a_this, a_pos->end_of_line);
 
1109
        cr_input_set_end_of_file (a_this, a_pos->end_of_file);
 
1110
 
 
1111
        return CR_OK;
 
1112
}