system/corennnnn
Revisão | 14c2823a631b444687b9d26b7baf4c864091c07b (tree) |
---|---|
Hora | 2011-06-19 03:56:48 |
Autor | Jean-Baptiste Queru <jbq@goog...> |
Commiter | Android Code Review |
Merge "add strutils"
@@ -46,7 +46,8 @@ commonSources := \ | ||
46 | 46 | properties.c \ |
47 | 47 | threads.c \ |
48 | 48 | sched_policy.c \ |
49 | - iosched_policy.c | |
49 | + iosched_policy.c \ | |
50 | + str_parms.c | |
50 | 51 | |
51 | 52 | commonHostSources := \ |
52 | 53 | ashmem-host.c |
@@ -0,0 +1,329 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2011 The Android Open Source Project | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | + | |
17 | +#define LOG_TAG "str_params" | |
18 | +//#define LOG_NDEBUG 0 | |
19 | + | |
20 | +#define _GNU_SOURCE 1 | |
21 | +#include <errno.h> | |
22 | +#include <stdint.h> | |
23 | +#include <stdio.h> | |
24 | +#include <stdlib.h> | |
25 | +#include <string.h> | |
26 | + | |
27 | +#include <cutils/hashmap.h> | |
28 | +#include <cutils/log.h> | |
29 | +#include <cutils/memory.h> | |
30 | + | |
31 | +#include <cutils/str_parms.h> | |
32 | + | |
33 | +struct str_parms { | |
34 | + Hashmap *map; | |
35 | +}; | |
36 | + | |
37 | + | |
38 | +static bool str_eq(void *key_a, void *key_b) | |
39 | +{ | |
40 | + return !strcmp((const char *)key_a, (const char *)key_b); | |
41 | +} | |
42 | + | |
43 | +/* use djb hash unless we find it inadequate */ | |
44 | +static int str_hash_fn(void *str) | |
45 | +{ | |
46 | + uint32_t hash = 5381; | |
47 | + char *p; | |
48 | + | |
49 | + for (p = str; p && *p; p++) | |
50 | + hash = ((hash << 5) + hash) + *p; | |
51 | + return (int)hash; | |
52 | +} | |
53 | + | |
54 | +struct str_parms *str_parms_create(void) | |
55 | +{ | |
56 | + struct str_parms *str_parms; | |
57 | + | |
58 | + str_parms = calloc(1, sizeof(struct str_parms)); | |
59 | + if (!str_parms) | |
60 | + return NULL; | |
61 | + | |
62 | + str_parms->map = hashmapCreate(5, str_hash_fn, str_eq); | |
63 | + if (!str_parms->map) | |
64 | + goto err; | |
65 | + | |
66 | + return str_parms; | |
67 | + | |
68 | +err: | |
69 | + free(str_parms); | |
70 | + return NULL; | |
71 | +} | |
72 | + | |
73 | +static bool remove_pair(void *key, void *value, void *context) | |
74 | +{ | |
75 | + struct str_parms *str_parms = context; | |
76 | + | |
77 | + hashmapRemove(str_parms->map, key); | |
78 | + free(key); | |
79 | + free(value); | |
80 | + return true; | |
81 | +} | |
82 | + | |
83 | +void str_parms_destroy(struct str_parms *str_parms) | |
84 | +{ | |
85 | + hashmapForEach(str_parms->map, remove_pair, str_parms); | |
86 | + hashmapFree(str_parms->map); | |
87 | + free(str_parms); | |
88 | +} | |
89 | + | |
90 | +struct str_parms *str_parms_create_str(const char *_string) | |
91 | +{ | |
92 | + struct str_parms *str_parms; | |
93 | + char *str; | |
94 | + char *kvpair; | |
95 | + char *tmpstr; | |
96 | + int items = 0; | |
97 | + | |
98 | + str_parms = str_parms_create(); | |
99 | + if (!str_parms) | |
100 | + goto err_create_str_parms; | |
101 | + | |
102 | + str = strdup(_string); | |
103 | + if (!str) | |
104 | + goto err_strdup; | |
105 | + | |
106 | + LOGV("%s: source string == '%s'\n", __func__, _string); | |
107 | + | |
108 | + kvpair = strtok_r(str, ";", &tmpstr); | |
109 | + while (kvpair && *kvpair) { | |
110 | + char *eq = strchr(kvpair, '='); /* would love strchrnul */ | |
111 | + char *value; | |
112 | + char *key; | |
113 | + void *old_val; | |
114 | + | |
115 | + if (eq == kvpair) | |
116 | + goto next_pair; | |
117 | + | |
118 | + if (eq) { | |
119 | + key = strndup(kvpair, eq - kvpair); | |
120 | + if (*(++eq)) | |
121 | + value = strdup(eq); | |
122 | + else | |
123 | + value = strdup(""); | |
124 | + } else { | |
125 | + key = strdup(kvpair); | |
126 | + value = strdup(""); | |
127 | + } | |
128 | + | |
129 | + /* if we replaced a value, free it */ | |
130 | + old_val = hashmapPut(str_parms->map, key, value); | |
131 | + if (old_val) | |
132 | + free(old_val); | |
133 | + | |
134 | + items++; | |
135 | +next_pair: | |
136 | + kvpair = strtok_r(NULL, ";", &tmpstr); | |
137 | + } | |
138 | + | |
139 | + if (!items) | |
140 | + LOGV("%s: no items found in string\n", __func__); | |
141 | + | |
142 | + free(str); | |
143 | + | |
144 | + return str_parms; | |
145 | + | |
146 | +err_strdup: | |
147 | + str_parms_destroy(str_parms); | |
148 | +err_create_str_parms: | |
149 | + return NULL; | |
150 | +} | |
151 | + | |
152 | +void str_parms_del(struct str_parms *str_parms, const char *key) | |
153 | +{ | |
154 | + hashmapRemove(str_parms->map, (void *)key); | |
155 | +} | |
156 | + | |
157 | +int str_parms_add_str(struct str_parms *str_parms, const char *key, | |
158 | + const char *value) | |
159 | +{ | |
160 | + void *old_val; | |
161 | + char *tmp; | |
162 | + | |
163 | + tmp = strdup(value); | |
164 | + old_val = hashmapPut(str_parms->map, (void *)key, tmp); | |
165 | + | |
166 | + if (old_val) { | |
167 | + free(old_val); | |
168 | + } else if (errno == ENOMEM) { | |
169 | + free(tmp); | |
170 | + return -ENOMEM; | |
171 | + } | |
172 | + return 0; | |
173 | +} | |
174 | + | |
175 | +int str_parms_add_int(struct str_parms *str_parms, const char *key, int value) | |
176 | +{ | |
177 | + char val_str[12]; | |
178 | + int ret; | |
179 | + | |
180 | + ret = snprintf(val_str, sizeof(val_str), "%d", value); | |
181 | + if (ret < 0) | |
182 | + return -EINVAL; | |
183 | + | |
184 | + ret = str_parms_add_str(str_parms, key, val_str); | |
185 | + return ret; | |
186 | +} | |
187 | + | |
188 | +int str_parms_add_float(struct str_parms *str_parms, const char *key, | |
189 | + float value) | |
190 | +{ | |
191 | + char val_str[23]; | |
192 | + int ret; | |
193 | + | |
194 | + ret = snprintf(val_str, sizeof(val_str), "%.10f", value); | |
195 | + if (ret < 0) | |
196 | + return -EINVAL; | |
197 | + | |
198 | + ret = str_parms_add_str(str_parms, key, val_str); | |
199 | + return ret; | |
200 | +} | |
201 | + | |
202 | +int str_parms_get_str(struct str_parms *str_parms, const char *key, char *val, | |
203 | + int len) | |
204 | +{ | |
205 | + char *value; | |
206 | + | |
207 | + value = hashmapGet(str_parms->map, (void *)key); | |
208 | + if (value) | |
209 | + return strlcpy(val, value, len); | |
210 | + | |
211 | + return -ENOENT; | |
212 | +} | |
213 | + | |
214 | +int str_parms_get_int(struct str_parms *str_parms, const char *key, int *val) | |
215 | +{ | |
216 | + char *value; | |
217 | + char *end; | |
218 | + | |
219 | + value = hashmapGet(str_parms->map, (void *)key); | |
220 | + if (!value) | |
221 | + return -ENOENT; | |
222 | + | |
223 | + *val = (int)strtol(value, &end, 0); | |
224 | + if (*value != '\0' && *end == '\0') | |
225 | + return 0; | |
226 | + | |
227 | + return -EINVAL; | |
228 | +} | |
229 | + | |
230 | +int str_parms_get_float(struct str_parms *str_parms, const char *key, | |
231 | + float *val) | |
232 | +{ | |
233 | + float out; | |
234 | + char *value; | |
235 | + char *end; | |
236 | + | |
237 | + value = hashmapGet(str_parms->map, (void *)key); | |
238 | + if (!value) | |
239 | + return -ENOENT; | |
240 | + | |
241 | + out = strtof(value, &end); | |
242 | + if (*value != '\0' && *end == '\0') | |
243 | + return 0; | |
244 | + | |
245 | + return -EINVAL; | |
246 | +} | |
247 | + | |
248 | +static bool combine_strings(void *key, void *value, void *context) | |
249 | +{ | |
250 | + char **old_str = context; | |
251 | + char *new_str; | |
252 | + int ret; | |
253 | + | |
254 | + ret = asprintf(&new_str, "%s%s%s=%s", | |
255 | + *old_str ? *old_str : "", | |
256 | + *old_str ? ";" : "", | |
257 | + (char *)key, | |
258 | + (char *)value); | |
259 | + if (*old_str) | |
260 | + free(*old_str); | |
261 | + | |
262 | + if (ret >= 0) { | |
263 | + *old_str = new_str; | |
264 | + return true; | |
265 | + } | |
266 | + | |
267 | + *old_str = NULL; | |
268 | + return false; | |
269 | +} | |
270 | + | |
271 | +char *str_parms_to_str(struct str_parms *str_parms) | |
272 | +{ | |
273 | + char *str = NULL; | |
274 | + | |
275 | + if (hashmapSize(str_parms->map) > 0) | |
276 | + hashmapForEach(str_parms->map, combine_strings, &str); | |
277 | + else | |
278 | + str = strdup(""); | |
279 | + return str; | |
280 | +} | |
281 | + | |
282 | +static bool dump_entry(void *key, void *value, void *context) | |
283 | +{ | |
284 | + LOGI("key: '%s' value: '%s'\n", (char *)key, (char *)value); | |
285 | + return true; | |
286 | +} | |
287 | + | |
288 | +void str_parms_dump(struct str_parms *str_parms) | |
289 | +{ | |
290 | + hashmapForEach(str_parms->map, dump_entry, str_parms); | |
291 | +} | |
292 | + | |
293 | +#ifdef TEST_STR_PARMS | |
294 | +static void test_str_parms_str(const char *str) | |
295 | +{ | |
296 | + struct str_parms *str_parms; | |
297 | + char *out_str; | |
298 | + int ret; | |
299 | + | |
300 | + str_parms = str_parms_create_str(str); | |
301 | + str_parms_dump(str_parms); | |
302 | + out_str = str_parms_to_str(str_parms); | |
303 | + str_parms_destroy(str_parms); | |
304 | + LOGI("%s: '%s' stringified is '%s'", __func__, str, out_str); | |
305 | + free(out_str); | |
306 | +} | |
307 | + | |
308 | +int main(void) | |
309 | +{ | |
310 | + struct str_parms *str_parms; | |
311 | + | |
312 | + test_str_parms_str(""); | |
313 | + test_str_parms_str(";"); | |
314 | + test_str_parms_str("="); | |
315 | + test_str_parms_str("=;"); | |
316 | + test_str_parms_str("=bar"); | |
317 | + test_str_parms_str("=bar;"); | |
318 | + test_str_parms_str("foo="); | |
319 | + test_str_parms_str("foo=;"); | |
320 | + test_str_parms_str("foo=bar"); | |
321 | + test_str_parms_str("foo=bar;"); | |
322 | + test_str_parms_str("foo=bar;baz"); | |
323 | + test_str_parms_str("foo=bar;baz="); | |
324 | + test_str_parms_str("foo=bar;baz=bat"); | |
325 | + test_str_parms_str("foo=bar;baz=bat;"); | |
326 | + | |
327 | + return 0; | |
328 | +} | |
329 | +#endif |