📄 xml.cpp
字号:
break;
case dbField::tpStructure:
fprintf(out, "\n");
exportRecord(fd->components, out, src, indent+1);
for (i = indent; --i >= 0;) {
fprintf(out, " ");
}
break;
}
fprintf(out, "</%s>\n", fieldName);
} while ((fd = fd->next) != fieldList);
}
void dbDatabase::exportScheme(FILE* out)
{
fprintf(out, "<!DOCTYPE database [\n");
if (tables == NULL) {
fprintf(out, "<!ELEMENT database EMPTY>\n");
} else {
fprintf(out, "<!ELEMENT database (%s*", tables->name);
dbTableDescriptor* desc = tables;
while ((desc = desc->nextDbTable) != NULL) {
if (desc->tableId != dbMetaTableId) {
fprintf(out, ", %s*", desc->name);
}
}
fprintf(out, ")>\n");
}
for (dbTableDescriptor* desc = tables; desc != NULL; desc = desc->nextDbTable) {
if (desc->tableId != dbMetaTableId) {
exportClass(out, desc->name, desc->columns);
fprintf(out, "<!ATTLIST %s id CDATA #REQUIRED>\n", desc->name);
}
}
fprintf(out, "<!ELEMENT array-element ANY>\n<!ELEMENT ref EMPTY>\n<!ATTLIST ref id CDATA #REQUIRED>\n]>\n");
}
void dbDatabase::exportClass(FILE* out, char* name, dbFieldDescriptor* fieldList)
{
fprintf(out, "<!ELEMENT %s (%s", name, fieldList->name);
dbFieldDescriptor* fd = fieldList;
while ((fd = fd->next) != fieldList) {
fprintf(out, ", %s", fd->name);
}
fprintf(out, ")>\n");
fd = fieldList;
do {
switch (fd->type) {
case dbField::tpStructure:
exportClass(out, fd->name, fd->components);
break;
case dbField::tpArray:
fprintf(out, "<!ELEMENT %s (array-element*)>\n", fd->name);
if (fd->components->type == dbField::tpStructure) {
exportClass(out, fd->name, fd->components->components);
}
break;
default:
fprintf(out, "<!ELEMENT %s (#PCDATA)>\n", fd->name);
}
} while ((fd = fd->next) != fieldList);
}
void dbDatabase::exportDatabaseToXml(FILE* out)
{
fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
beginTransaction(dbSharedLock);
exportScheme(out);
fprintf(out, "<database>\n");
for (dbTableDescriptor* desc=tables; desc != NULL; desc=desc->nextDbTable) {
if (desc->tableId != dbMetaTableId) {
dbTable* table = (dbTable*)getRow(desc->tableId);
oid_t oid = table->firstRow;
int n = table->nRows;
int percent = 0;
for (int i = 0; oid != 0; i++) {
dbRecord* rec = getRow(oid);
fprintf(out, " <%s id=\"%lu\">\n", desc->name, (unsigned long)oid);
exportRecord(desc->columns, out, (byte*)rec, 2);
fprintf(out, " </%s>\n", desc->name);
oid = rec->next;
int p = (i+1)*100/n;
if (p != percent) {
fprintf(stderr, "Exporting table %s: %d%%\r", desc->name, p);
fflush(stderr);
percent = p;
}
}
fprintf(stderr, "Exporting table %s: 100%% \n", desc->name);
}
}
fprintf(out, "</database>\n");
}
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;
} else if (ch == '!') {
int nParen = 1;
do {
switch (get()) {
case '<':
nParen += 1;
break;
case '>':
nParen -= 1;
break;
case EOF:
return xml_error;
}
} while (nParen != 0);
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':
ch = get();
if (ch == 'm' && get() == 'p' && get() == ';') {
ch = '&';
} else if (ch == 'p' && get() == 'o' && get() == 's' && get() == ';') {
ch = '\'';
} else {
return xml_error;
}
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, i);
delete[] sconst;
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 == '.' || ch == 'E') {
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)
static 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 dbDatabase::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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -