/* for REWRITEAOF and DESC */ sds rebuildOrigNRLcmd(robj *o) { d_l_t *nrlind = o->ptr; int tmatch = Index[server.dbid][nrlind->num].table; list *nrltoks = nrlind->l1; list *nrlcols = nrlind->l2; listIter *li1 = listGetIterator(nrltoks, AL_START_HEAD); listNode *ln1 = listNext(li1); listIter *li2 = listGetIterator(nrlcols, AL_START_HEAD); listNode *ln2 = listNext(li2); sds cmd = sdsnewlen("\"", 1); /* has to be one arg */ while (ln1 || ln2) { if (ln1) { sds token = ln1->value; cmd = sdscatlen(cmd, token, sdslen(token)); ln1 = listNext(li1); } if (ln2) { int cmatch = (int)(long)ln2->value; cmatch--; /* because (0 != NULL) */ sds cname = Tbl[server.dbid][tmatch].col_name[cmatch]->ptr; cmd = sdscatlen(cmd, "$", 1); /* "$" variable delim */ cmd = sdscatlen(cmd, cname, sdslen(cname)); ln2 = listNext(li2); } } listReleaseIterator(li1); listReleaseIterator(li2); cmd = sdscatlen(cmd, "\"", 1); /* has to be one arg */ return cmd; }
int rdbSaveNRL(FILE *fp, robj *o) { listNode *ln; d_l_t *nrlind = o->ptr; list *nrltoks = nrlind->l1; int imatch = nrlind->num; if (rdbSaveLen(fp, imatch) == -1) return -1; robj *iname = Index[server.dbid][imatch].obj; if (rdbSaveStringObject(fp, iname) == -1) return -1; int tmatch = Index[server.dbid][imatch].table; if (rdbSaveLen(fp, tmatch) == -1) return -1; if (rdbSaveLen(fp, listLength(nrltoks)) == -1) return -1; listIter *li = listGetIterator(nrltoks, AL_START_HEAD); while((ln = listNext(li)) != NULL) { sds s = ln->value; robj *r = createStringObject(s, sdslen(s)); if (rdbSaveStringObject(fp, r) == -1) return -1; decrRefCount(r); } listReleaseIterator(li); list *nrlcols = nrlind->l2; if (rdbSaveLen(fp, listLength(nrlcols)) == -1) return -1; li = listGetIterator(nrlcols, AL_START_HEAD); while((ln = listNext(li)) != NULL) { uint32 i = (uint32)(long)ln->value; if (rdbSaveLen(fp, i) == -1) return -1; } listReleaseIterator(li); return 0; }
void createList() { pList = listCreate(); T_msgNode *pMsgNode1 = (T_msgNode*)malloc(sizeof(T_msgNode)); pMsgNode1->pSendMsg = (char*)malloc(16); strcpy((char*)pMsgNode1->pSendMsg, "send msg hello"); pMsgNode1->uiMsgType = 0x8d48; pMsgNode1->uiTid = 0x701; pList = listAddNodeTail(pList, (void*)pMsgNode1); T_msgNode *pMsgNode2 = (T_msgNode*)malloc(sizeof(T_msgNode)); pMsgNode2->pSendMsg = (char*)malloc(16); strcpy((char*)pMsgNode2->pSendMsg, "send msg world"); pMsgNode2->uiMsgType = 0x8d49; pMsgNode2->uiTid = 0x702; pList = listAddNodeTail(pList, (void*)pMsgNode2); T_msgNode *pMsgNode3 = (T_msgNode*)malloc(sizeof(T_msgNode)); pMsgNode3->pSendMsg = (char*)malloc(16); strcpy((char*)pMsgNode3->pSendMsg, "send msg ack"); pMsgNode3->uiMsgType = 0x8d50; pMsgNode3->uiTid = 0x703; pList = listAddNodeTail(pList, (void*)pMsgNode3); T_msgNode *pMsgNode4 = (T_msgNode*)malloc(sizeof(T_msgNode)); pMsgNode4->pSendMsg = (char*)malloc(16); strcpy((char*)pMsgNode4->pSendMsg, "send msg end"); pMsgNode4->uiMsgType = 0x8d51; pMsgNode4->uiTid = 0x704; pList = listAddNodeTail(pList, (void*)pMsgNode4); listIter *iter = listGetIterator(pList, DL_START_TAIL); listNode *node = NULL; while ((node = listNext(iter)) != NULL) { T_msgNode *pNode = (T_msgNode *)node->value; printf("msg type: 0x%x\n", pNode->uiMsgType); printf("msg tid : 0x%x\n", pNode->uiTid); printf("msg body: %s\n", (char*)pNode->pSendMsg); printf("***********************\n"); } printf("*********************************\n"); iter = listGetIterator(pList, DL_START_HEAD); while ((node = listNext(iter)) != NULL) { T_msgNode *pNode = (T_msgNode *)node->value; printf("msg type: 0x%x\n", pNode->uiMsgType); printf("msg tid : 0x%x\n", pNode->uiTid); printf("msg body: %s\n", (char*)pNode->pSendMsg); printf("***********************\n"); } }
/* creates text for trigger's command */ static sds genNRL_Cmd(bt *btr, d_l_t *nrlind, aobj *apk, char *vals, uint32 cofsts[], void *rrow, int tmatch) { sds cmd = sdsempty(); /* DESTROY ME 016 */ list *nrltoks = nrlind->l1; list *nrlcols = nrlind->l2; listIter *li1 = listGetIterator(nrltoks, AL_START_HEAD); listIter *li2 = listGetIterator(nrlcols, AL_START_HEAD); listNode *ln1 = listNext(li1); listNode *ln2 = listNext(li2); while (ln1 || ln2) { if (ln1) { sds token = ln1->value; cmd = sdscatlen(cmd, token, sdslen(token)); ln1 = listNext(li1); } int cmatch = -1; if (ln2) { cmatch = ((int)(long)ln2->value) - 1; /* because (0 != NULL) */ ln2 = listNext(li2); } if (cmatch != -1) { char *x; int xlen; if (vals) { /* from INSERT */ if (!cmatch) { /* PK not stored in ROW */ x = strFromAobj(apk, &xlen); } else { /* get COL from cofsts */ x = vals + cofsts[cmatch - 1]; xlen = cofsts[cmatch] - cofsts[cmatch - 1] - 1; } cmd = sdscatlen(cmd, x, xlen); if (!cmatch) free(x); /* FREED 015 */ } else { /* not from INSERT -> fetch row */ aobj rcol = getRawCol(btr, rrow, cmatch, apk, tmatch, NULL, 1); x = rcol.s; xlen = rcol.len; cmd = sdscatlen(cmd, x, xlen); releaseAobj(&rcol); } } } listReleaseIterator(li1); listReleaseIterator(li2); return cmd; }
list *listSearchKey(list *list, void *key) /*{{{*/ { listIter *iter; listNode *node; iter = listGetIterator(list, AL_START_HEAD); while((node = listNext(iter)) != NULL) { if(list->match) { if(list->match(node->value, key)) { listReleaseIterator(iter); return node; } } else { //如果match函数不存在,理论上讲是比较不了 //这时候只需要看地址就行了 if(key == node->value) { listReleaseIterator(iter); return node; } } } listReleaseIterator(iter); return NULL; }
void freeClient(vuiClient *c) { listNode *ln; listIter *it; cJSON *json; /* Free the query buffer */ sdsfree(c->querybuf); sdsfree(c->querymsg); sdsfree(c->res.body); sdsfree(c->res.reason); sdsfree(c->res.buf); /* Close socket, unregister events, and remove list of replies and * accumulated arguments. */ if (c->fd != -1) { aeDeleteFileEvent(server.el,c->fd,AE_READABLE); aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); close(c->fd); } it = listGetIterator(c->jsons, AL_START_HEAD); while((ln = listNext(it))) { json = (cJSON *)ln->value; cJSON_Delete(json); listDelNode(c->jsons, ln); } listRelease(c->jsons); listReleaseIterator(it); zfree(c); server.client = NULL; }
static void calculate_bm25(fts_t *fts, list *indices, dict_t *scores) { listIter *iter; listNode *node; unsigned long doc_size = fts_size(fts); unsigned long list_size = listLength(indices); doc_size = doc_size ? doc_size : 1; double avgdl = (fts->len * 1.0) / doc_size; iter = listGetIterator(indices, AL_START_HEAD); while((node = listNext(iter)) != NULL) { index_item_t *idx = node->value; int dl = idx->doc->len; fts_doc_score_t *fds = dict_get(scores, idx->doc->title->ptr); if (!fds) { fds = rr_malloc(sizeof(*fds)); fds->doc = idx->doc; fds->score = .0f; dict_set(scores, idx->doc->title->ptr, fds); } double idf = log((doc_size - list_size + 0.5) / (list_size + 0.5)); double tf = idx->tf * (BM25_K + 1) / (idx->tf + BM25_K * (1 - BM25_B + BM25_B*dl/avgdl)); fds->score += tf * idf; } listReleaseIterator(iter); }
/* Search the list for a node matching a given key. * The match is performed using the 'match' method * set with listSetMatchMethod(). If no 'match' method * is set, the 'value' pointer of every node is directly * compared with the 'key' pointer. * * On success the first matching node pointer is returned * (search starts from head). If no matching node exists * NULL is returned. */ listNode *listSearchKey(list *pList, void *key) { listIter *iter = listGetIterator(pList, DL_START_HEAD); listNode *node = listNext(iter); while(node != NULL) { if (pList->match) { if (pList->match(node->value, key)) { listReleaseIterator(iter); return node; } } else { if (key == node->value) { listReleaseIterator(iter); return node; } } } listReleaseIterator(iter); return NULL; }
/* Duplicate the whole list. On out of memory NULL is returned. * On success a copy of the original list is returned. * * The 'Dup' method set with listSetDupMethod() function is used * to copy the node value. Otherwise the same pointer value of * the original node is used as value of the copied node. * * The original list both on success or error is never modified. */ hilist *listDup(hilist *orig) { hilist *copy; listIter *iter; listNode *node; if ((copy = listCreate()) == NULL) return NULL; copy->dup = orig->dup; copy->free = orig->free; copy->match = orig->match; iter = listGetIterator(orig, AL_START_HEAD); while((node = listNext(iter)) != NULL) { void *value; if (copy->dup) { value = copy->dup(node->value); if (value == NULL) { listRelease(copy); listReleaseIterator(iter); return NULL; } } else value = node->value; if (listAddNodeTail(copy, value) == NULL) { listRelease(copy); listReleaseIterator(iter); return NULL; } } listReleaseIterator(iter); return copy; }
int luaworkDoDir(lua_State *L,const char *path, char *err) { int ret = UGOK; sds relpath = sdsempty(); list *queue = listCreate(); listNode *node=NULL; listIter *iter = NULL; if (xfilelistdir(path, "*.lua", queue) == UGERR) { luaworkSetError(err, "list files for %s failed", path); ret = UGERR; goto END; } iter = listGetIterator(queue, AL_START_HEAD); while ((node=listNext(iter))!=NULL) { const char *filename = (char *) (node->value); sdsclear(relpath); relpath = sdscatprintf(relpath, "%s/%s", path, filename); ret = luaworkDoFile(L, relpath, err); if (ret != UGOK) break; } listReleaseIterator(iter); END: listRelease(queue); sdsfree(relpath); return ret; }
/* Search the list for a node matching a given key. * The match is performed using the 'match' method * set with listSetMatchMethod(). If no 'match' method * is set, the 'value' pointer of every node is directly * compared with the 'key' pointer. * * On success the first matching node pointer is returned * (search starts from head). If no matching node exists * NULL is returned. */ listNode *listSearchKey(list *list, void *key) { listIter *iter; listNode *node; //遍历整个链表 iter = listGetIterator(list, AL_START_HEAD); while((node = listNext(iter)) != NULL) { //如果有比较的回调函数,调用该函数 if (list->match) { if (list->match(node->value, key)) { listReleaseIterator(iter); return node; } } else { //否则比较两个value是否相同 if (key == node->value) { listReleaseIterator(iter); return node; } } } //也就是默认的match函数就是比较两个value是否相等 listReleaseIterator(iter); return NULL; }
int UniqueGetAllCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (argc != 2) { return RedisModule_WrongArity(ctx); } RedisModule_AutoMemory(ctx); // open the key and make sure it is indeed a Hash and not empty RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ); int type = RedisModule_KeyType(key); if (type == REDISMODULE_KEYTYPE_EMPTY) { RedisModule_ReplyWithNull(ctx); return REDISMODULE_OK; } if (RedisModule_ModuleTypeGetType(key) != UniqueType) { return RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE); } unique *unique = RedisModule_ModuleTypeGetValue(key); size_t len = uniqueLen(unique); RedisModule_ReplyWithArray(ctx, len*2); size_t i; listIter *it = listGetIterator(unique->l, AL_START_HEAD); listNode *node; for (node = listNext(it), i=0; node && i<len; node = listNext(it),i++) { dictEntry *en = node->value; RedisModule_ReplyWithStringBuffer(ctx, en->key, sdslen(en->key)); RedisModule_ReplyWithStringBuffer(ctx, en->v.val, sdslen(en->v.val)); } return REDISMODULE_OK; }
static void sendStaticFileReply(cli *c) { robj *o; if ((o = lookupKeyRead(c->db, c->http.file)) == NULL) SEND_404 else if (o->type != REDIS_STRING) SEND_404 else { //NOTE: STATIC expire in 10 years (HARDCODED) listNode *ln; bool dfl = 0; listIter *li = listGetIterator(c->http.req_hdr, AL_START_HEAD); while((ln = listNext(li))) { // check for "deflate" two_sds *ss = ln->value; if (!strncasecmp(ss->a, "Accept-Encoding", 15)) { if (DXDB_strcasestr(ss->b, "deflate")) { dfl = 1; break; } } } listReleaseIterator(li); if (dfl) { robj *dfile = _createStringObject("DEFLATE/"); dfile->ptr = sdscatlen(dfile->ptr, c->http.file->ptr, sdslen(c->http.file->ptr)); robj *od; if ((od = lookupKeyRead(c->db, dfile)) && od->type == REDIS_STRING){ o = od; addHttpResponseHeader(sdsnew("Content-Encoding"), sdsnew("deflate")); } } addHttpResponseHeader(sdsnew("Expires"), sdsnew("Wed, 09 Jun 2021 10:18:14 GMT;")); SEND_REPLY_FROM_STRING(send_http200_reponse_header(c, sdslen(o->ptr))); addReply(c, o); } }
int _msg_check(const char *file, int line, rmtContext *ctx, struct msg *msg, int panic) { struct mbuf *mbuf; listIter *iter; listNode *node; uint32_t total_mbuf_len = 0; int err = 0; if (msg == NULL) { return RMT_ERROR; } //check msg length iter = listGetIterator(msg->data, AL_START_HEAD); while ((node = listNext(iter)) != NULL) { mbuf = listNodeValue(node); total_mbuf_len += mbuf_length(mbuf); if (mbuf->pos < mbuf->start) { _log(file, line, 0, "MSG CHECK Error: mbuf->pos(%p) < mbuf->start(%p)", mbuf->pos, mbuf->start); err = 1; } if (mbuf->pos > mbuf->last) { _log(file, line, 0, "MSG CHECK Error: mbuf->pos(%p) > mbuf->last(%p)", mbuf->pos, mbuf->last); err = 1; } } listReleaseIterator(iter); if (msg->mlen != total_mbuf_len) { _log(file, line, 0, "MSG CHECK Error: msg->mlen(%u) != total_mbuf_len(%u)", msg->mlen, total_mbuf_len); err = 1; } if (msg->request == 1) { if (memcmp(ctx->cmd, RMT_CMD_REDIS_MIGRATE, MIN(sdslen(ctx->cmd),strlen(RMT_CMD_REDIS_MIGRATE))) == 0 && msg->noreply != ctx->noreply) { _log(file, line, 0, "MSG CHECK Error: msg->noreply(%u) != ctx->noreply(%d)", msg->noreply, ctx->noreply); err = 1; } } if (err) goto error; return RMT_OK; error: MSG_DUMP(msg, LOG_ERR, 0); if (panic) { rmt_stacktrace(1); abort(); } return RMT_ERROR; }
void aio_submit_queue() { int rv; struct aiocb *cb; if (0 == listLength(aio_queue)) return; listIter *it; listNode *nd; it = listGetIterator(aio_queue, AL_START_HEAD); while ((nd = listNext(it))) { cb = (struct aiocb *)nd->value; cb->retries += 1; rv = aio_submit(cb); if (0 == rv) { listDelNode(aio_queue, nd); } else if (-2 == rv) { break; } } end: zfree(it); }
/* 关键字搜索Node结点此时用到了list的match方法了 */ listNode *listSearchKey(list *list, void *key) { listIter *iter; listNode *node; //获取迭代器 iter = listGetIterator(list, AL_START_HEAD); while((node = listNext(iter)) != NULL) { //遍历循环 if (list->match) { //如果定义了list的match方法,则调用match方法 if (list->match(node->value, key)) { //如果方法返回true,则代表找到结点,释放迭代器 listReleaseIterator(iter); return node; } } else { //如果没有定义list 的match方法,则直接比较函数指针 if (key == node->value) { //如果相等,则代表找到结点,释放迭代器 listReleaseIterator(iter); return node; } } } listReleaseIterator(iter); return NULL; }
static void freeListOfIndRow(list *ll, int num_cols, bool is_ob) { listNode *ln; listIter *li = listGetIterator(ll, AL_START_HEAD); while((ln = listNext(li)) != NULL) { freeIndRow(ln->value, num_cols, is_ob, 1); } listReleaseIterator(li); listRelease(ll); }
void UniqueTypeRdbSave(RedisModuleIO *rdb, void *value) { unique *unique = value; listIter *it = listGetIterator(unique->l, AL_START_HEAD); listNode *node; RedisModule_SaveUnsigned(rdb, listLength(unique->l)); for (node = listNext(it); node; node = listNext(it)) { dictEntry *en = node->value; RedisModule_SaveStringBuffer(rdb, en->key, sdslen(en->key)); RedisModule_SaveStringBuffer(rdb, en->v.val, sdslen(en->v.val)); } }
/* compare msg content with a string * * return 0 : equal * return 1 : msg content bigger than string * return -1: string bigger than msg content * return -2: error */ int msg_cmp_str(struct msg *msg, const uint8_t *str, uint32_t len) { int ret; struct mbuf *mbuf; listIter *iter; listNode *node; uint8_t *p, *q, *start; uint32_t mlen, left; //mbuf len if(msg == NULL) { return -2; } if(str == NULL || len == 0) { return -2; } if(msg->mlen > len) { return 1; } else if(msg->mlen < len) { return -1; } start = (uint8_t *)str; left = len; iter = listGetIterator(msg->data, AL_START_HEAD); while((node = listNext(iter)) != NULL && left > 0) { mbuf = listNodeValue(node); p = mbuf->start; q = mbuf->last; mlen = (uint32_t)(q - p); ret = memcmp(p, start, mlen); if(ret != 0) { listReleaseIterator(iter); return ret; } left -= mlen; } listReleaseIterator(iter); return 0; }
static sds send_http_response_header_extended(cli *c, sds s) { if (c->http.resp_hdr) { listNode *ln; listIter *li = listGetIterator(c->http.resp_hdr, AL_START_HEAD); while((ln = listNext(li))) {// POPULATE Lua Global HTTP_HEADER[] two_sds *ss = ln->value; s = sdscatprintf(s, "%s: %s\r\n", ss->a, ss->b); } listReleaseIterator(li); } return sdscatlen(s, "\r\n", 2); }
void UniqueTypeDigest(RedisModuleDigest *md, void *value) { unique *unique = value; listIter *it = listGetIterator(unique->l, AL_START_HEAD); listNode *node; for (node = listNext(it); node; node = listNext(it)) { dictEntry *en = node->value; RedisModule_DigestAddStringBuffer(md, en->key, sdslen(en->key)); RedisModule_DigestAddStringBuffer(md, en->v.val, sdslen(en->v.val)); } RedisModule_DigestEndSequence(md); }
/** * index>=0 从0位置正向开始 * index<0 从最后一个位置开始 */ listNode *listIndex(list *list, long index) /*{{{*/ { listNode *node; listIter *iter; if(index < 0) { index = -index; iter = listGetIterator(list, AL_START_TAIL); while(index-- && (node = listNext(iter)); }
void UniqueTypeAofRewrite(RedisModuleIO *aof, RedisModuleString *key, void *value) { unique *unique = value; listIter *it = listGetIterator(unique->l, AL_START_HEAD); listNode *node; sds k, v; for (node = listNext(it); node; node = listNext(it)) { dictEntry *en = node->value; k = en->key; v = en->v.val; RedisModule_EmitAOF(aof,"unique.pushup","sbb",key,k, sdslen(k), v, sdslen(v)); } }
void displayall_list() { if(listall->len==0){ printf("没有任何链表,返回\n"); return ; } listIter *iter=listGetIterator(listall,0); listNode *node; while((node=listNext(iter))!=NULL){ list *ll=(list*)node->value; printf("链表%s:",ll->name); listpretraval(ll); } listReleaseIterator(iter); }
list *listDup(list *orign) /*{{{*/ { list *cpy; listIter *iter; listNode *node; if((cpy = listCreate()) == NULL) { return NULL; } cpy->free = orign->free; cpy->dup = orign->dup; cpy->match = orign->match; iter = listGetIterator(orign, AL_START_HEAD); while((node = listNext(iter)) != NULL) { void *value; if(cpy->dup) { value = cpy->dup(node->value); if(value == NULL) { listRelease(cpy); listReleaseIterator(iter); return NULL; } } else { value = node->value; } //出错只有一种情况,就是malloc失败了,return NULL; if(listAddNodeTail(cpy, value) == NULL) { listRelease(cpy); listReleaseIterator(iter); return NULL; } } listReleaseIterator(iter); return cpy; }
struct gwseriport *find_transfer_media(const char *transfer_type) { struct gwseriport *s; listNode *node; listIter *iter; iter = listGetIterator(server.seriports,AL_START_HEAD); while( (node=listNext(iter)) != NULL){ s = node->value; if(strcasecmp(transfer_type,s->transfer_media) == 0){ listReleaseIterator(iter); return s; } } listReleaseIterator(iter); return NULL; }
/* 列表赋值方法,传入的参数为原始列表 */ list *listDup(list *orig) { list *copy; listIter *iter; listNode *node; //如果创建列表失败则直接返回 if ((copy = listCreate()) == NULL) return NULL; //为新列表赋值好3个函数指针 copy->dup = orig->dup; copy->free = orig->free; copy->match = orig->match; //获得从头方向开始的迭代器 iter = listGetIterator(orig, AL_START_HEAD); while((node = listNext(iter)) != NULL) { //从前往后遍历结点 void *value; if (copy->dup) { //如果定义了列表复制方法,则调用dup方法 value = copy->dup(node->value); if (value == NULL) { //如果发生OOM内存溢出问题,直接释放所有空间 listRelease(copy); listReleaseIterator(iter); return NULL; } } else //没定义直接复制函数指针 value = node->value; if (listAddNodeTail(copy, value) == NULL) { //后面的结点都是从尾部逐一添加结点,如果内存溢出,同上操作 listRelease(copy); listReleaseIterator(iter); return NULL; } } //最后释放迭代器 listReleaseIterator(iter); return copy; }
/* Search the list for a node matching a given key. * The match is performed using the 'match' method * set with listSetMatchMethod(). If no 'match' method * is set, the 'value' pointer of every node is directly * compared with the 'key' pointer. * * On success the first matching node pointer is returned * (search starts from head). If no matching node exists * NULL is returned. */ listNode *listSearchKey(list *list, void *value) { listIter *iter = listGetIterator(list, DL_START_HEAD); listNode *node; while((node = listNextElement(iter)) != NULL) { if (list->match) { if (list->match(node->value, value)) { listReleaseIterator(iter); return node; } } else { if (value == node->value) { listReleaseIterator(iter); return node; } } } listReleaseIterator(iter); return NULL; }
static void fts_cat_index(fts_t *fts) { dict_iterator_t *iter; iter = dict_iter_create(fts->index); while (dict_iter_hasnext(iter)) { dict_kv_t kv = dict_iter_next(iter); rr_debug("key: %s", kv.key); list *l = kv.value; listIter *liter = listGetIterator(l, AL_START_HEAD); listNode *node; while((node = listNext(liter)) != NULL) { index_item_t *item = node->value; rr_debug("doc title: %s, tf: %d", (char *) item->doc->title->ptr, item->tf); } listReleaseIterator(liter); } dict_iter_free(iter); }
int main() { list * ls = listCreate(); listIter *iter; listNode *node; char val1[] = "value1"; char val2[] = "value2"; char val3[] = "value3"; listAddNodeHead(ls, val1); listAddNodeHead(ls, val2); listAddNodeHead(ls, val3); iter = listGetIterator(ls, AL_START_HEAD); while((node = listNext(iter)) != NULL) { printf("value = %s\n", (char*)node->value); } listReleaseIterator(iter); return 0; }