Code

9485df3c59a12431bd886ba6007bcd1430b59353
[inkscape.git] / src / libcroco / cr-input.c
1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8-*- */
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  */
24 #include "stdio.h"
25 #include <string.h>
26 #include "cr-input.h"
27 #include "cr-enc-handler.h"
29 /**
30  *@file
31  *The definition of the #CRInput class.
32  */
34 /*******************
35  *Private type defs
36  *******************/
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;
49         gulong nb_bytes;
51         /*
52          *The index of the next byte
53          *to be read.
54          */
55         gulong next_byte_index;
57         /*
58          *The current line number
59          */
60         gulong line;
62         /*
63          *The current col number
64          */
65         gulong col;
67         gboolean end_of_line;
68         gboolean end_of_input;
70         /*
71          *the reference count of this
72          *instance.
73          */
74         guint ref_count;
75         gboolean free_in_buf;
76 };
78 #define PRIVATE(object) (object)->priv
80 /***************************
81  *private constants
82  **************************/
83 #define CR_INPUT_MEM_CHUNK_SIZE 1024 * 4
85 static CRInput *cr_input_new_real (void);
87 static CRInput *
88 cr_input_new_real (void)
89 {
90         CRInput *result = NULL;
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));
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;
110 /****************
111  *Public methods
112  ***************/
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)
131         CRInput *result = NULL;
132         enum CRStatus status = CR_OK;
133         CREncHandler *enc_handler = NULL;
134         gulong len = a_len;
136         g_return_val_if_fail (a_buf, NULL);
138         result = cr_input_new_real ();
139         g_return_val_if_fail (result, NULL);
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                 }
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;
170  error:
171         if (result) {
172                 cr_input_destroy (result);
173                 result = NULL;
174         }
176         return NULL;
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  */
191 CRInput *
192 cr_input_new_from_uri (const gchar * a_file_uri, enum CREncoding a_enc)
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;
204         g_return_val_if_fail (a_file_uri, NULL);
206         file_ptr = fopen (a_file_uri, "r");
208         if (file_ptr == NULL) {
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);
215                 return NULL;
216         }
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);
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                 }
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         }
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         }
258  cleanup:
259         if (file_ptr) {
260                 fclose (file_ptr);
261                 file_ptr = NULL;
262         }
264         if (buf) {
265                 g_free (buf);
266                 buf = NULL;
267         }
269         return result;
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)
279         if (a_this == NULL)
280                 return;
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                 }
288                 g_free (PRIVATE (a_this));
289                 PRIVATE (a_this) = NULL;
290         }
292         g_free (a_this);
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)
303         g_return_if_fail (a_this && PRIVATE (a_this));
305         PRIVATE (a_this)->ref_count++;
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)
318         g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
320         if (PRIVATE (a_this)->ref_count) {
321                 PRIVATE (a_this)->ref_count--;
322         }
324         if (PRIVATE (a_this)->ref_count == 0) {
325                 cr_input_destroy (a_this);
326                 return TRUE;
327         }
328         return FALSE;
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)
345         g_return_val_if_fail (a_this && PRIVATE (a_this)
346                               && a_end_of_input, CR_BAD_PARAM_ERROR);
348         *a_end_of_input = (PRIVATE (a_this)->next_byte_index
349                            >= PRIVATE (a_this)->in_buf_size) ? TRUE : FALSE;
351         return CR_OK;
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)
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);
369         if (PRIVATE (a_this)->end_of_input)
370                 return 0;
372         return PRIVATE (a_this)->nb_bytes - PRIVATE (a_this)->next_byte_index;
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)
390         g_return_val_if_fail (a_this && PRIVATE (a_this)
391                               && a_byte, CR_BAD_PARAM_ERROR);
393         g_return_val_if_fail (PRIVATE (a_this)->next_byte_index <=
394                               PRIVATE (a_this)->nb_bytes, CR_BAD_PARAM_ERROR);
396         if (PRIVATE (a_this)->end_of_input == TRUE)
397                 return CR_END_OF_INPUT_ERROR;
399         *a_byte = PRIVATE (a_this)->in_buf[PRIVATE (a_this)->next_byte_index];
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         }
408         return CR_OK;
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)
422         enum CRStatus status = CR_OK;
423         gulong consumed = 0,
424                 nb_bytes_left = 0;
426         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
427                               CR_BAD_PARAM_ERROR);
429         if (PRIVATE (a_this)->end_of_input == TRUE)
430                 return CR_END_OF_INPUT_ERROR;
432         nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
434         if (nb_bytes_left < 1) {
435                 return CR_END_OF_INPUT_ERROR;
436         }
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);
444         if (status == CR_OK) {
445                 /*update next byte index */
446                 PRIVATE (a_this)->next_byte_index += consumed;
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                 }
457                 if (*a_char == '\n') {
458                         PRIVATE (a_this)->end_of_line = TRUE;
459                 }
461         }
463         return status;
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)
476         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
478         PRIVATE (a_this)->line = a_line_num;
480         return CR_OK;
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)
493         g_return_val_if_fail (a_this && PRIVATE (a_this)
494                               && a_line_num, CR_BAD_PARAM_ERROR);
496         *a_line_num = PRIVATE (a_this)->line;
498         return CR_OK;
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)
511         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
513         PRIVATE (a_this)->col = a_col;
515         return CR_OK;
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)
528         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_col,
529                               CR_BAD_PARAM_ERROR);
531         *a_col = PRIVATE (a_this)->col;
533         return CR_OK;
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)
545         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
547         PRIVATE (a_this)->line += a_increment;
549         return CR_OK;
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)
561         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
563         PRIVATE (a_this)->col += a_increment;
565         return CR_OK;
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)
581         guint32 c;
582         enum CRStatus status;
584         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
586         if ((status = cr_input_peek_char (a_this, &c)) != CR_OK) {
587                 return status;
588         }
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         }
596         return status;
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)
620         enum CRStatus status = CR_OK;
621         gulong nb_consumed = 0;
623         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_char,
624                               CR_BAD_PARAM_ERROR);
626         g_return_val_if_fail (a_char != 0 || a_nb_char != NULL,
627                               CR_BAD_PARAM_ERROR);
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         }
636         *a_nb_char = nb_consumed;
638         if ((nb_consumed > 0)
639             && ((status == CR_PARSING_ERROR)
640                 || (status == CR_END_OF_INPUT_ERROR))) {
641                 status = CR_OK;
642         }
644         return status;
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)
659         enum CRStatus status = CR_OK;
660         guint32 cur_char = 0,
661                 nb_consumed = 0;
663         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_chars,
664                               CR_BAD_PARAM_ERROR);
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;
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                 }
681                 break;
683         }
685         if (nb_consumed && status == CR_END_OF_INPUT_ERROR) {
686                 status = CR_OK;
687         }
689         return status;
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)
705         enum CRStatus status = CR_OK;
706         glong consumed = 0,
707                 nb_bytes_left = 0;
709         g_return_val_if_fail (a_this && PRIVATE (a_this)
710                               && a_char, CR_BAD_PARAM_ERROR);
712         if (PRIVATE (a_this)->next_byte_index >=
713             PRIVATE (a_this)->in_buf_size) {
714                 return CR_END_OF_INPUT_ERROR;
715         }
717         nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
719         if (nb_bytes_left < 1) {
720                 return CR_END_OF_INPUT_ERROR;
721         }
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);
728         return status;
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)
756         gulong abs_offset = 0;
758         g_return_val_if_fail (a_this && PRIVATE (a_this)
759                               && a_byte, CR_BAD_PARAM_ERROR);
761         switch (a_origin) {
763         case CR_SEEK_CUR:
764                 abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_offset;
765                 break;
767         case CR_SEEK_BEGIN:
768                 abs_offset = a_offset;
769                 break;
771         case CR_SEEK_END:
772                 abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_offset;
773                 break;
775         default:
776                 return CR_BAD_PARAM_ERROR;
777         }
779         if (abs_offset < PRIVATE (a_this)->in_buf_size) {
781                 *a_byte = PRIVATE (a_this)->in_buf[abs_offset];
783                 return CR_OK;
785         } else {
786                 return CR_END_OF_INPUT_ERROR;
787         }
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)
804         guchar result = 0;
805         enum CRStatus status = CR_ERROR;
807         g_return_val_if_fail (a_this && PRIVATE (a_this), 0);
809         if (a_eof)
810                 *a_eof = FALSE;
812         status = cr_input_peek_byte (a_this, CR_SEEK_CUR, a_offset, &result);
814         if ((status == CR_END_OF_INPUT_ERROR)
815             && a_eof)
816                 *a_eof = TRUE;
818         return result;
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)
832         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
834         if (a_offset >= PRIVATE (a_this)->nb_bytes) {
835                 return NULL;
836         }
838         return &PRIVATE (a_this)->in_buf[a_offset];
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)
850         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_offset,
851                               CR_BAD_PARAM_ERROR);
853         if (!PRIVATE (a_this)->next_byte_index) {
854                 return CR_START_OF_INPUT_ERROR;
855         }
857         *a_offset = cr_input_get_byte_addr
858                 (a_this, PRIVATE (a_this)->next_byte_index - 1);
860         return CR_OK;
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)
886         glong abs_offset = 0;
888         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
890         switch (a_origin) {
892         case CR_SEEK_CUR:
893                 abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_pos;
894                 break;
896         case CR_SEEK_BEGIN:
897                 abs_offset = a_pos;
898                 break;
900         case CR_SEEK_END:
901                 abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_pos;
902                 break;
904         default:
905                 return CR_BAD_PARAM_ERROR;
906         }
908         if ((abs_offset > 0)
909             && (gulong) abs_offset < PRIVATE (a_this)->nb_bytes) {
911                 /*update the input stream's internal state */
912                 PRIVATE (a_this)->next_byte_index = abs_offset + 1;
914                 return CR_OK;
915         }
917         return CR_OUT_OF_BOUNDS_ERROR;
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)
942         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
943                               CR_BAD_PARAM_ERROR);
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;
951         return CR_OK;
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)
968         g_return_val_if_fail (a_this 
969                               && PRIVATE (a_this)
970                               && a_loc, 
971                               CR_BAD_PARAM_ERROR) ;
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 ;
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)
996         g_return_val_if_fail (a_this && PRIVATE (a_this)
997                               && a_index, CR_BAD_PARAM_ERROR);
999         *a_index = PRIVATE (a_this)->next_byte_index;
1001         return CR_OK;
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)
1015         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
1017         PRIVATE (a_this)->next_byte_index = a_index;
1019         return CR_OK;
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)
1031         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
1033         PRIVATE (a_this)->end_of_input = a_eof;
1035         return CR_OK;
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)
1048         g_return_val_if_fail (a_this && PRIVATE (a_this)
1049                               && a_eof, CR_BAD_PARAM_ERROR);
1051         *a_eof = PRIVATE (a_this)->end_of_input;
1053         return CR_OK;
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)
1066         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
1068         PRIVATE (a_this)->end_of_line = a_eol;
1070         return CR_OK;
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)
1084         g_return_val_if_fail (a_this && PRIVATE (a_this)
1085                               && a_eol, CR_BAD_PARAM_ERROR);
1087         *a_eol = PRIVATE (a_this)->end_of_line;
1089         return CR_OK;
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)
1102         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
1103                               CR_BAD_PARAM_ERROR);
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);
1111         return CR_OK;