From c068f22329d5cc722622a2183bbb22eef2093df7 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 24 Aug 2026 11:16:07 +0200 Subject: initial import --- tool_src/QvLib/QvInput.cpp | 568 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 568 insertions(+) create mode 100644 tool_src/QvLib/QvInput.cpp (limited to 'tool_src/QvLib/QvInput.cpp') diff --git a/tool_src/QvLib/QvInput.cpp b/tool_src/QvLib/QvInput.cpp new file mode 100644 index 0000000..2f77669 --- /dev/null +++ b/tool_src/QvLib/QvInput.cpp @@ -0,0 +1,568 @@ +#include +#include +#include +#include +#include +#include +#include + +#define CURVERSION 1.0 // Current version of file format +#define COMMENT_CHAR '#' + +static const int numValidASCIIHeaders = 1; +struct headerStorage +{ + const char *string; + float version; +}; + +static const headerStorage ASCIIHeader[1] = { + { "#VRML V1.0 ascii", /* 20 chars */ 1.0 }, +}; + +float +QvInput::isASCIIHeader(const char *string) +{ + for (int i = 0; i < numValidASCIIHeaders; i++) { + if (strcmp(ASCIIHeader[i].string, string) == 0) + return ASCIIHeader[i].version; + } + return FALSE; +} + +QvInput::QvInput() +{ + setFilePointer(stdin); +} + +QvInput::~QvInput() +{ +} + +void +QvInput::setFilePointer(FILE *newFP) +{ + fp = newFP; + lineNum = 1; + version = CURVERSION; + readHeader = FALSE; + headerOk = TRUE; + backBufIndex = -1; +} + +float +QvInput::getVersion() +{ + if (! readHeader) + (void) checkHeader(); + + return version; +} + +QvBool +QvInput::get(char &c) +{ + QvBool ret; + + if (backBufIndex >= 0) { + c = backBuf.getString()[backBufIndex++]; + + if (c != '\0') + return TRUE; + + backBuf.makeEmpty(); + backBufIndex = -1; + } + + if (! readHeader && ! checkHeader()) + return FALSE; + + if (eof()) { + c = (char)EOF; + ret = FALSE; + } + + else { + int i = getc(fp); + + if (i == EOF) { + c = (char)EOF; + ret = FALSE; + } + else { + c = (char) i; + ret = TRUE; + } + } + + return ret; +} + +QvBool +QvInput::read(char &c) +{ + return (skipWhiteSpace() && get(c)); +} + +QvBool +QvInput::read(QvString &s) +{ + if (! skipWhiteSpace()) + return FALSE; + + QvBool quoted; + char c; + char bufStore[256]; + char *buf; + int bytesLeft; + + s.makeEmpty(); + + if (! get(c)) + return FALSE; + + quoted = (c == '\"'); + if (! quoted) + putBack(c); + + do { + buf = bufStore; + bytesLeft = sizeof(bufStore) - 1; + + while (bytesLeft > 0) { + + if (! get(*buf)) + break; + + if (quoted) { + if (*buf == '\"') + break; + + if (*buf == '\\') { + if ((get(c)) && c == '\"') + *buf = '\"'; + else + putBack(c); + } + + if (*buf == '\n') + lineNum++; + } + + else if (isspace(*buf)) { + putBack(*buf); + break; + } + + buf++; + bytesLeft--; + } + *buf = '\0'; + + s += bufStore; + + } while (bytesLeft == 0); + + return TRUE; +} + +QvBool +QvInput::read(QvName &n, QvBool validIdent) +{ + QvBool gotChar; + + if (! skipWhiteSpace()) + return FALSE; + + if (! validIdent) { + QvString s; + + if (! read(s)) + return FALSE; + + n = s; + } + + else { + char buf[256]; + char *b = buf; + char c; + + if ((gotChar = get(c)) && QvName::isIdentStartChar(c)) { + *b++ = c; + + while ((gotChar = get(c)) && QvName::isIdentChar(c)) { + if (b - buf < 255) + *b++ = c; + } + } + *b = '\0'; + + if (gotChar) + putBack(c); + + n = buf; + } + + return TRUE; +} + +#define READ_NUM(reader, readType, num, type) \ + QvBool ok; \ + if (! skipWhiteSpace()) \ + ok = FALSE; \ + else { \ + readType _tmp; \ + ok = reader(_tmp); \ + if (ok) \ + num = (type) _tmp; \ + } \ + return ok + +#define READ_INTEGER(num, type) \ + READ_NUM(readInteger, long, num, type) + +#define READ_UNSIGNED_INTEGER(num, type) \ + READ_NUM(readUnsignedInteger, unsigned long, num, type) + +#define READ_REAL(num, type) \ + READ_NUM(readReal, double, num, type) + +QvBool +QvInput::read(int &i) +{ + READ_INTEGER(i, int); +} + +QvBool +QvInput::read(unsigned int &i) +{ + READ_UNSIGNED_INTEGER(i, unsigned int); +} + +QvBool +QvInput::read(short &s) +{ + READ_INTEGER(s, short); +} + +QvBool +QvInput::read(unsigned short &s) +{ + READ_UNSIGNED_INTEGER(s, unsigned short); +} + +QvBool +QvInput::read(long &l) +{ + READ_INTEGER(l, long); +} + +QvBool +QvInput::read(unsigned long &l) +{ + READ_UNSIGNED_INTEGER(l, unsigned long); +} + +QvBool +QvInput::read(float &f) +{ + READ_REAL(f, float); +} + +QvBool +QvInput::read(double &d) +{ + READ_REAL(d, double); +} + +QvBool +QvInput::eof() const +{ + return feof(fp); +} + +void +QvInput::getLocationString(QvString &string) const +{ + char buf[128]; + sprintf(buf, "\tOccurred at line %3d", lineNum); + string = buf; +} + +void +QvInput::putBack(char c) +{ + if (c == (char) EOF) + return; + + if (backBufIndex >= 0) + --backBufIndex; + else + ungetc(c, fp); +} + +void +QvInput::putBack(const char *string) +{ + backBuf = string; + backBufIndex = 0; +} + +QvBool +QvInput::checkHeader() +{ + char c; + + readHeader = TRUE; + + if (get(c)) { + if (c == COMMENT_CHAR) { + char buf[256]; + int i = 0; + + buf[i++] = c; + while (get(c) && c != '\n') + buf[i++] = c; + buf[i] = '\0'; + if (c == '\n') + lineNum++; + + if ((version = isASCIIHeader(buf))) + return TRUE; + } + + else + putBack(c); + } + + QvReadError::post(this, "File does not have a valid header string"); + headerOk = FALSE; + return FALSE; +} + +QvBool +QvInput::skipWhiteSpace() +{ + char c; + QvBool gotChar; + + if (! readHeader && ! checkHeader()) + return FALSE; + + while (TRUE) { + + while ((gotChar = get(c)) && isspace(c)) + if (c == '\n') + lineNum++; + + if (! gotChar) + break; + + if (c == COMMENT_CHAR) { + while (get(c) && c != '\n') + ; + + if (eof()) + QvReadError::post(this, "EOF reached before end of comment"); + else + lineNum++; + } + else { + putBack(c); + break; } + } + + return TRUE; +} + +QvBool +QvInput::readInteger(long &l) +{ + char str[32]; + char *s = str; + + if (readChar(s, '-') || readChar(s, '+')) + s++; + + if (! readUnsignedIntegerString(s)) + return FALSE; + + l = strtol(str, NULL, 0); + + return TRUE; +} + +QvBool +QvInput::readUnsignedInteger(unsigned long &l) +{ + char str[32]; + if (! readUnsignedIntegerString(str)) + return FALSE; + + l = strtoul(str, NULL, 0); + + return TRUE; +} + +QvBool +QvInput::readUnsignedIntegerString(char *str) +{ + int minSize = 1; + char *s = str; + + if (readChar(s, '0')) { + + if (readChar(s + 1, 'x')) { + s += 2 + readHexDigits(s + 2); + minSize = 3; + } + + else + s += 1 + readDigits(s + 1); + } + + else + s += readDigits(s); + + if (s - str < minSize) + return FALSE; + + *s = '\0'; + + return TRUE; +} + +QvBool +QvInput::readReal(double &d) +{ + char str[32]; + int n; + char *s = str; + QvBool gotNum = FALSE; + + n = readChar(s, '-'); + if (n == 0) + n = readChar(s, '+'); + s += n; + + if ((n = readDigits(s)) > 0) { + gotNum = TRUE; + s += n; + } + + if (readChar(s, '.') > 0) { + s++; + + if ((n = readDigits(s)) > 0) { + gotNum = TRUE; + s += n; + } + } + + if (! gotNum) + return FALSE; + + n = readChar(s, 'e'); + if (n == 0) + n = readChar(s, 'E'); + + if (n > 0) { + s += n; + + n = readChar(s, '-'); + if (n == 0) + n = readChar(s, '+'); + s += n; + + if ((n = readDigits(s)) > 0) + s += n; + + else + return FALSE; } + + *s = '\0'; + + d = atof(str); + + return TRUE; +} + +int +QvInput::readDigits(char *string) +{ + char c, *s = string; + + while (get(c)) { + + if (isdigit(c)) + *s++ = c; + + else { + putBack(c); + break; + } + } + + return s - string; +} + +int +QvInput::readHexDigits(char *string) +{ + char c, *s = string; + + while (get(c)) { + + if (isxdigit(c)) + *s++ = c; + + else { + putBack(c); + break; + } + } + + return s - string; +} + +int +QvInput::readChar(char *string, char charToRead) +{ + char c; + int ret; + + if (! get(c)) + ret = 0; + + else if (c == charToRead) { + *string = c; + ret = 1; + } + + else { + putBack(c); + ret = 0; + } + + return ret; +} + +void +QvInput::addReference(const QvName &name, QvNode *node) +{ + refDict.enter((u_long) name.getString(), (void *) node); + + node->setName(name); +} + +QvNode * +QvInput::findReference(const QvName &name) const +{ + void *node; + + if (refDict.find((u_long) name.getString(), node)) + return (QvNode *) node; + + return NULL; +} -- cgit v1.2.3