123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "ufdt_prop_dict.h"
- #include "libfdt.h"
- #include "libufdt_sysdeps.h"
- #define UFDT_PROP_DICT_INIT_SZ 4
- /* Empirical values for hash functions. */
- #define HASH_BASE 13131
- #define DICT_LIMIT_NUM 2
- #define DICT_LIMIT_DEN 3
- static int _ufdt_prop_dict_str_hash(const char *str) {
- int res = 0;
- for (; *str != '\0'; str++) {
- res *= HASH_BASE;
- res += *str;
- }
- return res;
- }
- static const struct fdt_property **_ufdt_prop_dict_find_index_by_name(
- const struct ufdt_prop_dict *dict, const char *name) {
- /* size should be 2^k for some k */
- int hash = _ufdt_prop_dict_str_hash(name);
- int size = dict->mem_size;
- int idx = hash & (size - 1);
- /* If collision, use linear probing to find idx in the hash table */
- for (int i = 0; i < size; i++) {
- const struct fdt_property **prop_ptr = &dict->props[idx];
- const struct fdt_property *prop = *prop_ptr;
- if (prop == NULL) return prop_ptr;
- const char *prop_name = fdt_string(dict->fdtp, fdt32_to_cpu(prop->nameoff));
- if (dto_strcmp(prop_name, name) == 0) return prop_ptr;
- idx = (idx + 1) & (size - 1);
- }
- return NULL;
- }
- static const struct fdt_property **_ufdt_prop_dict_find_index(
- struct ufdt_prop_dict *dict, const struct fdt_property *prop) {
- const char *name = fdt_string(dict->fdtp, fdt32_to_cpu(prop->nameoff));
- return _ufdt_prop_dict_find_index_by_name(dict, name);
- }
- int _ufdt_prop_dict_construct_int(struct ufdt_prop_dict *dict, void *fdtp,
- int size) {
- const size_t entry_size = sizeof(const struct fdt_property *);
- const struct fdt_property **props =
- (const struct fdt_property **)dto_malloc(size * entry_size);
- if (props == NULL) return -1;
- dto_memset(props, 0, size * entry_size);
- dict->mem_size = size;
- dict->num_used = 0;
- dict->fdtp = fdtp;
- dict->props = props;
- return 0;
- }
- int ufdt_prop_dict_construct(struct ufdt_prop_dict *dict, void *fdtp) {
- return _ufdt_prop_dict_construct_int(dict, fdtp, UFDT_PROP_DICT_INIT_SZ);
- }
- void ufdt_prop_dict_destruct(struct ufdt_prop_dict *dict) {
- if (dict == NULL) return;
- dto_free(dict->props);
- }
- static int _ufdt_prop_dict_enlarge_if_needed(struct ufdt_prop_dict *dict) {
- if (dict == NULL) return -1;
- /* Enlarge if the used number over than DICT_LIMIT_NUM / DICT_LIMIT_DEN */
- if (dict->num_used * DICT_LIMIT_DEN <= dict->mem_size * DICT_LIMIT_NUM) {
- return 0;
- }
- int new_size = dict->mem_size * 2;
- struct ufdt_prop_dict temp_dict;
- _ufdt_prop_dict_construct_int(&temp_dict, dict->fdtp, new_size);
- for (int i = 0; i < dict->mem_size; i++) {
- const struct fdt_property *prop = dict->props[i];
- if (prop == NULL) continue;
- const struct fdt_property **new_prop_ptr =
- _ufdt_prop_dict_find_index(&temp_dict, prop);
- if (new_prop_ptr == NULL) {
- dto_error("ufdt_prop_dict: failed to find new index when enlarging.\n");
- ufdt_prop_dict_destruct(&temp_dict);
- return -1;
- }
- *new_prop_ptr = prop;
- }
- dto_free(dict->props);
- dict->mem_size = new_size;
- dict->props = temp_dict.props;
- return 0;
- }
- int ufdt_prop_dict_add(struct ufdt_prop_dict *dict,
- const struct fdt_property *prop) {
- const struct fdt_property **prop_ptr = _ufdt_prop_dict_find_index(dict, prop);
- if (prop_ptr == NULL) {
- dto_error("ufdt_prop_dict: failed to find new index when adding.\n");
- return -1;
- }
- if (*prop_ptr == NULL) dict->num_used++;
- *prop_ptr = prop;
- return _ufdt_prop_dict_enlarge_if_needed(dict);
- }
- const struct fdt_property *ufdt_prop_dict_find(const struct ufdt_prop_dict *dict,
- const char *name) {
- const struct fdt_property **prop_ptr =
- _ufdt_prop_dict_find_index_by_name(dict, name);
- return prop_ptr ? *prop_ptr : NULL;
- }
|