int sampgdk_fakeamx_push_float(float value, cell *address) { return sampgdk_fakeamx_push_cell(amx_ftoc(value), address); }
cell sampgdk_native_invoke_array(AMX_NATIVE native, const char *format, void **args) { AMX *amx = sampgdk_fakeamx_amx(); char *format_ptr = (char *)format; /* cast away const for strtol() */ cell i = 0; cell params[_SAMPGDK_NATIVE_MAX_ARGS + 1]; cell size[_SAMPGDK_NATIVE_MAX_ARGS] = {0}; char type[_SAMPGDK_NATIVE_MAX_ARGS]; int needs_size = -1; enum { ST_READ_SPEC, ST_NEED_SIZE, ST_READING_SIZE, ST_READING_SIZE_ARG, ST_READ_SIZE } state = ST_READ_SPEC; cell retval; while (*format_ptr != '\0' && i < _SAMPGDK_NATIVE_MAX_ARGS) { switch (state) { case ST_READ_SPEC: switch (*format_ptr) { case 'i': /* integer */ case 'd': /* integer */ params[i + 1] = *(int *)args[i]; break; case 'b': /* boolean */ params[i + 1] = *(bool *)args[i]; break; case 'f': /* floating-point */ { float value = *(float *)args[i]; params[i + 1] = amx_ftoc(value); break; } case 'r': /* const reference */ case 'R': /* non-const reference */ { cell *ptr = args[i]; sampgdk_fakeamx_push_cell(*ptr, ¶ms[i + 1]); size[i] = sizeof(cell); break; } case 's': /* const string */ { char *str = args[i]; int str_size; sampgdk_fakeamx_push_string(str, &str_size, ¶ms[i + 1]); size[i] = str_size; break; } case 'S': /* non-const string */ case 'a': /* const array */ case 'A': /* non-const array */ needs_size = i; state = ST_NEED_SIZE; break; default: sampgdk_log_warn("Unrecognized type specifier '%c'", *format_ptr); } type[i++] = *format_ptr++; break; case ST_NEED_SIZE: if (*format_ptr == '[') { state = ST_READING_SIZE; } else { sampgdk_log_warn("Bad format string: expected '[' but got '%c'", *format_ptr); } format_ptr++; break; case ST_READING_SIZE: if (*format_ptr == '*') { format_ptr++; state = ST_READING_SIZE_ARG; } else { size[needs_size] = (int)strtol(format_ptr, &format_ptr, 10); state = ST_READ_SIZE; } break; case ST_READING_SIZE_ARG: { int index = (int)strtol(format_ptr, &format_ptr, 10); size[needs_size] = *(int *)args[index]; state = ST_READ_SIZE; break; } case ST_READ_SIZE: { if (*format_ptr == ']') { switch (type[needs_size]) { case 'a': case 'A': case 'S': if (size[needs_size] > 0) { sampgdk_fakeamx_push_array(args[needs_size], size[needs_size], ¶ms[needs_size + 1]); } else { sampgdk_log_warn("Invalid buffer size"); } break; } needs_size = -1; state = ST_READ_SPEC; } else { sampgdk_log_warn("Bad format string (expected ']' but got '%c')", *format_ptr); } format_ptr++; break; } } } if (*format_ptr != '\0') { sampgdk_log_warn("Too many native arguments (at most %d allowed)", _SAMPGDK_NATIVE_MAX_ARGS); } params[0] = i * sizeof(cell); retval = native(amx, params); while (--i >= 0) { if (size[i] > 0) { /* If this is an output parameter we have to write the updated value * back to the argument. */ switch (type[i]) { case 'R': sampgdk_fakeamx_get_cell(params[i + 1], args[i]); break; case 'S': sampgdk_fakeamx_get_string(params[i + 1], args[i], size[i]); break; case 'A': sampgdk_fakeamx_get_array(params[i + 1], args[i], size[i]); break; } sampgdk_fakeamx_pop(params[i + 1]); } } return retval; }