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