summaryrefslogtreecommitdiff
path: root/src/cr-input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cr-input.c')
-rw-r--r--src/cr-input.c1188
1 files changed, 1188 insertions, 0 deletions
diff --git a/src/cr-input.c b/src/cr-input.c
new file mode 100644
index 0000000..d094492
--- /dev/null
+++ b/src/cr-input.c
@@ -0,0 +1,1188 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+
+#include "stdio.h"
+#include <string.h>
+#include "cr-input.h"
+#include "cr-enc-handler.h"
+
+
+/**
+ *@file
+ *The definition of the #CRInput class.
+ */
+
+/*******************
+ *Private type defs
+ *******************/
+
+
+/**
+ *The privated attributes of
+ *the #CRInputPriv class.
+ */
+struct _CRInputPriv
+{
+ /*
+ *The input buffer
+ */
+ guchar *in_buf ;
+ gulong in_buf_size ;
+
+ gulong nb_bytes ;
+
+ /*
+ *The index of the next byte
+ *to be read.
+ */
+ gulong next_byte_index ;
+
+ /*
+ *The current line number
+ */
+ gulong line ;
+
+ /*
+ *The current col number.
+ */
+ gulong col ;
+
+ gboolean end_of_line ;
+ gboolean end_of_input ;
+
+ /*
+ *the reference count of this
+ *instance.
+ */
+ guint ref_count ;
+ gboolean free_in_buf ;
+} ;
+
+
+#define PRIVATE(object) (object)->priv
+
+
+/***************************
+ *private constants
+ **************************/
+#define CR_INPUT_MEM_CHUNK_SIZE 1024 * 4
+
+static CRInput *
+cr_input_new_real (void) ;
+
+
+static CRInput *
+cr_input_new_real (void)
+{
+ CRInput *result = NULL ;
+
+ result = g_try_malloc (sizeof (CRInput)) ;
+ if (!result)
+ {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ memset (result, 0, sizeof (CRInput)) ;
+
+ PRIVATE (result) = g_try_malloc (sizeof (CRInputPriv)) ;
+ if (!PRIVATE (result))
+ {
+ cr_utils_trace_info ("Out of memory") ;
+ g_free (result) ;
+ return NULL ;
+ }
+ memset (PRIVATE (result), 0, sizeof (CRInputPriv)) ;
+ PRIVATE (result)->free_in_buf = TRUE ;
+ return result ;
+}
+
+
+/****************
+ *Public methods
+ ***************/
+
+
+/**
+ *Creates a new input stream from a memory buffer.
+ *@param a_buf the memory buffer to create the input stream from.
+ *@param a_len the size of the input buffer.
+ *@param a_enc the buffer's encoding.
+ *@param a_free_buf is set to TRUE, this a_buf will be freed
+ *at the destruction of this instance. If set to false, it is up
+ *to the caller to free it.
+ *@return the newly built instance of #CRInput.
+ */
+CRInput *
+cr_input_new_from_buf (const guchar *a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_buf)
+{
+ CRInput *result = NULL;
+ enum CRStatus status = CR_OK ;
+ CREncHandler *enc_handler = NULL ;
+ gulong len = a_len ;
+ g_return_val_if_fail (a_buf, NULL) ;
+
+ result = cr_input_new_real () ;
+ g_return_val_if_fail (result, NULL) ;
+
+ /*transform the encoding in utf8*/
+ if (a_enc != CR_UTF_8)
+ {
+ enc_handler = cr_enc_handler_get_instance (a_enc) ;
+ if (!enc_handler)
+ {
+ goto error ;
+ }
+
+ status = cr_enc_handler_convert_input
+ (enc_handler, a_buf, &len,
+ &PRIVATE (result)->in_buf,
+ &PRIVATE (result)->in_buf_size) ;
+
+ if (status != CR_OK)
+ goto error ;
+
+ PRIVATE (result)->line = 1 ;
+ PRIVATE (result)->nb_bytes = PRIVATE (result)->in_buf_size ;
+ }
+ else
+ {
+ PRIVATE (result)->in_buf = (guchar *) a_buf ;
+ PRIVATE (result)->in_buf_size = a_len ;
+ PRIVATE (result)->nb_bytes = a_len ;
+ }
+
+ PRIVATE (result)->free_in_buf = a_free_buf ;
+
+ return result ;
+
+ error:
+ if (result)
+ {
+ cr_input_destroy (result) ;
+ result = NULL ;
+ }
+
+ return NULL ;
+}
+
+/**
+ *Creates a new input stream from
+ *a file.
+ *@param a_file_uri the file to create
+ *the input stream from.
+ *@param a_enc the encoding of the file
+ *to create the input from
+ *@return the newly created input stream if
+ *this method couldn read the file and create it,
+ *NULL otherwise.
+ */
+
+CRInput *
+cr_input_new_from_uri (const gchar *a_file_uri, enum CREncoding a_enc)
+{
+ CRInput * result = NULL ;
+ enum CRStatus status = CR_OK ;
+ FILE * file_ptr = NULL ;
+ guchar tmp_buf[CR_INPUT_MEM_CHUNK_SIZE] = {0} ;
+ gulong nb_read = 0, len = 0, buf_size = 0 ;
+ gboolean loop = TRUE ;
+ guchar *buf = NULL ;
+
+ g_return_val_if_fail (a_file_uri, NULL) ;
+
+ file_ptr = fopen (a_file_uri, "r") ;
+
+ if (file_ptr == NULL)
+ {
+
+#ifdef CR_DEBUG
+ cr_utils_trace_debug ("could not open file") ;
+#endif
+ g_warning ("Could not open file %s\n", a_file_uri) ;
+
+ return NULL ;
+ }
+
+ /*load the file*/
+ while (loop)
+ {
+ nb_read =
+ fread (tmp_buf, 1/*read bytes*/,
+ CR_INPUT_MEM_CHUNK_SIZE/*nb of bytes*/,
+ file_ptr) ;
+
+ if (nb_read != CR_INPUT_MEM_CHUNK_SIZE)
+ {
+ /*we read less chars than we wanted*/
+ if (feof (file_ptr))
+ {
+ /*we reached eof*/
+ loop = FALSE ;
+ }
+ else
+ {
+ /*a pb occured !!*/
+ cr_utils_trace_debug
+ ("an io error occured") ;
+ status = CR_ERROR ;
+ goto cleanup ;
+ }
+ }
+
+ if (status == CR_OK)
+ {
+ /*read went well*/
+ buf = g_realloc
+ (buf, len + CR_INPUT_MEM_CHUNK_SIZE) ;
+ memcpy (buf + len, tmp_buf, nb_read) ;
+ len += nb_read ;
+ buf_size += CR_INPUT_MEM_CHUNK_SIZE ;
+ }
+ }
+
+
+ if (status == CR_OK)
+ {
+ result = cr_input_new_from_buf (buf, len, a_enc,
+ TRUE) ;
+ if (!result)
+ {
+ goto cleanup ;
+ }
+ }
+
+cleanup:
+
+ if (file_ptr)
+ {
+ fclose (file_ptr) ;
+ file_ptr = NULL ;
+ }
+
+ if (buf)
+ {
+ g_free (buf) ;
+ buf = NULL ;
+ }
+
+ return result ;
+}
+
+/**
+ *The destructor of the #CRInput class.
+ *@param a_this the current instance of #CRInput.
+ */
+void
+cr_input_destroy (CRInput *a_this)
+{
+ if (a_this == NULL)
+ return ;
+
+ if (PRIVATE (a_this))
+ {
+ if (PRIVATE (a_this)->in_buf
+ && PRIVATE (a_this)->free_in_buf)
+ {
+ g_free (PRIVATE (a_this)->in_buf) ;
+ PRIVATE (a_this)->in_buf = NULL ;
+ }
+
+ g_free (PRIVATE (a_this)) ;
+ PRIVATE (a_this) = NULL ;
+ }
+
+ g_free (a_this) ;
+}
+
+
+/**
+ *Increments the reference count of the current
+ *instance of #CRInput.
+ *@param a_this the current instance of #CRInput.
+ */
+void
+cr_input_ref (CRInput *a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this)) ;
+
+ PRIVATE (a_this)->ref_count ++ ;
+}
+
+
+/**
+ *Decrements the reference count of this instance
+ *of #CRInput. If the reference count goes down to
+ *zero, this instance is destroyed.
+ *@param a_this the current instance of #CRInput.
+ *
+ */
+gboolean
+cr_input_unref (CRInput *a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE) ;
+
+ if (PRIVATE (a_this)->ref_count)
+ {
+ PRIVATE (a_this)->ref_count -- ;
+ }
+
+ if (PRIVATE (a_this)->ref_count == 0)
+ {
+ cr_input_destroy (a_this) ;
+ return TRUE ;
+ }
+ return FALSE ;
+}
+
+
+/**
+ *Tests wether the current instance of
+ *#CRInput has reached it's input buffer.
+ *@param a_this the current instance of #CRInput.
+ *@param a_end_of_input out parameter. Is set to TRUE if
+ *the current instance has reached the end of its input buffer,
+ *FALSE otherwise.
+ *@param CR_OK upon successfull completion, an error code otherwise.
+ *Note that all the out parameters of this method are valid if
+ *and only if this method returns CR_OK.
+ */
+enum CRStatus
+cr_input_end_of_input (CRInput *a_this, gboolean *a_end_of_input)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_end_of_input, CR_BAD_PARAM_ERROR) ;
+
+ *a_end_of_input = (PRIVATE (a_this)->next_byte_index
+ >= PRIVATE (a_this)->in_buf_size)? TRUE : FALSE ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Retunrs the number of bytes left in the input stream
+ *before the end.
+ *@param a_this the current instance of #CRInput.
+ *@return the number of characters left or -1 in case of error.
+ */
+glong
+cr_input_get_nb_bytes_left (CRInput *a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), -1) ;
+ g_return_val_if_fail (PRIVATE (a_this)->nb_bytes
+ <= PRIVATE (a_this)->in_buf_size, -1) ;
+ g_return_val_if_fail (PRIVATE (a_this)->next_byte_index
+ <= PRIVATE (a_this)->nb_bytes, -1) ;
+
+ if (PRIVATE (a_this)->end_of_input)
+ return 0 ;
+
+ return PRIVATE (a_this)->nb_bytes
+ - PRIVATE (a_this)->next_byte_index ;
+}
+
+
+/**
+ *Returns the next byte of the input.
+ *Update the state of the input so that
+ *the next invocation of this method returns
+ *the next coming byte.
+ *
+ *@param a_this the current instance of #CRInput.
+ *@param a_byte out parameter the returned byte.
+ *@return CR_OK upon sucessfull completion, an error code
+ *otherwise. All the out param of this method are valid if
+ *and only if this method returns CR_OK.
+ */
+enum CRStatus
+cr_input_read_byte (CRInput *a_this, guchar *a_byte)
+{
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && a_byte,
+ CR_BAD_PARAM_ERROR) ;
+
+ g_return_val_if_fail (PRIVATE (a_this)->next_byte_index <=
+ PRIVATE (a_this)->nb_bytes,
+ CR_BAD_PARAM_ERROR) ;
+
+ if (PRIVATE (a_this)->end_of_input == TRUE)
+ return CR_END_OF_INPUT_ERROR ;
+
+ *a_byte =
+ PRIVATE
+ (a_this)->in_buf[PRIVATE (a_this)->next_byte_index] ;
+
+ if (PRIVATE (a_this)->nb_bytes -
+ PRIVATE (a_this)->next_byte_index < 2)
+ {
+ PRIVATE (a_this)->end_of_input = TRUE ;
+ }
+ else
+ {
+ PRIVATE (a_this)->next_byte_index ++ ;
+ }
+
+ return CR_OK ;
+}
+
+
+/**
+ *Reads an unicode character from the current instance of
+ *#CRInput.
+ *@param a_this the current instance of CRInput.
+ *@param a_char out parameter. The read character.
+ *@return CR_OK upon successfull completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_read_char (CRInput *a_this, guint32 *a_char)
+{
+ enum CRStatus status = CR_OK ;
+ gulong consumed = 0, nb_bytes_left = 0 ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
+ CR_BAD_PARAM_ERROR) ;
+
+ if (PRIVATE (a_this)->end_of_input == TRUE)
+ return CR_END_OF_INPUT_ERROR ;
+
+ nb_bytes_left = cr_input_get_nb_bytes_left (a_this) ;
+
+ if (nb_bytes_left < 1)
+ {
+ return CR_END_OF_INPUT_ERROR ;
+ }
+
+ status =
+ cr_utils_read_char_from_utf8_buf
+ (PRIVATE (a_this)->in_buf
+ +
+ PRIVATE (a_this)->next_byte_index,
+ nb_bytes_left, a_char, &consumed) ;
+
+ if (status == CR_OK)
+ {
+ /*update next byte index*/
+ PRIVATE (a_this)->next_byte_index += consumed ;
+
+ /*upate line and column number*/
+ if (PRIVATE (a_this)->end_of_line == TRUE)
+ {
+ PRIVATE (a_this)->col = 1 ;
+ PRIVATE (a_this)->line ++ ;
+ PRIVATE (a_this)->end_of_line = FALSE ;
+ }
+ else if (*a_char != '\n')
+ {
+ PRIVATE (a_this)->col ++ ;
+ }
+
+ if (*a_char == '\n')
+ {
+ PRIVATE (a_this)->end_of_line = TRUE ;
+ }
+
+ }
+
+ return status ;
+}
+
+
+/**
+ *Setter of the current line number.
+ *@param a_this the "this pointer" of the current instance of
+ *#CRInput.
+ *@param a_line_num the new line number.
+ *@return CR_OK upon successfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_line_num (CRInput *a_this, glong a_line_num)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR) ;
+
+ PRIVATE (a_this)->line = a_line_num ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Getter of the curren line number.
+ *@param a_this the "this pointer" of the current instance of
+ *#CRInput.
+ *@param a_line_num the returned line number.
+ *@return CR_OK upon successfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_line_num (CRInput *a_this, glong *a_line_num)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_line_num,
+ CR_BAD_PARAM_ERROR) ;
+
+ *a_line_num = PRIVATE (a_this)->line ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Setter of the current column number.
+ *@param a_this the "this pointer" of the current instance of
+ *#CRInput.
+ *@param a_col the new column column number.
+ *@return CR_OK upon successfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_column_num (CRInput *a_this, glong a_col)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR) ;
+
+ PRIVATE (a_this)->col = a_col ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Getter of the current column number.
+ *@param a_this the "this pointer" of the current instance of
+ *#CRInput.
+ *@param a_col out parameter
+ *@return CR_OK upon successfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_column_num (CRInput *a_this, glong *a_col)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_col,
+ CR_BAD_PARAM_ERROR) ;
+
+ *a_col = PRIVATE (a_this)->col ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Increments the current line number.
+ *@param a_this the "this pointer" of the current instance of
+ *#CRInput.
+ *@return CR_OK upon successfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_increment_line_num (CRInput *a_this, glong a_increment)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR) ;
+
+ PRIVATE (a_this)->line += a_increment ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Increments the current column number.
+ *@param a_this the "this pointer" of the current instance of
+ *#CRInput.
+ *@return CR_OK upon successfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_increment_col_num (CRInput *a_this, glong a_increment)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR) ;
+
+ PRIVATE (a_this)->col += a_increment ;
+
+ return CR_OK ;
+}
+
+
+
+/**
+ *Consumes the next character of the input stream if
+ *and only if that character equals a_char.
+ *
+ *@param a_this the this pointer.
+ *@param a_char the character to consume. If set to zero,
+ *consumes any character.
+ *@return CR_OK upon successfull completion, CR_PARSING_ERROR if
+ *next char is different from a_char, an other error code otherwise
+ */
+enum CRStatus
+cr_input_consume_char (CRInput *a_this, guint32 a_char)
+{
+ guint32 c ;
+ enum CRStatus status ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR) ;
+
+ if ((status = cr_input_peek_char (a_this, &c)) != CR_OK)
+ {
+ return status ;
+ }
+
+ if (c == a_char || a_char == 0)
+ {
+ status = cr_input_read_char (a_this, &c) ;
+ }
+ else
+ {
+ return CR_PARSING_ERROR ;
+ }
+
+ return status ;
+}
+
+
+/**
+ *Consumes up to a_nb_char occurences of the next contiguous characters
+ *which equal a_char. Note that the next character of the input stream
+ **MUST* equal a_char to trigger the consumption, or else, the error
+ *code CR_PARSING_ERROR is returned.
+ *If the number of contiguous characters that equals a_char is less than
+ *a_nb_char, then this function consumes all the characters it can consumed.
+ *
+ *@param a_this the this pointer of the current instance of #CRInput.
+ *@param a_char the character to consume.
+ *@param a_nb_char in/out parameter. The number of characters to consume.
+ *If set to a negative value, the function will consume all the occurences
+ *of a_char found.
+ *After return, if the return value equals CR_OK, this variable contains
+ *the number of characters actually consumed.
+ *@return CR_OK if at least one character has been consumed, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_consume_chars (CRInput *a_this, guint32 a_char, gulong *a_nb_char)
+{
+ enum CRStatus status = CR_OK ;
+ gulong nb_consumed = 0 ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_char,
+ CR_BAD_PARAM_ERROR) ;
+
+ g_return_val_if_fail (a_char != 0 || a_nb_char != NULL,
+ CR_BAD_PARAM_ERROR) ;
+
+ for (nb_consumed = 0 ;
+ ((status == CR_OK)
+ && (*a_nb_char > 0 && nb_consumed < *a_nb_char)) ;
+ nb_consumed ++)
+ {
+ status = cr_input_consume_char (a_this, a_char) ;
+ }
+
+ *a_nb_char = nb_consumed ;
+
+ if ((nb_consumed > 0)
+ && ((status == CR_PARSING_ERROR)
+ || (status == CR_END_OF_INPUT_ERROR)))
+ {
+ status = CR_OK ;
+ }
+
+ return status ;
+}
+
+/**
+ *Same as cr_input_consume_chars() but this one consumes white
+ *spaces.
+ *
+ *@param a_this the "this pointer" of the current instance of #CRInput.
+ *@param a_nb_chars in/out parameter. The number of white spaces to
+ *consume. After return, holds the number of white spaces actually consumed.
+ *@return CR_OK upon successfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_consume_white_spaces (CRInput *a_this, gulong *a_nb_chars)
+{
+ enum CRStatus status = CR_OK ;
+ guint32 cur_char = 0, nb_consumed = 0 ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_chars,
+ CR_BAD_PARAM_ERROR) ;
+
+ for (nb_consumed = 0;
+ ((*a_nb_chars > 0) && (nb_consumed < *a_nb_chars)) ;
+ nb_consumed ++)
+ {
+ status = cr_input_peek_char (a_this, &cur_char) ;
+ if (status != CR_OK) break ;
+
+ /*if the next char is a white space, consume it !*/
+ if (cr_utils_is_white_space (cur_char) == TRUE)
+ {
+ status = cr_input_read_char (a_this, &cur_char) ;
+ if (status != CR_OK) break ;
+ continue ;
+ }
+
+ break ;
+
+ }
+
+ if (nb_consumed && status == CR_END_OF_INPUT_ERROR)
+ {
+ status = CR_OK ;
+ }
+
+ return status ;
+}
+
+
+/**
+ *Same as cr_input_read_char() but does not update the
+ *internal state of the input stream. The next call
+ *to cr_input_peek_char() or cr_input_read_char() will thus
+ *return the same character as the current one.
+ *@param a_this the current instance of #CRInput.
+ *@param a_char out parameter. The returned character.
+ *@return CR_OK upon successfull completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_peek_char (CRInput *a_this, guint32 *a_char)
+{
+ enum CRStatus status = CR_OK ;
+ glong consumed = 0, nb_bytes_left = 0 ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_char, CR_BAD_PARAM_ERROR) ;
+
+ if (PRIVATE (a_this)->next_byte_index >=
+ PRIVATE (a_this)->in_buf_size)
+ {
+ return CR_END_OF_INPUT_ERROR ;
+ }
+
+ nb_bytes_left = cr_input_get_nb_bytes_left (a_this) ;
+
+ if (nb_bytes_left < 1)
+ {
+ return CR_END_OF_INPUT_ERROR ;
+ }
+
+ status =
+ cr_utils_read_char_from_utf8_buf
+ (PRIVATE (a_this)->in_buf +
+ PRIVATE (a_this)->next_byte_index,
+ nb_bytes_left, a_char, &consumed) ;
+
+ return status ;
+}
+
+
+
+/**
+ *Gets a byte from the input stream.
+ *starting from the current position in the input stream.
+ *Unlike cr_input_peek_next_byte() this method
+ *does not update the state of the current input stream.
+ *Subsequent calls to cr_input_peek_byte with the same arguments
+ *will return the same byte.
+ *
+ *@param a_this the current instance of #CRInput.
+ *@param a_origin the origin to consider in the calculation
+ *of the position of the byte to peek.
+ *@param a_offset the offset of the byte to peek, starting from
+ *the origin specified by a_origin.
+ *@param a_byte out parameter the peeked byte.
+ *@return CR_OK upon successfull completion or,
+ *
+ *<ul>
+ *<li>CR_BAD_PARAM_ERROR if at least of of the parameters is invalid</li>
+ *<li>CR_OUT_OF_BOUNDS_ERROR if the indexed byte is out of bounds</li>
+ *</ul>
+ */
+enum CRStatus
+cr_input_peek_byte (CRInput *a_this, enum CRSeekPos a_origin,
+ gulong a_offset, guchar *a_byte)
+{
+ gulong abs_offset = 0 ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_byte,
+ CR_BAD_PARAM_ERROR) ;
+
+
+ switch (a_origin) {
+
+ case CR_SEEK_CUR:
+ abs_offset =
+ PRIVATE (a_this)->next_byte_index - 1 + a_offset ;
+ break ;
+
+ case CR_SEEK_BEGIN:
+ abs_offset = a_offset ;
+ break ;
+
+ case CR_SEEK_END:
+ abs_offset =
+ PRIVATE (a_this)->in_buf_size - 1 - a_offset ;
+ break;
+
+ default:
+ return CR_BAD_PARAM_ERROR ;
+ }
+
+ if (abs_offset < PRIVATE (a_this)->in_buf_size) {
+
+ *a_byte =
+ PRIVATE (a_this)->in_buf[abs_offset] ;
+
+ return CR_OK ;
+
+ } else {
+ return CR_END_OF_INPUT_ERROR ;
+ }
+}
+
+/**
+ *Same as cr_input_peek_byte() but with a simplified
+ *interface.
+ *@param a_this the current byte input stream.
+ *@param a_offset the offset of the byte to peek, starting
+ *from the current input postion pointer.
+ *@param a_eof out parameter. Is set to true is we reach end of
+ *stream. If set to NULL by the caller, this parameter is not taken
+ *in account.
+ *@return the read byte or 0 if smthing bad happened.
+ */
+guchar
+cr_input_peek_byte2 (CRInput *a_this, gulong a_offset,
+ gboolean *a_eof)
+{
+ guchar result = 0 ;
+ enum CRStatus status = CR_ERROR ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this),
+ 0) ;
+
+ if (a_eof)
+ *a_eof = FALSE ;
+
+ status = cr_input_peek_byte (a_this, CR_SEEK_CUR, a_offset,
+ &result) ;
+
+ if ((status == CR_END_OF_INPUT_ERROR)
+ && a_eof)
+ *a_eof = TRUE ;
+
+ return result ;
+}
+
+
+/**
+ *Returns the memory address of the byte located at a given offset
+ *in the input stream.
+ *@param a_this the current instance of #CRInput.
+ *@param a_offset the offset of the byte in the input stream starting
+ *from the begining of the stream.
+ *@return the address, otherwise NULL if an error occured.
+ */
+guchar *
+cr_input_get_byte_addr (CRInput *a_this,
+ gulong a_offset)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL) ;
+
+ if (a_offset >= PRIVATE (a_this)->nb_bytes)
+ {
+ return NULL ;
+ }
+
+ return &PRIVATE (a_this)->in_buf[a_offset] ;
+}
+
+/**
+ *Returns the address of the current character pointer.
+ *@param a_this the current input stream
+ *@param a_offset out parameter. The returned address.
+ *@return CR_OK upon successfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_cur_byte_addr (CRInput *a_this, guchar ** a_offset)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_offset,
+ CR_BAD_PARAM_ERROR) ;
+
+ if (!PRIVATE (a_this)->next_byte_index)
+ {
+ return CR_START_OF_INPUT_ERROR ;
+ }
+
+ *a_offset = cr_input_get_byte_addr
+ (a_this, PRIVATE (a_this)->next_byte_index -1) ;
+
+ return CR_OK ;
+}
+
+/**
+ *Sets the "current byte index" of the current instance
+ *of #CRInput. Next call to cr_input_get_byte() will return
+ *the byte next after the new "current byte index".
+ *
+ *@param a_this the current instance of #CRInput.
+ *
+ *@param a_origin the origin to consider during the calculation
+ *of the absolute position of the new "current byte index".
+ *
+ *@param a_pos the relative offset of the new "current byte index."
+ *This offset is relative to the origin a_origin.
+ *
+ *@return CR_OK upon successfull completion otherwise returns
+ *<ul>
+ *<li>CR_BAD_PARAM_ERROR if at least one of the parameters is not valid</li>
+ *<li>CR_OUT_BOUNDS_ERROR</li>
+ *</ul>
+ */
+enum CRStatus
+cr_input_seek_index (CRInput *a_this, enum CRSeekPos a_origin, gint a_pos)
+{
+
+ glong abs_offset = 0 ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR) ;
+
+
+ switch (a_origin) {
+
+ case CR_SEEK_CUR:
+ abs_offset =
+ PRIVATE (a_this)->next_byte_index - 1 + a_pos ;
+ break ;
+
+ case CR_SEEK_BEGIN:
+ abs_offset = a_pos ;
+ break ;
+
+ case CR_SEEK_END:
+ abs_offset =
+ PRIVATE (a_this)->in_buf_size - 1 - a_pos ;
+ break ;
+
+ default:
+ return CR_BAD_PARAM_ERROR ;
+ }
+
+ if ((abs_offset > 0)
+ && (gulong) abs_offset < PRIVATE (a_this)->nb_bytes) {
+
+ /*update the input stream's internal state*/
+ PRIVATE (a_this)->next_byte_index = abs_offset + 1 ;
+
+ return CR_OK ;
+ }
+
+ return CR_OUT_OF_BOUNDS_ERROR ;
+}
+
+
+/**
+ *Gets the position of the "current byte index" which
+ *is basically the position of the last returned byte in the
+ *input stream.
+ *
+ *@param a_this the current instance of #CRInput.
+ *
+ *@param a_pos out parameter. The returned position.
+ *
+ *@return CR_OK upon sucessfull completion. Otherwise,
+ *<ul>
+ *<li>CR_BAD_PARAMETER_ERROR if at least of the arguments is invalid.</li>
+ *<li>CR_START_OF_INPUT if no call to neither cr_input_read_byte()
+ *not cr_input_seek_index() have been issued before calling
+ *cr_input_get_cur_pos()</li>
+ *</ul>
+ *Note that the out parameters of this function are valid if and only if this
+ *function returns CR_OK.
+ */
+enum CRStatus
+cr_input_get_cur_pos (CRInput *a_this, CRInputPos * a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
+ CR_BAD_PARAM_ERROR) ;
+
+ a_pos->next_byte_index = PRIVATE (a_this)->next_byte_index ;
+ a_pos->line = PRIVATE (a_this)->line ;
+ a_pos->col = PRIVATE (a_this)->col ;
+ a_pos->end_of_line = PRIVATE (a_this)->end_of_line ;
+ a_pos->end_of_file = PRIVATE (a_this)->end_of_input ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Getter of the next byte index.
+ *It actually returns the index of the
+ *next byte to be read.
+ *@param a_this the "this pointer" of the current instance of
+ *#CRInput
+ *@param a_index out parameter. The returned index.
+ *@return CR_OK upon sucessfull completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_get_cur_index (CRInput *a_this, glong *a_index)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_index,
+ CR_BAD_PARAM_ERROR) ;
+
+ *a_index = PRIVATE (a_this)->next_byte_index ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Setter of the next byte index.
+ *It sets the index of the next byte to be read.
+ *@param a_this the "this pointer" of the current instance
+ *of #CRInput .
+ *@param a_index the new index to set.
+ *@return CR_OK upon sucessfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_cur_index (CRInput *a_this, glong a_index)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR) ;
+
+ PRIVATE (a_this)->next_byte_index = a_index ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Sets the end of file flag.
+ *@param a_this the current instance of #CRInput.
+ *@param a_eof the new end of file flag.
+ *@return CR_OK upon successfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_end_of_file (CRInput *a_this, gboolean a_eof)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR) ;
+
+ PRIVATE (a_this)->end_of_input = a_eof ;
+
+ return CR_OK ;
+}
+
+/**
+ *Gets the end of file flag.
+ *@param a_this the current instance of #CRInput.
+ *@param a_eof out parameter the place where to put the end of
+ *file flag.
+ *@return CR_OK upon sucessfull completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_end_of_file (CRInput *a_this, gboolean *a_eof)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_eof,
+ CR_BAD_PARAM_ERROR) ;
+
+ *a_eof = PRIVATE (a_this)->end_of_input ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Sets the end of line flag.
+ *@param a_this the current instance of #CRInput.
+ *@param a_eol the new end of line flag.
+ *@return CR_OK upon successfull completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_set_end_of_line (CRInput *a_this, gboolean a_eol)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR) ;
+
+ PRIVATE (a_this)->end_of_line = a_eol ;
+
+ return CR_OK ;
+}
+
+/**
+ *Gets the end of line flag of the current input.
+ *@param a_this the current instance of #CRInput
+ *@param a_eol out parameter. The place where to put
+ *the returned flag
+ *@return CR_OK upon successfull completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_get_end_of_line (CRInput *a_this, gboolean *a_eol)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_eol,
+ CR_BAD_PARAM_ERROR) ;
+
+ *a_eol = PRIVATE (a_this)->end_of_line ;
+
+ return CR_OK ;
+}
+
+
+/**
+ *Sets the current position in the input stream.
+ *
+ *@param a_this the "this pointer" of the current instance of
+ *#CRInput.
+ *@param a_pos the new position.
+ */
+enum CRStatus
+cr_input_set_cur_pos (CRInput *a_this, CRInputPos *a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
+ CR_BAD_PARAM_ERROR) ;
+
+ cr_input_set_column_num (a_this, a_pos->col) ;
+ cr_input_set_line_num (a_this, a_pos->line) ;
+ cr_input_set_cur_index (a_this, a_pos->next_byte_index) ;
+ cr_input_set_end_of_line (a_this, a_pos->end_of_line) ;
+ cr_input_set_end_of_file (a_this, a_pos->end_of_file) ;
+
+ return CR_OK ;
+}