38 #define ED_MAX_KEYS_PER_ENT 32
39 #define ED_MAX_TOKEN_LEN 512
40 #define ED_MAX_ERR_LEN 512
52 #define ED_RETURN_ERROR(...) \
54 snprintf(lastErr, sizeof(lastErr), __VA_ARGS__); \
62 #define ED_TEST_RETURN_ERROR(condition,...) \
64 snprintf(lastErr, sizeof(lastErr), __VA_ARGS__); \
73 #define ED_PASS_ERROR(function_call) \
74 if ((function_call) == ED_ERROR) { \
84 #define ED_PASS_ERROR_EXTRAMSG(function_call,...) \
85 if ((function_call) == ED_ERROR) { \
86 snprintf(lastErrExtra, sizeof(lastErr), __VA_ARGS__); \
87 strncat(lastErr, lastErrExtra, sizeof(lastErr) - strlen(lastErr) -1); \
123 for (
int i = 0;
i < numDefs;
i++) {
140 if (
Q_streq(strType,
"V_FLOAT"))
142 else if (
Q_streq(strType,
"V_INT"))
144 else if (
Q_streq(strType,
"V_BOOL"))
146 else if (
Q_streq(strType,
"V_STRING"))
149 ED_RETURN_ERROR(
"ED_Type2Constant: type string not recognised: \"%s\"", strType);
169 snprintf(
lastErr,
sizeof(
lastErr),
"ED_Constant2Type: constant not recognised");
186 const char* buf_p = str;
188 for (i = 0; buf_p; i++) {
192 ED_TEST_RETURN_ERROR(i >= n,
"ED_GetIntVectorFromString: v[%i] too small for ints from string \"%s\"", n, str);
195 ED_TEST_RETURN_ERROR(i != n,
"ED_GetIntVectorFromString: v[%i] wrong size for ints from string \"%s\"", n, str);
235 || strstr(value,
"0x") || strstr(value,
"0X"),
236 "infinity, NaN, hex (0x...) not allowed. found \"%s\"", value);
237 switch (floatOrInt) {
239 parsedNumber->
f = strtof(value, &end_p);
240 ED_TEST_RETURN_ERROR(insistPositive && parsedNumber->
f < 0.0f,
"ED_CheckNumber: not positive %s", value);
243 parsedNumber->
i = (
int)strtol(value, &end_p, 10);
247 parsedNumber->
i = (
int)strtol(value, &end_p, 10);
248 ED_TEST_RETURN_ERROR(insistPositive && parsedNumber->
i < 0,
"ED_CheckNumber: not positive %s", value);
251 ED_RETURN_ERROR(
"ED_CheckNumber: type to test against not recognised");
255 "problem with numeric value: \"%s\" declared as %s. (might be relevant: only use whitespace to delimit values)",
272 const int useRangeIndex = (keyDef->
numRanges == 1) ? 0 : index;
274 const float discreteFloatEpsilon = 0.0001f;
277 assert(useRangeIndex < keyDef->numRanges);
278 kr = keyDef->
ranges[useRangeIndex];
285 "ED_CheckRange: %.1f out of range, \"%s\" in %s",
286 parsedNumber.
f, kr->
str, keyDef->
name);
290 if (fabs(parsedNumber.
f - kr->
fArr[j]) < discreteFloatEpsilon)
297 "ED_CheckRange: %i out of range, \"%s\" in %s",
298 parsedNumber.
i, kr->
str, keyDef->
name);
302 if (kr->
iArr[j] == parsedNumber.
i)
307 ED_RETURN_ERROR(
"ED_CheckRange: type to test against not recognised in %s", keyDef->
name);
309 ED_RETURN_ERROR(
"ED_CheckRange: value not specified in range definition, \"%s\" in %s",
324 static char tokBuf[64];
325 const char* buf_p = tokBuf;
327 strncpy(tokBuf, value,
sizeof(tokBuf));
336 " in key \"%s\"", keyDef->
name);
343 ED_TEST_RETURN_ERROR(i != keyDef->
vLen,
"ED_CheckNumericType: %i elements in vector that should have %i for \"%s\" key",
357 int ED_Check (
const char* classname,
const char*
key,
const char* value)
386 ED_RETURN_ERROR(
"ED_CheckTypeEntityKey: type not recognised in key def");
396 static char tokBuf[64];
400 const char* partToken;
406 "ED_ParseType: type string too long for buffer for key %s", kd->
name);
407 strncpy(tokBuf, parsedToken,
sizeof(tokBuf));
408 tokBuf[
sizeof(tokBuf) - 1] =
'\0';
413 if (
Q_streq(
"SIGNED", partToken)) {
415 }
else if (
Q_streq(
"UNSIGNED", partToken)) {
420 if (partToken[0] !=
'\0') {
429 vectorLen = atoi(partToken);
432 "ED_ParseType: problem with vector length \"%s\" in key %s",
433 partToken, kd->
name);
434 kd->
vLen = strlen(partToken) ? (vectorLen ? vectorLen : 1) : 1;
444 if (
Q_streq(
"optional", blockName))
446 else if (
Q_streq(
"mandatory", blockName))
448 else if (
Q_streq(
"abstract", blockName))
450 else if (
Q_streq(
"default", blockName))
452 else if (
Q_streq(
"type", blockName))
454 else if (
Q_streq(
"range", blockName))
481 snprintf(
lastErr,
sizeof(
lastErr),
"ED_Constant2Block: constant not recognised");
490 char* newStr = strdup(rangeStr);
495 if(!newRanges || !newStr || !newRange) {
501 newRange->
str = newStr;
516 const char* newName,
const char* newVal,
const int mode)
523 keyDef = &keyDefsBuf[(*numKeyDefsSoFar_p)++];
525 keyDef->
name = strdup(newName);
531 "Duplicate %s for %s key. second value: %s",
ED_Constant2Block(mode), newName, newVal);
540 keyDef->
desc = strdup(newVal);
568 int tokensOnLevel0 = 0;
579 if (parsedToken[0] ==
'\0' && braceLevel == 0)
582 if (parsedToken[0] ==
'{') {
591 if (parsedToken[0] ==
'}') {
595 if (braceLevel == 0) {
606 if (braceLevel == 0) {
607 if (tokensOnLevel0 == 0 && !
Q_streq(parsedToken,
"entity"))
610 if (tokensOnLevel0 == 1) {
612 ED_TEST_RETURN_ERROR(prevED,
"ED_ParseEntities: duplicate entity definition \"%s\"", parsedToken);
619 if (tokensOnLevel0 > 1)
620 ED_RETURN_ERROR(
"Start of entity block expected found \"%s\"", parsedToken);
627 if (
'\0' == parsedToken[0])
628 ED_RETURN_ERROR(
"key name null string, \"\", or missing closing brace");
629 strncpy(lastTokenBuf, parsedToken,
sizeof(lastTokenBuf));
630 lastTokenBuf[
sizeof(lastTokenBuf) - 1] =
'\0';
657 " while checking default block entry agrees with type")
671 static float fbuf[32];
676 for (
int i = 0;
i < kd->numRanges ;
i++) {
679 const char* tmpRange_p = kr->
str;
680 ED_TEST_RETURN_ERROR(!keyType || (keyType &
ED_TYPE_STRING),
"ED_ProcessRanges: ranges may not be specified for strings. note that V_STRING is the default type. %s in %s",
681 kd->name, ed->classname);
684 const char* tok =
Com_Parse(&tmpRange_p);
689 ED_TEST_RETURN_ERROR(numElements != 1,
"ED_ProcessRanges: problem with continuous range, \"%s\" in %s in %s",
690 kr->
str, kd->name, ed->classname);
697 ibuf[numElements++] = atoi(tok);
700 fbuf[numElements++] = atof(tok);
708 "ED_ProcessRanges: continuous range should only have 2 elements, upper and lower bounds, \"%s\" in %s in %s",
709 kr->
str, kd->name, ed->classname);
711 const size_t size = numElements *
sizeof(
int);
712 kr->
iArr = (
int*)malloc(size);
714 memcpy(kr->
iArr, ibuf, size);
716 const size_t size = numElements *
sizeof(float);
717 kr->
fArr = (
float*)malloc(size);
719 memcpy(kr->
fArr, fbuf, size);
723 "ED_ProcessRanges: if range definitions are supplied, "
724 "there must be one (which is applied to each element of a vector), "
725 "or one for each element of the vector. "
726 "%s in %s has %i elements in vector and %i range definitions",
727 ed->classname, kd->name, kd->vLen, kd->numRanges);
807 snprintf(
lastErr,
sizeof(
lastErr),
"ED_GetKeyDefEntity: no key definition for %s found in entity %s entities.ufo", keyname, ed->
classname);
823 snprintf(
lastErr,
sizeof(
lastErr),
"ED_GetEntityDef: no entity definition for %s found in entities.ufo", classname);
835 free(kd->defaultVal);
837 for (
int i = 0;
i < kd->numRanges ;
i++) {
int ED_CheckKey(const entityKeyDef_t *kd, const char *value)
as ED_Check, but where the entity and key are known, so takes different arguments.
static int ED_AllocEntityDef(entityKeyDef_t *newKeyDefs, int numKeyDefs, int entityIndex)
allocate space for key defs etc, pointers for which are stored in the entityDef_t ...
static int ED_GetIntVectorFromString(const char *str, int v[], const int n)
parses an int array from a string
QGL_EXTERN GLint GLenum type
const entityKeyDef_t * ED_GetKeyDefEntity(const entityDef_t *ed, const char *keyname, const int abstract)
searches for the parsed key def, when the entity def is known
static int ED_CheckNumericType(const entityKeyDef_t *keyDef, const char *value, const int type)
tests if a value string matches the type for this key. this includes each element of a numeric array...
const entityDef_t * ED_GetEntityDef(const char *classname)
searches for the parsed entity def by classname
static char lastErrExtra[ED_MAX_ERR_LEN]
static int ED_CheckNumber(const char *value, const int floatOrInt, const int insistPositive, int_float_tu *parsedNumber)
checks that a string represents a single number
static int ED_CheckDefaultTypes(void)
checks if the default block entries meet the type and range definitions.
Shared parsing functions.
entityDef_t entityDefs[ED_MAX_DEFS+1]
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define ED_INSIST_POSITIVE
#define ED_RETURN_ERROR(...)
write an error message and exit the current function returning ED_ERROR
Handles definition of entities, parsing them from entities.ufo.
static int ED_PairParsed(entityKeyDef_t keyDefsBuf[], int *numKeyDefsSoFar_p, const char *newName, const char *newVal, const int mode)
static int ED_ParseType(entityKeyDef_t *kd, const char *parsedToken)
takes a type string (eg "V_FLOAT 6") and configures entity def
static const char * ED_Constant2Block(int constInt)
converts an internal constant integer to a string representation of a type (eg V_FLOAT) ...
static int ED_Block2Constant(const char *blockName)
converts a block name (eg "optional") to an constant (eg ED_OPTIONAL).
#define ED_MAX_KEYS_PER_ENT
static int ED_Type2Constant(const char *strType)
converts a string representation of a type (eg V_FLOAT) to the appropriate internal constant integer ...
static int ED_ProcessRanges(void)
finish parsing ranges. Could not be done earlier as would not have necessarily known types and defaul...
static int ED_ParseEntities(const char **data_p)
int ED_Check(const char *classname, const char *key, const char *value)
tests if a value string matches the type for this key. Also checks the value against the range...
#define ED_PASS_ERROR_EXTRAMSG(function_call,...)
if the function returns ED_ERROR, then the function that the macro is in also returns ED_ERROR...
int ED_Parse(const char *data_p)
char parsedToken[MAX_TOKEN_CHARS]
#define ED_PASS_ERROR(function_call)
if the function returns ED_ERROR, then the function that the macro is in also returns ED_ERROR...
const entityKeyDef_t * ED_GetKeyDef(const char *classname, const char *keyname, const int abstract)
searches for the parsed key def
static int ED_CheckRange(const entityKeyDef_t *keyDef, const int type, const int index, int_float_tu parsedNumber)
check a value against the range for the key
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
static entityKeyDef_t * ED_FindKeyDefInArray(entityKeyDef_t keyDefs[], int numDefs, const char *name, int parseMode)
search for an existing keyDef to add a new parsed pair info to.
const char * ED_GetLastError(void)
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
int ED_GetIntVector(const entityKeyDef_t *kd, int v[], const int n)
parses a value from the definition
struct entityKeyDef_s entityKeyDef_t
static const char * ED_Constant2Type(int constInt)
converts an internal constant integer to a string representation of a type (eg V_FLOAT) ...
#define ED_TEST_RETURN_ERROR(condition,...)
test a condition, write an error message and exit the current function with ED_ERROR ...
static int ED_AllocRange(entityKeyDef_t *kd, const char *rangeStr)
QGL_EXTERN int GLboolean GLfloat * v
entityKeyRange_t ** ranges
static char lastErr[ED_MAX_ERR_LEN]