35 return result; |
36 return result; |
36 } |
37 } |
37 |
38 |
38 char *flib_vasprintf(const char *fmt, va_list args) { |
39 char *flib_vasprintf(const char *fmt, va_list args) { |
39 char *result = NULL; |
40 char *result = NULL; |
40 if(!fmt) { |
41 if(!log_badargs_if(fmt==NULL)) { |
41 flib_log_e("null parameter in flib_vasprintf"); |
|
42 } else { |
|
43 int requiredSize = vsnprintf(NULL, 0, fmt, args)+1; // Figure out how much memory we need, |
42 int requiredSize = vsnprintf(NULL, 0, fmt, args)+1; // Figure out how much memory we need, |
44 if(requiredSize<0) { |
43 if(!log_e_if(requiredSize<0, "Error formatting string with template \"%s\"", fmt)) { |
45 flib_log_e("Error formatting string with template \"%s\" in flib_vasprintf", fmt); |
|
46 } else { |
|
47 char *tmpbuf = flib_malloc(requiredSize); // allocate it |
44 char *tmpbuf = flib_malloc(requiredSize); // allocate it |
48 if(tmpbuf && vsnprintf(tmpbuf, requiredSize, fmt, args)>=0) { // and then do the actual formatting. |
45 if(tmpbuf && vsnprintf(tmpbuf, requiredSize, fmt, args)>=0) { // and then do the actual formatting. |
49 result = tmpbuf; |
46 result = tmpbuf; |
50 tmpbuf = NULL; |
47 tmpbuf = NULL; |
51 } |
48 } |
54 } |
51 } |
55 return result; |
52 return result; |
56 } |
53 } |
57 |
54 |
58 char *flib_join(char **parts, int partCount, const char *delimiter) { |
55 char *flib_join(char **parts, int partCount, const char *delimiter) { |
59 size_t totalSize = 1; |
56 char *result = NULL; |
60 size_t delimLen = strlen(delimiter); |
57 if(!log_badargs_if2(parts==NULL, delimiter==NULL)) { |
61 for(int i=0; i<partCount; i++) { |
58 size_t totalSize = 1; |
62 totalSize += strlen(parts[i]) + delimLen; |
59 size_t delimLen = strlen(delimiter); |
63 } |
|
64 |
|
65 char *result = flib_malloc(totalSize); |
|
66 if(result) { |
|
67 size_t outpos = 0; |
|
68 for(int i=0; i<partCount; i++) { |
60 for(int i=0; i<partCount; i++) { |
69 if(i>0) { |
61 totalSize += strlen(parts[i]) + delimLen; |
70 strcpy(result+outpos, delimiter); |
62 } |
71 outpos += delimLen; |
63 result = flib_malloc(totalSize); |
72 } |
64 |
73 strcpy(result+outpos, parts[i]); |
65 if(result) { |
74 outpos += strlen(parts[i]); |
66 size_t outpos = 0; |
|
67 for(int i=0; i<partCount; i++) { |
|
68 if(i>0) { |
|
69 strcpy(result+outpos, delimiter); |
|
70 outpos += delimLen; |
|
71 } |
|
72 strcpy(result+outpos, parts[i]); |
|
73 outpos += strlen(parts[i]); |
|
74 } |
75 } |
75 } |
76 } |
76 } |
77 return result; |
77 return result; |
78 } |
78 } |
79 |
79 |
80 char *flib_strdupnull(const char *str) { |
80 char *flib_strdupnull(const char *str) { |
81 if(!str) { |
81 return str==NULL ? NULL : flib_asprintf("%s", str); |
82 return NULL; |
|
83 } |
|
84 return flib_asprintf("%s", str); |
|
85 } |
82 } |
86 |
83 |
87 void *flib_bufdupnull(const void *buf, size_t size) { |
84 void *flib_bufdupnull(const void *buf, size_t size) { |
88 if(!buf || size==0) { |
85 void *result = NULL; |
89 return NULL; |
86 if(!log_badargs_if(buf==NULL && size>0)) { |
90 } |
87 result = flib_malloc(size); |
91 void *result = flib_malloc(size); |
88 if(result) { |
92 if(result) { |
89 memcpy(result, buf, size); |
93 memcpy(result, buf, size); |
90 } |
94 } |
91 } |
95 return result; |
92 return result; |
96 } |
93 } |
97 |
94 |
98 void *flib_malloc(size_t size) { |
95 void *flib_malloc(size_t size) { |
125 |
122 |
126 char *flib_urlencode(const char *inbuf) { |
123 char *flib_urlencode(const char *inbuf) { |
127 return flib_urlencode_pred(inbuf, isAsciiAlnum); |
124 return flib_urlencode_pred(inbuf, isAsciiAlnum); |
128 } |
125 } |
129 |
126 |
|
127 static size_t countCharsToEscape(const char *inbuf, bool (*needsEscaping)(char c)) { |
|
128 size_t result = 0; |
|
129 for(const char *c=inbuf; *c; c++) { |
|
130 if(needsEscaping(*c)) { |
|
131 result++; |
|
132 } |
|
133 } |
|
134 return result; |
|
135 } |
|
136 |
130 char *flib_urlencode_pred(const char *inbuf, bool (*needsEscaping)(char c)) { |
137 char *flib_urlencode_pred(const char *inbuf, bool (*needsEscaping)(char c)) { |
|
138 char *result = NULL; |
|
139 if(inbuf && !log_badargs_if(needsEscaping == NULL)) { |
|
140 size_t insize = strlen(inbuf); |
|
141 if(!log_e_if(insize > SIZE_MAX/4, "String too long: %zu bytes.", insize)) { |
|
142 size_t escapeCount = countCharsToEscape(inbuf, needsEscaping); |
|
143 result = flib_malloc(insize + escapeCount*2 + 1); |
|
144 } |
|
145 if(result) { |
|
146 char *out = result; |
|
147 for(const char *in = inbuf; *in; in++) { |
|
148 if(!needsEscaping(*in)) { |
|
149 *out = *in; |
|
150 out++; |
|
151 } else { |
|
152 snprintf(out, 4, "%%%02x", (unsigned)(*(uint8_t*)in)); |
|
153 out += 3; |
|
154 } |
|
155 } |
|
156 *out = 0; |
|
157 } |
|
158 } |
|
159 return result; |
|
160 } |
|
161 |
|
162 char *flib_urldecode(const char *inbuf) { |
131 if(!inbuf) { |
163 if(!inbuf) { |
132 return NULL; |
164 return NULL; |
133 } |
165 } |
134 size_t insize = strlen(inbuf); |
|
135 if(insize > SIZE_MAX/4) { |
|
136 flib_log_e("String too long in flib_urlencode: %zu bytes.", insize); |
|
137 return NULL; |
|
138 } |
|
139 |
|
140 char *outbuf = flib_malloc(insize*3+1); |
|
141 if(!outbuf) { |
|
142 return NULL; |
|
143 } |
|
144 |
|
145 size_t inpos = 0, outpos = 0; |
|
146 while(inbuf[inpos]) { |
|
147 if(!needsEscaping(inbuf[inpos])) { |
|
148 outbuf[outpos++] = inbuf[inpos++]; |
|
149 } else { |
|
150 if(snprintf(outbuf+outpos, 4, "%%%02X", (unsigned)((uint8_t*)inbuf)[inpos])<0) { |
|
151 flib_log_e("printf error in flib_urlencode"); |
|
152 free(outbuf); |
|
153 return NULL; |
|
154 } |
|
155 inpos++; |
|
156 outpos += 3; |
|
157 } |
|
158 } |
|
159 outbuf[outpos] = 0; |
|
160 char *shrunk = realloc(outbuf, outpos+1); |
|
161 return shrunk ? shrunk : outbuf; |
|
162 } |
|
163 |
|
164 char *flib_urldecode(const char *inbuf) { |
|
165 char *outbuf = flib_malloc(strlen(inbuf)+1); |
166 char *outbuf = flib_malloc(strlen(inbuf)+1); |
166 if(!outbuf) { |
167 if(!outbuf) { |
167 return NULL; |
168 return NULL; |
168 } |
169 } |
169 |
170 |
181 char *shrunk = realloc(outbuf, outpos+1); |
182 char *shrunk = realloc(outbuf, outpos+1); |
182 return shrunk ? shrunk : outbuf; |
183 return shrunk ? shrunk : outbuf; |
183 } |
184 } |
184 |
185 |
185 bool flib_contains_dir_separator(const char *str) { |
186 bool flib_contains_dir_separator(const char *str) { |
186 if(!log_badparams_if(!str)) { |
187 if(!log_badargs_if(!str)) { |
187 for(;*str;str++) { |
188 for(;*str;str++) { |
188 if(*str=='\\' || *str=='/') { |
189 if(*str=='\\' || *str=='/') { |
189 return true; |
190 return true; |
190 } |
191 } |
191 } |
192 } |
192 } |
193 } |
193 return false; |
194 return false; |
|
195 } |
|
196 |
|
197 bool flib_strempty(const char *str) { |
|
198 return !str || !*str; |
194 } |
199 } |
195 |
200 |
196 int flib_gets(char *str, size_t strlen) { |
201 int flib_gets(char *str, size_t strlen) { |
197 if(fgets(str, strlen, stdin)) { |
202 if(fgets(str, strlen, stdin)) { |
198 for(char *s=str; *s; s++) { |
203 for(char *s=str; *s; s++) { |