diff options
Diffstat (limited to 'tool_src/QvLib/QvFieldData.cpp')
| -rw-r--r-- | tool_src/QvLib/QvFieldData.cpp | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/tool_src/QvLib/QvFieldData.cpp b/tool_src/QvLib/QvFieldData.cpp new file mode 100644 index 0000000..afe55da --- /dev/null +++ b/tool_src/QvLib/QvFieldData.cpp @@ -0,0 +1,266 @@ +#include <QvInput.h> +#include <QvReadError.h> +#include <QvField.h> +#include <QvFieldData.h> +#include <QvUnknownNode.h> + +#define OPEN_BRACE_CHAR '[' +#define CLOSE_BRACE_CHAR ']' +#define VALUE_SEPARATOR_CHAR ',' + +struct QvFieldEntry { + QvName name; + long offset; +}; + +struct QvEnumEntry { + QvName typeName; + int num; + int arraySize; + int *vals; + QvName *names; + QvEnumEntry(const QvName &name); + ~QvEnumEntry(); + + static int growSize; +}; + +int QvEnumEntry::growSize = 6; + +QvEnumEntry::QvEnumEntry(const QvName &name) +{ + typeName = name; + num = 0; + arraySize = growSize; + vals = new int[arraySize]; + names = new QvName[arraySize]; +} + +QvEnumEntry::~QvEnumEntry() +{ + delete [] vals; + delete [] names; +} + +QvFieldData::~QvFieldData() +{ + struct QvFieldEntry *tmpField; + struct QvEnumEntry *tmpEnum; + + for (int i=0; i<fields.getLength(); i++) { + tmpField = (struct QvFieldEntry *)fields[i]; + delete tmpField; + } + + for (int j=0; j<enums.getLength(); j++) { + tmpEnum = (struct QvEnumEntry *)enums[j]; + delete tmpEnum; + } +} + +void +QvFieldData::addField(QvNode *defobj, const char *fieldName, + const QvField *field) +{ + struct QvFieldEntry *newField = new struct QvFieldEntry; + newField->name = fieldName; + newField->offset = (const char *) field - (const char *) defobj; + + fields.append((void *) newField); +} + +const QvName & +QvFieldData::getFieldName(int index) const +{ + return ((QvFieldEntry *) fields[index])->name; +} + +QvField * +QvFieldData::getField(const QvNode *object, int index) const +{ + return (QvField *) ((char *) object + + ((QvFieldEntry *) fields[index])->offset); +} + +#include <ctype.h> +static QvName +stripWhite(const char *name) +{ + int firstchar = -1; + int lastchar = -1; + int lastwhite = -1; + int i =0; + for ( i=0; name[i]; i++) { + if (isspace(name[i])) + lastwhite = i; + else { + if (firstchar == -1) firstchar = i; + lastchar = i; + } + } + + if (lastchar > lastwhite) + return QvName(&name[firstchar]); + + char buf[500]; + int b; + for (b=0, i=firstchar; i<=lastchar; i++, b++) + buf[b] = name[i]; + buf[b] = 0; + return QvName(buf); +} + +void +QvFieldData::addEnumValue(const char *typeNameArg, + const char *valNameArg, int val) +{ + struct QvEnumEntry *e = NULL; + QvName typeName = stripWhite(typeNameArg); + QvName valName = stripWhite(valNameArg); + + for (int i=0; i<enums.getLength(); i++) { + e = (struct QvEnumEntry *) enums[i]; + if (e->typeName == typeName) + break; + else + e = NULL; + } + if (e == NULL) { + e = new QvEnumEntry(typeName); + enums.append((void*) e); + } + if (e->num == e->arraySize) { + e->arraySize += QvEnumEntry::growSize; + int *ovals = e->vals; + QvName *onames = e->names; + e->vals = new int[e->arraySize]; + e->names = new QvName[e->arraySize]; + for (int i=0; i<e->num; i++) { + e->vals[i] = ovals[i]; + e->names[i] = onames[i]; + } + delete [] ovals; + delete [] onames; + } + e->vals[e->num] = val; + e->names[e->num] = valName; + e->num++; +} + +void +QvFieldData::getEnumData(const char *typeNameArg, int &num, + const int *&vals, const QvName *&names) +{ + QvName typeName = stripWhite(typeNameArg); + + for (int i=0; i<enums.getLength(); i++) { + struct QvEnumEntry *e = (struct QvEnumEntry *) enums[i]; + if (e->typeName == typeName) { + num = e->num; + vals = e->vals; + names = e->names; + return; + } + } + num = 0; + vals = NULL; + names = NULL; +} + +QvBool +QvFieldData::readFieldTypes(QvInput *in, QvNode *object) +{ + QvBool gotChar; + QvName fieldType, fieldName; + char c; + + if (! ((gotChar = in->read(c)) || c != OPEN_BRACE_CHAR)) + return FALSE; + + if (in->read(c) && c == CLOSE_BRACE_CHAR) + return TRUE; + + in->putBack(c); + + QvBool alreadyHasFields = (object->isBuiltIn || getNumFields() != 0); + + while (TRUE) { + + if (! in->read(fieldType, TRUE) || ! in->read(fieldName, TRUE)) + return FALSE; + + if (! alreadyHasFields) { + QvField *fld = QvField::createInstanceFromName(fieldType); + fld->setContainer(object); + addField(object, fieldName.getString(), fld); + } + + if (! in->read(c)) + return FALSE; + if (c == VALUE_SEPARATOR_CHAR) { + + if (in->read(c)) { + if (c == CLOSE_BRACE_CHAR) + return TRUE; + else + in->putBack(c); + } + } + else if (c == CLOSE_BRACE_CHAR) + return TRUE; + else + return FALSE; + } +} + +QvBool +QvFieldData::read(QvInput *in, QvNode *object, + QvBool errorOnUnknownField) const +{ + QvName fieldName; + + if (fields.getLength() == 0) return TRUE; + + while (TRUE) { + + if (! in->read(fieldName, TRUE) || ! fieldName) + return TRUE; + + QvBool foundName; + if (! read(in, object, fieldName, foundName)) + return FALSE; + + if (!foundName) { + if (errorOnUnknownField) { + QvReadError::post(in, "Unknown field \"%s\"", + fieldName.getString()); + return FALSE; + } + else { + in->putBack(fieldName.getString()); + return TRUE; + } + } + } +} + +QvBool +QvFieldData::read(QvInput *in, QvNode *object, + const QvName &fieldName, QvBool &foundName) const +{ + int i = 0; + for ( i = 0; i < fields.getLength(); i++) { + QvName fni = getFieldName(i); + + if (fieldName == fni) { + if (! getField(object, i)->read(in, fieldName)) + return FALSE; + break; + } + } + if (i == fields.getLength()) + foundName = FALSE; + else foundName = TRUE; + + return TRUE; +} |
