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