📄 xmlexporter.cs
字号:
namespace Perst.Impl
{
using System;
using System.Reflection;
using System.Diagnostics;
using System.Text;
using System.IO;
using Perst;
public class XMLExporter
{
public XMLExporter(StorageImpl storage, System.IO.StreamWriter writer)
{
this.storage = storage;
this.writer = writer;
}
public virtual void exportDatabase(int rootOid)
{
if (storage.encoding != null)
{
writer.Write("<?xml version=\"1.0\" encoding=\"" + storage.encoding + "\"?>\n");
}
else
{
writer.Write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
}
writer.Write("<database root=\"" + rootOid + "\">\n");
exportedBitmap = new int[(storage.currIndexSize + 31) / 32];
markedBitmap = new int[(storage.currIndexSize + 31) / 32];
markedBitmap[rootOid >> 5] |= 1 << (rootOid & 31);
int nExportedObjects;
do
{
nExportedObjects = 0;
for (int i = 0; i < markedBitmap.Length; i++)
{
int mask = markedBitmap[i];
if (mask != 0)
{
for (int j = 0, bit = 1; j < 32; j++, bit <<= 1)
{
if ((mask & bit) != 0)
{
int oid = (i << 5) + j;
exportedBitmap[i] |= bit;
markedBitmap[i] &= ~ bit;
byte[] obj = storage.get(oid);
int typeOid = ObjectHeader.getType(obj, 0);
ClassDescriptor desc = storage.findClassDescriptor(typeOid);
string name = desc.name;
#if USE_GENERICS
if (typeof(Btree).IsAssignableFrom(desc.cls))
{
Type t = desc.cls.GetGenericTypeDefinition();
if (t == typeof(Btree<,>) || t == typeof(BitIndex<>))
{
exportIndex(oid, obj, name);
}
else if (t == typeof(PersistentSet<>))
{
exportSet(oid, obj, name);
}
else if (t == typeof(BtreeFieldIndex<,>))
{
exportFieldIndex(oid, obj, name);
}
else if (t == typeof(BtreeMultiFieldIndex<>))
{
exportMultiFieldIndex(oid, obj, name);
}
else if (t == typeof(BtreeCompoundIndex<>))
{
exportCompoundIndex(oid, obj, name);
}
}
#else
if (desc.cls == typeof(Btree) || desc.cls == typeof(BitIndexImpl))
{
exportIndex(oid, obj, name);
}
else if (desc.cls == typeof(PersistentSet))
{
exportSet(oid, obj, name);
}
else if (desc.cls == typeof(BtreeFieldIndex))
{
exportFieldIndex(oid, obj, name);
}
else if (desc.cls == typeof(BtreeMultiFieldIndex))
{
exportMultiFieldIndex(oid, obj, name);
}
else if (desc.cls == typeof(BtreeCompoundIndex))
{
exportCompoundIndex(oid, obj, name);
}
#endif
else
{
String className = exportIdentifier(desc.name);
writer.Write(" <" + className + " id=\"" + oid + "\">\n");
exportObject(desc, obj, ObjectHeader.Sizeof, 2);
writer.Write(" </" + className + ">\n");
}
nExportedObjects += 1;
}
}
}
}
}
while (nExportedObjects != 0);
writer.Write("</database>\n");
}
internal String exportIdentifier(String name)
{
name = name.Replace('+', '-');
#if USE_GENERICS
name = name.Replace("`", ".1");
name = name.Replace(",", ".2");
name = name.Replace("[", ".3");
name = name.Replace("]", ".4");
name = name.Replace("=", ".5");
#endif
return name;
}
Btree createBtree(int oid, byte[] data)
{
Btree btree = storage.createBtreeStub(data, 0);
storage.assignOid(btree, oid);
return btree;
}
internal void exportSet(int oid, byte[] data, string name)
{
Btree btree = createBtree(oid, data);
name = exportIdentifier(name);
writer.Write(" <" + name + " id=\"" + oid + "\">\n");
btree.export(this);
writer.Write(" </" + name + ">\n");
}
internal void exportIndex(int oid, byte[] data, string name)
{
Btree btree = createBtree(oid, data);
name = exportIdentifier(name);
writer.Write(" <" + name + " id=\"" + oid + "\" unique=\"" + (btree.IsUnique ? '1' : '0')
+ "\" type=\"" + btree.FieldType + "\">\n");
btree.export(this);
writer.Write(" </" + name + ">\n");
}
internal void exportFieldIndex(int oid, byte[] data, string name)
{
Btree btree = createBtree(oid, data);
name = exportIdentifier(name);
writer.Write(" <" + name + " id=\"" + oid + "\" unique=\"" + (btree.IsUnique?'1':'0') + "\" class=");
int offs = exportString(data, btree.HeaderSize);
writer.Write(" field=");
offs = exportString(data, offs);
writer.Write(" autoinc=\"" + Bytes.unpack8(data, offs) + "\">\n");
btree.export(this);
writer.Write(" </" + name + ">\n");
}
internal void exportMultiFieldIndex(int oid, byte[] data, string name)
{
Btree btree = createBtree(oid, data);
name = exportIdentifier(name);
writer.Write(" <" + name + " id=\"" + oid + "\" unique=\"" + (btree.IsUnique ? '1' : '0')
+ "\" class=");
int offs = exportString(data, btree.HeaderSize);
int nFields = Bytes.unpack4(data, offs);
offs += 4;
for (int i = 0; i < nFields; i++)
{
writer.Write(" field" + i + "=");
offs = exportString(data, offs);
}
writer.Write(">\n");
int nTypes = Bytes.unpack4(data, offs);
offs += 4;
compoundKeyTypes = new ClassDescriptor.FieldType[nTypes];
for (int i = 0; i < nTypes; i++)
{
compoundKeyTypes[i] = (ClassDescriptor.FieldType)Bytes.unpack4(data, offs);
offs += 4;
}
btree.export(this);
compoundKeyTypes = null;
writer.Write(" </" + name + ">\n");
}
internal void exportCompoundIndex(int oid, byte[] data, string name)
{
Btree btree = createBtree(oid, data);
name = exportIdentifier(name);
writer.Write(" <" + name + " id=\"" + oid + "\" unique=\"" + (btree.IsUnique ? '1' : '0') + "\"");
int offs = btree.HeaderSize;
int nTypes = Bytes.unpack4(data, offs);
offs += 4;
compoundKeyTypes = new ClassDescriptor.FieldType[nTypes];
for (int i = 0; i < nTypes; i++)
{
ClassDescriptor.FieldType type = (ClassDescriptor.FieldType)Bytes.unpack4(data, offs);
compoundKeyTypes[i] = type;
writer.Write(" type" + i + "=\"" + type + "\"");
offs += 4;
}
writer.Write(">\n");
btree.export(this);
compoundKeyTypes = null;
writer.Write(" </" + name + ">\n");
}
int exportKey(byte[] body, int offs, int size, ClassDescriptor.FieldType type)
{
switch (type)
{
case ClassDescriptor.FieldType.tpBoolean:
writer.Write(body[offs++] != 0?"1":"0");
break;
case ClassDescriptor.FieldType.tpByte:
writer.Write(System.Convert.ToString((byte) body[offs++]));
break;
case ClassDescriptor.FieldType.tpSByte:
writer.Write(System.Convert.ToString((sbyte) body[offs++]));
break;
case ClassDescriptor.FieldType.tpChar:
writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs)));
offs += 2;
break;
case ClassDescriptor.FieldType.tpShort:
writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs)));
offs += 2;
break;
case ClassDescriptor.FieldType.tpUShort:
writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs)));
offs += 2;
break;
case ClassDescriptor.FieldType.tpInt:
writer.Write(System.Convert.ToString(Bytes.unpack4(body, offs)));
offs += 4;
break;
case ClassDescriptor.FieldType.tpUInt:
case ClassDescriptor.FieldType.tpObject:
case ClassDescriptor.FieldType.tpOid:
case ClassDescriptor.FieldType.tpEnum:
writer.Write(System.Convert.ToString((uint)Bytes.unpack4(body, offs)));
offs += 4;
break;
case ClassDescriptor.FieldType.tpLong:
writer.Write(System.Convert.ToString(Bytes.unpack8(body, offs)));
offs += 8;
break;
case ClassDescriptor.FieldType.tpULong:
writer.Write(System.Convert.ToString((ulong)Bytes.unpack8(body, offs)));
offs += 8;
break;
case ClassDescriptor.FieldType.tpFloat:
writer.Write(System.Convert.ToString(Bytes.unpackF4(body, offs)));
offs += 4;
break;
case ClassDescriptor.FieldType.tpDouble:
writer.Write(System.Convert.ToString(Bytes.unpackF8(body, offs)));
offs += 8;
break;
case ClassDescriptor.FieldType.tpGuid:
writer.Write(Bytes.unpackGuid(body, offs).ToString());
offs += 16;
break;
case ClassDescriptor.FieldType.tpDecimal:
writer.Write(Bytes.unpackDecimal(body, offs).ToString());
offs += 16;
break;
case ClassDescriptor.FieldType.tpString:
for (int i = 0; i < size; i++)
{
exportChar((char) Bytes.unpack2(body, offs));
offs += 2;
}
break;
case ClassDescriptor.FieldType.tpArrayOfByte:
for (int i = 0; i < size; i++)
{
byte b = body[offs++];
writer.Write(hexDigit[(b >> 4) & 0xF]);
writer.Write(hexDigit[b & 0xF]);
}
break;
case ClassDescriptor.FieldType.tpDate:
writer.Write(Bytes.unpackDate(body, offs).ToString());
offs += 8;
break;
default:
Debug.Assert(false, "Invalid type");
break;
}
return offs;
}
void exportCompoundKey(byte[] body, int offs, int size, ClassDescriptor.FieldType type)
{
Debug.Assert(type == ClassDescriptor.FieldType.tpArrayOfByte);
int end = offs + size;
for (int i = 0; i < compoundKeyTypes.Length; i++)
{
type = compoundKeyTypes[i];
if (type == ClassDescriptor.FieldType.tpArrayOfByte || type == ClassDescriptor.FieldType.tpString)
{
size = Bytes.unpack4(body, offs);
offs += 4;
}
writer.Write(" key" + i + "=\"");
offs = exportKey(body, offs, size, type);
writer.Write("\"");
}
Debug.Assert(offs == end);
}
internal void exportAssoc(int oid, byte[] body, int offs, int size, ClassDescriptor.FieldType type)
{
writer.Write(" <ref id=\"" + oid + "\"");
if ((exportedBitmap[oid >> 5] & (1 << (oid & 31))) == 0)
{
markedBitmap[oid >> 5] |= 1 << (oid & 31);
}
if (compoundKeyTypes != null)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -