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