/** * qhasharr->remove_by_idx(): Remove an object from this table by index number. * * @param tbl qhasharr_t container pointer. * @param idx slot index number * * @return true if successful, otherwise(not found) returns false * @retval errno will be set in error condition. * - ENOENT : Index is not pointing a valid object. * - EINVAL : Invald argument. * - EFAULT : Unexpected error. Data structure is not constant. * * @code * int idx = 0; * qhasharr_obj_t obj; * while(tbl->getnext(tbl, &obj, &idx) == true) { * if (condition_to_remove) { * idx--; // adjust index by -1 * remove_by_idx(idx); * } * free(obj.name); * free(obj.data); * } * @endcode * * @note * This function is to remove an object in getnext() traversal loop without * knowing the object name but index value. When key names are longer than * defined size, the keys are stored with truncation with their fingerprint, * so this method provides a way to remove those keys. * getnext() returns actual index + 1(pointing next slot of current finding), * so you need to adjust it by -1 for the valid index number. And once you * remove object by this method, rewind idx by -1 before calling getnext() * because collision objects can be moved back to removed index again, so * by adjusting index by -1, getnext() can continue search from the removed * slot index again. Please refer an example code. */ bool qhasharr_remove_by_idx(qhasharr_t *tbl, int idx) { if (idx < 0) { errno = EINVAL; return false; } qhasharr_data_t *tbldata = tbl->data; qhasharr_slot_t *tblslots = get_slots(tbl); if (tblslots[idx].count == 1) { // just remove remove_data(tbl, idx); } else if (tblslots[idx].count > 1) { // leading slot and has collision // find the collision key int idx2; for (idx2 = idx + 1;; idx2++) { if (idx2 >= tbldata->maxslots) idx2 = 0; if (idx2 == idx) { errno = EFAULT; return false; } if (tblslots[idx2].count == COLLISION_MARK && tblslots[idx2].hash == tblslots[idx].hash) { break; } } // move to leading slot int backupcount = tblslots[idx].count; remove_data(tbl, idx); // remove leading data copy_slot(tbl, idx, idx2); // copy slot remove_slot(tbl, idx2); // remove moved slot tblslots[idx].count = backupcount - 1; // adjust collision counter if (tblslots[idx].link != -1) { tblslots[tblslots[idx].link].hash = idx; } } else if (tblslots[idx].count == COLLISION_MARK) { // collision key // decrease counter from leading slot if (tblslots[tblslots[idx].hash].count <= 1) { errno = EFAULT; return false; } tblslots[tblslots[idx].hash].count--; // remove data remove_data(tbl, idx); } else { errno = ENOENT; return false; } return true; }
int main(void) { struct linked_list l = { .head = NULL }; append(&l, 4.5); append(&l, 2.5); append(&l, 6); remove_data(&l, 2.5); append(&l, 4.5); append(&l, 9); remove_data(&l, 4.5); print(&l); free_list(&l); return 0; }
/* * The last few bytes of the image look like the following: * * \0version\0vendore_name\0product_namechksum * the chksum is 16bits wide, and the version is no more than 20bytes. * * version is w.x.y[nz], where n is ubpi, and w, x, y and z are 1 or 2 digit * numbers. * */ int check_vendor(char *vendorName, char *productName, char *version) { struct fileblock_t *currBlock; int versionInfo; char *cp; char imageVendorName[MAX_VENDOR_SIZE]; char imageProductName[MAX_PRODUCT_SIZE]; char imageVersion[MAX_VERSION_SIZE]; /* * Point to what should be the last byte in the product name string. */ if (fileblocks == NULL) return 5; for (currBlock = fileblocks; currBlock->next; currBlock = currBlock->next); cp = currBlock->data + currBlock->length - 1; /* * Now try to get the vendor/product/version strings, from the end * of the image */ cp = get_string(&currBlock, cp, imageProductName, MAX_PRODUCT_SIZE); if (cp == NULL) return 5; cp = get_string(&currBlock, cp, imageVendorName, MAX_VENDOR_SIZE); if (cp == NULL) return 5; cp = get_string(&currBlock, cp, imageVersion, MAX_VERSION_SIZE); if (cp == NULL) return 5; #ifdef CONFIG_PROP_LOGD_LOGD memcpy(new_image_version, imageVersion, MAX_VERSION_SIZE); new_image_version[MAX_VERSION_SIZE] = '\0'; #endif /* Looks like there was versioning information there, strip it off * now so that we don't write it to flash, or try to decompress it, etc */ remove_data(strlen(imageProductName) + strlen(imageVendorName) + strlen(imageVersion) + 3); /* * Check the product name. */ if (strcmp(productName, imageProductName) != 0) return 1; /* * Check the vendor name. */ if (strcmp(vendorName, imageVendorName) != 0) return 2; /* * Check the version number. */ versionInfo = check_version_info(version, imageVersion); return versionInfo; }
int main(int argc, char const *argv[]) { list_t *list = (list_t*)malloc(sizeof (list_t)); init(list); //make a node add_at(list, (void*)2, 0); assert(list->head && list->tail); assert((int) get(list, 0) == 2); //do more adding int i = 3; for(; i < 15; ++i){ add_front(list, (void*)i); assert(list->head && list->tail); assert((int) get(list, 0) == i); } assert((int) get(list, list->size - 1) == 2); assert((int) fold_left(list, add_list, (void*)0) == 104); assert((int) fold_left(list, add_list, (void*)0) == (int)fold_right(list, add_list, (void*)0)); add_back(list, (void*)0); assert(list->tail->data == (void*)0); assert((int) get(list, list->size - 1) == 0); add_front(list, (void*)2); add_front(list, (void*)2); assert((int) fold_left(list, count_2, (void*)0) == 3); remove_data(list, (void*)2, is_2); return 0; }
void test_crud(void) { cut_assert_create(); add_data(1, 1, "API.JA"); add_data(2, 1, "CHECKINSTALL.JA"); add_data(3, 1, "FUTUREWORKS.JA"); add_data(4, 1, "INSTALL.JA"); gcut_assert_equal_list_string(gcut_take_new_list_string("1", "2", "3", NULL), retrieve_record_ids("検索")); remove_data(1, 1, "API.JA"); gcut_assert_equal_list_string(gcut_take_new_list_string("2", "3", NULL), retrieve_record_ids("検索")); update_data(3, 1, "FUTUREWORKS.JA", "Makefile.am"); gcut_assert_equal_list_string(gcut_take_new_list_string("2", NULL), retrieve_record_ids("検索")); remove_data(2, 1, "CHECKINSTALL.JA"); add_data(3, 2, "FUTUREWORKS.JA"); gcut_assert_equal_list_string(gcut_take_new_list_string("3", NULL), retrieve_record_ids("検索")); update_data(4, 1, "INSTALL.JA", "README.JA"); gcut_assert_equal_list_string(gcut_take_new_list_string("3", "4", NULL), retrieve_record_ids("検索")); remove_data(4, 1, "README.JA"); gcut_assert_equal_list_string(gcut_take_new_list_string("3", NULL), retrieve_record_ids("検索")); remove_data(3, 2, "FUTUREWORKS.JA"); cut_set_message("this assertion is wrong?"); gcut_assert_equal_list_string(NULL, retrieve_record_ids("検索")); }
/** * Function timer_expired() is called after the timer is elapsed. * @param id and data are set by caller of abs_eap_am_tools::set_timer() function. * @param id could be used to separate different timer events. * @param data could be pointer to any data that is needed in timer processing. */ EAP_FUNC_EXPORT eap_status_e eap_am_memory_store_c::timer_expired( const u32_t id, void *data) { EAP_TRACE_DEBUG( m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("eap_am_memory_store_c::timer_expired(): id %d, data 0x%08x\n"), id, data)); if (data != 0) { eap_variable_data_c * const key = reinterpret_cast<eap_variable_data_c *>(data); EAP_TRACE_DATA_DEBUG( m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("eap_am_memory_store_c::timer_expired(): key"), key->get_data(), key->get_data_length())); eap_am_memory_store_tlv_data_c * const tlv_data = m_store_new.get_handler(key); if (tlv_data != 0) { if (id == tlv_data->get_timer_id()) { eap_status_e status = remove_data(key); EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); return EAP_STATUS_RETURN(m_am_tools, status); } else { EAP_TRACE_DEBUG( m_am_tools, TRACE_FLAGS_ERROR, (EAPL("eap_am_memory_store_c::timer_expired(): id %d != tlv_data->id %d, tlv_data 0x%08x\n"), id, tlv_data->get_timer_id(), tlv_data)); EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); return EAP_STATUS_RETURN(m_am_tools, eap_status_not_found); } } } EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); }
/** * Read a message from a queue. * * Read and dequeue a message. * This service may panic if err parameter is NULL and: * -# queue parameter is invalid, or * -# message parameter is NULL, or * -# when called from an ISR. * * Authorized execution levels: task, fiber. * * @param queue : handler on the queue (value returned by queue_create). * * @param message (out): pointer to read message. * * @param timeout: maximum number of milliseconds to wait for the message. Special * values OS_NO_WAIT and OS_WAIT_FOREVER may be used. * * @param err (out): execution status: * -# E_OS_OK : a message was read * -# E_OS_ERR_TIMEOUT: no message was received * -# E_OS_ERR_EMPTY: the queue is empty * -# E_OS_ERR: invalid parameter * -# E_OS_ERR_NOT_ALLOWED: service cannot be executed from ISR context. */ void queue_get_message (T_QUEUE queue, T_QUEUE_MESSAGE* message, int timeout, OS_ERR_TYPE* err) { OS_ERR_TYPE _err; T_EXEC_LEVEL execLvl = _getExecLevel(); queue_impl_t * q = (queue_impl_t*) queue; /* check input parameters */ if( (message == NULL) || (!queue_used(q)) || (q->sema==NULL) || (timeout<OS_WAIT_FOREVER) ) { error_management (err, E_OS_ERR); return; } /* check execution level */ if ((E_EXEC_LVL_FIBER == execLvl) || (E_EXEC_LVL_TASK == execLvl)) { _err = semaphore_take(q->sema, timeout); switch(_err){ case E_OS_OK: { uint32_t it_mask = interrupt_lock(); _err = remove_data(q, message); interrupt_unlock(it_mask); error_management (err, E_OS_OK); } break; case E_OS_ERR_TIMEOUT: error_management (err, E_OS_ERR_TIMEOUT); break; case E_OS_ERR_BUSY: if(err){ //QUEUE EMPTY, is a common use case, do not panic even if err == NULL *err = E_OS_ERR_EMPTY; } break; default: //unknown error panic(E_OS_ERR_UNKNOWN); } } else { error_management (err, E_OS_ERR_NOT_ALLOWED); } return; }
static bool put_data(qhasharr_t *tbl, int idx, uint32_t hash, const void *name, size_t namesize, const void *data, size_t datasize, int count) { qhasharr_data_t *tbldata = tbl->data; qhasharr_slot_t *tblslots = get_slots(tbl); assert(tblslots[idx].count == 0); unsigned char namemd5[16]; qhashmd5(name, namesize, namemd5); // store name tblslots[idx].count = count; tblslots[idx].hash = hash; memcpy(tblslots[idx].data.pair.name, name, (namesize < Q_HASHARR_NAMESIZE) ? namesize : Q_HASHARR_NAMESIZE); memcpy((char *) tblslots[idx].data.pair.namemd5, (char *) namemd5, 16); tblslots[idx].data.pair.namesize = namesize; tblslots[idx].link = -1; // store data int newidx; size_t savesize; for (newidx = idx, savesize = 0; savesize < datasize;) { if (savesize > 0) { // find next empty slot int tmpidx = find_avail(tbl, newidx + 1); if (tmpidx < 0) { remove_data(tbl, idx); errno = ENOBUFS; return false; } // clear & set memset((void *) (&tblslots[tmpidx]), '\0', sizeof(qhasharr_slot_t)); tblslots[tmpidx].count = EXTBLOCK_MARK; // extended data block tblslots[tmpidx].hash = newidx; // previous link tblslots[tmpidx].link = -1; // end block mark tblslots[tmpidx].datasize = 0; tblslots[newidx].link = tmpidx; // link chain newidx = tmpidx; } // copy data size_t copysize = datasize - savesize; if (tblslots[newidx].count == EXTBLOCK_MARK) { // extended value if (copysize > sizeof(struct Q_HASHARR_SLOT_EXT)) { copysize = sizeof(struct Q_HASHARR_SLOT_EXT); } memcpy(tblslots[newidx].data.ext.data, data + savesize, copysize); } else { // first slot if (copysize > Q_HASHARR_DATASIZE) { copysize = Q_HASHARR_DATASIZE; } memcpy(tblslots[newidx].data.pair.data, data + savesize, copysize); // increase stored key counter tbldata->num++; } tblslots[newidx].datasize = copysize; savesize += copysize; // increase used slot counter tbldata->usedslots++; } #ifdef QHASHARR_TIMESTAMP time(&tblslots[idx].timestamp); #endif return true; }
int main() { unsigned int key_space = 1024; HashMap * hm = create_hashmap(key_space); char * string_1 = "TI2725-C"; char * string_2 = "Embedded"; char * string_3 = "Software"; const char * key_1 = "ab"; const char * key_2 = "cd"; const char * key_3 = "ad"; const char * key_4 = "xy"; // Insert ("ab" -> "TI2725-C"). insert_data(hm, key_1, string_1, resolve_collision); assert(memcmp(get_data(hm, key_1), string_1, mystrlen(string_1)) == 0); // Insert ("cd" -> "Embedded"). insert_data(hm, key_2, string_2, resolve_collision); assert(memcmp(get_data(hm, key_2), string_2, mystrlen(string_2)) == 0); // Insert ("ad" -> "Software"). insert_data(hm, key_3, string_3, resolve_collision); assert(memcmp(get_data(hm, key_3), string_3, mystrlen(string_3)) == 0); // Insert ("ab" -> "Embedded"). insert_data(hm, key_1, string_2, resolve_collision); assert(memcmp(get_data(hm, key_1), string_2, mystrlen(string_2)) == 0); // Get data for a not inserted key. assert(get_data(hm, key_4) == NULL); // Iterate the hash map iterate(hm, print_element); #ifdef NEW_HASH set_hash_function(hm, your_own_hash); printf("\nHERE WE GO AGAIN!\n\n"); // Iterate the hash map iterate(hm, print_element); #endif // Delete key "cd". remove_data(hm, key_2, NULL); assert(get_data(hm, key_2) == NULL); // Delete key "ab". remove_data(hm, key_1, NULL); assert(get_data(hm, key_1) == NULL); // Delete key "ad". remove_data(hm, key_3, NULL); assert(get_data(hm, key_3) == NULL); // Delete the hash map. delete_hashmap(hm, NULL); #ifdef COUNTING_WORDS // Create a temporary file FILE *stream = tmpfile(); // Write to the stream fprintf(stream, "foo bar_, baz!\n"); fprintf(stream, "foo\t\"bar\".\n"); fprintf(stream, "foo?\n"); // Set the position to the start of the stream fseek(stream, 0, SEEK_SET); // Count the words count_words(stream); // Close the file fclose(stream); #endif return 0; }