1 /* 2 * Automated Testing Framework (atf) 3 * 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <errno.h> 31 #include <stdarg.h> 32 #include <stdint.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 #include "atf-c/error.h" 38 39 #include "dynstr.h" 40 #include "sanity.h" 41 #include "text.h" 42 43 /* --------------------------------------------------------------------- 44 * Auxiliary functions. 45 * --------------------------------------------------------------------- */ 46 47 static 48 atf_error_t 49 resize(atf_dynstr_t *ad, size_t newsize) 50 { 51 char *newdata; 52 atf_error_t err; 53 54 PRE(newsize > ad->m_datasize); 55 56 newdata = (char *)malloc(newsize); 57 if (newdata == NULL) { 58 err = atf_no_memory_error(); 59 } else { 60 strcpy(newdata, ad->m_data); 61 free(ad->m_data); 62 ad->m_data = newdata; 63 ad->m_datasize = newsize; 64 err = atf_no_error(); 65 } 66 67 return err; 68 } 69 70 static 71 atf_error_t 72 prepend_or_append(atf_dynstr_t *ad, const char *fmt, va_list ap, 73 bool prepend) 74 { 75 char *aux; 76 atf_error_t err; 77 size_t newlen; 78 va_list ap2; 79 80 va_copy(ap2, ap); 81 err = atf_text_format_ap(&aux, fmt, ap2); 82 va_end(ap2); 83 if (atf_is_error(err)) 84 goto out; 85 newlen = ad->m_length + strlen(aux); 86 87 if (newlen + sizeof(char) > ad->m_datasize) { 88 err = resize(ad, newlen + sizeof(char)); 89 if (atf_is_error(err)) 90 goto out_free; 91 } 92 93 if (prepend) { 94 memmove(ad->m_data + strlen(aux), ad->m_data, ad->m_length + 1); 95 memcpy(ad->m_data, aux, strlen(aux)); 96 } else 97 strcpy(ad->m_data + ad->m_length, aux); 98 ad->m_length = newlen; 99 err = atf_no_error(); 100 101 out_free: 102 free(aux); 103 out: 104 return err; 105 } 106 107 /* --------------------------------------------------------------------- 108 * The "atf_dynstr" type. 109 * --------------------------------------------------------------------- */ 110 111 /* 112 * Constants. 113 */ 114 115 const size_t atf_dynstr_npos = SIZE_MAX; 116 117 /* 118 * Constructors and destructors. 119 */ 120 121 atf_error_t 122 atf_dynstr_init(atf_dynstr_t *ad) 123 { 124 atf_error_t err; 125 126 ad->m_data = (char *)malloc(sizeof(char)); 127 if (ad->m_data == NULL) { 128 err = atf_no_memory_error(); 129 goto out; 130 } 131 132 ad->m_data[0] = '\0'; 133 ad->m_datasize = 1; 134 ad->m_length = 0; 135 err = atf_no_error(); 136 137 out: 138 return err; 139 } 140 141 atf_error_t 142 atf_dynstr_init_ap(atf_dynstr_t *ad, const char *fmt, va_list ap) 143 { 144 atf_error_t err; 145 146 ad->m_datasize = strlen(fmt) + 1; 147 ad->m_length = 0; 148 149 do { 150 va_list ap2; 151 int ret; 152 153 ad->m_datasize *= 2; 154 ad->m_data = (char *)malloc(ad->m_datasize); 155 if (ad->m_data == NULL) { 156 err = atf_no_memory_error(); 157 goto out; 158 } 159 160 va_copy(ap2, ap); 161 ret = vsnprintf(ad->m_data, ad->m_datasize, fmt, ap2); 162 va_end(ap2); 163 if (ret < 0) { 164 free(ad->m_data); 165 err = atf_libc_error(errno, "Cannot format string"); 166 goto out; 167 } 168 169 INV(ret >= 0); 170 if ((size_t)ret >= ad->m_datasize) { 171 free(ad->m_data); 172 ad->m_data = NULL; 173 } 174 ad->m_length = ret; 175 } while (ad->m_length >= ad->m_datasize); 176 177 err = atf_no_error(); 178 out: 179 POST(atf_is_error(err) || ad->m_data != NULL); 180 return err; 181 } 182 183 atf_error_t 184 atf_dynstr_init_fmt(atf_dynstr_t *ad, const char *fmt, ...) 185 { 186 va_list ap; 187 atf_error_t err; 188 189 va_start(ap, fmt); 190 err = atf_dynstr_init_ap(ad, fmt, ap); 191 va_end(ap); 192 193 return err; 194 } 195 196 atf_error_t 197 atf_dynstr_init_raw(atf_dynstr_t *ad, const void *mem, size_t memlen) 198 { 199 atf_error_t err; 200 201 if (memlen >= SIZE_MAX - 1) { 202 err = atf_no_memory_error(); 203 goto out; 204 } 205 206 ad->m_data = (char *)malloc(memlen + 1); 207 if (ad->m_data == NULL) { 208 err = atf_no_memory_error(); 209 goto out; 210 } 211 212 ad->m_datasize = memlen + 1; 213 memcpy(ad->m_data, mem, memlen); 214 ad->m_data[memlen] = '\0'; 215 ad->m_length = strlen(ad->m_data); 216 INV(ad->m_length <= memlen); 217 err = atf_no_error(); 218 219 out: 220 return err; 221 } 222 223 atf_error_t 224 atf_dynstr_init_rep(atf_dynstr_t *ad, size_t len, char ch) 225 { 226 atf_error_t err; 227 228 if (len == SIZE_MAX) { 229 err = atf_no_memory_error(); 230 goto out; 231 } 232 233 ad->m_datasize = (len + 1) * sizeof(char); 234 ad->m_data = (char *)malloc(ad->m_datasize); 235 if (ad->m_data == NULL) { 236 err = atf_no_memory_error(); 237 goto out; 238 } 239 240 memset(ad->m_data, ch, len); 241 ad->m_data[len] = '\0'; 242 ad->m_length = len; 243 err = atf_no_error(); 244 245 out: 246 return err; 247 } 248 249 atf_error_t 250 atf_dynstr_init_substr(atf_dynstr_t *ad, const atf_dynstr_t *src, 251 size_t beg, size_t end) 252 { 253 if (beg > src->m_length) 254 beg = src->m_length; 255 256 if (end == atf_dynstr_npos || end > src->m_length) 257 end = src->m_length; 258 259 return atf_dynstr_init_raw(ad, src->m_data + beg, end - beg); 260 } 261 262 atf_error_t 263 atf_dynstr_copy(atf_dynstr_t *dest, const atf_dynstr_t *src) 264 { 265 atf_error_t err; 266 267 dest->m_data = (char *)malloc(src->m_datasize); 268 if (dest->m_data == NULL) 269 err = atf_no_memory_error(); 270 else { 271 memcpy(dest->m_data, src->m_data, src->m_datasize); 272 dest->m_datasize = src->m_datasize; 273 dest->m_length = src->m_length; 274 err = atf_no_error(); 275 } 276 277 return err; 278 } 279 280 void 281 atf_dynstr_fini(atf_dynstr_t *ad) 282 { 283 INV(ad->m_data != NULL); 284 free(ad->m_data); 285 } 286 287 char * 288 atf_dynstr_fini_disown(atf_dynstr_t *ad) 289 { 290 INV(ad->m_data != NULL); 291 return ad->m_data; 292 } 293 294 /* 295 * Getters. 296 */ 297 298 const char * 299 atf_dynstr_cstring(const atf_dynstr_t *ad) 300 { 301 return ad->m_data; 302 } 303 304 size_t 305 atf_dynstr_length(const atf_dynstr_t *ad) 306 { 307 return ad->m_length; 308 } 309 310 size_t 311 atf_dynstr_rfind_ch(const atf_dynstr_t *ad, char ch) 312 { 313 size_t pos; 314 315 for (pos = ad->m_length; pos > 0 && ad->m_data[pos - 1] != ch; pos--) 316 ; 317 318 return pos == 0 ? atf_dynstr_npos : pos - 1; 319 } 320 321 /* 322 * Modifiers. 323 */ 324 325 atf_error_t 326 atf_dynstr_append_ap(atf_dynstr_t *ad, const char *fmt, va_list ap) 327 { 328 atf_error_t err; 329 va_list ap2; 330 331 va_copy(ap2, ap); 332 err = prepend_or_append(ad, fmt, ap2, false); 333 va_end(ap2); 334 335 return err; 336 } 337 338 atf_error_t 339 atf_dynstr_append_fmt(atf_dynstr_t *ad, const char *fmt, ...) 340 { 341 va_list ap; 342 atf_error_t err; 343 344 va_start(ap, fmt); 345 err = prepend_or_append(ad, fmt, ap, false); 346 va_end(ap); 347 348 return err; 349 } 350 351 void 352 atf_dynstr_clear(atf_dynstr_t *ad) 353 { 354 ad->m_data[0] = '\0'; 355 ad->m_length = 0; 356 } 357 358 atf_error_t 359 atf_dynstr_prepend_ap(atf_dynstr_t *ad, const char *fmt, va_list ap) 360 { 361 atf_error_t err; 362 va_list ap2; 363 364 va_copy(ap2, ap); 365 err = prepend_or_append(ad, fmt, ap2, true); 366 va_end(ap2); 367 368 return err; 369 } 370 371 atf_error_t 372 atf_dynstr_prepend_fmt(atf_dynstr_t *ad, const char *fmt, ...) 373 { 374 va_list ap; 375 atf_error_t err; 376 377 va_start(ap, fmt); 378 err = prepend_or_append(ad, fmt, ap, true); 379 va_end(ap); 380 381 return err; 382 } 383 384 /* 385 * Operators. 386 */ 387 388 bool 389 atf_equal_dynstr_cstring(const atf_dynstr_t *ad, const char *str) 390 { 391 return strcmp(ad->m_data, str) == 0; 392 } 393 394 bool 395 atf_equal_dynstr_dynstr(const atf_dynstr_t *s1, const atf_dynstr_t *s2) 396 { 397 return strcmp(s1->m_data, s2->m_data) == 0; 398 } 399