Code

User message context in extensions
[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 = (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));
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;
108 /****************
109  *Public methods
110  ***************/
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)
129         CRInput *result = NULL;
130         enum CRStatus status = CR_OK;
131         CREncHandler *enc_handler = NULL;
132         gulong len = a_len;
134         g_return_val_if_fail (a_buf, NULL);
136         result = cr_input_new_real ();
137         g_return_val_if_fail (result, NULL);
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                 }
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;
168  error:
169         if (result) {
170                 cr_input_destroy (result);
171                 result = NULL;
172         }
174         return NULL;
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  */
189 CRInput *
190 cr_input_new_from_uri (const gchar * a_file_uri, enum CREncoding a_enc)
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;
202         g_return_val_if_fail (a_file_uri, NULL);
204         file_ptr = fopen (a_file_uri, "r");
206         if (file_ptr == NULL) {
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);
213                 return NULL;
214         }
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);
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                 }
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         }
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         }
256  cleanup:
257         if (file_ptr) {
258                 fclose (file_ptr);
259                 file_ptr = NULL;
260         }
262         if (buf) {
263                 g_free (buf);
264                 buf = NULL;
265         }
267         return result;
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)
277         if (a_this == NULL)
278                 return;
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                 }
286                 g_free (PRIVATE (a_this));
287                 PRIVATE (a_this) = NULL;
288         }
290         g_free (a_this);
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)
301         g_return_if_fail (a_this && PRIVATE (a_this));
303         PRIVATE (a_this)->ref_count++;
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)
316         g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
318         if (PRIVATE (a_this)->ref_count) {
319                 PRIVATE (a_this)->ref_count--;
320         }
322         if (PRIVATE (a_this)->ref_count == 0) {
323                 cr_input_destroy (a_this);
324                 return TRUE;
325         }
326         return FALSE;
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)
343         g_return_val_if_fail (a_this && PRIVATE (a_this)
344                               && a_end_of_input, CR_BAD_PARAM_ERROR);
346         *a_end_of_input = (PRIVATE (a_this)->next_byte_index
347                            >= PRIVATE (a_this)->in_buf_size) ? TRUE : FALSE;
349         return CR_OK;
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)
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);
367         if (PRIVATE (a_this)->end_of_input)
368                 return 0;
370         return PRIVATE (a_this)->nb_bytes - PRIVATE (a_this)->next_byte_index;
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)
388         g_return_val_if_fail (a_this && PRIVATE (a_this)
389                               && a_byte, CR_BAD_PARAM_ERROR);
391         g_return_val_if_fail (PRIVATE (a_this)->next_byte_index <=
392                               PRIVATE (a_this)->nb_bytes, CR_BAD_PARAM_ERROR);
394         if (PRIVATE (a_this)->end_of_input == TRUE)
395                 return CR_END_OF_INPUT_ERROR;
397         *a_byte = PRIVATE (a_this)->in_buf[PRIVATE (a_this)->next_byte_index];
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         }
406         return CR_OK;
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)
420         enum CRStatus status = CR_OK;
421         gulong consumed = 0,
422                 nb_bytes_left = 0;
424         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
425                               CR_BAD_PARAM_ERROR);
427         if (PRIVATE (a_this)->end_of_input == TRUE)
428                 return CR_END_OF_INPUT_ERROR;
430         nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
432         if (nb_bytes_left < 1) {
433                 return CR_END_OF_INPUT_ERROR;
434         }
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);
442         if (status == CR_OK) {
443                 /*update next byte index */
444                 PRIVATE (a_this)->next_byte_index += consumed;
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                 }
455                 if (*a_char == '\n') {
456                         PRIVATE (a_this)->end_of_line = TRUE;
457                 }
459         }
461         return status;
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)
474         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
476         PRIVATE (a_this)->line = a_line_num;
478         return CR_OK;
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)
491         g_return_val_if_fail (a_this && PRIVATE (a_this)
492                               && a_line_num, CR_BAD_PARAM_ERROR);
494         *a_line_num = PRIVATE (a_this)->line;
496         return CR_OK;
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)
509         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
511         PRIVATE (a_this)->col = a_col;
513         return CR_OK;
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)
526         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_col,
527                               CR_BAD_PARAM_ERROR);
529         *a_col = PRIVATE (a_this)->col;
531         return CR_OK;
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)
543         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
545         PRIVATE (a_this)->line += a_increment;
547         return CR_OK;
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)
559         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
561         PRIVATE (a_this)->col += a_increment;
563         return CR_OK;
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)
579         guint32 c;
580         enum CRStatus status;
582         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
584         if ((status = cr_input_peek_char (a_this, &c)) != CR_OK) {
585                 return status;
586         }
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         }
594         return status;
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)
618         enum CRStatus status = CR_OK;
619         gulong nb_consumed = 0;
621         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_char,
622                               CR_BAD_PARAM_ERROR);
624         g_return_val_if_fail (a_char != 0 || a_nb_char != NULL,
625                               CR_BAD_PARAM_ERROR);
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         }
634         *a_nb_char = nb_consumed;
636         if ((nb_consumed > 0)
637             && ((status == CR_PARSING_ERROR)
638                 || (status == CR_END_OF_INPUT_ERROR))) {
639                 status = CR_OK;
640         }
642         return status;
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)
657         enum CRStatus status = CR_OK;
658         guint32 cur_char = 0,
659                 nb_consumed = 0;
661         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_chars,
662                               CR_BAD_PARAM_ERROR);
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;
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                 }
679                 break;
681         }
683         if (nb_consumed && status == CR_END_OF_INPUT_ERROR) {
684                 status = CR_OK;
685         }
687         return status;
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)
703         enum CRStatus status = CR_OK;
704         glong consumed = 0,
705                 nb_bytes_left = 0;
707         g_return_val_if_fail (a_this && PRIVATE (a_this)
708                               && a_char, CR_BAD_PARAM_ERROR);
710         if (PRIVATE (a_this)->next_byte_index >=
711             PRIVATE (a_this)->in_buf_size) {
712                 return CR_END_OF_INPUT_ERROR;
713         }
715         nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
717         if (nb_bytes_left < 1) {
718                 return CR_END_OF_INPUT_ERROR;
719         }
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);
726         return status;
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)
754         gulong abs_offset = 0;
756         g_return_val_if_fail (a_this && PRIVATE (a_this)
757                               && a_byte, CR_BAD_PARAM_ERROR);
759         switch (a_origin) {
761         case CR_SEEK_CUR:
762                 abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_offset;
763                 break;
765         case CR_SEEK_BEGIN:
766                 abs_offset = a_offset;
767                 break;
769         case CR_SEEK_END:
770                 abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_offset;
771                 break;
773         default:
774                 return CR_BAD_PARAM_ERROR;
775         }
777         if (abs_offset < PRIVATE (a_this)->in_buf_size) {
779                 *a_byte = PRIVATE (a_this)->in_buf[abs_offset];
781                 return CR_OK;
783         } else {
784                 return CR_END_OF_INPUT_ERROR;
785         }
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)
802         guchar result = 0;
803         enum CRStatus status = CR_ERROR;
805         g_return_val_if_fail (a_this && PRIVATE (a_this), 0);
807         if (a_eof)
808                 *a_eof = FALSE;
810         status = cr_input_peek_byte (a_this, CR_SEEK_CUR, a_offset, &result);
812         if ((status == CR_END_OF_INPUT_ERROR)
813             && a_eof)
814                 *a_eof = TRUE;
816         return result;
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)
830         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
832         if (a_offset >= PRIVATE (a_this)->nb_bytes) {
833                 return NULL;
834         }
836         return &PRIVATE (a_this)->in_buf[a_offset];
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)
848         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_offset,
849                               CR_BAD_PARAM_ERROR);
851         if (!PRIVATE (a_this)->next_byte_index) {
852                 return CR_START_OF_INPUT_ERROR;
853         }
855         *a_offset = cr_input_get_byte_addr
856                 (a_this, PRIVATE (a_this)->next_byte_index - 1);
858         return CR_OK;
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)
884         glong abs_offset = 0;
886         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
888         switch (a_origin) {
890         case CR_SEEK_CUR:
891                 abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_pos;
892                 break;
894         case CR_SEEK_BEGIN:
895                 abs_offset = a_pos;
896                 break;
898         case CR_SEEK_END:
899                 abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_pos;
900                 break;
902         default:
903                 return CR_BAD_PARAM_ERROR;
904         }
906         if ((abs_offset > 0)
907             && (gulong) abs_offset < PRIVATE (a_this)->nb_bytes) {
909                 /*update the input stream's internal state */
910                 PRIVATE (a_this)->next_byte_index = abs_offset + 1;
912                 return CR_OK;
913         }
915         return CR_OUT_OF_BOUNDS_ERROR;
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)
940         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
941                               CR_BAD_PARAM_ERROR);
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;
949         return CR_OK;
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)
966         g_return_val_if_fail (a_this 
967                               && PRIVATE (a_this)
968                               && a_loc, 
969                               CR_BAD_PARAM_ERROR) ;
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 ;
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)
994         g_return_val_if_fail (a_this && PRIVATE (a_this)
995                               && a_index, CR_BAD_PARAM_ERROR);
997         *a_index = PRIVATE (a_this)->next_byte_index;
999         return CR_OK;
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)
1013         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
1015         PRIVATE (a_this)->next_byte_index = a_index;
1017         return CR_OK;
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)
1029         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
1031         PRIVATE (a_this)->end_of_input = a_eof;
1033         return CR_OK;
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)
1046         g_return_val_if_fail (a_this && PRIVATE (a_this)
1047                               && a_eof, CR_BAD_PARAM_ERROR);
1049         *a_eof = PRIVATE (a_this)->end_of_input;
1051         return CR_OK;
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)
1064         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
1066         PRIVATE (a_this)->end_of_line = a_eol;
1068         return CR_OK;
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)
1082         g_return_val_if_fail (a_this && PRIVATE (a_this)
1083                               && a_eol, CR_BAD_PARAM_ERROR);
1085         *a_eol = PRIVATE (a_this)->end_of_line;
1087         return CR_OK;
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)
1100         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
1101                               CR_BAD_PARAM_ERROR);
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);
1109         return CR_OK;