📄 xmlio.cpp
字号:
#include "StdAfx.h"
#include "fastdb.h"
#include "symtab.h"
#include "compiler.h"
#include "database.h"
#include "hashtab.h"
#include "ttree.h"
#include "xmlio.h"
inline int dbXmlScanner::get
()
{
int ch = getc(in);
if (ch == '\n')
{
pos = 0;
line += 1;
}
else if (ch == '\t')
{
pos = DOALIGN(pos + 1, 8);
}
else
{
pos += 1;
}
return ch;
}
inline void dbXmlScanner::unget(int ch)
{
if (ch != EOF)
{
if (ch != '\n')
{
pos -= 1;
}
else
{
line -= 1;
}
ungetc(ch, in);
}
}
dbXmlScanner::token dbXmlScanner::scan()
{
int ch, i, pos;
bool floatingPoint;
retry:
do
{
if ((ch = get
()) == EOF)
{
return xml_eof;
}
}
while (ch <= ' ');
switch (ch)
{
case '<':
ch = get
();
if (ch == '?')
{
while ((ch = get
()) != '?')
{
if (ch == EOF)
{
return xml_error;
}
}
if ((ch = get
()) != '>')
{
return xml_error;
}
goto retry;
}
if (ch != '/')
{
unget(ch);
return xml_lt;
}
return xml_lts;
case '>':
return xml_gt;
case '/':
ch = get
();
if (ch != '>')
{
unget(ch);
return xml_error;
}
return xml_gts;
case '=':
return xml_eq;
case '"':
i = 0;
while (true)
{
ch = get
();
switch (ch)
{
case EOF:
return xml_error;
case '&':
switch (get
())
{
case 'a':
if (get
() != 'm' || get
() != 'p' || get
() != ';')
{
return xml_error;
}
ch = '&';
break;
case 'l':
if (get
() != 't' || get
() != ';')
{
return xml_error;
}
ch = '<';
break;
case 'g':
if (get
() != 't' || get
() != ';')
{
return xml_error;
}
ch = '>';
break;
case 'q':
if (get
() != 'u' || get
() != 'o' || get
() != 't' || get
() != ';')
{
return xml_error;
}
ch = '"';
break;
default:
return xml_error;
}
break;
case '"':
slen = i;
sconst[i] = 0;
return xml_sconst;
}
if ((size_t)i+1 >= size)
{
char* newBuf = new char[size *= 2];
memcpy(newBuf, sconst, slen);
sconst = newBuf;
}
sconst[i++] = (char)ch;
}
case '-':
case '+':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
i = 0;
floatingPoint = false;
while (true)
{
if ((size_t)i == size)
{
return xml_error;
}
if (!isdigit(ch) && ch != '-' && ch != '+' && ch != '.' && ch != 'E')
{
unget(ch);
sconst[i] = '\0';
if (floatingPoint)
{
return sscanf(sconst, "%lf%n", &fconst, &pos) == 1 && pos == i
? xml_fconst : xml_error;
}
else
{
return sscanf(sconst, INT8_FORMAT "%n", &iconst, &pos) == 1 && pos == i
? xml_iconst : xml_error;
}
}
sconst[i++] = (char)ch;
if (ch == '.')
{
floatingPoint = true;
}
ch = get
();
}
default:
i = 0;
while (isalnum(ch) || ch == '-' || ch == ':' || ch == '_')
{
if (i == MaxIdentSize)
{
return xml_error;
}
ident[i++] = (char)ch;
ch = get
();
}
unget(ch);
if (i == MaxIdentSize || i == 0)
{
return xml_error;
}
ident[i] = '\0';
return xml_ident;
}
}
#define EXPECT(x) scanner.expect(__LINE__, x)
dbXmlIo::dbXmlIo(dbDatabase* db) : m_db(db)
{}
dbXmlIo::~dbXmlIo()
{}
bool skipElement(dbXmlScanner& scanner)
{
int depth = 1;
do
{
switch (scanner.scan())
{
case dbXmlScanner::xml_lt:
depth += 1;
continue;
case dbXmlScanner::xml_lts:
depth -= 1;
if (depth < 0 || !EXPECT(dbXmlScanner::xml_ident) || !EXPECT(dbXmlScanner::xml_gt))
{
return false;
}
break;
case dbXmlScanner::xml_gts:
depth -= 1;
break;
default:
continue;
}
}
while (depth != 0);
return true;
}
bool dbXmlIo::importRecord(char* terminator, dbFieldDescriptor* fieldList, byte* rec, dbXmlScanner& scanner)
{
dbXmlScanner::token tkn;
while ((tkn = scanner.scan()) != dbXmlScanner::xml_lts)
{
if (tkn != dbXmlScanner::xml_lt || !EXPECT(dbXmlScanner::xml_ident)
|| !EXPECT(dbXmlScanner::xml_gt))
{
return false;
}
char* fieldName = scanner.getIdentifier();
dbSymbolTable::add
(fieldName, tkn_ident, FASTDB_CLONE_ANY_IDENTIFIER);
dbFieldDescriptor* fd = fieldList;
while (true)
{
if (fd->name == fieldName)
{
if (!importField(fd->name, fd, rec, scanner))
{
return false;
}
break;
}
if ((fd = fd->next) == fieldList)
{
if (!skipElement(scanner))
{
return false;
}
break;
}
}
}
return EXPECT(terminator) && EXPECT(dbXmlScanner::xml_gt);
}
#define HEX_DIGIT(ch) ((ch) >= 'a' ? ((ch) - 'a' + 10) : (ch) >= 'A' ? (((ch) - 'A' + 10)) : ((ch) - '0'))
bool dbXmlIo::importField(char* terminator, dbFieldDescriptor* fd, byte* rec, dbXmlScanner& scanner)
{
dbXmlScanner::token tkn;
int i;
long id;
byte* dst = rec + fd->appOffs;
switch (fd->type)
{
case dbField::tpStructure:
return importRecord(terminator, fd->components, rec, scanner);
case dbField::tpArray:
{
int arrSize = 8;
int elemSize = fd->components->appSize;
byte* arr = (byte*)tmpAlloc.alloc(elemSize*arrSize);
memset(arr, 0, elemSize*arrSize);
for (i = 0; (tkn = scanner.scan()) == dbXmlScanner::xml_lt; i++)
{
if (!EXPECT("array-element")
|| !EXPECT(dbXmlScanner::xml_gt))
{
return false;
}
if (i == arrSize)
{
arrSize *= 2;
byte* newArr = (byte*)tmpAlloc.alloc(elemSize*arrSize);
memcpy(newArr, arr, i*elemSize);
memset(newArr + i*elemSize, 0, i*elemSize);
arr = newArr;
}
importField("array-element", fd->components, arr + i*elemSize, scanner);
}
dbAnyArray::arrayAllocator((dbAnyArray*)dst, arr, i);
return tkn == dbXmlScanner::xml_lts
&& EXPECT(terminator)
&& EXPECT(dbXmlScanner::xml_gt);
}
case dbField::tpReference:
if (!EXPECT(dbXmlScanner::xml_lt)
|| !EXPECT("ref")
|| !EXPECT("id")
|| !EXPECT(dbXmlScanner::xml_eq)
|| !EXPECT(dbXmlScanner::xml_sconst)
|| sscanf(scanner.getString(), "%ld", &id) != 1
|| !EXPECT(dbXmlScanner::xml_gts))
{
return false;
}
*(oid_t*)dst = mapId(id);
break;
case dbField::tpBool:
switch (scanner.scan())
{
case dbXmlScanner::xml_iconst:
*(bool*)dst = scanner.getInt() != 0;
break;
case dbXmlScanner::xml_fconst:
*(bool*)dst = scanner.getReal() != 0.0;
break;
default:
fprintf(stderr, "Failed to convert field '%s'\n", fd->name);
}
break;
case dbField::tpInt1:
switch (scanner.scan())
{
case dbXmlScanner::xml_iconst:
*(int1*)dst = (int1)scanner.getInt();
break;
case dbXmlScanner::xml_fconst:
*(int1*)dst = (int1)scanner.getReal();
break;
default:
fprintf(stderr, "Failed to convert field '%s'\n", fd->name);
}
break;
case dbField::tpInt2:
switch (scanner.scan())
{
case dbXmlScanner::xml_iconst:
*(int2*)dst = (int2)scanner.getInt();
break;
case dbXmlScanner::xml_fconst:
*(int2*)dst = (int2)scanner.getReal();
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -