1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 5 * Copyright (c) Intel Corporation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <stdarg.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <ctype.h> 40 41 #include "spdk/string.h" 42 43 char * 44 spdk_sprintf_alloc(const char *format, ...) 45 { 46 va_list args; 47 char *buf; 48 size_t bufsize; 49 int rc; 50 51 /* Try with a small buffer first. */ 52 bufsize = 32; 53 54 /* Limit maximum buffer size to something reasonable so we don't loop forever. */ 55 while (bufsize <= 1024 * 1024) { 56 buf = malloc(bufsize); 57 if (buf == NULL) { 58 return NULL; 59 } 60 61 va_start(args, format); 62 rc = vsnprintf(buf, bufsize, format, args); 63 va_end(args); 64 65 /* 66 * If vsnprintf() returned a count within our current buffer size, we are done. 67 * The count does not include the \0 terminator, so rc == bufsize is not OK. 68 */ 69 if (rc >= 0 && (size_t)rc < bufsize) { 70 return buf; 71 } 72 73 /* 74 * vsnprintf() should return the required space, but some libc versions do not 75 * implement this correctly, so just double the buffer size and try again. 76 * 77 * We don't need the data in buf, so rather than realloc(), use free() and malloc() 78 * again to avoid a copy. 79 */ 80 free(buf); 81 bufsize *= 2; 82 } 83 84 return NULL; 85 } 86 87 char * 88 spdk_strlwr(char *s) 89 { 90 char *p; 91 92 if (s == NULL) { 93 return NULL; 94 } 95 96 p = s; 97 while (*p != '\0') { 98 *p = tolower(*p); 99 p++; 100 } 101 102 return s; 103 } 104 105 char * 106 spdk_strsepq(char **stringp, const char *delim) 107 { 108 char *p, *q, *r; 109 int quoted = 0, bslash = 0; 110 111 p = *stringp; 112 if (p == NULL) { 113 return NULL; 114 } 115 116 r = q = p; 117 while (*q != '\0' && *q != '\n') { 118 /* eat quoted characters */ 119 if (bslash) { 120 bslash = 0; 121 *r++ = *q++; 122 continue; 123 } else if (quoted) { 124 if (quoted == '"' && *q == '\\') { 125 bslash = 1; 126 q++; 127 continue; 128 } else if (*q == quoted) { 129 quoted = 0; 130 q++; 131 continue; 132 } 133 *r++ = *q++; 134 continue; 135 } else if (*q == '\\') { 136 bslash = 1; 137 q++; 138 continue; 139 } else if (*q == '"' || *q == '\'') { 140 quoted = *q; 141 q++; 142 continue; 143 } 144 145 /* separator? */ 146 if (strchr(delim, *q) == NULL) { 147 *r++ = *q++; 148 continue; 149 } 150 151 /* new string */ 152 q++; 153 break; 154 } 155 *r = '\0'; 156 157 /* skip tailer */ 158 while (*q != '\0' && strchr(delim, *q) != NULL) { 159 q++; 160 } 161 if (*q != '\0') { 162 *stringp = q; 163 } else { 164 *stringp = NULL; 165 } 166 167 return p; 168 } 169 170 char * 171 spdk_str_trim(char *s) 172 { 173 char *p, *q; 174 175 if (s == NULL) { 176 return NULL; 177 } 178 179 /* remove header */ 180 p = s; 181 while (*p != '\0' && isspace(*p)) { 182 p++; 183 } 184 185 /* remove tailer */ 186 q = p + strlen(p); 187 while (q - 1 >= p && isspace(*(q - 1))) { 188 q--; 189 *q = '\0'; 190 } 191 192 /* if remove header, move */ 193 if (p != s) { 194 q = s; 195 while (*p != '\0') { 196 *q++ = *p++; 197 } 198 *q = '\0'; 199 } 200 201 return s; 202 } 203 204 void 205 spdk_strcpy_pad(void *dst, const char *src, size_t size, int pad) 206 { 207 size_t len; 208 209 len = strlen(src); 210 if (len < size) { 211 memcpy(dst, src, len); 212 memset((char *)dst + len, pad, size - len); 213 } else { 214 memcpy(dst, src, size); 215 } 216 } 217