Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

cr-input.c

Go to the documentation of this file.
00001 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8-*- */
00002 
00003 /*
00004  * This file is part of The Croco Library
00005  *
00006  * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of version 2.1 of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00020  * USA
00021  */
00022 
00023 /*
00024  *$Id: cr-input.c,v 1.3 2003/06/08 11:47:05 dodji Exp $
00025  */
00026 
00027 
00028 #include "stdio.h"
00029 #include <string.h>
00030 #include "cr-input.h"
00031 #include "cr-enc-handler.h"
00032 
00033 
00034 /**
00035  *@file
00036  *The definition of the #CRInput class.
00037  */
00038 
00039 /*******************
00040  *Private type defs
00041  *******************/
00042 
00043 
00044 /**
00045  *The privated attributes of
00046  *the #CRInputPriv class.
00047  */
00048 struct _CRInputPriv 
00049 {
00050         /*
00051          *The input buffer
00052          */
00053         guchar *in_buf ;
00054         gulong in_buf_size ;
00055 
00056         gulong nb_bytes ;
00057 
00058         /*
00059          *The index of the next byte
00060          *to be read.
00061          */
00062         gulong next_byte_index ;
00063 
00064         /*
00065          *The current line number
00066          */
00067         gulong line ;
00068 
00069         /*
00070          *The current col number.
00071          */
00072         gulong col ;
00073 
00074         gboolean end_of_line ;
00075         gboolean end_of_input ;
00076 
00077         /*
00078          *the reference count of this
00079          *instance.
00080          */
00081         guint ref_count ;
00082         gboolean free_in_buf ;
00083 } ;
00084 
00085 
00086 #define PRIVATE(object) (object)->priv
00087 
00088 
00089 /***************************
00090  *private constants
00091  **************************/
00092 #define CR_INPUT_MEM_CHUNK_SIZE 1024 * 4
00093 
00094 static CRInput *
00095 cr_input_new_real (void) ;
00096 
00097 
00098 static CRInput *
00099 cr_input_new_real (void)
00100 {
00101         CRInput *result = NULL ;
00102 
00103         result = g_try_malloc (sizeof (CRInput)) ;
00104         if (!result)
00105         {
00106                 cr_utils_trace_info ("Out of memory") ;
00107                 return NULL ;
00108         }
00109         memset (result, 0, sizeof (CRInput)) ;
00110 
00111         PRIVATE (result) = g_try_malloc (sizeof (CRInputPriv)) ;
00112         if (!PRIVATE (result))
00113         {
00114                 cr_utils_trace_info ("Out of memory") ;
00115                 g_free (result) ;
00116                 return NULL ;
00117         }        
00118         memset (PRIVATE (result), 0, sizeof (CRInputPriv)) ;
00119         PRIVATE (result)->free_in_buf = TRUE ;
00120         return result ;
00121 }
00122 
00123 
00124 /****************
00125  *Public methods
00126  ***************/
00127 
00128 
00129 /**
00130  *Creates a new input stream from a memory buffer.
00131  *@param a_buf the memory buffer to create the input stream from.
00132  *@param a_len the size of the input buffer.
00133  *@param a_enc the buffer's encoding.
00134  *@param a_free_buf is set to TRUE, this a_buf will be freed
00135  *at the destruction of this instance. If set to false, it is up
00136  *to the caller to free it.
00137  *@return the newly built instance of #CRInput.
00138  */
00139 CRInput *
00140 cr_input_new_from_buf (const guchar *a_buf, 
00141                        gulong a_len,
00142                        enum CREncoding a_enc, 
00143                        gboolean a_free_buf)
00144 {
00145         CRInput *result = NULL;
00146         enum CRStatus status = CR_OK ;
00147         CREncHandler *enc_handler = NULL ;
00148         gulong len = a_len ;
00149         g_return_val_if_fail (a_buf, NULL) ;
00150 
00151         result = cr_input_new_real () ;
00152         g_return_val_if_fail (result, NULL) ;
00153 
00154         /*transform the encoding in utf8*/
00155         if (a_enc != CR_UTF_8)
00156         {
00157                 enc_handler = cr_enc_handler_get_instance (a_enc) ;
00158                 if (!enc_handler)
00159                 {
00160                         goto error ;
00161                 }
00162 
00163                 status = cr_enc_handler_convert_input
00164                         (enc_handler, a_buf, &len,
00165                          &PRIVATE (result)->in_buf,
00166                          &PRIVATE (result)->in_buf_size) ;
00167 
00168                 if (status != CR_OK)
00169                         goto error ;
00170 
00171                 PRIVATE (result)->line = 1 ;
00172                 PRIVATE (result)->nb_bytes =  PRIVATE (result)->in_buf_size ;
00173         }
00174         else
00175         {
00176                 PRIVATE (result)->in_buf = (guchar *) a_buf ;
00177                 PRIVATE (result)->in_buf_size = a_len ;
00178                 PRIVATE (result)->nb_bytes = a_len ;
00179         }
00180 
00181         PRIVATE (result)->free_in_buf = a_free_buf ;
00182 
00183         return result ;
00184 
00185  error:
00186         if (result)
00187         {
00188                 cr_input_destroy (result) ;
00189                 result = NULL ;
00190         }
00191 
00192         return NULL ;
00193 }
00194 
00195 /**
00196  *Creates a new input stream from
00197  *a file.
00198  *@param a_file_uri the file to create
00199  *the input stream from.
00200  *@param a_enc the encoding of the file
00201  *to create the input from
00202  *@return the newly created input stream if
00203  *this method couldn read the file and create it,
00204  *NULL otherwise.
00205  */
00206 
00207 CRInput *
00208 cr_input_new_from_uri (const gchar *a_file_uri, enum CREncoding a_enc)
00209 {
00210         CRInput * result = NULL ;
00211         enum CRStatus status = CR_OK ;
00212         FILE * file_ptr = NULL ;
00213         guchar tmp_buf[CR_INPUT_MEM_CHUNK_SIZE] = {0} ;
00214         gulong nb_read = 0, len = 0, buf_size = 0 ;
00215         gboolean loop = TRUE ;
00216         guchar *buf = NULL ;
00217 
00218         g_return_val_if_fail (a_file_uri, NULL) ;
00219 
00220         file_ptr = fopen (a_file_uri, "r") ;
00221 
00222         if (file_ptr == NULL) 
00223         {
00224 
00225 #ifdef CR_DEBUG
00226                 cr_utils_trace_debug ("could not open file") ;
00227 #endif
00228                 g_warning ("Could not open file %s\n", a_file_uri) ;
00229                 
00230                 return NULL ;
00231         }
00232 
00233         /*load the file*/
00234         while (loop) 
00235         {
00236                 nb_read =
00237                         fread (tmp_buf, 1/*read bytes*/,
00238                                CR_INPUT_MEM_CHUNK_SIZE/*nb of bytes*/,
00239                                file_ptr) ;
00240 
00241                 if (nb_read != CR_INPUT_MEM_CHUNK_SIZE) 
00242                 {                        
00243                         /*we read less chars than we wanted*/
00244                         if (feof (file_ptr)) 
00245                         {
00246                                 /*we reached eof*/
00247                                 loop = FALSE ;
00248                         } 
00249                         else 
00250                         {  
00251                                 /*a pb occured !!*/
00252                                 cr_utils_trace_debug 
00253                                         ("an io error occured") ;
00254                                 status = CR_ERROR ;
00255                                 goto cleanup ;
00256                         }
00257                 }
00258 
00259                 if (status == CR_OK)
00260                 {
00261                         /*read went well*/
00262                        buf = g_realloc 
00263                                (buf, len + CR_INPUT_MEM_CHUNK_SIZE) ;
00264                        memcpy (buf + len, tmp_buf, nb_read) ;
00265                        len +=  nb_read ;
00266                        buf_size += CR_INPUT_MEM_CHUNK_SIZE ;
00267                 }
00268         }
00269 
00270 
00271         if (status == CR_OK) 
00272         {
00273                 result = cr_input_new_from_buf (buf, len, a_enc,
00274                                                 TRUE) ;
00275                 if (!result)
00276                 {
00277                         goto cleanup ;
00278                 }                
00279         }
00280 
00281 cleanup:
00282 
00283         if (file_ptr)
00284         {
00285                 fclose (file_ptr) ;
00286                 file_ptr = NULL ;
00287         }
00288 
00289         if (buf)
00290         {
00291                 g_free (buf) ;
00292                 buf = NULL ;
00293         }
00294 
00295         return result ;
00296 }
00297 
00298 /**
00299  *The destructor of the #CRInput class.
00300  *@param a_this the current instance of #CRInput.
00301  */
00302 void
00303 cr_input_destroy (CRInput *a_this)
00304 {
00305         if (a_this == NULL)
00306                 return ;
00307 
00308         if (PRIVATE (a_this)) 
00309         {
00310                 if (PRIVATE (a_this)->in_buf 
00311                     && PRIVATE (a_this)->free_in_buf) 
00312                 {
00313                         g_free (PRIVATE (a_this)->in_buf) ;
00314                         PRIVATE (a_this)->in_buf = NULL ;
00315                 }
00316 
00317                 g_free (PRIVATE (a_this)) ;
00318                 PRIVATE (a_this) = NULL ;
00319         }
00320 
00321         g_free (a_this) ;
00322 }
00323 
00324 
00325 /**
00326  *Increments the reference count of the current
00327  *instance of #CRInput.
00328  *@param a_this the current instance of #CRInput.
00329  */
00330 void 
00331 cr_input_ref (CRInput *a_this)
00332 {
00333         g_return_if_fail (a_this && PRIVATE (a_this)) ;
00334         
00335         PRIVATE (a_this)->ref_count ++ ;
00336 }
00337 
00338 
00339 /**
00340  *Decrements the reference count of this instance
00341  *of #CRInput. If the reference count goes down to
00342  *zero, this instance is destroyed.
00343  *@param a_this the current instance of #CRInput.
00344  *
00345  */        
00346 gboolean
00347 cr_input_unref (CRInput *a_this)
00348 {
00349         g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE) ;
00350         
00351         if (PRIVATE (a_this)->ref_count)  
00352         {
00353                 PRIVATE (a_this)->ref_count -- ;
00354         }
00355 
00356         if (PRIVATE (a_this)->ref_count == 0) 
00357         {
00358                 cr_input_destroy (a_this) ;
00359                 return TRUE ;
00360         }
00361         return FALSE ;
00362 }
00363 
00364 
00365 /**
00366  *Tests wether the current instance of
00367  *#CRInput has reached it's input buffer.
00368  *@param a_this the current instance of #CRInput.
00369  *@param a_end_of_input out parameter. Is set to TRUE if
00370  *the current instance has reached the end of its input buffer,
00371  *FALSE otherwise.
00372  *@param CR_OK upon successfull completion, an error code otherwise.
00373  *Note that all the out parameters of this method are valid if
00374  *and only if this method returns CR_OK.
00375  */
00376 enum CRStatus
00377 cr_input_end_of_input (CRInput *a_this, gboolean *a_end_of_input)
00378 {
00379         g_return_val_if_fail (a_this && PRIVATE (a_this)
00380                               && a_end_of_input, CR_BAD_PARAM_ERROR) ;
00381 
00382         *a_end_of_input = (PRIVATE (a_this)->next_byte_index 
00383                            >= PRIVATE (a_this)->in_buf_size)? TRUE : FALSE ;
00384 
00385         return CR_OK ;
00386 }
00387 
00388 
00389 /**
00390  *Retunrs the number of bytes left in the input stream
00391  *before the end.
00392  *@param a_this the current instance of #CRInput.
00393  *@return the number of characters left or -1 in case of error.
00394  */
00395 glong
00396 cr_input_get_nb_bytes_left (CRInput *a_this)
00397 {
00398         g_return_val_if_fail (a_this && PRIVATE (a_this), -1) ;
00399         g_return_val_if_fail (PRIVATE (a_this)->nb_bytes 
00400                               <= PRIVATE (a_this)->in_buf_size, -1) ;
00401         g_return_val_if_fail (PRIVATE (a_this)->next_byte_index 
00402                               <= PRIVATE (a_this)->nb_bytes, -1) ;
00403 
00404         if (PRIVATE (a_this)->end_of_input)
00405                 return 0 ;
00406         
00407         return PRIVATE (a_this)->nb_bytes 
00408                 - PRIVATE (a_this)->next_byte_index ;
00409 }
00410 
00411 
00412 /**
00413  *Returns the next byte of the input.
00414  *Update the state of the input so that
00415  *the next invocation of this method  returns
00416  *the next coming byte.
00417  *
00418  *@param a_this the current instance of #CRInput.
00419  *@param a_byte out parameter the returned byte.
00420  *@return CR_OK upon sucessfull completion, an error code
00421  *otherwise. All the out param of this method are valid if
00422  *and only if this method returns CR_OK.
00423  */
00424 enum CRStatus
00425 cr_input_read_byte (CRInput *a_this, guchar *a_byte)
00426 {
00427         g_return_val_if_fail (a_this 
00428                               && PRIVATE (a_this) 
00429                               && a_byte,
00430                               CR_BAD_PARAM_ERROR) ;
00431 
00432         g_return_val_if_fail (PRIVATE (a_this)->next_byte_index <= 
00433                               PRIVATE (a_this)->nb_bytes,
00434                               CR_BAD_PARAM_ERROR) ;
00435 
00436         if (PRIVATE (a_this)->end_of_input == TRUE)
00437                 return CR_END_OF_INPUT_ERROR ; 
00438 
00439         *a_byte =
00440                 PRIVATE 
00441                 (a_this)->in_buf[PRIVATE (a_this)->next_byte_index] ;
00442 
00443         if (PRIVATE (a_this)->nb_bytes -
00444             PRIVATE (a_this)->next_byte_index < 2)
00445         {
00446                 PRIVATE (a_this)->end_of_input = TRUE ;
00447         }
00448         else
00449         {
00450                 PRIVATE (a_this)->next_byte_index ++ ;
00451         }
00452 
00453         return CR_OK ;
00454 }
00455 
00456 
00457 /**
00458  *Reads an unicode character from the current instance of
00459  *#CRInput.
00460  *@param a_this the current instance of CRInput.
00461  *@param a_char out parameter. The read character.
00462  *@return CR_OK upon successfull completion, an error code
00463  *otherwise.
00464  */
00465 enum CRStatus
00466 cr_input_read_char (CRInput *a_this, guint32 *a_char)
00467 {
00468         enum CRStatus status = CR_OK ;
00469         gulong consumed = 0, nb_bytes_left = 0 ;
00470         
00471         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
00472                               CR_BAD_PARAM_ERROR) ;
00473 
00474         if (PRIVATE (a_this)->end_of_input == TRUE)
00475                 return CR_END_OF_INPUT_ERROR ; 
00476 
00477         nb_bytes_left = cr_input_get_nb_bytes_left (a_this) ;
00478 
00479         if (nb_bytes_left < 1)
00480         {
00481                 return  CR_END_OF_INPUT_ERROR ;
00482         }
00483 
00484         status =
00485                 cr_utils_read_char_from_utf8_buf 
00486                 (PRIVATE (a_this)->in_buf 
00487                  + 
00488                  PRIVATE (a_this)->next_byte_index,
00489                  nb_bytes_left, a_char, &consumed) ;
00490 
00491         if (status == CR_OK)
00492         {
00493                 /*update next byte index*/
00494                 PRIVATE (a_this)->next_byte_index += consumed ;
00495 
00496                 /*upate line and column number*/
00497                 if (PRIVATE (a_this)->end_of_line == TRUE)
00498                 {
00499                         PRIVATE (a_this)->col = 1 ;
00500                         PRIVATE (a_this)->line ++ ;
00501                         PRIVATE (a_this)->end_of_line = FALSE ;
00502                 }
00503                 else if (*a_char != '\n')
00504                 {
00505                         PRIVATE (a_this)->col ++ ;
00506                 }
00507                 
00508                 if (*a_char == '\n')
00509                 {
00510                         PRIVATE (a_this)->end_of_line = TRUE ;
00511                 }
00512 
00513         }
00514 
00515         return status ;
00516 }
00517 
00518 
00519 /**
00520  *Setter of the current line number.
00521  *@param a_this the "this pointer" of the current instance of
00522  *#CRInput.
00523  *@param a_line_num the new line number.
00524  *@return CR_OK upon successfull completion, an error code otherwise.
00525  */
00526 enum CRStatus
00527 cr_input_set_line_num (CRInput *a_this, glong a_line_num)
00528 {
00529         g_return_val_if_fail (a_this && PRIVATE (a_this),
00530                               CR_BAD_PARAM_ERROR) ;
00531 
00532         PRIVATE (a_this)->line = a_line_num ;
00533 
00534         return CR_OK ;
00535 }
00536 
00537 
00538 /**
00539  *Getter of the curren line number.
00540  *@param a_this the "this pointer" of the current instance of
00541  *#CRInput.
00542  *@param a_line_num the returned line number.
00543  *@return CR_OK upon successfull completion, an error code otherwise.
00544  */
00545 enum CRStatus
00546 cr_input_get_line_num (CRInput *a_this, glong *a_line_num)
00547 {
00548         g_return_val_if_fail (a_this && PRIVATE (a_this)
00549                               && a_line_num,
00550                               CR_BAD_PARAM_ERROR) ;
00551         
00552         *a_line_num = PRIVATE (a_this)->line ;
00553 
00554         return CR_OK ;
00555 }
00556 
00557 
00558 /**
00559  *Setter of the current column number.
00560  *@param a_this the "this pointer" of the current instance of
00561  *#CRInput.
00562  *@param a_col the new column column number.
00563  *@return CR_OK upon successfull completion, an error code otherwise.
00564  */
00565 enum CRStatus
00566 cr_input_set_column_num (CRInput *a_this, glong a_col)
00567 {
00568         g_return_val_if_fail (a_this && PRIVATE (a_this),
00569                           CR_BAD_PARAM_ERROR) ;
00570 
00571         PRIVATE (a_this)->col = a_col ;
00572 
00573         return CR_OK ;
00574 }
00575 
00576 
00577 /**
00578  *Getter of the current column number.
00579  *@param a_this the "this pointer" of the current instance of
00580  *#CRInput.
00581  *@param a_col out parameter
00582  *@return CR_OK upon successfull completion, an error code otherwise.
00583  */
00584 enum CRStatus
00585 cr_input_get_column_num (CRInput *a_this, glong *a_col)
00586 {
00587         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_col,
00588                           CR_BAD_PARAM_ERROR) ;
00589         
00590         *a_col = PRIVATE (a_this)->col ;
00591 
00592         return CR_OK ;
00593 }
00594 
00595 
00596 /**
00597  *Increments the current line number.
00598  *@param a_this the "this pointer" of the current instance of
00599  *#CRInput.
00600  *@return CR_OK upon successfull completion, an error code otherwise.
00601  */
00602 enum CRStatus
00603 cr_input_increment_line_num (CRInput *a_this, glong a_increment)
00604 {
00605         g_return_val_if_fail (a_this && PRIVATE (a_this),
00606                               CR_BAD_PARAM_ERROR) ;
00607         
00608         PRIVATE (a_this)->line += a_increment ;
00609 
00610         return CR_OK ;
00611 }
00612 
00613 
00614 /**
00615  *Increments the current column number.
00616  *@param a_this the "this pointer" of the current instance of
00617  *#CRInput.
00618  *@return CR_OK upon successfull completion, an error code otherwise.
00619  */
00620 enum CRStatus
00621 cr_input_increment_col_num (CRInput *a_this, glong a_increment)
00622 {
00623         g_return_val_if_fail (a_this && PRIVATE (a_this),
00624                               CR_BAD_PARAM_ERROR) ;
00625 
00626         PRIVATE (a_this)->col += a_increment ;
00627 
00628         return CR_OK ;
00629 }
00630 
00631 
00632 
00633 /**
00634  *Consumes the next character of the input stream if
00635  *and only if that character equals a_char.
00636  *
00637  *@param a_this the this pointer.
00638  *@param a_char the character to consume. If set to zero,
00639  *consumes any character.
00640  *@return CR_OK upon successfull completion, CR_PARSING_ERROR if
00641  *next char is different from a_char, an other error code otherwise
00642  */
00643 enum CRStatus
00644 cr_input_consume_char (CRInput *a_this, guint32 a_char)
00645 {
00646         guint32 c ;
00647         enum CRStatus status ;
00648 
00649         g_return_val_if_fail (a_this && PRIVATE (a_this),
00650                               CR_BAD_PARAM_ERROR) ;
00651 
00652         if ((status = cr_input_peek_char (a_this, &c)) != CR_OK)
00653         {
00654                 return status ;
00655         }
00656 
00657         if (c == a_char || a_char == 0)
00658         {
00659                 status = cr_input_read_char (a_this, &c) ;
00660         }
00661         else
00662         {
00663                 return CR_PARSING_ERROR ;
00664         }
00665 
00666         return status ;
00667 }
00668 
00669 
00670 /**
00671  *Consumes up to a_nb_char occurences of the next contiguous characters 
00672  *which equal a_char. Note that the next character of the input stream
00673  **MUST* equal a_char to trigger the consumption, or else, the error
00674  *code CR_PARSING_ERROR is returned.
00675  *If the number of contiguous characters that equals a_char is less than
00676  *a_nb_char, then this function consumes all the characters it can consumed.
00677  *
00678  *@param a_this the this pointer of the current instance of #CRInput.
00679  *@param a_char the character to consume.
00680  *@param a_nb_char in/out parameter. The number of characters to consume.
00681  *If set to a negative value, the function will consume all the occurences
00682  *of a_char found.
00683  *After return, if the return value equals CR_OK, this variable contains 
00684  *the number of characters actually consumed.
00685  *@return CR_OK if at least one character has been consumed, an error code
00686  *otherwise.
00687  */
00688 enum CRStatus
00689 cr_input_consume_chars (CRInput *a_this, guint32 a_char, gulong *a_nb_char)
00690 {
00691         enum CRStatus status = CR_OK ;
00692         gulong nb_consumed = 0 ;
00693 
00694         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_char,
00695                               CR_BAD_PARAM_ERROR) ;
00696 
00697         g_return_val_if_fail (a_char != 0 || a_nb_char != NULL,
00698                               CR_BAD_PARAM_ERROR) ;
00699 
00700         for (nb_consumed = 0 ;
00701              ((status == CR_OK)
00702               && (*a_nb_char > 0 && nb_consumed < *a_nb_char)) ;
00703              nb_consumed ++)
00704         {
00705                 status = cr_input_consume_char (a_this, a_char) ;
00706         }
00707 
00708         *a_nb_char = nb_consumed ;
00709 
00710         if ((nb_consumed > 0) 
00711             && ((status == CR_PARSING_ERROR) 
00712                 ||  (status == CR_END_OF_INPUT_ERROR)))
00713         {                
00714                 status = CR_OK ;
00715         }
00716 
00717         return status ;
00718 }
00719 
00720 /**
00721  *Same as cr_input_consume_chars() but this one consumes white
00722  *spaces.
00723  *
00724  *@param a_this the "this pointer" of the current instance of #CRInput.
00725  *@param a_nb_chars in/out parameter. The number of white spaces to
00726  *consume. After return, holds the number of white spaces actually consumed.
00727  *@return CR_OK upon successfull completion, an error code otherwise.
00728  */
00729 enum CRStatus
00730 cr_input_consume_white_spaces (CRInput *a_this, gulong *a_nb_chars)
00731 {
00732         enum CRStatus status = CR_OK ;
00733         guint32 cur_char = 0, nb_consumed = 0 ;
00734 
00735         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_chars,
00736                               CR_BAD_PARAM_ERROR) ;
00737 
00738         for (nb_consumed = 0;
00739              ((*a_nb_chars > 0) && (nb_consumed < *a_nb_chars)) ;
00740              nb_consumed ++)
00741         {
00742                 status = cr_input_peek_char (a_this, &cur_char) ;
00743                 if (status != CR_OK) break ;
00744 
00745                 /*if the next char is a white space, consume it !*/
00746                 if (cr_utils_is_white_space (cur_char) == TRUE)
00747                 {
00748                         status = cr_input_read_char (a_this, &cur_char) ;
00749                         if (status != CR_OK) break ;
00750                         continue ;
00751                 }
00752                 
00753                 break ;
00754         
00755         }
00756 
00757         if (nb_consumed && status == CR_END_OF_INPUT_ERROR) 
00758         {
00759                 status = CR_OK ;
00760         }
00761         
00762         return status ;
00763 }
00764 
00765 
00766 /**
00767  *Same as cr_input_read_char() but does not update the
00768  *internal state of the input stream. The next call
00769  *to cr_input_peek_char() or cr_input_read_char() will thus
00770  *return the same character as the current one.
00771  *@param a_this the current instance of #CRInput.
00772  *@param a_char out parameter. The returned character.
00773  *@return CR_OK upon successfull completion, an error code
00774  *otherwise.
00775  */
00776 enum CRStatus
00777 cr_input_peek_char (CRInput *a_this, guint32 *a_char)
00778 {
00779         enum CRStatus status = CR_OK ;
00780         glong consumed = 0, nb_bytes_left = 0 ;
00781 
00782         g_return_val_if_fail (a_this && PRIVATE (a_this) 
00783                               && a_char, CR_BAD_PARAM_ERROR) ;
00784 
00785         if (PRIVATE (a_this)->next_byte_index >= 
00786             PRIVATE (a_this)->in_buf_size)
00787         {
00788                 return CR_END_OF_INPUT_ERROR ;
00789         }
00790 
00791         nb_bytes_left = cr_input_get_nb_bytes_left (a_this) ;
00792 
00793         if (nb_bytes_left < 1)
00794         {
00795                 return CR_END_OF_INPUT_ERROR ;
00796         }
00797 
00798         status =
00799                 cr_utils_read_char_from_utf8_buf 
00800                 (PRIVATE (a_this)->in_buf + 
00801                  PRIVATE (a_this)->next_byte_index,
00802                  nb_bytes_left, a_char, &consumed) ;
00803 
00804         return status ;
00805 }
00806 
00807 
00808 
00809 /**
00810  *Gets a byte from the input stream.
00811  *starting from the current position in the input stream.
00812  *Unlike cr_input_peek_next_byte() this method
00813  *does not update the state of the current input stream.
00814  *Subsequent calls to cr_input_peek_byte with the same arguments
00815  *will return the same byte.
00816  *
00817  *@param a_this the current instance of #CRInput.
00818  *@param a_origin the origin to consider in the calculation
00819  *of the position of the byte to peek.
00820  *@param a_offset the offset of the byte to peek, starting from
00821  *the origin specified by a_origin.
00822  *@param a_byte out parameter the peeked byte.
00823  *@return CR_OK upon successfull completion or,
00824  *
00825  *<ul>
00826  *<li>CR_BAD_PARAM_ERROR if at least of of the parameters is invalid</li>
00827  *<li>CR_OUT_OF_BOUNDS_ERROR if the indexed byte is out of bounds</li>
00828  *</ul>
00829  */
00830 enum CRStatus
00831 cr_input_peek_byte (CRInput *a_this, enum CRSeekPos a_origin,
00832                     gulong a_offset, guchar *a_byte)
00833 {
00834         gulong abs_offset = 0 ;
00835 
00836         g_return_val_if_fail (a_this && PRIVATE (a_this)
00837                               && a_byte, 
00838                               CR_BAD_PARAM_ERROR) ;
00839         
00840 
00841         switch (a_origin) {
00842 
00843         case CR_SEEK_CUR:
00844                 abs_offset = 
00845                         PRIVATE (a_this)->next_byte_index - 1 + a_offset ;
00846                 break ;
00847 
00848         case CR_SEEK_BEGIN:
00849                 abs_offset = a_offset ;
00850                 break ;
00851 
00852         case CR_SEEK_END:
00853                 abs_offset = 
00854                         PRIVATE (a_this)->in_buf_size - 1 - a_offset ;
00855                 break;
00856 
00857         default:
00858                 return CR_BAD_PARAM_ERROR ;
00859         }
00860 
00861         if (abs_offset < PRIVATE (a_this)->in_buf_size) {
00862 
00863                 *a_byte =
00864                         PRIVATE (a_this)->in_buf[abs_offset] ;
00865 
00866                 return CR_OK ;
00867 
00868         } else {
00869                 return CR_END_OF_INPUT_ERROR ;
00870         }
00871 }
00872 
00873 /**
00874  *Same as cr_input_peek_byte() but with a simplified
00875  *interface.
00876  *@param a_this the current byte input stream.
00877  *@param a_offset the offset of the byte to peek, starting
00878  *from the current input postion pointer.
00879  *@param a_eof out parameter. Is set to true is we reach end of
00880  *stream. If set to NULL by the caller, this parameter is not taken
00881  *in account.
00882  *@return the read byte or 0 if smthing bad happened.
00883  */
00884 guchar 
00885 cr_input_peek_byte2 (CRInput *a_this, gulong a_offset, 
00886                      gboolean *a_eof)
00887 {
00888         guchar result = 0 ;
00889         enum CRStatus status = CR_ERROR ;
00890 
00891         g_return_val_if_fail (a_this && PRIVATE (a_this),
00892                               0) ;
00893 
00894         if (a_eof) 
00895                 *a_eof = FALSE ;
00896 
00897         status = cr_input_peek_byte (a_this, CR_SEEK_CUR, a_offset,
00898                                      &result) ;
00899 
00900         if ((status == CR_END_OF_INPUT_ERROR)
00901             && a_eof)
00902                 *a_eof = TRUE ;
00903 
00904         return result ;
00905 }
00906 
00907 
00908 /**
00909  *Returns the memory address of the byte located at a given offset
00910  *in the input stream.
00911  *@param a_this the current instance of #CRInput.
00912  *@param a_offset the offset of the byte in the input stream starting
00913  *from the begining of the stream.
00914  *@return the address, otherwise NULL if an error occured.
00915  */
00916 guchar *
00917 cr_input_get_byte_addr (CRInput *a_this, 
00918                         gulong a_offset)
00919 {
00920         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL) ;
00921         
00922         if (a_offset >= PRIVATE (a_this)->nb_bytes)
00923         {
00924                 return NULL ;
00925         }
00926 
00927         return &PRIVATE (a_this)->in_buf[a_offset] ;
00928 }
00929 
00930 /**
00931  *Returns the address of the current character pointer.
00932  *@param a_this the current input stream
00933  *@param a_offset out parameter. The returned address.
00934  *@return CR_OK upon successfull completion, an error code otherwise.
00935  */
00936 enum CRStatus
00937 cr_input_get_cur_byte_addr (CRInput *a_this, guchar ** a_offset)
00938 {
00939         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_offset,
00940                               CR_BAD_PARAM_ERROR) ;
00941 
00942         if (!PRIVATE (a_this)->next_byte_index)
00943         {
00944                 return CR_START_OF_INPUT_ERROR ;   
00945         }
00946 
00947         *a_offset = cr_input_get_byte_addr 
00948                 (a_this, PRIVATE (a_this)->next_byte_index -1) ;
00949 
00950         return CR_OK ;
00951 }
00952 
00953 /**
00954  *Sets the "current byte index" of the current instance
00955  *of #CRInput. Next call to cr_input_get_byte() will return
00956  *the byte next after the new "current byte index".
00957  *
00958  *@param a_this the current instance of #CRInput.
00959  *
00960  *@param a_origin the origin to consider during the calculation
00961  *of the absolute position of the new "current byte index".
00962  *
00963  *@param a_pos the relative offset of the new "current byte index."
00964  *This offset is relative to the origin a_origin.
00965  *
00966  *@return CR_OK upon successfull completion otherwise returns
00967  *<ul>
00968  *<li>CR_BAD_PARAM_ERROR if at least one of the parameters is not valid</li>
00969  *<li>CR_OUT_BOUNDS_ERROR</li>
00970  *</ul>
00971  */
00972 enum CRStatus
00973 cr_input_seek_index (CRInput *a_this, enum CRSeekPos a_origin, gint a_pos)
00974 {
00975 
00976         glong abs_offset = 0 ;
00977 
00978         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR) ;
00979 
00980   
00981         switch (a_origin) {
00982 
00983         case CR_SEEK_CUR:
00984                 abs_offset =
00985                         PRIVATE (a_this)->next_byte_index - 1 + a_pos ;
00986                 break ;
00987 
00988         case CR_SEEK_BEGIN:
00989                 abs_offset = a_pos ;
00990                 break ;
00991 
00992         case CR_SEEK_END:
00993                 abs_offset =
00994                         PRIVATE (a_this)->in_buf_size - 1 - a_pos ;
00995                 break ;
00996 
00997         default:
00998                 return CR_BAD_PARAM_ERROR ;
00999         }
01000 
01001         if ((abs_offset > 0)
01002             && (gulong) abs_offset < PRIVATE (a_this)->nb_bytes) {
01003 
01004                 /*update the input stream's internal state*/
01005                 PRIVATE (a_this)->next_byte_index = abs_offset + 1 ;
01006 
01007                 return CR_OK ;
01008         }
01009 
01010         return CR_OUT_OF_BOUNDS_ERROR ;
01011 }
01012 
01013 
01014 /**
01015  *Gets the position of the "current byte index" which
01016  *is basically the position of the last returned byte in the
01017  *input stream.
01018  *
01019  *@param a_this the current instance of #CRInput.
01020  *
01021  *@param a_pos out parameter. The returned position.
01022  *
01023  *@return CR_OK upon sucessfull completion. Otherwise,
01024  *<ul>
01025  *<li>CR_BAD_PARAMETER_ERROR if at least of the arguments is invalid.</li>
01026  *<li>CR_START_OF_INPUT if no call to neither cr_input_read_byte()
01027  *not cr_input_seek_index() have been issued before calling 
01028  *cr_input_get_cur_pos()</li>
01029  *</ul>
01030  *Note that the out parameters of this function are valid if and only if this
01031  *function returns CR_OK.
01032  */
01033 enum CRStatus
01034 cr_input_get_cur_pos (CRInput *a_this, CRInputPos * a_pos)
01035 {
01036         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
01037                               CR_BAD_PARAM_ERROR) ;
01038 
01039         a_pos->next_byte_index = PRIVATE (a_this)->next_byte_index ;
01040         a_pos->line = PRIVATE (a_this)->line ;
01041         a_pos->col = PRIVATE (a_this)->col ;
01042         a_pos->end_of_line = PRIVATE (a_this)->end_of_line ;
01043         a_pos->end_of_file = PRIVATE (a_this)->end_of_input ;
01044         
01045         return CR_OK ;
01046 }
01047 
01048 
01049 /**
01050  *Getter of the next byte index. 
01051  *It actually returns the index of the
01052  *next byte to be read.
01053  *@param a_this the "this pointer" of the current instance of
01054  *#CRInput
01055  *@param a_index out parameter. The returned index.
01056  *@return CR_OK upon sucessfull completion, an error code
01057  *otherwise.
01058  */
01059 enum CRStatus
01060 cr_input_get_cur_index (CRInput *a_this, glong *a_index)
01061 {
01062         g_return_val_if_fail (a_this && PRIVATE (a_this) 
01063                               && a_index, 
01064                               CR_BAD_PARAM_ERROR) ;
01065 
01066         *a_index = PRIVATE (a_this)->next_byte_index ;
01067 
01068         return CR_OK ;
01069 }
01070 
01071 
01072 /**
01073  *Setter of the next byte index.
01074  *It sets the index of the next byte to be read.
01075  *@param a_this the "this pointer" of the current instance
01076  *of #CRInput .
01077  *@param a_index the new index to set.
01078  *@return CR_OK upon sucessfull completion, an error code otherwise.
01079  */
01080 enum CRStatus
01081 cr_input_set_cur_index (CRInput *a_this, glong a_index)
01082 {
01083         g_return_val_if_fail (a_this && PRIVATE (a_this),
01084                               CR_BAD_PARAM_ERROR) ;
01085         
01086         PRIVATE (a_this)->next_byte_index = a_index ;
01087 
01088         return CR_OK ;
01089 }
01090 
01091 
01092 /**
01093  *Sets the end of file flag.
01094  *@param a_this the current instance of #CRInput.
01095  *@param a_eof the new end of file flag.
01096  *@return CR_OK upon successfull completion, an error code otherwise.
01097  */
01098 enum CRStatus
01099 cr_input_set_end_of_file (CRInput *a_this, gboolean a_eof)
01100 {
01101         g_return_val_if_fail (a_this && PRIVATE (a_this),
01102                               CR_BAD_PARAM_ERROR) ;
01103 
01104         PRIVATE (a_this)->end_of_input = a_eof ;
01105 
01106         return CR_OK ;
01107 }
01108 
01109 /**
01110  *Gets the end of file flag.
01111  *@param a_this the current instance of #CRInput.
01112  *@param a_eof out parameter the place where to put the end of
01113  *file flag.
01114  *@return CR_OK upon sucessfull completion, an error code otherwise.
01115  */
01116 enum CRStatus
01117 cr_input_get_end_of_file (CRInput *a_this, gboolean *a_eof)
01118 {
01119         g_return_val_if_fail (a_this && PRIVATE (a_this)
01120                               && a_eof,
01121                               CR_BAD_PARAM_ERROR) ;
01122 
01123         *a_eof = PRIVATE (a_this)->end_of_input ;
01124 
01125         return CR_OK ;
01126 }
01127 
01128 
01129 /**
01130  *Sets the end of line flag.
01131  *@param a_this the current instance of #CRInput.
01132  *@param a_eol the new end of line flag.
01133  *@return CR_OK upon successfull completion, an error code
01134  *otherwise.
01135  */
01136 enum CRStatus
01137 cr_input_set_end_of_line (CRInput *a_this, gboolean a_eol)
01138 {
01139         g_return_val_if_fail (a_this && PRIVATE (a_this),
01140                               CR_BAD_PARAM_ERROR) ;
01141 
01142         PRIVATE (a_this)->end_of_line = a_eol ;
01143 
01144         return CR_OK ;
01145 }
01146 
01147 /**
01148  *Gets the end of line flag of the current input.
01149  *@param a_this the current instance of #CRInput
01150  *@param a_eol out parameter. The place where to put
01151  *the returned flag
01152  *@return CR_OK upon successfull completion, an error code
01153  *otherwise.
01154  */
01155 enum CRStatus
01156 cr_input_get_end_of_line (CRInput *a_this, gboolean *a_eol)
01157 {
01158         g_return_val_if_fail (a_this && PRIVATE (a_this)
01159                               && a_eol,
01160                               CR_BAD_PARAM_ERROR) ;
01161 
01162         *a_eol = PRIVATE (a_this)->end_of_line ;
01163 
01164         return CR_OK ;
01165 }
01166 
01167 
01168 /**
01169  *Sets the current position in the input stream.
01170  *
01171  *@param a_this the "this pointer" of the current instance of
01172  *#CRInput.
01173  *@param a_pos the new position.
01174  */
01175 enum CRStatus
01176 cr_input_set_cur_pos (CRInput *a_this, CRInputPos *a_pos)
01177 {
01178         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
01179                               CR_BAD_PARAM_ERROR) ;
01180         
01181         cr_input_set_column_num (a_this, a_pos->col) ;
01182         cr_input_set_line_num (a_this, a_pos->line) ;
01183         cr_input_set_cur_index (a_this, a_pos->next_byte_index) ;
01184         cr_input_set_end_of_line (a_this, a_pos->end_of_line) ;
01185         cr_input_set_end_of_file (a_this, a_pos->end_of_file) ;
01186 
01187         return CR_OK ;
01188 }

Generated on Wed Oct 1 01:36:45 2003 for Libcroco by doxygen 1.3.3