10fad7d023f0229f763a58dd479f78397322baa6dDima Zavin/*
20fad7d023f0229f763a58dd479f78397322baa6dDima Zavin * Copyright (C) 2011 The Android Open Source Project
30fad7d023f0229f763a58dd479f78397322baa6dDima Zavin *
40fad7d023f0229f763a58dd479f78397322baa6dDima Zavin * Licensed under the Apache License, Version 2.0 (the "License");
50fad7d023f0229f763a58dd479f78397322baa6dDima Zavin * you may not use this file except in compliance with the License.
60fad7d023f0229f763a58dd479f78397322baa6dDima Zavin * You may obtain a copy of the License at
70fad7d023f0229f763a58dd479f78397322baa6dDima Zavin *
80fad7d023f0229f763a58dd479f78397322baa6dDima Zavin *      http://www.apache.org/licenses/LICENSE-2.0
90fad7d023f0229f763a58dd479f78397322baa6dDima Zavin *
100fad7d023f0229f763a58dd479f78397322baa6dDima Zavin * Unless required by applicable law or agreed to in writing, software
110fad7d023f0229f763a58dd479f78397322baa6dDima Zavin * distributed under the License is distributed on an "AS IS" BASIS,
120fad7d023f0229f763a58dd479f78397322baa6dDima Zavin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130fad7d023f0229f763a58dd479f78397322baa6dDima Zavin * See the License for the specific language governing permissions and
140fad7d023f0229f763a58dd479f78397322baa6dDima Zavin * limitations under the License.
150fad7d023f0229f763a58dd479f78397322baa6dDima Zavin */
160fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
170fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#define LOG_TAG "str_params"
180fad7d023f0229f763a58dd479f78397322baa6dDima Zavin//#define LOG_NDEBUG 0
190fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
200fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#define _GNU_SOURCE 1
210fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#include <errno.h>
220fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#include <stdint.h>
230fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#include <stdio.h>
240fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#include <stdlib.h>
250fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#include <string.h>
260fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
270fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#include <cutils/hashmap.h>
280fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#include <cutils/log.h>
290fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#include <cutils/memory.h>
300fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
310fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#include <cutils/str_parms.h>
320fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
330fad7d023f0229f763a58dd479f78397322baa6dDima Zavinstruct str_parms {
340fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    Hashmap *map;
350fad7d023f0229f763a58dd479f78397322baa6dDima Zavin};
360fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
370fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
380fad7d023f0229f763a58dd479f78397322baa6dDima Zavinstatic bool str_eq(void *key_a, void *key_b)
390fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
400fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return !strcmp((const char *)key_a, (const char *)key_b);
410fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
420fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
430fad7d023f0229f763a58dd479f78397322baa6dDima Zavin/* use djb hash unless we find it inadequate */
440fad7d023f0229f763a58dd479f78397322baa6dDima Zavinstatic int str_hash_fn(void *str)
450fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
460fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    uint32_t hash = 5381;
470fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *p;
480fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
490fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    for (p = str; p && *p; p++)
500fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        hash = ((hash << 5) + hash) + *p;
510fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return (int)hash;
520fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
530fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
540fad7d023f0229f763a58dd479f78397322baa6dDima Zavinstruct str_parms *str_parms_create(void)
550fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
560fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    struct str_parms *str_parms;
570fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
580fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    str_parms = calloc(1, sizeof(struct str_parms));
590fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (!str_parms)
600fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return NULL;
610fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
620fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    str_parms->map = hashmapCreate(5, str_hash_fn, str_eq);
630fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (!str_parms->map)
640fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        goto err;
650fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
660fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return str_parms;
670fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
680fad7d023f0229f763a58dd479f78397322baa6dDima Zavinerr:
690fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    free(str_parms);
700fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return NULL;
710fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
720fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
73efd7501d535fb165792013763027cf50a5b37e08Dima Zavinstruct remove_ctxt {
74efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    struct str_parms *str_parms;
75efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    const char *key;
76efd7501d535fb165792013763027cf50a5b37e08Dima Zavin};
77efd7501d535fb165792013763027cf50a5b37e08Dima Zavin
780fad7d023f0229f763a58dd479f78397322baa6dDima Zavinstatic bool remove_pair(void *key, void *value, void *context)
790fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
80efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    struct remove_ctxt *ctxt = context;
81efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    bool should_continue;
82efd7501d535fb165792013763027cf50a5b37e08Dima Zavin
83efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    /*
84efd7501d535fb165792013763027cf50a5b37e08Dima Zavin     * - if key is not supplied, then we are removing all entries,
85efd7501d535fb165792013763027cf50a5b37e08Dima Zavin     *   so remove key and continue (i.e. return true)
86efd7501d535fb165792013763027cf50a5b37e08Dima Zavin     * - if key is supplied and matches, then remove it and don't
87efd7501d535fb165792013763027cf50a5b37e08Dima Zavin     *   continue (return false). Otherwise, return true and keep searching
88efd7501d535fb165792013763027cf50a5b37e08Dima Zavin     *   for key.
89efd7501d535fb165792013763027cf50a5b37e08Dima Zavin     *
90efd7501d535fb165792013763027cf50a5b37e08Dima Zavin     */
91efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    if (!ctxt->key) {
92efd7501d535fb165792013763027cf50a5b37e08Dima Zavin        should_continue = true;
93efd7501d535fb165792013763027cf50a5b37e08Dima Zavin        goto do_remove;
94efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    } else if (!strcmp(ctxt->key, key)) {
95efd7501d535fb165792013763027cf50a5b37e08Dima Zavin        should_continue = false;
96efd7501d535fb165792013763027cf50a5b37e08Dima Zavin        goto do_remove;
97efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    }
980fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
99efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    return true;
100efd7501d535fb165792013763027cf50a5b37e08Dima Zavin
101efd7501d535fb165792013763027cf50a5b37e08Dima Zavindo_remove:
102efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    hashmapRemove(ctxt->str_parms->map, key);
1030fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    free(key);
1040fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    free(value);
105efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    return should_continue;
106efd7501d535fb165792013763027cf50a5b37e08Dima Zavin}
107efd7501d535fb165792013763027cf50a5b37e08Dima Zavin
108efd7501d535fb165792013763027cf50a5b37e08Dima Zavinvoid str_parms_del(struct str_parms *str_parms, const char *key)
109efd7501d535fb165792013763027cf50a5b37e08Dima Zavin{
110efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    struct remove_ctxt ctxt = {
111efd7501d535fb165792013763027cf50a5b37e08Dima Zavin        .str_parms = str_parms,
112efd7501d535fb165792013763027cf50a5b37e08Dima Zavin        .key = key,
113efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    };
114efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    hashmapForEach(str_parms->map, remove_pair, &ctxt);
1150fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
1160fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1170fad7d023f0229f763a58dd479f78397322baa6dDima Zavinvoid str_parms_destroy(struct str_parms *str_parms)
1180fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
119efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    struct remove_ctxt ctxt = {
120efd7501d535fb165792013763027cf50a5b37e08Dima Zavin        .str_parms = str_parms,
121efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    };
122efd7501d535fb165792013763027cf50a5b37e08Dima Zavin
123efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    hashmapForEach(str_parms->map, remove_pair, &ctxt);
1240fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    hashmapFree(str_parms->map);
1250fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    free(str_parms);
1260fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
1270fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1280fad7d023f0229f763a58dd479f78397322baa6dDima Zavinstruct str_parms *str_parms_create_str(const char *_string)
1290fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
1300fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    struct str_parms *str_parms;
1310fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *str;
1320fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *kvpair;
1330fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *tmpstr;
1340fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    int items = 0;
1350fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1360fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    str_parms = str_parms_create();
1370fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (!str_parms)
1380fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        goto err_create_str_parms;
1390fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1400fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    str = strdup(_string);
1410fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (!str)
1420fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        goto err_strdup;
1430fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
14469f4cd7f5add7a7c7f5915e5292aab7eb2a42e9fSteve Block    ALOGV("%s: source string == '%s'\n", __func__, _string);
1450fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1460fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    kvpair = strtok_r(str, ";", &tmpstr);
1470fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    while (kvpair && *kvpair) {
1480fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        char *eq = strchr(kvpair, '='); /* would love strchrnul */
1490fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        char *value;
1500fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        char *key;
1510fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        void *old_val;
1520fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1530fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        if (eq == kvpair)
1540fad7d023f0229f763a58dd479f78397322baa6dDima Zavin            goto next_pair;
1550fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1560fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        if (eq) {
1570fad7d023f0229f763a58dd479f78397322baa6dDima Zavin            key = strndup(kvpair, eq - kvpair);
1580fad7d023f0229f763a58dd479f78397322baa6dDima Zavin            if (*(++eq))
1590fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                value = strdup(eq);
1600fad7d023f0229f763a58dd479f78397322baa6dDima Zavin            else
1610fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                value = strdup("");
1620fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        } else {
1630fad7d023f0229f763a58dd479f78397322baa6dDima Zavin            key = strdup(kvpair);
1640fad7d023f0229f763a58dd479f78397322baa6dDima Zavin            value = strdup("");
1650fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        }
1660fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1670fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        /* if we replaced a value, free it */
1680fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        old_val = hashmapPut(str_parms->map, key, value);
16986bfbe3cae1f5e480ba9756ec7404fa4d5a7f2c9Dima Zavin        if (old_val) {
1700fad7d023f0229f763a58dd479f78397322baa6dDima Zavin            free(old_val);
17186bfbe3cae1f5e480ba9756ec7404fa4d5a7f2c9Dima Zavin            free(key);
17286bfbe3cae1f5e480ba9756ec7404fa4d5a7f2c9Dima Zavin        }
1730fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1740fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        items++;
1750fad7d023f0229f763a58dd479f78397322baa6dDima Zavinnext_pair:
1760fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        kvpair = strtok_r(NULL, ";", &tmpstr);
1770fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    }
1780fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1790fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (!items)
18069f4cd7f5add7a7c7f5915e5292aab7eb2a42e9fSteve Block        ALOGV("%s: no items found in string\n", __func__);
1810fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1820fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    free(str);
1830fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1840fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return str_parms;
1850fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1860fad7d023f0229f763a58dd479f78397322baa6dDima Zavinerr_strdup:
1870fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    str_parms_destroy(str_parms);
1880fad7d023f0229f763a58dd479f78397322baa6dDima Zavinerr_create_str_parms:
1890fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return NULL;
1900fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
1910fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
1920fad7d023f0229f763a58dd479f78397322baa6dDima Zavinint str_parms_add_str(struct str_parms *str_parms, const char *key,
1930fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                      const char *value)
1940fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
1950fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    void *old_val;
19670b93034f3ce06404e9b042c80759da25dac99d8Dima Zavin    void *tmp_key;
19770b93034f3ce06404e9b042c80759da25dac99d8Dima Zavin    void *tmp_val;
1980fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
19970b93034f3ce06404e9b042c80759da25dac99d8Dima Zavin    tmp_key = strdup(key);
20070b93034f3ce06404e9b042c80759da25dac99d8Dima Zavin    tmp_val = strdup(value);
20170b93034f3ce06404e9b042c80759da25dac99d8Dima Zavin    old_val = hashmapPut(str_parms->map, tmp_key, tmp_val);
2020fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2030fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (old_val) {
2040fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        free(old_val);
20586bfbe3cae1f5e480ba9756ec7404fa4d5a7f2c9Dima Zavin        free(tmp_key);
2060fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    } else if (errno == ENOMEM) {
20770b93034f3ce06404e9b042c80759da25dac99d8Dima Zavin        free(tmp_key);
20870b93034f3ce06404e9b042c80759da25dac99d8Dima Zavin        free(tmp_val);
2090fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return -ENOMEM;
2100fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    }
2110fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return 0;
2120fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
2130fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2140fad7d023f0229f763a58dd479f78397322baa6dDima Zavinint str_parms_add_int(struct str_parms *str_parms, const char *key, int value)
2150fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
2160fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char val_str[12];
2170fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    int ret;
2180fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2190fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    ret = snprintf(val_str, sizeof(val_str), "%d", value);
2200fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (ret < 0)
2210fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return -EINVAL;
2220fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2230fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    ret = str_parms_add_str(str_parms, key, val_str);
2240fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return ret;
2250fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
2260fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2270fad7d023f0229f763a58dd479f78397322baa6dDima Zavinint str_parms_add_float(struct str_parms *str_parms, const char *key,
2280fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                        float value)
2290fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
2300fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char val_str[23];
2310fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    int ret;
2320fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2330fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    ret = snprintf(val_str, sizeof(val_str), "%.10f", value);
2340fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (ret < 0)
2350fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return -EINVAL;
2360fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2370fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    ret = str_parms_add_str(str_parms, key, val_str);
2380fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return ret;
2390fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
2400fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2410fad7d023f0229f763a58dd479f78397322baa6dDima Zavinint str_parms_get_str(struct str_parms *str_parms, const char *key, char *val,
2420fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                      int len)
2430fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
2440fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *value;
2450fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2460fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    value = hashmapGet(str_parms->map, (void *)key);
2470fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (value)
2480fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return strlcpy(val, value, len);
2490fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2500fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return -ENOENT;
2510fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
2520fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2530fad7d023f0229f763a58dd479f78397322baa6dDima Zavinint str_parms_get_int(struct str_parms *str_parms, const char *key, int *val)
2540fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
2550fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *value;
2560fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *end;
2570fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2580fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    value = hashmapGet(str_parms->map, (void *)key);
2590fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (!value)
2600fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return -ENOENT;
2610fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2620fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    *val = (int)strtol(value, &end, 0);
2630fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (*value != '\0' && *end == '\0')
2640fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return 0;
2650fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2660fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return -EINVAL;
2670fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
2680fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2690fad7d023f0229f763a58dd479f78397322baa6dDima Zavinint str_parms_get_float(struct str_parms *str_parms, const char *key,
2700fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                        float *val)
2710fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
2720fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    float out;
2730fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *value;
2740fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *end;
2750fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2760fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    value = hashmapGet(str_parms->map, (void *)key);
2770fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (!value)
2780fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return -ENOENT;
2790fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2800fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    out = strtof(value, &end);
2810fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (*value != '\0' && *end == '\0')
2820fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return 0;
2830fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2840fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return -EINVAL;
2850fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
2860fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2870fad7d023f0229f763a58dd479f78397322baa6dDima Zavinstatic bool combine_strings(void *key, void *value, void *context)
2880fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
2890fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char **old_str = context;
2900fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *new_str;
2910fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    int ret;
2920fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
2930fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    ret = asprintf(&new_str, "%s%s%s=%s",
2940fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                   *old_str ? *old_str : "",
2950fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                   *old_str ? ";" : "",
2960fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                   (char *)key,
2970fad7d023f0229f763a58dd479f78397322baa6dDima Zavin                   (char *)value);
2980fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (*old_str)
2990fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        free(*old_str);
3000fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3010fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (ret >= 0) {
3020fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        *old_str = new_str;
3030fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        return true;
3040fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    }
3050fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3060fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    *old_str = NULL;
3070fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return false;
3080fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
3090fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3100fad7d023f0229f763a58dd479f78397322baa6dDima Zavinchar *str_parms_to_str(struct str_parms *str_parms)
3110fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
3120fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *str = NULL;
3130fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3140fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    if (hashmapSize(str_parms->map) > 0)
3150fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        hashmapForEach(str_parms->map, combine_strings, &str);
3160fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    else
3170fad7d023f0229f763a58dd479f78397322baa6dDima Zavin        str = strdup("");
3180fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return str;
3190fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
3200fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3210fad7d023f0229f763a58dd479f78397322baa6dDima Zavinstatic bool dump_entry(void *key, void *value, void *context)
3220fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
323fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block    ALOGI("key: '%s' value: '%s'\n", (char *)key, (char *)value);
3240fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return true;
3250fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
3260fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3270fad7d023f0229f763a58dd479f78397322baa6dDima Zavinvoid str_parms_dump(struct str_parms *str_parms)
3280fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
3290fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    hashmapForEach(str_parms->map, dump_entry, str_parms);
3300fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
3310fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3320fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#ifdef TEST_STR_PARMS
3330fad7d023f0229f763a58dd479f78397322baa6dDima Zavinstatic void test_str_parms_str(const char *str)
3340fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
3350fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    struct str_parms *str_parms;
3360fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    char *out_str;
3370fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    int ret;
3380fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3390fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    str_parms = str_parms_create_str(str);
340a603e40f9efa0239ea18c9e98a0ae0f437c057f1Dima Zavin    str_parms_add_str(str_parms, "dude", "woah");
341efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    str_parms_add_str(str_parms, "dude", "woah");
342efd7501d535fb165792013763027cf50a5b37e08Dima Zavin    str_parms_del(str_parms, "dude");
3430fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    str_parms_dump(str_parms);
3440fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    out_str = str_parms_to_str(str_parms);
3450fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    str_parms_destroy(str_parms);
346fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block    ALOGI("%s: '%s' stringified is '%s'", __func__, str, out_str);
3470fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    free(out_str);
3480fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
3490fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3500fad7d023f0229f763a58dd479f78397322baa6dDima Zavinint main(void)
3510fad7d023f0229f763a58dd479f78397322baa6dDima Zavin{
3520fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    struct str_parms *str_parms;
3530fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3540fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("");
3550fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str(";");
3560fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("=");
3570fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("=;");
3580fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("=bar");
3590fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("=bar;");
3600fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("foo=");
3610fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("foo=;");
3620fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("foo=bar");
3630fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("foo=bar;");
3640fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("foo=bar;baz");
3650fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("foo=bar;baz=");
3660fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("foo=bar;baz=bat");
3670fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    test_str_parms_str("foo=bar;baz=bat;");
36886bfbe3cae1f5e480ba9756ec7404fa4d5a7f2c9Dima Zavin    test_str_parms_str("foo=bar;baz=bat;foo=bar");
3690fad7d023f0229f763a58dd479f78397322baa6dDima Zavin
3700fad7d023f0229f763a58dd479f78397322baa6dDima Zavin    return 0;
3710fad7d023f0229f763a58dd479f78397322baa6dDima Zavin}
3720fad7d023f0229f763a58dd479f78397322baa6dDima Zavin#endif
373