📄 xml.cpp
字号:
#define HEX_DIGIT(ch) ((ch) >= 'a' ? ((ch) - 'a' + 10) : (ch) >= 'A' ? (((ch) - 'A' + 10)) : ((ch) - '0'))
bool dbDatabase::importField(char* terminator, dbFieldDescriptor* fd, byte* rec, dbXmlScanner& scanner)
{
dbXmlScanner::token tkn;
int i;
long id;
byte* dst = rec + fd->appOffs;
switch (fd->appType) {
case dbField::tpStructure:
return importRecord(terminator, fd->components, dst, scanner);
case dbField::tpArray:
{
int arrSize = 8;
int elemSize = fd->components->appSize;
byte* arr = (byte*)xmlContext->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*)xmlContext->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::tpRectangle:
if (!EXPECT("rectangle")
|| !EXPECT(dbXmlScanner::xml_gt)
|| !EXPECT(dbXmlScanner::xml_lt)
|| !EXPECT("vertex"))
{
return false;
} else {
rectangle& r = *(rectangle*)dst;
for (i = 0; i < rectangle::dim; i++) {
if (!EXPECT(dbXmlScanner::xml_ident)
|| !EXPECT(dbXmlScanner::xml_eq)
|| !EXPECT(dbXmlScanner::xml_sconst)
|| sscanf(scanner.getString(), "%d", &r.boundary[i]) != 1)
{
return false;
}
}
if (!EXPECT(dbXmlScanner::xml_gts)
|| !EXPECT(dbXmlScanner::xml_lt)
|| !EXPECT("vertex"))
{
return false;
}
for (i = 0; i < rectangle::dim; i++) {
if (!EXPECT(dbXmlScanner::xml_ident)
|| !EXPECT(dbXmlScanner::xml_eq)
|| !EXPECT(dbXmlScanner::xml_sconst)
|| sscanf(scanner.getString(), "%d", &r.boundary[rectangle::dim+i]) != 1)
{
return false;
}
}
if (!EXPECT(dbXmlScanner::xml_gts)
|| !EXPECT(dbXmlScanner::xml_lts)
|| !EXPECT("rectangle")
|| !EXPECT(dbXmlScanner::xml_gt))
{
return false;
}
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:
scanner.warning("Failed to convert field");
}
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:
scanner.warning("Failed to convert field");
}
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;
default:
scanner.warning("Failed to convert field");
}
break;
case dbField::tpInt4:
switch (scanner.scan()) {
case dbXmlScanner::xml_iconst:
*(int4*)dst = (int4)scanner.getInt();
break;
case dbXmlScanner::xml_fconst:
*(int4*)dst = (int4)scanner.getReal();
break;
default:
scanner.warning("Failed to convert field");
}
break;
case dbField::tpInt8:
switch (scanner.scan()) {
case dbXmlScanner::xml_iconst:
*(db_int8*)dst = scanner.getInt();
break;
case dbXmlScanner::xml_fconst:
*(db_int8*)dst = (int8)scanner.getReal();
break;
default:
scanner.warning("Failed to convert field");
}
break;
case dbField::tpReal4:
switch (scanner.scan()) {
case dbXmlScanner::xml_iconst:
*(real4*)dst = (real4)scanner.getInt();
break;
case dbXmlScanner::xml_fconst:
*(real4*)dst = (real4)scanner.getReal();
break;
default:
scanner.warning("Failed to convert field");
}
break;
case dbField::tpReal8:
switch (scanner.scan()) {
case dbXmlScanner::xml_iconst:
*(real8*)dst = (real8)scanner.getInt();
break;
case dbXmlScanner::xml_fconst:
*(real8*)dst = scanner.getReal();
break;
default:
scanner.warning("Failed to convert field");
}
break;
case dbField::tpString:
switch (scanner.scan()) {
case dbXmlScanner::xml_iconst:
case dbXmlScanner::xml_sconst:
case dbXmlScanner::xml_fconst:
{
char* str = (char*)xmlContext->tmpAlloc.alloc((scanner.getStringLength()+1));
memcpy(str, scanner.getString(), scanner.getStringLength());
str[scanner.getStringLength()] = '\0';
*(char**)dst = str;
break;
}
default:
scanner.warning("Failed to convert field");
}
break;
case dbField::tpRawBinary:
{
if (scanner.scan() != dbXmlScanner::xml_sconst) {
scanner.warning("Failed to convert field");
break;
}
char* src = scanner.getString();
int len = scanner.getStringLength() >> 1;
if (fd->appSize != (size_t)len) {
scanner.warning("Length of raw binary field was changed");
} else {
while (--len >= 0) {
*dst++ = (HEX_DIGIT(src[0]) << 4) | HEX_DIGIT(src[1]);
src += 2;
}
}
break;
}
#ifdef USE_STD_STRING
case dbField::tpStdString:
if (scanner.scan() != dbXmlScanner::xml_sconst) {
scanner.warning("Failed to convert field");
break;
}
((tmp_basic_string*)dst)->assign(tmp_basic_string(scanner.getString(), scanner.getStringLength(), xmlContext->stdAlloc));
break;
#endif
}
return EXPECT(dbXmlScanner::xml_lts)
&& EXPECT(terminator)
&& EXPECT(dbXmlScanner::xml_gt);
}
oid_t dbDatabase::mapId(long id)
{
oid_t oid;
if (id == 0) {
return 0;
}
if ((oid_t)id >= xmlContext->oidMapSize) {
oid_t* newOidMap = new oid_t[id*2];
memcpy(newOidMap, xmlContext->oidMap, xmlContext->oidMapSize*sizeof(oid_t));
memset(newOidMap + xmlContext->oidMapSize, 0, (id*2-xmlContext->oidMapSize)*sizeof(oid_t));
xmlContext->oidMapSize = id*2;
xmlContext->oidMap = newOidMap;
}
oid = xmlContext->oidMap[id];
if (oid == 0) {
oid = allocateId();
xmlContext->oidMap[id] = oid;
}
return oid;
}
void dbDatabase::insertRecord(dbTableDescriptor* desc, oid_t oid, void const* record)
{
dbFieldDescriptor* fd;
byte* src = (byte*)record;
size_t size = desc->columns->calculateRecordSize(src, desc->fixedSize);
allocateRow(desc->tableId, oid, size);
dbTable* table = (dbTable*)getRow(desc->tableId);
#ifdef AUTOINCREMENT_SUPPORT
desc->autoincrementCount = table->count;
#endif
dbRecord* dst = getRow(oid);
desc->columns->storeRecordFields((byte*)dst, src, desc->fixedSize, dbFieldDescriptor::Import);
#ifdef AUTOINCREMENT_SUPPORT
if ((nat4)desc->autoincrementCount > table->count) {
table->count = desc->autoincrementCount;
}
#endif
int nRows = table->nRows;
for (fd = desc->hashedFields; fd != NULL; fd = fd->nextHashedField) {
dbHashTable::insert(this, fd->hashTable, oid, fd->type, fd->dbsSize, fd->dbsOffs, nRows);
}
for (fd = desc->indexedFields; fd != NULL; fd = fd->nextIndexedField) {
if (fd->type == dbField::tpRectangle) {
dbRtree::insert(this, fd->tTree, oid, fd->dbsOffs);
} else {
dbTtree::insert(this, fd->tTree, oid, fd->type, fd->dbsSize, fd->comparator, fd->dbsOffs);
}
}
}
bool dbDatabase::importDatabaseFromXml(FILE* in)
{
dbXmlContext ctx;
xmlContext = &ctx;
dbXmlScanner scanner(in);
dbXmlScanner::token tkn;
if (!EXPECT(dbXmlScanner::xml_lt) ||
!EXPECT("database") ||
!EXPECT(dbXmlScanner::xml_gt))
{
return false;
}
beginTransaction(dbExclusiveLock);
ctx.oidMapSize = dbDefaultInitIndexSize;
ctx.oidMap = new oid_t[ctx.oidMapSize];
memset(ctx.oidMap, 0, ctx.oidMapSize*sizeof(oid_t));
while ((tkn = scanner.scan()) != dbXmlScanner::xml_lts) {
if (tkn != dbXmlScanner::xml_lt || !EXPECT(dbXmlScanner::xml_ident)) {
return false;
}
dbTableDescriptor* desc = findTableByName(scanner.getIdentifier());
if (desc == NULL) {
fprintf(stderr, "Table '%s' not found\n", scanner.getIdentifier());
}
if (!EXPECT("id")
|| !EXPECT(dbXmlScanner::xml_eq)
|| !EXPECT(dbXmlScanner::xml_sconst)
|| !EXPECT(dbXmlScanner::xml_gt))
{
return false;
}
if (desc != NULL) {
long id;
if (sscanf(scanner.getString(), "%ld", &id) != 1 || id == 0) {
return false;
}
oid_t oid = mapId(id);
byte *record = (byte*)xmlContext->tmpAlloc.alloc(desc->appSize);
memset(record, 0, desc->appSize);
if (!importRecord(desc->name, desc->columns, record, scanner)) {
xmlContext->tmpAlloc.reset();
return false;
}
insertRecord(desc, oid, record);
xmlContext->tmpAlloc.reset();
} else { // skip record
if (!skipElement(scanner)) {
return false;
}
}
}
return EXPECT("database") && EXPECT(dbXmlScanner::xml_gt);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -