/** * Adds a new element to the hash with a value * * Parameters: * - hash: A valid quickhash * - key: The key * - value: The value * * Returns: * - 1 if the element was added or 0 if the element couldn't be added */ int qhi_hash_add(qhi *hash, qhv key, qhv value) { uint32_t idx; qhl *list; // obtain the hashed key, and the bucket list for the hashed key idx = qhi_set_hash(hash, key); list = &(hash->bucket_list[idx]); // check if we already have the key in the list if requested if (hash->options->check_for_dupes && find_bucket_from_list(hash, list, key, NULL)) { return 0; } return qhi_add_entry_to_list(hash, list, hash_add_key(hash, key), hash_add_value(hash, value)); }
/** * Updates the value belonging to a bucket. * * This function updates the value that belongs to the bucket, by updating it * in the integer store when there is an integer values, or it will *add* a new * value to the store for string values. The function does not clean up holes * in the string store. * * Params: * - hash: the hash the bucket belongs to * - bucket: the bucket itself * - value: the new value * * Returns: * - 1 if the key was of a known type, or 0 otherwise. Only if something is * really wrong, 0 should be returned. */ static int qhi_update_value_in_bucket(qhi *hash, qhb *bucket, qhv value) { switch (hash->value_type) { case QHI_VALUE_TYPE_INT: hash->i.values[bucket->value_idx] = value.i; return 1; case QHI_VALUE_TYPE_STRING: bucket->value_idx = hash_add_value(hash, value); return 1; break; default: /* FAIL */ break; } return 0; }
/** * Adds a new element, or updates the value if the key already is part of the hash * * Parameters: * - hash: A valid quickhash * - key: The key * - value: The value * * Returns: * - 1 if the element is part of the hash and was updated, 2 if the element was * added or 0 if an error occurred. */ int qhi_hash_set(qhi *hash, qhv key, qhv value) { uint32_t idx; qhl *list; qhb *bucket; // obtain the hashed key, and the bucket list for the hashed key idx = qhi_set_hash(hash, key); list = &(hash->bucket_list[idx]); // check if we already have the key in the list if requested if (find_bucket_from_list(hash, list, key, &bucket)) { // update return qhi_update_value_in_bucket(hash, bucket, value); } else { // add return qhi_add_entry_to_list(hash, list, hash_add_key(hash, key), hash_add_value(hash, value)) ? 2 : 0; } return 0; }
/** * Creates a hash from a string containing a serialized hash * * Parameters: * - options: the options to create the hash with. This structure contains at * least the nr of hash buckets, and whether set additions should be checked * for duplicates. See the description of qho for a full list of options. * - context: the context that reader functions can use to store specific data * in (such as a filedescription, or a PHP stream) * - int32t_apply_func: The function to use for reading int32s. * - chars_apply_func: The function to use for reading chars. * * Returns: * - A new hash, or NULL upon failure */ qhi *qhi_obtain_hash(qho *options, void *context, qhi_int32t_read_buffer_apply_func int32t_apply_func, qhi_char_read_buffer_apply_func chars_apply_func) { uint32_t nr_of_elements, elements_read = 0; int32_t key_buffer[1024]; qhi *tmp; // we read the first int32s for the signature and nr of items if (!int32t_apply_func(context, key_buffer, 2)) { return NULL; } if ((key_buffer[0] & 0xffff) != 0x4851) { return NULL; } options->key_type = (key_buffer[0] & 0xf00000) >> 20; options->value_type = (key_buffer[0] & 0x0f0000) >> 16; nr_of_elements = key_buffer[1]; // override the nr of bucket lists if the size is still 0. options->size = qhi_normalize_size(options->size == 0 ? nr_of_elements : options->size); #if DEBUG printf("Picking size: %u\n", options->size); #endif // read the keys if we have QHI_KEY_TYPE_STRING if (options->key_type == QHI_KEY_TYPE_STRING) { int32t_apply_func(context, key_buffer, 2); options->size = key_buffer[1]; #if DEBUG printf("Loading size: %u\n", options->size); #endif // create the hash tmp = qhi_create(options); if (!tmp) { return NULL; } // load the keys tmp->keys.values = tmp->options->memory.malloc(key_buffer[0] + 1); tmp->keys.size = tmp->keys.count = key_buffer[0]; chars_apply_func(context, tmp->keys.values, key_buffer[0]); tmp->keys.values[key_buffer[0]] = '\0'; } else { // create the hash tmp = qhi_create(options); if (!tmp) { return NULL; } } // read the strings if we have QHI_VALUE_TYPE_STRING if (tmp->value_type == QHI_VALUE_TYPE_STRING) { int32t_apply_func(context, key_buffer, 1); tmp->s.values = tmp->options->memory.malloc(key_buffer[0] + 1); tmp->s.size = tmp->s.count = key_buffer[0]; chars_apply_func(context, tmp->s.values, key_buffer[0]); tmp->s.values[key_buffer[0]] = '\0'; } if (tmp->key_type == QHI_KEY_TYPE_STRING) { do { int32_t idx, list_elements; qhl *list; // read hash key, and nr of elements in list int32t_apply_func(context, key_buffer, 2); idx = key_buffer[0]; list_elements = key_buffer[1]; // read the hash elements do { int32t_apply_func(context, key_buffer, 2); list = &(tmp->bucket_list[idx]); qhi_add_entry_to_list(tmp, list, key_buffer[0], hash_add_value(tmp, (qhv) key_buffer[1])); elements_read++; list_elements--; } while (list_elements); } while (elements_read < nr_of_elements); } else { // read the elements (key and value idx) and add them to the hash do { elements_read = int32t_apply_func(context, key_buffer, 1024) / 2; qhi_hash_add_elements_from_buffer(tmp, key_buffer, elements_read * 2); nr_of_elements -= elements_read; } while (elements_read && nr_of_elements); } return tmp; }
int ac_rtld_config::process_map_file(unsigned int fd, hash_node **hashtable) { unsigned int i, num1, num2; char buffer[20]; unsigned int line = 0; buffer[0] = 'a'; while (buffer[0] != '\0') { char* endptr; line++; request_read(fd, buffer, 1); /* Ignore line */ if (buffer[0] == '#') { while (buffer[0] != '\n' && buffer[0] != '\0') request_read(fd, buffer, 1); continue; } /* Skips whitespace */ while (buffer[0] == ' ' || buffer[0] == '\t') request_read(fd, buffer, 1); /* Nothing to parse here, go to next line */ if (buffer[0] == '\n' || buffer[0] == '\0') continue; /** Parse num = num statement **/ /* Not a number */ if (buffer[0] < '0' || buffer[0] > '9') { return ERROR; } i = 0; while (buffer[i] >= '0' && buffer[i] <= '9') { request_read(fd, &buffer[++i], 1); if (i >= 20) { return ERROR; } } /* Unexpected end of line */ if (buffer[i] == '\n' || buffer[i] == '\0') { return ERROR; } endptr = NULL; num1 = strtol(buffer, &endptr, 10); if (endptr != &buffer[i]) { return ERROR; } buffer[0] = buffer[i]; /* Skips whitespace */ while (buffer[0] == ' ' || buffer[0] == '\t') request_read(fd, buffer, 1); /* Unexpected token */ if (buffer[0] != '=') { return ERROR; } request_read(fd, buffer, 1); /* Skips whitespace */ while (buffer[0] == ' ' || buffer[0] == '\t') request_read(fd, buffer, 1); /* Unexpected end of line */ if (buffer[0] == '\n' || buffer[0] == '\0') { return ERROR; } /* Parse the second number at num = num statement */ /* Not a number */ if (buffer[0] < '0' || buffer[0] > '9') { return ERROR; } i = 0; while (buffer[i] >= '0' && buffer[i] <= '9') { request_read(fd, &buffer[++i], 1); if (i >= 20) { return ERROR; } } endptr = NULL; num2 = strtol(buffer, &endptr, 10); if (endptr != &buffer[i]) { return ERROR; } buffer[0] = buffer[i]; if (buffer[0] != '\n' && buffer[0] != '\0') { return ERROR; } if (hash_add_value(hashtable, num1, num2) == ERROR) { return ERROR; } } return FINE; }
int process_map_file(unsigned int fd, hash_node **hashtable, char reverse_mode) { unsigned int i, num1, num2; char buffer[20]; unsigned int line = 0; buffer[0] = 'a'; while (buffer[0] != '\0') { char* endptr; line++; request_read(fd, buffer, 1, FALSE); /* Ignore line */ if (buffer[0] == '#') { while (buffer[0] != '\n' && buffer[0] != '\0') request_read(fd, buffer, 1, FALSE); continue; } /* Skips whitespace */ while (buffer[0] == ' ' || buffer[0] == '\t') request_read(fd, buffer, 1, FALSE); /* Nothing to parse here, go to next line */ if (buffer[0] == '\n' || buffer[0] == '\0') continue; /** Parse num = num statement **/ /* Not a number */ if (buffer[0] < '0' || buffer[0] > '9') { fprintf(stderr, "Error while parsing map file: expecting number = number statement at line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } i = 0; while (buffer[i] >= '0' && buffer[i] <= '9') { request_read(fd, &buffer[++i], 1, FALSE); if (i >= 20) { fprintf(stderr, "Error while parsing map file: number too large at line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } } /* Unexpected end of line */ if (buffer[i] == '\n' || buffer[i] == '\0') { fprintf(stderr, "Error while parsing map file: unexpected end of line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } endptr = NULL; num1 = strtol(buffer, &endptr, 10); if (endptr != &buffer[i]) { fprintf(stderr, "Error while parsing map file: first number of line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } buffer[0] = buffer[i]; /* Skips whitespace */ while (buffer[0] == ' ' || buffer[0] == '\t') request_read(fd, buffer, 1, FALSE); /* Unexpected token */ if (buffer[0] != '=') { fprintf(stderr, "Error while parsing map file: expected token \"=\" at line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } request_read(fd, buffer, 1, FALSE); /* Skips whitespace */ while (buffer[0] == ' ' || buffer[0] == '\t') request_read(fd, buffer, 1, FALSE); /* Unexpected end of line */ if (buffer[0] == '\n' || buffer[0] == '\0') { fprintf(stderr, "Error while parsing map file: unexpected end of line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } /* Parse the second number at num = num statement */ /* Not a number */ if (buffer[0] < '0' || buffer[0] > '9') { fprintf(stderr, "Error while parsing map file: expecting number = number statement at line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } i = 0; while (buffer[i] >= '0' && buffer[i] <= '9') { request_read(fd, &buffer[++i], 1, FALSE); if (i >= 20) { fprintf(stderr, "Error while parsing map file: number too large at line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } } endptr = NULL; num2 = strtol(buffer, &endptr, 10); if (endptr != &buffer[i]) { fprintf(stderr, "Error while parsing map file: second number of line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } buffer[0] = buffer[i]; if (buffer[0] != '\n' && buffer[0] != '\0') { fprintf(stderr, "Error while parsing map file: junk at end of line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } if (!reverse_mode) { if (hash_add_value(hashtable, num1, num2) == ACRELCONVERT_FUNC_ERROR) { fprintf(stderr, "Error while parsing map file: failed to add hash value corresponding to line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } } else /* Reverse map */ { if (hash_add_value(hashtable, num2, num1) == ACRELCONVERT_FUNC_ERROR) { fprintf(stderr, "Error while parsing map file: failed to add hash value corresponding to line %d\n", line); return ACRELCONVERT_FUNC_ERROR; } } } return ACRELCONVERT_FUNC_OK; }