static inline void _co_tree_print_r(co_obj_t *tree, _treenode_t *current, int *count) { CHECK(IS_TREE(tree), "Recursion target is not a tree."); if(current == NULL) return; char *key = NULL; char *value = NULL; if(co_node_value(current) != NULL) { (*count)++; co_obj_data(&key, co_node_key(current)); co_obj_data(&value, co_node_value(current)); //CHECK(IS_STR(key) && IS_STR(value), "Incorrect types for profile."); if(*count < co_tree_length(tree)) { printf(" \"%s\": \"%s\", ", key, value); } else { printf(" \"%s\": \"%s\" ", key, value); } } _co_tree_print_r(tree, current->low, count); _co_tree_print_r(tree, current->equal, count); _co_tree_print_r(tree, current->high, count); return; error: return; }
int co_response_print(co_obj_t *response) { CHECK(response != NULL && IS_TREE(response), "Invalid response object."); return co_tree_print(response); error: return 0; }
co_obj_t * co_response_get(co_obj_t *response, const char *key, const size_t klen) { CHECK(response != NULL && IS_TREE(response), "Invalid response object."); CHECK(key != NULL && klen > 0, "Invalid key."); return co_tree_find(response, key, klen); error: return NULL; }
int co_call(co_obj_t *connection, co_obj_t **response, const char *method, const size_t mlen, co_obj_t *request) { CHECK(method != NULL && mlen > 0 && mlen < UINT8_MAX, "Invalid method name."); CHECK(connection != NULL && IS_SOCK(connection), "Invalid connection."); co_obj_t *params = NULL, *rlist = NULL, *rtree = NULL; int retval = 0; size_t reqlen = 0, resplen = 0; char req[REQUEST_MAX]; char resp[RESPONSE_MAX]; if(request != NULL) { CHECK(IS_LIST(request), "Not a valid request."); params = request; } else { params = co_list16_create(); } co_obj_t *m = co_str8_create(method, mlen, 0); reqlen = co_request_alloc(req, sizeof(req), m, params); CHECK(((co_socket_t*)connection)->send((co_obj_t*)((co_socket_t*)connection)->fd, req, reqlen) != -1, "Send error!"); if((resplen = ((co_socket_t*)connection)->receive(connection, (co_obj_t*)((co_socket_t*)connection)->fd, resp, sizeof(resp))) > 0) { CHECK(co_list_import(&rlist, resp, resplen) > 0, "Failed to parse response."); rtree = co_list_element(rlist, 3); if(!IS_NIL(rtree)) { retval = 1; } else { rtree = co_list_element(rlist, 2); retval = 0; } if(rtree != NULL && IS_TREE(rtree)) { *response = rtree; hattach(*response, _pool); } else SENTINEL("Invalid response."); } else SENTINEL("Failed to receive data."); co_obj_free(m); if(params != request) co_obj_free(params); return retval; error: co_obj_free(m); if(params != request) co_obj_free(params); return retval; }
static inline void _co_tree_process_r(co_obj_t *tree, _treenode_t *current, const co_iter_t iter, void *context) { CHECK(IS_TREE(tree), "Recursion target is not a tree."); if(current != NULL) { if(current->value != NULL) iter(tree, current->value, context); _co_tree_process_r(tree, current->low, iter, context); _co_tree_process_r(tree, current->equal, iter, context); _co_tree_process_r(tree, current->high, iter, context); } return; error: return; }
static inline void _co_tree_raw_r(char **output, const size_t *olen, size_t *written, _treenode_t *current) { if(current == NULL) return; size_t klen = 0, vlen = 0; char *kbuf = NULL, *vbuf = NULL; if(current->value != NULL) { CHECK((klen = co_obj_raw(&kbuf, current->key)) > 0, "Failed to read key."); memmove(*output, kbuf, klen); *output += klen; *written += klen; if(IS_TREE(current->value)) { vlen = co_tree_raw(*output, *olen - *written, current->value); CHECK(vlen > 0, "Failed to dump tree value."); } else if(IS_LIST(current->value)) { vlen = co_list_raw(*output, *olen, current->value); CHECK(vlen > 0, "Failed to dump tree value."); } else { CHECK((vlen = co_obj_raw(&vbuf, current->value)) > 0, "Failed to read value."); CHECK((klen + vlen) < ((*olen) - (*written)), "Data too large for buffer."); DEBUG("Dumping value %s of size %d with key %s of size %d.", vbuf, (int)vlen, kbuf, (int)klen); memmove(*output, vbuf, vlen); } *written += vlen; *output += vlen; } _co_tree_raw_r(output, olen, written, current->low); _co_tree_raw_r(output, olen, written, current->equal); _co_tree_raw_r(output, olen, written, current->high); return; error: return; }
static inline void _co_tree_print_raw_r(co_obj_t *tree, _treenode_t *current) { CHECK(IS_TREE(tree), "Recursion target is not a tree."); if(current == NULL) return; size_t klen = 0, vlen = 0; char *kbuf = NULL, *vbuf = NULL; if(current->value != NULL) { CHECK((klen = co_obj_raw(&kbuf, current->key)) > 0, "Failed to read key."); CHECK((vlen = co_obj_raw(&vbuf, current->value)) > 0, "Failed to read value."); printf("KEY:\n"); hexdump((void *)kbuf, klen); printf("VAL:\n"); hexdump((void *)vbuf, vlen); } _co_tree_print_raw_r(tree, current->low); _co_tree_print_raw_r(tree, current->equal); _co_tree_print_raw_r(tree, current->high); return; error: return; }
static int describe_object(int x, int y, int votyp, char *buf, int known_embed, boolean *feature_described) { int num_objs = 0; struct obj *otmp; int typ; *feature_described = FALSE; if (votyp == -1) return -1; otmp = vobj_at(x, y); if (!otmp || otmp->otyp != votyp) { /* We have a mimic. */ if (votyp == STRANGE_OBJECT) { strcpy(buf, "strange object"); } else { otmp = mktemp_sobj(level, votyp); otmp->corpsenm = PM_TENGU; /* (basic object only, no random features) */ if (otmp->oclass == COIN_CLASS) otmp->quan = 1L; /* to force pluralization off */ else if (otmp->otyp == SLIME_MOLD) otmp->spe = gamestate.fruits.current;/* give the fruit a type */ strcpy(buf, distant_name(otmp, xname)); dealloc_obj(otmp); otmp = vobj_at(x, y); /* make sure we don't point to the temp obj any more */ } } else strcpy(buf, distant_name(otmp, xname)); typ = level->locations[x][y].typ; if (known_embed && IS_TREE(typ)) strcat(buf, " stuck"); else if (known_embed && (IS_ROCK(typ) || closed_door(level, x, y))) strcat(buf, " embedded"); else if (IS_TREE(typ)) { strcat(buf, " stuck in a tree"); *feature_described = TRUE; } else if (typ == STONE || typ == SCORR) { strcat(buf, " embedded in stone"); *feature_described = TRUE; } else if (IS_WALL(typ) || typ == SDOOR) { strcat(buf, " embedded in a wall"); *feature_described = TRUE; } else if (closed_door(level, x, y)) { strcat(buf, " embedded in a door"); *feature_described = TRUE; } else if (is_pool(level, x, y)) { strcat(buf, " in water"); *feature_described = TRUE; } else if (is_lava(level, x, y)) { strcat(buf, " in molten lava"); /* [can this ever happen?] */ *feature_described = TRUE; } if (!cansee(x, y)) return -1; /* don't disclose the number of objects for location out of LOS */ if (!otmp) /* There is no object here. Since the player sees one it must be a mimic */ return 1; if (otmp->otyp != votyp) /* Hero sees something other than the actual top object. Probably a mimic */ num_objs++; for (; otmp; otmp = otmp->nexthere) num_objs++; return num_objs; }
size_t co_response_alloc(char *output, const size_t olen, const uint32_t id, const co_obj_t *error, co_obj_t *result) { CHECK(((output != NULL) && (error != NULL) && (result != NULL)), "Invalid response components."); CHECK(olen > sizeof(_resp_header) + sizeof(uint32_t) + sizeof(co_str16_t) + sizeof(co_list16_t), "Output buffer too small."); size_t written = 0; char *cursor = NULL; size_t s = 0; /* Pack response header */ memmove(output + written, &_resp_header.list_type, sizeof(_resp_header.list_type)); written += sizeof(_resp_header.list_type); memmove(output + written, &_resp_header.list_len, sizeof(_resp_header.list_len)); written += sizeof(_resp_header.list_len); memmove(output + written, &_resp_header.type_type, sizeof(_resp_header.type_type)); written += sizeof(_resp_header.type_type); memmove(output + written, &_resp_header.type_value, sizeof(_resp_header.type_value)); written += sizeof(_resp_header.type_value); memmove(output + written, &_resp_header.id_type, sizeof(_resp_header.id_type)); written += sizeof(_resp_header.id_type); /* Pack response ID */ memmove(output + written, &id, sizeof(uint32_t)); written += sizeof(uint32_t); /* Pack error code */ //CHECK(IS_STR(error) || IS_NIL(error), "Not a valid error name."); if(error != NULL) { if(IS_LIST(error)) written += co_list_raw(output + written, olen - written, error); else if(IS_TREE(error)) { written += co_tree_raw(output + written, olen - written, error); } else { s = co_obj_raw(&cursor, error); memmove(output + written, cursor, s); written += s; } } /* Pack method result */ CHECK(written < olen, "Output buffer too small."); if(result != NULL) { if(IS_LIST(result)) written += co_list_raw(output + written, olen - written, result); else if(IS_TREE(result)) { written += co_tree_raw(output + written, olen - written, result); } else { s = co_obj_raw(&cursor, result); memmove(output + written, cursor, s); written += s; } } DEBUG("Response bytes written: %d", (int)written); CHECK(written < olen, "Output buffer too small."); return written; error: return -1; }