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 */ 78bstring 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 */ 101int 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 */ 123struct bstrList *bstrListCreateMin(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 */ 141int 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 */ 156bstring bstrListPop(struct bstrList *sl) 157{ 158 return NULL; 159} 160 161/*! 162 * @brief Inverse bjoin 163 */ 164bstring 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} 209