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

Generated on Fri Oct 29 08:29:11 2004 for Libcroco by  doxygen 1.3.9.1