1 /*************************************************************************** 2 begin : Fri Sep 12 2003 3 copyright : (C) 2020 by Martin Preuss 4 email : martin@libchipcard.de 5 6 *************************************************************************** 7 * * 8 * This library is free software; you can redistribute it and/or * 9 * modify it under the terms of the GNU Lesser General Public * 10 * License as published by the Free Software Foundation; either * 11 * version 2.1 of the License, or (at your option) any later version. * 12 * * 13 * This library is distributed in the hope that it will be useful, * 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 16 * Lesser General Public License for more details. * 17 * * 18 * You should have received a copy of the GNU Lesser General Public * 19 * License along with this library; if not, write to the Free Software * 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 21 * MA 02111-1307 USA * 22 * * 23 ***************************************************************************/ 24 25 26 #ifndef GWENHYWFAR_BUFFER_H 27 #define GWENHYWFAR_BUFFER_H 28 29 #include <gwenhywfar/gwenhywfarapi.h> 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 /** 34 * @brief A dynamically resizeable text buffer. 35 * 36 * @ingroup MOD_BUFFER 37 */ 38 typedef struct GWEN_BUFFER GWEN_BUFFER; 39 #ifdef __cplusplus 40 } 41 #endif 42 43 #include <gwenhywfar/types.h> 44 //#include <gwenhywfar/syncio.h> 45 46 47 #include <stdio.h> 48 /* This is needed for PalmOS, because it define some functions needed */ 49 #include <string.h> 50 51 #ifdef __cplusplus 52 extern "C" { 53 #endif 54 55 /** @defgroup MOD_BUFFER Buffer Management 56 * @ingroup MOD_BASE 57 * 58 * @brief This file contains the definition of a GWEN_BUFFER, a 59 * dynamically resizeable text buffer. 60 * 61 */ 62 /*@{*/ 63 64 #define GWEN_BUFFER_MAX_BOOKMARKS 64 65 66 #define GWEN_BUFFER_MODE_DYNAMIC 0x0001 67 #define GWEN_BUFFER_MODE_ABORT_ON_MEMFULL 0x0002 68 #define GWEN_BUFFER_MODE_READONLY 0x0020 69 70 #define GWEN_BUFFER_MODE_DEFAULT \ 71 (\ 72 GWEN_BUFFER_MODE_DYNAMIC | \ 73 GWEN_BUFFER_MODE_ABORT_ON_MEMFULL\ 74 ) 75 76 77 /** 78 * Creates a new GWEN_BUFFER, which is a dynamically resizeable 79 * text buffer. 80 * 81 * @param buffer If non-NULL, then this buffer will be used as 82 * actual storage space. Otherwise a new buffer will be allocated 83 * (with @c size bytes) 84 * 85 * @param size If @c buffer was non-NULL, then this argument 86 * <i>must</i> specifiy the size of that buffer. If @c buffer was 87 * NULL, then this argument specifies the number of bytes that 88 * will be allocated. 89 * 90 * @param used Number of bytes of the buffer actually used. This is 91 * interesting when reading from a buffer. 92 * 93 * @param take_ownership If @c buffer was non-NULL and this 94 * argument is nonzero, then the new GWEN_BUFFER object takes over 95 * the ownership of the given @c buffer so that it will be freed 96 * on GWEN_Buffer_free(). If this argument is zero, the given @c 97 * buffer will not be freed. If @c buffer was NULL, this argument 98 * has no effect. 99 */ 100 GWENHYWFAR_API 101 GWEN_BUFFER *GWEN_Buffer_new(char *buffer, 102 uint32_t size, 103 uint32_t used, 104 int take_ownership); 105 106 /** 107 * Increases the internal reference counter. It is decreased by 108 * @ref GWEN_Buffer_free(). 109 */ 110 GWENHYWFAR_API 111 void GWEN_Buffer_Attach(GWEN_BUFFER *bf); 112 113 114 /** Frees the given buffer. 115 * 116 * If the internal storage was allocated for this new buffer, then 117 * it will freed here. If the internal storage is used from a 118 * different @c buffer, then it will only be freed if the argument 119 * @c take_ownership of GWEN_Buffer_new() was nonzero. */ 120 GWENHYWFAR_API 121 void GWEN_Buffer_free(GWEN_BUFFER *bf); 122 123 124 /** Create a new copy as a duplicate of the buffer @c bf. */ 125 GWENHYWFAR_API 126 GWEN_BUFFER *GWEN_Buffer_dup(GWEN_BUFFER *bf); 127 128 129 /** This function relinquishes ownership of the internal buffer 130 * if possible. It returns an error if this object does not own the 131 * buffer (it can't give you what it doesn't possess) or if the 132 * internal pointer to the memory allocated does not match the internal 133 * pointer to the current start of the buffer (this can be the case 134 * when @ref GWEN_Buffer_ReserveBytes() of @ref GWEN_Buffer_Crop() 135 * have been called). 136 */ 137 GWENHYWFAR_API 138 int GWEN_Buffer_Relinquish(GWEN_BUFFER *bf); 139 140 /** 141 * Returns the current mode of the buffer 142 * (such as @ref GWEN_BUFFER_MODE_DYNAMIC). 143 */ 144 GWENHYWFAR_API 145 uint32_t GWEN_Buffer_GetMode(GWEN_BUFFER *bf); 146 147 /** 148 * Changes the current mode of the buffer 149 * (such as @ref GWEN_BUFFER_MODE_DYNAMIC). 150 */ 151 GWENHYWFAR_API 152 void GWEN_Buffer_SetMode(GWEN_BUFFER *bf, uint32_t mode); 153 154 /** 155 * Adds the give mode to the current mode of the buffer 156 * (such as @ref GWEN_BUFFER_MODE_DYNAMIC). 157 */ 158 GWENHYWFAR_API 159 void GWEN_Buffer_AddMode(GWEN_BUFFER *bf, uint32_t mode); 160 161 /** 162 * Removes the give mode from the current mode of the buffer 163 * (such as @ref GWEN_BUFFER_MODE_DYNAMIC). 164 */ 165 GWENHYWFAR_API 166 void GWEN_Buffer_SubMode(GWEN_BUFFER *bf, uint32_t mode); 167 168 /** 169 * Returns the hard limit. This is the maximum size of a GWEN_BUFFER in 170 * dynamic mode. 171 */ 172 GWENHYWFAR_API 173 uint32_t GWEN_Buffer_GetHardLimit(GWEN_BUFFER *bf); 174 175 /** 176 * Changes the hard limit. This is the maximum size of a GWEN_BUFFER in 177 * dynamic mode. 178 */ 179 GWENHYWFAR_API 180 void GWEN_Buffer_SetHardLimit(GWEN_BUFFER *bf, uint32_t l); 181 182 183 /** 184 * In dynamic mode, whenever there is new data to allocate then this value 185 * specifies how much data to allocate in addition. 186 * The allocated data in total for this buffer will be aligned to this value. 187 */ 188 GWENHYWFAR_API 189 uint32_t GWEN_Buffer_GetStep(GWEN_BUFFER *bf); 190 191 /** 192 * In dynamic mode, whenever there is new data to allocate then this value 193 * specifies how much data to allocate in addition. 194 * The allocated data in total for this buffer will be aligned to this value. 195 * 1024 is a reasonable value. This value NEEDS to be aligned 2^n (i.e. 196 * only ONE bit must be set !) 197 */ 198 GWENHYWFAR_API 199 void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step); 200 201 202 /** 203 * Reserves the given amount of bytes at the beginning of the buffer. 204 * Please note that this most likely results in a shift of the current 205 * position inside the buffer, so after this call all pointers obtained 206 * from this module (e.g. via @ref GWEN_Buffer_GetStart) are invalid ! 207 * You can use this function to save some memory copy actions when 208 * inserting bytes at the beginning of the buffer. 209 */ 210 GWENHYWFAR_API 211 int GWEN_Buffer_ReserveBytes(GWEN_BUFFER *bf, uint32_t res); 212 213 214 /** 215 * Returns the start of the buffer. You can use the function 216 * @ref GWEN_Buffer_GetPos to navigate within the buffer. 217 */ 218 GWENHYWFAR_API 219 char *GWEN_Buffer_GetStart(const GWEN_BUFFER *bf); 220 221 222 /** 223 * Returns the size of the buffer (i.e. the number of bytes allocated). 224 */ 225 GWENHYWFAR_API 226 uint32_t GWEN_Buffer_GetSize(const GWEN_BUFFER *bf); 227 228 229 /** 230 * Returns the current position within the buffer. This pointer is adjusted 231 * by the various read and write functions. 232 */ 233 GWENHYWFAR_API 234 uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf); 235 236 /** 237 * @return 0 if ok, !=0 on error 238 */ 239 GWENHYWFAR_API 240 int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, uint32_t i); 241 242 /** 243 */ 244 GWENHYWFAR_API 245 uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf); 246 247 248 /** 249 * Returns the given bookmark 250 */ 251 GWENHYWFAR_API 252 uint32_t GWEN_Buffer_GetBookmark(const GWEN_BUFFER *bf, unsigned int idx); 253 254 255 /** 256 * Set a bookmark. These bookmarks are not used by the GWEN_BUFFER functions, 257 * but may be usefull for an application. 258 */ 259 GWENHYWFAR_API 260 void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx, 261 uint32_t v); 262 263 264 /** 265 * Copies the contents of the given buffer to this GWEN_BUFFER, if there is 266 * enough room. 267 * The position pointer is adjusted accordingly. 268 * @return 0 if ok, !=0 on error 269 */ 270 GWENHYWFAR_API 271 int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, 272 const char *buffer, 273 uint32_t size); 274 275 /** 276 * Append strings to buffer with a sprintf()-like argument list. 277 * 278 * @return 0 if okay, error code otherwise 279 * @param bf buffer to append data to 280 * @param fmt format string like that for sprintf(). 281 */ 282 GWENHYWFAR_API 283 int GWEN_Buffer_AppendArgs(GWEN_BUFFER *bf, const char *fmt, ...); 284 285 286 GWENHYWFAR_API 287 int GWEN_Buffer_FillWithBytes(GWEN_BUFFER *bf, 288 unsigned char c, 289 uint32_t size); 290 291 GWENHYWFAR_API 292 int GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER *bf, 293 unsigned char c, 294 uint32_t size); 295 296 297 /** 298 * Appends a string to the buffer (without the trailing null char!) 299 * The position pointer is adjusted accordingly. 300 * @return 0 if ok, !=0 on error 301 */ 302 GWENHYWFAR_API 303 int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, 304 const char *buffer); 305 306 307 /** 308 * Appends a single byte to this GWEN_BUFFER, if there is 309 * enough room. 310 * The position pointer is adjusted accordingly. 311 * @return 0 if ok, !=0 on error 312 */ 313 GWENHYWFAR_API 314 int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c); 315 316 /** 317 * Inserts multiple bytes at the current position. 318 * If the current position is 0 and there is reserved space at the beginning 319 * of the buffer then that space will be used. 320 * Otherwise the data at the current position will be moved out of the way 321 * and the new bytes inserted. 322 * The position pointer will not be altered, but all pointers obtained from 323 * this module (e.g. via @ref GWEN_Buffer_GetStart) become invalid ! 324 */ 325 GWENHYWFAR_API 326 int GWEN_Buffer_InsertBytes(GWEN_BUFFER *bf, 327 const char *buffer, 328 uint32_t size); 329 330 /** 331 * This function makes room for the given number of bytes at the current 332 * buffer position. It moves any existing data at the current position 333 * out of the way. 334 * The position pointer will not be altered, but after calling this function 335 * at that position there is the begin of the newly inserted room. 336 * All pointers obtained from this module (e.g. via 337 * @ref GWEN_Buffer_GetStart) become invalid ! 338 * This function updates the bookmarks accordingly. 339 */ 340 GWENHYWFAR_API 341 int GWEN_Buffer_InsertRoom(GWEN_BUFFER *bf, 342 uint32_t size); 343 344 /** 345 * This function removes the given number of bytes at the current 346 * buffer position. It moves any existing bytes behind the area to be removed 347 * to the current position. 348 * The position pointer will not be altered, but after calling this function 349 * at that position there is the begin of the data behind the removed area. 350 * All pointers obtained from this module (e.g. via 351 * @ref GWEN_Buffer_GetStart) become invalid ! 352 * This function updates the bookmarks accordingly. 353 */ 354 GWENHYWFAR_API 355 int GWEN_Buffer_RemoveRoom(GWEN_BUFFER *bf, uint32_t size); 356 357 /** 358 * This function remplaces the given number of bytes at the current 359 * buffer position with some new bytes. If the number of bytes to be replaced 360 * does not equal the number of replacement bytes then the buffer is resized 361 * accordingly (e.g. shrunk or extended). 362 * The position pointer will not be altered. 363 * All pointers obtained from this module (e.g. via 364 * @ref GWEN_Buffer_GetStart) become invalid ! 365 * This function updates the bookmarks accordingly. 366 */ 367 GWENHYWFAR_API 368 int GWEN_Buffer_ReplaceBytes(GWEN_BUFFER *bf, 369 uint32_t rsize, 370 const char *buffer, 371 uint32_t size); 372 373 374 /** 375 * Inserts the given string at the current position (without the trailing 376 * null byte) 377 * The position pointer will not be altered, but after calling this function 378 * at that position there is the begin of the newly inserted string. 379 * All pointers obtained from this module (e.g. via 380 * @ref GWEN_Buffer_GetStart) become invalid ! 381 * This function updates the bookmarks accordingly. 382 */ 383 GWENHYWFAR_API 384 int GWEN_Buffer_InsertString(GWEN_BUFFER *bf, 385 const char *buffer); 386 387 /** 388 * Inserts a byte at the current position. 389 * If the current position is 0 and there is reserved space at the beginning 390 * of the buffer then that space will be used. 391 * Otherwise the data at the current position will be moved out of the way 392 * and the new byte inserted. 393 * The position pointer will not be altered, but after calling this function 394 * at that position there is the begin of the newly inserted byte. 395 * All pointers obtained from this module (e.g. via 396 * @ref GWEN_Buffer_GetStart) become invalid ! 397 * This function updates the bookmarks accordingly. 398 */ 399 GWENHYWFAR_API 400 int GWEN_Buffer_InsertByte(GWEN_BUFFER *bf, char c); 401 402 /** 403 * Returns the byte from the current position. 404 * The position pointer is adjusted accordingly. 405 * @return -1 on error, read char otherwise (in low byte) 406 */ 407 GWENHYWFAR_API 408 int GWEN_Buffer_ReadByte(GWEN_BUFFER *bf); 409 410 411 /** 412 * Returns the bytes from the current position. 413 * The position pointer is adjusted accordingly. 414 * @return -1 on error, 0 if ok 415 */ 416 GWENHYWFAR_API 417 int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf, 418 char *buffer, 419 uint32_t *size); 420 421 422 /** 423 * Returns the byte from the current position without changing the 424 * position pointer. So multiple calls to this function will result 425 * in returning the same character. 426 * @return -1 on error, read char otherwise (in low byte) 427 */ 428 GWENHYWFAR_API 429 int GWEN_Buffer_PeekByte(GWEN_BUFFER *bf); 430 431 432 /** Move the position pointer forward by the given number @c i. */ 433 GWENHYWFAR_API 434 int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i); 435 436 /** Move the position pointer backward by the given number @c i. */ 437 GWENHYWFAR_API 438 int GWEN_Buffer_DecrementPos(GWEN_BUFFER *bf, uint32_t i); 439 440 /** 441 * The functions @ref GWEN_Buffer_IncrementPos and @ref GWEN_Buffer_DecrementPos 442 * only modify the internal position pointer. 443 * This function here adjusts the number of used bytes to just before the internal 444 * position pointer. This is often used to avoid copying, like in the following 445 * example: 446 * @code 447 * 448 * char *p; 449 * int i; 450 * 451 * for (i=0; i<100; i++) { 452 * GWEN_Buffer_AllocRoom(buffer, 512); 453 * p=GWEN_Buffer_GetPosPtr(buffer); 454 * READ_512_BYTES_TO_P; 455 * GWEN_Buffer_IncrementPos(buffer, 512); 456 * GWEN_Buffer_AdjustUsedBytes(buffer); 457 * } 458 * 459 * @endcode 460 * 461 */ 462 GWENHYWFAR_API 463 int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf); 464 465 466 /** Insert the content of the buffer @c sf into the buffer @c bf 467 * at the position of its current position pointer. The size of @c 468 * bf will be increased accordingly. Returns zero on success or 469 * nonzero if this failed (e.g. because of out of memory 470 * error). */ 471 GWENHYWFAR_API 472 int GWEN_Buffer_InsertBuffer(GWEN_BUFFER *bf, 473 GWEN_BUFFER *sf); 474 475 /** Append the content of the buffer @c sf at the end of the 476 * buffer @c bf. The size of @c bf will be increased 477 * accordingly. Returns zero on success or nonzero if this failed 478 * (e.g. because of out of memory error). */ 479 GWENHYWFAR_API 480 int GWEN_Buffer_AppendBuffer(GWEN_BUFFER *bf, 481 GWEN_BUFFER *sf); 482 483 484 /** 485 * Returns the maximum number of bytes which can be written to the buffer 486 * at once (i.e. without reallocation). 487 */ 488 GWENHYWFAR_API 489 uint32_t GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER *bf); 490 491 492 /** 493 * Returns the number of bytes from pos to the end of the used area. 494 */ 495 GWENHYWFAR_API 496 uint32_t GWEN_Buffer_GetBytesLeft(GWEN_BUFFER *bf); 497 498 499 /** 500 * Returns a pointer to the current position within the buffer. 501 */ 502 GWENHYWFAR_API 503 char *GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf); 504 505 506 /** 507 * Resets the position pointer and the byte counter. 508 */ 509 GWENHYWFAR_API 510 void GWEN_Buffer_Reset(GWEN_BUFFER *bf); 511 512 /** 513 * Resets the pos pointer 514 */ 515 GWENHYWFAR_API 516 void GWEN_Buffer_Rewind(GWEN_BUFFER *bf); 517 518 519 /** 520 * Make sure that the buffer has enough room for the given bytes. 521 */ 522 GWENHYWFAR_API 523 int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size); 524 525 526 /* crops the buffer to the specified bytes */ 527 GWENHYWFAR_API 528 int GWEN_Buffer_Crop(GWEN_BUFFER *bf, 529 uint32_t pos, 530 uint32_t l); 531 532 /* Overwrite complete buffer with a given value. 533 * This does not only overwrite the used bytes but all the memory held 534 * by this object. 535 */ 536 GWENHYWFAR_API 537 void GWEN_Buffer_OverwriteContent(GWEN_BUFFER *bf, int c); 538 539 540 /** Print the current content of buffer @c bf into the file @c f. */ 541 GWENHYWFAR_API 542 void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert); 543 544 545 /** 546 * This is a callback function to be used by GWEN_MULTICACHE (and only for that). 547 * It internally calls @ref GWEN_Buffer_Attach(). 548 */ 549 GWENHYWFAR_API int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Attach(void *ptr); 550 551 /** 552 * This is a callback function to be used by GWEN_MULTICACHE (and only for that). 553 * It internally calls @ref GWEN_Buffer_free(). 554 */ 555 GWENHYWFAR_API int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Free(void *ptr); 556 557 558 /*@}*/ 559 560 #ifdef __cplusplus 561 } 562 #endif 563 564 #endif 565 566 567 568 569 570 571