Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 2004-2015 Frediano Ziglio
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Library General Public
6 : * License as published by the Free Software Foundation; either
7 : * version 2 of the License, or (at your option) any later version.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Library General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Library General Public
15 : * License along with this library; if not, write to the
16 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 : * Boston, MA 02111-1307, USA.
18 : */
19 :
20 : #include <config.h>
21 :
22 : #include <stdarg.h>
23 : #include <stdio.h>
24 : #include <assert.h>
25 :
26 : #if HAVE_STDLIB_H
27 : #include <stdlib.h>
28 : #endif /* HAVE_STDLIB_H */
29 :
30 : #if HAVE_STRING_H
31 : #include <string.h>
32 : #endif /* HAVE_STRING_H */
33 :
34 : #include <freetds/utils/string.h>
35 :
36 :
37 : /**
38 : * \ingroup libtds
39 : * \defgroup dstring Dynamic string functions
40 : * Handle dynamic string. In this string are always valid
41 : * (you don't have NULL pointer, only empty strings)
42 : */
43 :
44 : /* This is in a separate module because we use the pointer to discriminate allocated and not allocated */
45 : const struct tds_dstr tds_str_empty = { 0, "" };
46 : #define EMPTY ((struct tds_dstr*) &tds_str_empty)
47 :
48 : /**
49 : * \addtogroup dstring
50 : * @{
51 : */
52 :
53 : /** clear all string filling with zeroes (mainly for security reason) */
54 : void
55 16610 : tds_dstr_zero(DSTR * s)
56 : {
57 16610 : memset((*s)->dstr_s, 0, (*s)->dstr_size);
58 16610 : }
59 :
60 : /** free string */
61 : void
62 657293 : tds_dstr_free(DSTR * s)
63 : {
64 657293 : if (*s != EMPTY)
65 182191 : free(*s);
66 657293 : *s = EMPTY;
67 657293 : }
68 :
69 : /**
70 : * Set string to a given buffer of characters
71 : * @param s dynamic string
72 : * @param src source buffer
73 : * @param length length of source buffer
74 : * @return string copied or NULL on memory error
75 : */
76 : DSTR*
77 114315 : tds_dstr_copyn(DSTR * s, const char *src, size_t length)
78 : {
79 114315 : if (!length) {
80 14928 : if (*s != EMPTY) {
81 1454 : free(*s);
82 1454 : *s = EMPTY;
83 : }
84 : } else {
85 99387 : struct tds_dstr *p = (struct tds_dstr *) malloc(length + TDS_OFFSET(struct tds_dstr, dstr_s) + 1);
86 99387 : if (TDS_UNLIKELY(!p))
87 : return NULL;
88 99387 : memcpy(p->dstr_s, src, length);
89 99387 : p->dstr_s[length] = 0;
90 99387 : p->dstr_size = length;
91 99387 : if (*s != EMPTY)
92 17382 : free(*s);
93 99387 : *s = p;
94 : }
95 : return s;
96 : }
97 :
98 : /**
99 : * set a string from another buffer.
100 : * The string will use the supplied buffer (it not copy the string),
101 : * so it should be a pointer returned by malloc.
102 : * @param s dynamic string
103 : * @param src source buffer
104 : * @return string copied or NULL on memory error
105 : */
106 : DSTR*
107 13377 : tds_dstr_set(DSTR * s, char *src)
108 : {
109 13377 : DSTR *res = tds_dstr_copy(s, src);
110 13377 : if (TDS_LIKELY(res != NULL))
111 13377 : free(src);
112 13377 : return res;
113 : }
114 :
115 : /**
116 : * copy a string from another
117 : * @param s dynamic string
118 : * @param src source buffer
119 : * @return string copied or NULL on memory error
120 : */
121 : DSTR*
122 39248 : tds_dstr_copy(DSTR * s, const char *src)
123 : {
124 52625 : return tds_dstr_copyn(s, src, strlen(src));
125 : }
126 :
127 : /**
128 : * Duplicate a string from another dynamic string
129 : * @param s output string
130 : * @param src source string to copy
131 : * @return string copied or NULL on memory error
132 : */
133 : DSTR*
134 60007 : tds_dstr_dup(DSTR * s, const DSTR * src)
135 : {
136 60007 : return tds_dstr_copyn(s, (*src)->dstr_s, (*src)->dstr_size);
137 : }
138 :
139 : /**
140 : * limit length of string, MUST be <= current length
141 : * @param s dynamic string
142 : * @param length new length
143 : */
144 : DSTR*
145 139853 : tds_dstr_setlen(DSTR *s, size_t length)
146 : {
147 : #if ENABLE_EXTRA_CHECKS
148 139853 : assert((*s)->dstr_size >= length);
149 : #endif
150 : /* test required for empty strings */
151 139853 : if ((*s)->dstr_size >= length && *s != EMPTY) {
152 139853 : (*s)->dstr_size = length;
153 139853 : (*s)->dstr_s[length] = 0;
154 : }
155 139853 : return s;
156 : }
157 :
158 : /**
159 : * allocate space for length char
160 : * @param s dynamic string
161 : * @param length new length
162 : * @return string allocated or NULL on memory error
163 : */
164 : DSTR*
165 114955 : tds_dstr_alloc(DSTR *s, size_t length)
166 : {
167 114955 : struct tds_dstr *p = (struct tds_dstr *) malloc(length + TDS_OFFSET(struct tds_dstr, dstr_s) + 1);
168 114955 : if (TDS_UNLIKELY(!p))
169 : return NULL;
170 :
171 114955 : if (*s != EMPTY)
172 13033 : free(*s);
173 114955 : p->dstr_s[0] = 0;
174 114955 : p->dstr_size = length;
175 114955 : *s = p;
176 114955 : return s;
177 : }
178 :
179 : /** @} */
|