internal int exportObject(ClassDescriptor desc, byte[] body, int offs, int indent) { ClassDescriptor.FieldDescriptor[] all = desc.allFields; for (int i = 0, n = all.Length; i < n; i++) { ClassDescriptor.FieldDescriptor fd = all[i]; FieldInfo f = fd.field; indentation(indent); String fieldName = exportIdentifier(fd.fieldName); writer.Write("<" + fieldName + ">"); switch (fd.type) { #if NET_FRAMEWORK_20 case ClassDescriptor.FieldType.tpNullableBoolean: writer.Write(body[offs++] == 0 ? "null" : body[offs++] != 0?"1":"0"); break; case ClassDescriptor.FieldType.tpNullableByte: writer.Write(body[offs++] == 0 ? "null" : System.Convert.ToString((byte) body[offs++])); break; case ClassDescriptor.FieldType.tpNullableSByte: writer.Write(body[offs++] == 0 ? "null" : System.Convert.ToString((sbyte) body[offs++])); break; case ClassDescriptor.FieldType.tpNullableChar: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; } break; case ClassDescriptor.FieldType.tpNullableShort: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; } break; case ClassDescriptor.FieldType.tpNullableUShort: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; } break; case ClassDescriptor.FieldType.tpNullableInt: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(System.Convert.ToString(Bytes.unpack4(body, offs))); offs += 4; } break; case ClassDescriptor.FieldType.tpNullableUInt: case ClassDescriptor.FieldType.tpNullableEnum: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(System.Convert.ToString((uint)Bytes.unpack4(body, offs))); offs += 4; } break; case ClassDescriptor.FieldType.tpNullableLong: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(System.Convert.ToString(Bytes.unpack8(body, offs))); offs += 8; } break; case ClassDescriptor.FieldType.tpNullableULong: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(System.Convert.ToString((ulong)Bytes.unpack8(body, offs))); offs += 8; } break; case ClassDescriptor.FieldType.tpNullableFloat: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(System.Convert.ToString(Bytes.unpackF4(body, offs))); offs += 4; } break; case ClassDescriptor.FieldType.tpNullableDouble: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(System.Convert.ToString(Bytes.unpackF8(body, offs))); offs += 8; } break; case ClassDescriptor.FieldType.tpNullableGuid: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(Bytes.unpackGuid(body, offs).ToString()); offs += 16; } break; case ClassDescriptor.FieldType.tpNullableDecimal: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write(Bytes.unpackDecimal(body, offs).ToString()); offs += 16; } break; case ClassDescriptor.FieldType.tpNullableDate: if (body[offs++] == 0) { writer.Write("null"); } else { writer.Write("\"" + Bytes.unpackDate(body, offs).ToString() + "\""); offs += 8; } break; #endif 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.tpEnum: writer.Write(Enum.ToObject(fd.MemberType, Bytes.unpack4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpUInt: 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) + "\""); offs += 16; break; case ClassDescriptor.FieldType.tpDecimal: writer.Write("\"" + Bytes.unpackDecimal(body, offs) + "\""); offs += 16; break; case ClassDescriptor.FieldType.tpString: case ClassDescriptor.FieldType.tpType: offs = exportString(body, offs); break; case ClassDescriptor.FieldType.tpDate: { long msec = Bytes.unpack8(body, offs); offs += 8; if (msec >= 0) { writer.Write("\"" + new System.DateTime(msec) + "\""); } else { writer.Write("null"); } break; } case ClassDescriptor.FieldType.tpObject: case ClassDescriptor.FieldType.tpOid: offs = exportRef(body, offs, indent); break; case ClassDescriptor.FieldType.tpValue: writer.Write('\n'); offs = exportObject(fd.valueDesc, body, offs, indent + 1); indentation(indent); break; case ClassDescriptor.FieldType.tpArrayOfByte: case ClassDescriptor.FieldType.tpArrayOfSByte: offs = exportBinary(body, offs); break; case ClassDescriptor.FieldType.tpCustom: { MemoryReader reader = new MemoryReader(storage, body, offs, null, true, false); object obj = storage.serializer.Unpack(reader); offs = reader.Position; writer.Write("\""); foreach (char ch in storage.serializer.Print(obj)) { exportChar(ch); } writer.Write("\""); break; } case ClassDescriptor.FieldType.tpArrayOfBoolean: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (body[offs++] != 0?"1":"0") + "</element>\n"); } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfChar: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (Bytes.unpack2(body, offs) & 0xFFFF) + "</element>\n"); offs += 2; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfShort: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpack2(body, offs) + "</element>\n"); offs += 2; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfUShort: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (ushort)Bytes.unpack2(body, offs) + "</element>\n"); offs += 2; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfInt: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpack4(body, offs) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfEnum: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { Type elemType = fd.MemberType.GetElementType(); writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Enum.ToObject(elemType, Bytes.unpack4(body, offs)) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfUInt: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (uint)Bytes.unpack4(body, offs) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfLong: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpack8(body, offs) + "</element>\n"); offs += 8; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfULong: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (ulong)Bytes.unpack8(body, offs) + "</element>\n"); offs += 8; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfFloat: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpackF4(body, offs) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfDouble: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpackF8(body, offs) + "</element>\n"); offs += 8; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfDate: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>\"" + Bytes.unpackDate(body, offs) + "\"</element>\n"); offs += 8; } } break; } case ClassDescriptor.FieldType.tpArrayOfGuid: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { writer.Write("<element>\"" + Bytes.unpackGuid(body, offs) + "\"</element>\n"); offs += 16; } } break; } case ClassDescriptor.FieldType.tpArrayOfDecimal: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { writer.Write("<element>\"" + Bytes.unpackDecimal(body, offs) + "\"</element>\n"); offs += 16; } } break; } case ClassDescriptor.FieldType.tpArrayOfString: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>"); offs = exportString(body, offs); writer.Write("</element>\n"); } indentation(indent); } break; } case ClassDescriptor.FieldType.tpLink: case ClassDescriptor.FieldType.tpArrayOfObject: case ClassDescriptor.FieldType.tpArrayOfOid: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent+1); writer.Write("<element>"); offs = exportRef(body, offs, indent+1); writer.Write("</element>\n"); } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfValue: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>\n"); offs = exportObject(fd.valueDesc, body, offs, indent + 2); indentation(indent + 1); writer.Write("</element>\n"); } indentation(indent); } break; } } writer.Write("</" + fieldName + ">\n"); } return offs; }
internal int exportRef(byte[] body, int offs, int indent) { int oid = Bytes.unpack4(body, offs); offs += 4; if (oid < 0) { int tid = -1-oid; switch ((ClassDescriptor.FieldType)tid) { case ClassDescriptor.FieldType.tpType: writer.Write("<type name=\""); offs = exportString(body, offs); writer.Write("\"/>"); break; case ClassDescriptor.FieldType.tpString: { offs = exportString(body, offs); break; } case ClassDescriptor.FieldType.tpBoolean: case ClassDescriptor.FieldType.tpByte: case ClassDescriptor.FieldType.tpSByte: case ClassDescriptor.FieldType.tpChar: case ClassDescriptor.FieldType.tpShort: case ClassDescriptor.FieldType.tpUShort: case ClassDescriptor.FieldType.tpInt: case ClassDescriptor.FieldType.tpUInt: case ClassDescriptor.FieldType.tpLong: case ClassDescriptor.FieldType.tpULong: case ClassDescriptor.FieldType.tpFloat: case ClassDescriptor.FieldType.tpDouble: case ClassDescriptor.FieldType.tpDate: case ClassDescriptor.FieldType.tpDecimal: case ClassDescriptor.FieldType.tpGuid: case ClassDescriptor.FieldType.tpEnum: { int len = ClassDescriptor.Sizeof[tid]; writer.Write("<scalar type=\"" + tid + "\" value=\""); while (--len >= 0) { byte b = body[offs++]; writer.Write(hexDigit[(b >> 4) & 0xF]); writer.Write(hexDigit[b & 0xF]); } writer.Write("\"/>"); break; } case ClassDescriptor.FieldType.tpCustom: { MemoryReader reader = new MemoryReader(storage, body, offs, null, true, false); object obj = storage.serializer.Unpack(reader); offs = reader.Position; writer.Write("<scalar type=\"" + tid + "\" value=\""); foreach (char ch in storage.serializer.Print(obj)) { exportChar(ch); } writer.Write("\"/>"); break; } default: { if (tid >= (int)ClassDescriptor.FieldType.tpValueTypeBias) { int typeOid = -(int)ClassDescriptor.FieldType.tpValueTypeBias - oid; ClassDescriptor desc = storage.findClassDescriptor(typeOid); if (desc.isCollection) { int len = Bytes.unpack4(body, offs); offs += 4; String className = exportIdentifier(desc.name); writer.Write("\n"); indentation(indent + 1); writer.Write("<" + className + ">\n"); for (int i = 0; i < len; i++) { indentation(indent + 2); writer.Write("<element>"); offs = exportRef(body, offs, indent + 2); writer.Write("</element>\n"); } indentation(indent + 1); writer.Write("</" + className + ">\n"); indentation(indent); } else if (desc.isDictionary) { int len = Bytes.unpack4(body, offs); offs += 4; String className = exportIdentifier(desc.name); writer.Write("\n"); indentation(indent + 1); writer.Write("<" + className + ">\n"); for (int i = 0; i < len; i++) { indentation(indent + 2); writer.Write("<element>\n"); indentation(indent + 4); writer.Write("<key>"); offs = exportRef(body, offs, indent + 4); writer.Write("</key>\n"); indentation(indent + 4); writer.Write("<value>"); offs = exportRef(body, offs, indent + 4); writer.Write("</value>\n"); indentation(indent + 2); writer.Write("</element>\n"); } indentation(indent + 1); writer.Write("</" + className + ">\n"); indentation(indent); } else { string className = exportIdentifier(desc.name); writer.Write("\n"); indentation(indent + 1); writer.Write("<" + className + ">\n"); offs = exportObject(desc, body, offs, indent + 2); indentation(indent + 1); writer.Write("</" + className + ">\n"); indentation(indent); } break; } else { throw new StorageError(StorageError.ErrorCode.UNSUPPORTED_TYPE); } } } } else { writer.Write("<ref id=\"" + oid + "\"/>"); if (oid != 0 && (exportedBitmap[oid >> 5] & (1 << (oid & 31))) == 0) { markedBitmap[oid >> 5] |= 1 << (oid & 31); } } return offs; }