aboutsummaryrefslogtreecommitdiff
path: root/tool_src/QvLib/QvFieldData.cpp
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
commitc068f22329d5cc722622a2183bbb22eef2093df7 (patch)
tree12d56c1aede67988a55e241364606bfbb4dba933 /tool_src/QvLib/QvFieldData.cpp
downloadopenparsec-main.tar.xz
openparsec-main.zip
initial importHEADmain
Diffstat (limited to 'tool_src/QvLib/QvFieldData.cpp')
-rw-r--r--tool_src/QvLib/QvFieldData.cpp266
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;
+}