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