/* * Execute a routine for each allocated structure. */ void mp_foreach(mem_pool *mp, mem_func func, void *cb_data) { void **ptr = mp_first(mp); while (ptr) { func(ptr, cb_data); ptr = mp_next(ptr); } }
static int tnt_iter_map_next(struct tnt_iter *i) { struct tnt_iter_map *itr = TNT_IMAP(i); itr->cur_index++; if ((uint32_t)itr->cur_index >= itr->pair_count) { i->status = TNT_ITER_FAIL; return 0; } if (itr->cur_index == 0) itr->key = itr->first_key; else itr->key = itr->value_end; itr->key_end = itr->key; mp_next(&itr->key_end); itr->value = itr->key_end; itr->value_end = itr->value; mp_next(&itr->value_end); return 1; }
int64_t php_tp_response(struct tnt_response *r, char *buf, size_t size) { memset(r, 0, sizeof(*r)); const char *p = buf; /* len */ uint32_t len = size; /* header */ if (mp_typeof(*p) != MP_MAP) return -1; uint32_t n = mp_decode_map(&p); while (n-- > 0) { if (mp_typeof(*p) != MP_UINT) return -1; uint32_t key = mp_decode_uint(&p); if (mp_typeof(*p) != MP_UINT) return -1; switch (key) { case TNT_SYNC: r->sync = mp_decode_uint(&p); break; case TNT_CODE: r->code = mp_decode_uint(&p); break; default: return -1; } r->bitmap |= (1ULL << key); } /* body */ if (mp_typeof(*p) != MP_MAP) return -1; n = mp_decode_map(&p); while (n-- > 0) { uint32_t key = mp_decode_uint(&p); switch (key) { case TNT_ERROR: if (mp_typeof(*p) != MP_STR) return -1; uint32_t elen = 0; r->error = mp_decode_str(&p, &elen); r->error_len = elen; r->code &= ((1 << 15) - 1); break; case TNT_DATA: if (mp_typeof(*p) != MP_ARRAY) return -1; r->data = p; mp_next(&p); r->data_len = p - r->data; break; } r->bitmap |= (1ULL << key); } return p - buf; }
static int tnt_iter_array_next(struct tnt_iter *i) { struct tnt_iter_array *itr = TNT_IARRAY(i); itr->cur_index++; if ((uint32_t)itr->cur_index >= itr->elem_count) { i->status = TNT_ITER_FAIL; return 0; } if (itr->cur_index == 0) itr->elem = itr->first_elem; else itr->elem = itr->elem_end; itr->elem_end = itr->elem; mp_next(&itr->elem_end); return 1; }
static void test_next_on_map(uint32_t count) { note("next/check on map(%u)", count); char *d1 = data; d1 = mp_encode_map(d1, count); for (uint32_t i = 0; i < 2 * count; i++) { d1 = mp_encode_uint(d1, i % 0x7f); /* one byte */ } uint32_t len = 2 * count + mp_sizeof_map(count); const char *d2 = data; const char *d3 = data; ok(!mp_check(&d2, data + BUF_MAXLEN), "mp_check(map %u))", count); is((d1 - data), (ptrdiff_t)len, "len(map %u) == %u", count, len); is((d2 - data), (ptrdiff_t)len, "len(mp_check(map %u)) == %u", count, len); mp_next(&d3); is((d3 - data), (ptrdiff_t)len, "len(mp_next(map %u)) == %u", count, len); }
static void test_next_on_array(uint32_t count) { note("next/check on array(%u)", count); char *d1 = data; d1 = mp_encode_array(d1, count); for (uint32_t i = 0; i < count; i++) { d1 = mp_encode_uint(d1, i % 0x7f); /* one byte */ } uint32_t len = count + mp_sizeof_array(count); const char *d2 = data; const char *d3 = data; ok(!mp_check(&d2, data + BUF_MAXLEN), "mp_check(array %u))", count); is((d1 - data), len, "len(array %u) == %u", count, len); is((d2 - data), len, "len(mp_check(array %u)) == %u", count, len); mp_next(&d3); is((d3 - data), len, "len(mp_next(array %u)) == %u", count, len); }
static int test_nils(void) { plan(6); header(); const char *d1 = mp_encode_nil(data); const char *d2 = data; const char *d3 = data; const char *d4 = data; note("nil"); mp_decode_nil(&d2); mp_next(&d3); ok(!mp_check(&d4, d3 + 1), "mp_check_nil()"); is((d1 - data), 1, "len(mp_encode_nil() == 1"); is(d1, d2, "len(mp_decode_nil()) == 1"); is(d1, d3, "len(mp_next_nil()) == 1"); is(d1, d4, "len(mp_check_nil()) == 1"); is(mp_sizeof_nil(), 1, "mp_sizeof_nil() == 1"); footer(); return check_plan(); }
int opts_parse_key(void *opts, const struct opt_def *reg, const char *key, uint32_t key_len, const char **data, uint32_t errcode, uint32_t field_no, struct region *region, bool skip_unknown_options) { for (const struct opt_def *def = reg; def->name != NULL; def++) { if (key_len != strlen(def->name) || memcmp(key, def->name, key_len) != 0) continue; return opt_set(opts, def, data, region, errcode, field_no); } if (! skip_unknown_options) { char *errmsg = tt_static_buf(); snprintf(errmsg, TT_STATIC_BUF_LEN, "unexpected option '%.*s'", key_len, key); diag_set(ClientError, errcode, field_no, errmsg); return -1; } mp_next(data); return 0; }
void run_game(lua_State *L) { uint32_t now = SDL_GetTicks(); /* Current real time. */ /* * Compute how much time has passed since last time. Watch out for time * wrap-around. */ uint32_t delta_time = (now >= before) ? now - before : (uint32_t)-1 - before + now; before = now; /* * If there was some huge lag, don't make worlds catch * up. Instead, assume last frame took 50ms. */ if (delta_time > 50) delta_time = 50; /* Game speed always normal. */ uint32_t game_delta_time = delta_time; game_time += game_delta_time; /* Advance game time. */ /* Calculate frames per second. */ fps_count++; if (now - fps_time >= config.FPSUpdateInterval && config.debug) { frames_per_second = fps_count*1000.0 / (now - fps_time); fps_time = now; fps_count = 0; extern int total_tile_count; log_msg("FPS: %.2f, tiles=%d", frames_per_second, total_tile_count); } process_events(L); #if ENABLE_AUDIO /* Dynamically adjust volume. */ audio_adjust_volume(); #endif /* Step worlds. */ extern mem_pool mp_world; for (World *world = mp_first(&mp_world); world != NULL; world = mp_next(world)) { if (world->killme) continue; /* We deal with these below. */ /* Bring world up to present game time. */ while (game_time >= world->next_step_time) { world->next_step_time += world->step_ms; /* * Step world -- execute body step functions, timers, * collision handlers. */ world_step(world, L); /* * Handle user input. To be more responsive, we do this * here between steps too. */ process_events(L); if (world->killme) break; /* No need to keep going. */ } } /* * Deal with worlds that have either been destroyed or created in the * loop above. Must do this here so scripts get a chance to set * everything up before a frame is rendered. */ for (World *world = mp_first(&mp_world); world != NULL;) { if (world->killme) { /* * Remove dying worlds. Take care to get next world * pointer before destruction. */ World *tmp = world; world = mp_next(world); world_free(tmp); continue; } /* Perform the initial step on recently created worlds. */ if (world->static_body.step == 0) { /* * We must give scripts control over what the contents * of the world look like before drawing it. Otherwise * we get such artifacts as camera centered on origin * even though it should be tracking a player character. */ world_step(world, L); } world = mp_next(world); } /* * Draw what each camera sees. */ render_clear(); for (Camera *cam = cam_list; cam != NULL; cam = cam->next) { if (!cam->disabled) render(cam); } #ifndef NDEBUG /* Debug stuff is drawn over normal stuff. */ if (debug_cam != NULL && debug_cam->objtype == OBJTYPE_CAMERA) render_debug(debug_cam); #endif }
static int opt_set(void *opts, const struct opt_def *def, const char **val, struct region *region, uint32_t errcode, uint32_t field_no) { int64_t ival; uint64_t uval; char *errmsg = tt_static_buf(); double dval; uint32_t str_len; const char *str; char *ptr; char *opt = ((char *) opts) + def->offset; switch (def->type) { case OPT_BOOL: if (mp_typeof(**val) != MP_BOOL) goto type_mismatch_err; store_bool(opt, mp_decode_bool(val)); break; case OPT_UINT32: if (mp_typeof(**val) != MP_UINT) goto type_mismatch_err; uval = mp_decode_uint(val); if (uval > UINT32_MAX) goto type_mismatch_err; store_u32(opt, uval); break; case OPT_INT64: if (mp_read_int64(val, &ival) != 0) goto type_mismatch_err; store_u64(opt, ival); break; case OPT_FLOAT: if (mp_read_double(val, &dval) != 0) goto type_mismatch_err; store_double(opt, dval); break; case OPT_STR: if (mp_typeof(**val) != MP_STR) goto type_mismatch_err; str = mp_decode_str(val, &str_len); str_len = MIN(str_len, def->len - 1); memcpy(opt, str, str_len); opt[str_len] = '\0'; break; case OPT_STRPTR: if (mp_typeof(**val) != MP_STR) goto type_mismatch_err; str = mp_decode_str(val, &str_len); if (str_len > 0) { ptr = (char *) region_alloc(region, str_len + 1); if (ptr == NULL) { diag_set(OutOfMemory, str_len + 1, "region", "opt string"); return -1; } memcpy(ptr, str, str_len); ptr[str_len] = '\0'; assert (strlen(ptr) == str_len); } else { ptr = NULL; } *(const char **)opt = ptr; break; case OPT_ENUM: if (mp_typeof(**val) != MP_STR) goto type_mismatch_err; str = mp_decode_str(val, &str_len); if (def->to_enum == NULL) { ival = strnindex(def->enum_strs, str, str_len, def->enum_max); } else { ival = def->to_enum(str, str_len); } switch(def->enum_size) { case sizeof(uint8_t): store_u8(opt, (uint8_t)ival); break; case sizeof(uint16_t): store_u16(opt, (uint16_t)ival); break; case sizeof(uint32_t): store_u32(opt, (uint32_t)ival); break; case sizeof(uint64_t): store_u64(opt, (uint64_t)ival); break; default: unreachable(); }; break; case OPT_ARRAY: if (mp_typeof(**val) != MP_ARRAY) goto type_mismatch_err; ival = mp_decode_array(val); assert(def->to_array != NULL); if (def->to_array(val, ival, opt, errcode, field_no) != 0) return -1; break; case OPT_LEGACY: mp_next(val); break; default: unreachable(); } return 0; type_mismatch_err: snprintf(errmsg, TT_STATIC_BUF_LEN, "'%s' must be %s", def->name, opt_type_strs[def->type]); diag_set(ClientError, errcode, field_no, errmsg); return -1; }