~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/libcroco/cr-input.c

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

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