1 /*
2 * Copyright (c) 2011 NLNet Labs. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
27 /**
28 *
29 * String utilities
30 */
31
32 #include "config.h"
33 #include "str.h"
34 #include "log.h"
35
36 #include <errno.h>
37 #include <assert.h>
38 #include <stdio.h> /* snprintf() */
39 #include <stdlib.h>
40 #include <string.h> /* strlen(), strcpy() */
41 #include <ctype.h> /* isspace() */
42
43 #include <unistd.h>
44 #include <getopt.h>
45
46 static const char *module_str = "str";
47
48 int
ods_str_explode(char * buf,int argc,const char * argv[])49 ods_str_explode(char *buf, int argc, const char *argv[])
50 {
51 int narg = 0;
52 char *p = strtok(buf, " ");
53 while(p != NULL) {
54 if (narg > argc)
55 return -1;
56 argv[narg] = p;
57 p = strtok(NULL, " ");
58 narg++;
59 }
60 return narg;
61 }
62
63 /**
64 * Concatenate characters without custom allocators.
65 *
66 * Will always allocate at least 1 byte (when catting empty strings) so
67 * result should always be freed by the caller.
68 *
69 * \param[in] argc, number of strings in argv.
70 * \param[in] argv, storage of strings. Must not be NULL;
71 * \param[in] delim, delimiter used to join the strings.
72 * \return string, may be empty string.
73 */
74 char *
ods_strcat_delim(int argc,char * argv[],char delim)75 ods_strcat_delim(int argc, char* argv[], char delim)
76 {
77 int i, pos = 0, len = 1;
78 char *cat;
79
80 assert(argv);
81
82 for (i = 0; i < argc; i++)
83 len += strlen(argv[i]) + 1;
84 cat = (char *) malloc(len * sizeof (char));
85 memset(cat, delim, len-1);
86 for (i = 0; i < argc; i++) {
87 memcpy(cat+pos, argv[i], strlen(argv[i]));
88 pos += strlen(argv[i]) + 1;
89 }
90 cat[len-1] = '\0';
91 return cat;
92 }
93
94 /**
95 * Remove leading and trailing whitespace.
96 * enforcer used ods_str_trim(s,0)
97 */
98 char *
ods_str_trim(char * str,int keep_newline)99 ods_str_trim(char *str, int keep_newline)
100 {
101 int has_newline = 0;
102 char *start, *end;
103 if (str) {
104 end = str + strlen(str); /* points at \0 */
105
106 for (start = str; start<end; start++) {
107 if (!isspace(*start)) break;
108 }
109 for (; end > start; end--) {
110 if (*(end-1) == '\n') has_newline = 1;
111 if (!isspace(*(end-1))) break;
112 }
113 memmove(str, start, end-start);
114 if(has_newline && keep_newline) {
115 str[(end++)-start] = '\n';
116 }
117 str[end-start] = '\0';
118 }
119 return str;
120 }
121
122 /**
123 * Version of ctime_r that does not feature a trailing '\n' character
124 *
125 */
126 char *
ods_ctime_r(char * buf,size_t nbuf,time_t t)127 ods_ctime_r(char *buf, size_t nbuf, time_t t)
128 {
129 #if 0
130 struct tm datetime;
131 if (localtime_r(&t,&datetime) == NULL) {
132 ods_log_error("[%s] time_datestamp: localtime_r() failed",
133 module_str);
134 return NULL;
135 }
136 snprintf(buf, nbuf, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
137 1900+datetime.tm_year, datetime.tm_mon + 1, datetime.tm_mday,
138 datetime.tm_hour, datetime.tm_min, datetime.tm_sec);
139 return buf;
140 #else
141 if (nbuf>=26 && buf!=NULL) {
142 char *p;
143 char *pbeg = ctime_r(&t,buf);
144 char *pend = pbeg ? (pbeg+strlen(pbeg)) : pbeg;
145 if (pbeg >= pend) {
146 ods_log_error("[%s] time_datestamp: ctime_r() failed",
147 module_str);
148 return NULL;
149 }
150 /* strip trailing space characters including '\n' from time string */
151 for (p=pend-1; p>=pbeg && isspace(*p); --p) {
152 *p = '\0';
153 }
154 }
155 return buf;
156 #endif
157 }
158