]> arthur.barton.de Git - netatalk.git/blob - libatalk/bstring/bstradd.c
Merge from branch-2-1
[netatalk.git] / libatalk / bstring / bstradd.c
1 /*
2   $Id: bstradd.c,v 1.1.2.1 2010-02-01 10:56:08 franklahm Exp $
3   Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
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
16 /*!
17  * @file
18  * Additional functions for bstrlib
19  */
20
21 #include <stdio.h>
22 #include <stddef.h>
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27
28 #include <atalk/bstrlib.h>
29
30 /* Optionally include a mechanism for debugging memory */
31
32 #if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG)
33 #include "memdbg.h"
34 #endif
35
36 #ifndef bstr__alloc
37 #define bstr__alloc(x) malloc (x)
38 #endif
39
40 #ifndef bstr__free
41 #define bstr__free(p) free (p)
42 #endif
43
44 #ifndef bstr__realloc
45 #define bstr__realloc(p,x) realloc ((p), (x))
46 #endif
47
48 #ifndef bstr__memcpy
49 #define bstr__memcpy(d,s,l) memcpy ((d), (s), (l))
50 #endif
51
52 #ifndef bstr__memmove
53 #define bstr__memmove(d,s,l) memmove ((d), (s), (l))
54 #endif
55
56 #ifndef bstr__memset
57 #define bstr__memset(d,c,l) memset ((d), (c), (l))
58 #endif
59
60 #ifndef bstr__memcmp
61 #define bstr__memcmp(d,c,l) memcmp ((d), (c), (l))
62 #endif
63
64 #ifndef bstr__memchr
65 #define bstr__memchr(s,c,l) memchr ((s), (c), (l))
66 #endif
67
68 /*************************************************************************
69  * Stuff for making bstrings referencing c-strings
70  ************************************************************************/
71
72 /*!
73  * @brief Create a bstring referencing "str"
74  *
75  * This is usefull if a well know code path uses string, often doing strlen on string.
76  * By converting to bstring which carries the strlen, the repeated computation can be avoided.
77  */
78 bstring brefcstr (char *str) {
79     bstring b;
80     int i;
81     size_t j;
82
83         if (str == NULL)
84         return NULL;
85         j = strlen(str);
86
87         b = (bstring)bstr__alloc(sizeof(struct tagbstring));
88         if (NULL == b)
89         return NULL;
90
91         b->slen = (int) j;
92     b->mlen = -1;
93     b->data = str;
94
95         return b;
96 }
97
98 /*!
99  * @brief Free up the bstring, WITHOUT freeing the pointed to c-string!
100  */
101 int bunrefcstr (bstring b) {
102         if (b == NULL || b->slen < 0 || b->mlen > 0 || b->data == NULL)
103                 return BSTR_ERR;
104
105         /* In case there is any stale usage, there is one more chance to 
106            notice this error. */
107
108         b->slen = -1;
109         b->mlen = -__LINE__;
110         b->data = NULL;
111
112         bstr__free (b);
113         return BSTR_OK;
114 }
115
116 /*************************************************************************
117  * stuff for bstrList
118  ************************************************************************/
119
120 /*!
121  * @brief Create an empty list with preallocated storage for at least 'min' members
122  */
123 struct bstrList *bstListCreateMin(int min)
124 {
125     struct bstrList *sl = NULL;
126
127     if ((sl = bstrListCreate()) == NULL)
128         return NULL;
129
130     if ((bstrListAlloc(sl, min)) != BSTR_OK) {
131         bstrListDestroy(sl);
132         return NULL;
133     }
134
135     return sl;
136 }
137
138 /*!
139  * @brief Push a bstring to the end of a list
140  */
141 int bstrListPush(struct bstrList *sl, bstring bs)
142 {
143     if (sl->qty == sl->mlen) {
144         if ((bstrListAlloc(sl, sl->qty + 1)) != BSTR_OK)
145             return BSTR_ERR;
146     }
147
148     sl->entry[sl->qty] = bs;
149     sl->qty++;
150     return BSTR_OK;
151 }
152
153 /*!
154  * @brief Pop a bstring from the end of a list
155  */
156 bstring bstrListPop(struct bstrList *sl)
157 {
158     return NULL;
159 }
160
161 /*!
162  * @brief Inverse bjoin
163  */
164 bstring bjoinInv(const struct bstrList * bl, const_bstring sep) {
165     bstring b;
166     int i, j, c, v;
167
168     if (bl == NULL || bl->qty < 0)
169         return NULL;
170     if (sep != NULL && (sep->slen < 0 || sep->data == NULL))
171         return NULL;
172
173     for (i = 0, c = 1; i < bl->qty; i++) {
174         v = bl->entry[i]->slen;
175         if (v < 0)
176             return NULL;/* Invalid input */
177         c += v;
178         if (c < 0)
179             return NULL;/* Wrap around ?? */
180     }
181
182     if (sep != NULL)
183         c += (bl->qty - 1) * sep->slen;
184
185     b = (bstring) bstr__alloc (sizeof (struct tagbstring));
186     if (NULL == b)
187         return NULL; /* Out of memory */
188     b->data = (unsigned char *) bstr__alloc (c);
189     if (b->data == NULL) {
190         bstr__free (b);
191         return NULL;
192     }
193
194     b->mlen = c;
195     b->slen = c-1;
196
197     for (i = bl->qty - 1, c = 0, j = 0; i >= 0; i--, j++) {
198         if (j > 0 && sep != NULL) {
199             bstr__memcpy (b->data + c, sep->data, sep->slen);
200             c += sep->slen;
201         }
202         v = bl->entry[i]->slen;
203         bstr__memcpy (b->data + c, bl->entry[i]->data, v);
204         c += v;
205     }
206     b->data[c] = (unsigned char) '\0';
207     return b;
208 }