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