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

Generated on Sat Mar 20 02:38:42 2004 for Libcroco by doxygen 1.3.5