1 /*   (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen
2  *   (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen
3  *
4  * This file is part of tingea.  You can redistribute and/or modify tingea
5  * under the terms of the GNU General Public License; either version 3 of the
6  * License or (at your option) any later version.  You should have received a
7  * copy of the GPL along with tingea, in the file COPYING.
8 */
9 
10 #ifndef tingea_ting
11 #define tingea_ting
12 
13 #include "types.h"
14 
15 typedef struct
16 {  char     *str
17 ;  dim      len
18 ;  dim      mxl
19 ;
20 }  mcxTing  ;
21 
22 
23 /*  **************************************************************************
24  * *
25  **            Implementation notes (a few).
26  *
27 *
28 
29   Synopsis
30  *    This little module provides an objectified C-string compatible interface
31  *    to strings.
32 
33  * Some philosophy
34  *    Do not mind the overhead of 2*sizeof(int) bytes per ting.
35  *    If you have humongous amounts of small strings, use C-strings. Optionally
36  *    you can do the needed char manipulation in a ting used as scratch-space
37  *    using the ting interface, then create a normal string once you are done.
38  *    Use mcxTinguish to avoid copying if needed.
39 
40  *    Feel free to use the str member with routines from <string.h>
41  *    or perhaps from ding.h. Just remember to treat it as a const object
42  *    when doing so.
43 
44  * Applications
45  *    Zoem is the macro processor that processes the zoem language. It is very
46  *    string-heavy and its string operations are entirely based on the ting
47  *    module.
48 
49  * Caveat
50  *    Nearly all routines return a NULL pointer to indicate malloc failure.
51 
52  * Data structure
53  *    str:  array of chars
54  *
55  *    len:  length of string in str (excluding '\0')
56  *          *(str+len) == '\0'
57  *
58  *    mxl:  current allocated number of writable char's (excluding '\0')
59  *          Allocated amount is mxl+1
60  *          *(str+mxl) == '\0' - but don't count on that.
61 
62  * Notes
63  *    mcxTingEnsure is the only routine allowed to fiddle with mxl.
64  *    (apart from mcxTingInit which sets it to zero).
65  *
66  *    Future idea
67  *       mcxTingFinalize,  (realloc to length)
68  *
69  *    Routines marked `!' will NOT accept ting==NULL argument.
70  *    Routines marked `#' should not be called other than by ting routines
71  *
72  *                _ #Init  _
73  *               /          \
74  *          Ensure   <--- #Instantiate
75  *         /       \               \
76  *   Empty       !Splice        New,Write,Print,PrintAfter
77  *   NWrite           |
78  *                    |
79  *           Append,Insert,Delete,PrintSplice
80 
81  * TODO
82  *    the library should be able to deal with embedded \0's. Really.
83 */
84 
85 
86 
87 /*  **************************************************************************
88  * *
89  **   Various instantiation routines.
90 */
91 
92                           /*     Accepts NULL argument.
93                            *     void arguments so that it can be used
94                            *     as callback.
95                            *
96                            *     Should ordinarily *not* be used, unless
97                            *     you want to initialize a ting allocated
98                            *     on the frame stack.
99                           */
100 void* mcxTingInit
101 (  void* ting
102 )  ;
103                           /*     Accepts NULL argument.
104                            *     Should ordinarily *not* be used.
105                           */
106 mcxTing* mcxTingInstantiate
107 (  mcxTing*    dst_ting
108 ,  const char* str
109 )  ;
110                           /*     Accepts NULL argument.  Does not affect
111                            *     ting->str.  used for preallocing, e.g. to
112                            *     prepare for successive calls of Append.  (see
113                            *     also Empty).
114                           */
115 mcxTing* mcxTingEnsure
116 (  mcxTing*    ting
117 ,  dim         length
118 )  ;
119                           /*     Accepts NULL argument. The string part is
120                            *     set to the empty string.
121                            *     Can be used for preallocing.
122                           */
123 mcxTing* mcxTingEmpty
124 (  mcxTing*    ting
125 ,  dim         length
126 )  ;
127 
128 
129 
130 /*  **************************************************************************
131  * *
132  **   Some freeing routines.
133 */
134                           /*     Free members and shell struct
135                            *     You pass the address of a variable,
136                            *     loosely speaking.
137                           */
138 void mcxTingFree
139 (  mcxTing     **tingpp
140 )  ;
141                           /*     Free members and shell struct
142                            *     Use with callbacks, e.g.
143                            *     for freeing hash with tings in one go.
144                           */
145 void mcxTingFree_v
146 (  void        *tingpp
147 )  ;
148                           /*     Free members
149                            *     Use for freeing array of ting;
150                            *     e.g. as callback in mcxNFree.
151                           */
152 void mcxTingRelease
153 (  void        *ting
154 )  ;
155 
156 
157 
158 /*  **************************************************************************
159  * *
160  **   A bunch of user-land creation routines.
161 */
162 
163                           /*     accepts NULL argument, maps to empty string.
164                           */
165 mcxTing* mcxTingNew
166 (  const char* str
167 )  ;
168                           /*     accepts NULL argument, maps to empty string.
169                           */
170 mcxTing* mcxTingNNew
171 (  const char* str
172 ,  dim         n
173 )  ;
174                           /*     accepts NULL argument.
175                           */
176 mcxTing* mcxTingWrite
177 (  mcxTing*    ting
178 ,  const char* str
179 )  ;
180                           /*     accepts NULL argument.
181                           */
182 mcxTing* mcxTingNWrite
183 (  mcxTing*    ting
184 ,  const char* str
185 ,  dim         n
186 )  ;
187 
188 
189                           /*    usurps argument.
190                           */
191 mcxTing* mcxTingify
192 (  char* str
193 )  ;
194 
195 
196                           /*    destroys argument, returns str member.
197                           */
198 char* mcxTinguish
199 (  mcxTing*    ting
200 )  ;
201 
202 
203 /*  **************************************************************************
204  * *
205  **   Appending, inserting, deleting, shrinking.
206  *    Some can be used as creation routine (e.g. append).
207 */
208 
209 
210 #define TING_INS_CENTER      -3
211 #define TING_INS_OVERRUN     -4
212 #define TING_INS_OVERWRITE   -5
213 
214 /*
215  *    The offset argument can be negative, for subscripting from the end.
216  *
217  *    The n_delete argument can be nonnegative, or one of
218  *    TING_INS_CENTER     center, (try to) overwrite without changing length.
219  *    TING_INS_OVERRUN    overwrite till the end.
220  *    TING_INS_OVERWRITE  (try to) overwrite without changing length.
221  *
222  *    The n_copy argument is not magical like the previous two.
223  *
224 */
225                           /*     does NOT accept NULL argument.
226                           */
227 mcxstatus mcxTingSplice
228 (  mcxTing*    ting
229 ,  const char* pstr
230 ,  ofs         d_offset   /*     negative offset refers to end     */
231 ,  ofs         n_delete   /*     special modes as documented above */
232 ,  dim         n_copy
233 )  ;
234                           /*     accepts NULL argument.
235                           */
236 mcxTing* mcxTingInsert
237 (  mcxTing*    ting
238 ,  const char* str
239 ,  ofs         offset
240 )  ;
241                           /*     accepts NULL argument.
242                           */
243 mcxTing* mcxTingNInsert
244 (  mcxTing*    ting
245 ,  const char* str
246 ,  ofs         offset     /*  of ting->str */
247 ,  dim         length     /*  of str       */
248 )  ;
249 
250                           /*     accepts NULL argument.
251                           */
252 mcxTing* mcxTingAppend
253 (  mcxTing*    ting
254 ,  const char* str
255 )  ;
256 
257                           /*     accepts NULL argument.
258                           */
259 mcxTing* mcxTingKAppend
260 (  mcxTing*    ting
261 ,  const char* str
262 ,  dim         n
263 )  ;
264                           /*     accepts NULL argument.
265                           */
266 mcxTing* mcxTingNAppend
267 (  mcxTing*    ting
268 ,  const char* str
269 ,  dim         n
270 )  ;
271                           /*     accepts NULL argument.
272                           */
273 mcxTing* mcxTingDelete
274 (  mcxTing*    ting
275 ,  ofs         offset
276 ,  dim         width
277 )  ;
278                           /*     accepts NULL argument.
279                           */
280 mcxTing* mcxTingShrink
281 (  mcxTing*    ting
282 ,  ofs         length
283 )  ;
284 
285 
286 
287 /* Fails only for memory reason */
288 
289 mcxstatus mcxTingTackc
290 (  mcxTing*  ting
291 ,  unsigned char c
292 )  ;
293 
294 
295 /* Fails if last char is not the same as c */
296 
297 mcxstatus mcxTingTickc
298 (  mcxTing*  ting
299 ,  unsigned char c
300 )  ;
301 
302 
303 /*  **************************************************************************
304  * *
305  **   A bunch of printf like routines.
306 */
307 
308                           /*     Accepts NULL argument.
309                           */
310 mcxTing* mcxTingPrint
311 (  mcxTing*    ting
312 ,  const char* fmt
313 ,  ...
314 )
315 #ifdef __GNUC__
316 __attribute__ ((format (printf, 2, 3)))
317 #endif
318    ;
319                           /*     Accepts NULL argument.
320                           */
321 mcxTing*  mcxTingPrintAfter
322 (  mcxTing*    dst
323 ,  const char* fmt
324 ,  ...
325 )
326 #ifdef __GNUC__
327 __attribute__ ((format (printf, 2, 3)))
328 #endif
329    ;
330                           /*     Accepts NULL argument.
331                            *     same offset and delete interface as
332                            *     mcxTingSplice.
333                           */
334 mcxTing*  mcxTingPrintSplice
335 (  mcxTing*    dst
336 ,  ofs         offset
337 ,  ofs         n_delete   /* count of chars to delete, special modes */
338 ,  const char* fmt
339 ,  ...
340 )
341 #ifdef __GNUC__
342 __attribute__ ((format (printf, 4, 5)))
343 #endif
344    ;
345 
346 
347 /*  **************************************************************************
348  * *
349  **   Miscellaneous.
350 */
351 
352 char*  mcxTingStr
353 (  const mcxTing* ting
354 )  ;
355 
356 
357 char* mcxTingSubStr
358 (  const mcxTing* ting
359 ,  ofs            offset
360 ,  ofs            length  /*     use -1 to indicate remainder of string */
361 )  ;
362 
363                           /*     accepts NULL argument.
364                           */
365 mcxTing*  mcxTingRoman
366 (  mcxTing*    dst
367 ,  long        x
368 ,  mcxbool     ucase
369 )  ;
370                           /*     accepts NULL argument.
371                           */
372 mcxTing*  mcxTingInteger
373 (  mcxTing*    dst
374 ,  long        x
375 )  ;
376                           /*     accepts NULL argument.
377                           */
378 mcxTing*  mcxTingDouble
379 (  mcxTing* dst
380 ,  double   x
381 ,  int      decimals
382 )  ;
383 
384 
385 /*  **************************************************************************
386  * *
387  **   Comparing.
388 */
389 
390                   /* compare two mcxTing* pointers */
391 int mcxTingCmp
392 (  const void* t1
393 ,  const void* t2
394 )  ;
395 
396                   /* compare two mcxTing* pointers */
397 int mcxTingRevCmp
398 (  const void* t1
399 ,  const void* t2
400 )  ;
401 
402                   /* compare two mcxTing** pointers */
403 int mcxTingPCmp
404 (  const void* t1
405 ,  const void* t2
406 )  ;
407 
408                   /* compare two mcxTing** pointers */
409 int mcxTingPRevCmp
410 (  const void* t1
411 ,  const void* t2
412 )  ;
413 
414                   /* compare two mcxKV** pointers by key as mcxTing* */
415 int mcxPKeyTingCmp
416 (  const void* k1
417 ,  const void* k2
418 )  ;
419 
420                   /* compare two mcxKV** pointers by key as mcxTing* */
421 int mcxPKeyTingRevCmp
422 (  const void* k1
423 ,  const void* k2
424 )  ;
425 
426 
427 /*  **************************************************************************
428  * *
429  **   Hashing.
430 */
431 
432 u32 (*mcxTingHFieByName(const char* id))(const void* ting)  ;
433 
434 
435 u32 mcxTingELFhash
436 (  const void* ting
437 )  ;
438 
439 u32 mcxTingHash
440 (  const void* ting
441 )  ;
442 
443 u32 mcxTingBJhash
444 (  const void* ting
445 )  ;
446 
447 u32 mcxTingCThash
448 (  const void* ting
449 )  ;
450 
451 u32 mcxTingDPhash
452 (  const void* ting
453 )  ;
454 
455 u32 mcxTingBDBhash
456 (  const void* ting
457 )  ;
458 
459 u32 mcxTingGEhash
460 (  const void* ting
461 )  ;
462 
463 u32 mcxTingOAThash
464 (  const void* ting
465 )  ;
466 
467 u32 mcxTingFNVhash
468 (  const void* ting
469 )  ;
470 
471 u32 mcxTingSvDhash
472 (  const void* ting
473 )  ;
474 
475 u32 mcxTingSvD2hash
476 (  const void* ting
477 )  ;
478 
479 u32 mcxTingSvD1hash
480 (  const void* ting
481 )  ;
482 
483 u32 mcxTingDJBhash
484 (  const void* ting
485 )  ;
486 
487 #endif
488 
489