Пример #1
0
        internal static void  exportPage(StorageImpl db, XMLExporter exporter, int pageId, ClassDescriptor.FieldType type, int height)
        {
            Page pg = db.getPage(pageId);
            try
            {
                int i, n = getnItems(pg);
                if (--height != 0)
                {
                    if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte)
                    {
                        // page of strings
                        for (i = 0; i <= n; i++)
                        {
                            exportPage(db, exporter, getKeyStrOid(pg, i), type, height);
                        }
                    }
                    else
                    {
                        for (i = 0; i <= n; i++)
                        {
                            exportPage(db, exporter, getReference(pg, maxItems - i - 1), type, height);
                        }
                    }
                }
                else
                {
                    if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte)
                    {
                        // page of strings
                        for (i = 0; i < n; i++)
                        {
                            exporter.exportAssoc(getKeyStrOid(pg, i), pg.data, BtreePage.firstKeyOffs + BtreePage.getKeyStrOffs(pg, i), BtreePage.getKeyStrSize(pg, i), type);
                        }
                    }
                    else
                    {
                        // page of scalars
                        for (i = 0; i < n; i++)
                        {
                            exporter.exportAssoc(getReference(pg, maxItems - 1 - i), pg.data, BtreePage.firstKeyOffs + i * ClassDescriptor.Sizeof[(int)type], ClassDescriptor.Sizeof[(int)type], type);
							
                        }
                    }
                }
            }
            finally
            {
                db.pool.unfix(pg);
            }
        }
Пример #2
0
 internal static int traverseForward(StorageImpl db, int pageId, ClassDescriptor.FieldType type, int height, object[] result, int pos)
 {
     Page pg = db.getPage(pageId);
     int oid;
     try
     {
         int i, n = getnItems(pg);
         if (--height != 0)
         {
             if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte)
             {
                 // page of strings
                 for (i = 0; i <= n; i++)
                 {
                     pos = traverseForward(db, getKeyStrOid(pg, i), type, height, result, pos);
                 }
             }
             else
             {
                 for (i = 0; i <= n; i++)
                 {
                     pos = traverseForward(db, getReference(pg, maxItems - i - 1), type, height, result, pos);
                 }
             }
         }
         else
         {
             if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte)
             {
                 // page of strings
                 for (i = 0; i < n; i++)
                 {
                     oid = getKeyStrOid(pg, i);
                     result[pos++] = db.lookupObject(oid, null);
                 }
             }
             else
             {
                 // page of scalars
                 for (i = 0; i < n; i++)
                 {
                     oid = getReference(pg, maxItems - 1 - i);
                     result[pos++] = db.lookupObject(oid, null);
                 }
             }
         }
         return pos;
     }
     finally
     {
         db.pool.unfix(pg);
     }
 }
Пример #3
0
 internal static int markPage(StorageImpl db, int pageId, ClassDescriptor.FieldType type, int height)
 {
     Debug.Assert(pageId != 0);
     Page pg = db.getGCPage(pageId);
     int nPages = 1;
     try 
     { 
         int i, n = getnItems(pg);
         if (--height != 0) 
         {
             if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte) 
             { // page of strings
                 for (i = 0; i <= n; i++) 
                 { 
                     nPages += markPage(db, getKeyStrOid(pg, i), type, height);
                 }
             } 
             else 
             { 
                 for (i = 0; i <= n; i++) 
                 { 
                     nPages += markPage(db, getReference(pg, maxItems-i-1), type, height);
                 }
             }
         } 
         else 
         { 
             if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte) 
             { // page of strings
                 for (i = 0; i < n; i++) 
                 {
                     db.markOid(getKeyStrOid(pg, i));
                 }
             }
             else 
             { // page of scalars
                 for (i = 0; i < n; i++) 
                 { 
                     db.markOid(getReference(pg, maxItems-1-i));
                 }
             } 
         }
     } 
     finally 
     { 
         db.pool.unfix(pg);
     }
     return nPages;
 }
Пример #4
0
 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) 
     { 
         exportCompoundKey(body, offs, size, type);
     } 
     else 
     { 
         writer.Write(" key=\"");
         exportKey(body, offs, size, type);
         writer.Write("\"");
     }
     writer.Write("/>\n");
 }
Пример #5
0
        Key createCompoundKey(ClassDescriptor.FieldType[] types, String[] values) 
        {
            ByteBuffer buf = new ByteBuffer();
            int dst = 0;

            for (int i = 0; i < types.Length; i++) 
            { 
                String val = values[i];
                switch (types[i]) 
                { 
                    case ClassDescriptor.FieldType.tpBoolean:
                        dst = buf.packBool(dst, Int32.Parse(val) != 0);
                        break;

                    case ClassDescriptor.FieldType.tpByte:
                    case ClassDescriptor.FieldType.tpSByte:
                        dst = buf.packI1(dst, Int32.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpChar:
                    case ClassDescriptor.FieldType.tpShort:
                    case ClassDescriptor.FieldType.tpUShort:
                        dst = buf.packI2(dst, Int32.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpInt:
                        dst = buf.packI4(dst, Int32.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpEnum:
                    case ClassDescriptor.FieldType.tpUInt:
                        dst = buf.packI4(dst, (int)UInt32.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpObject:
                    case ClassDescriptor.FieldType.tpOid:
                        dst = buf.packI4(dst, mapId((int)UInt32.Parse(val)));
                        break;

                    case ClassDescriptor.FieldType.tpLong:
                        dst = buf.packI8(dst, Int64.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpULong:
                        dst = buf.packI8(dst, (long)UInt64.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpDate:
                        dst = buf.packDate(dst, DateTime.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpFloat:
                        dst = buf.packF4(dst, Single.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpDouble:
                        dst = buf.packF8(dst, Double.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpDecimal: 
                        dst = buf.packDecimal(dst, Decimal.Parse(val));
                        break;

                    case ClassDescriptor.FieldType.tpGuid: 
                        dst = buf.packGuid(dst, new Guid(val));
                        break;

                    case ClassDescriptor.FieldType.tpString:
                    case ClassDescriptor.FieldType.tpType:
                        dst = buf.packString(dst, val);
                        break;

                    case ClassDescriptor.FieldType.tpArrayOfByte:
                        buf.extend(dst + 4 + (val.Length >> 1));
                        Bytes.pack4(buf.arr, dst, val.Length >> 1);
                        dst += 4;
                        for (int j = 0, n = val.Length; j < n; j+=2) 
                        { 
                            buf.arr[dst++] = (byte)((getHexValue(val[j]) << 4) | getHexValue(val[j+1]));
                        }
                        break;
                    default:
                        throwException("Bad key type");
                        break;
                }
            }
            return new Key(buf.toArray());
        }
Пример #6
0
 public override void OnLoad()
 {
     cls = ClassDescriptor.lookup(Storage, className);
     locateFields();
 }
Пример #7
0
        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: 
                case ClassDescriptor.FieldType.tpType: 
                    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;                                            
        }
        private void generateUnpackMethod(ClassDescriptor desc, MethodBuilder builder)
        {
            ILGenerator il = builder.GetILGenerator();
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Castclass, desc.cls);
            LocalBuilder obj = il.DeclareLocal(desc.cls);
            il.Emit(OpCodes.Stloc_0, obj);
            il.Emit(OpCodes.Ldc_I4, ObjectHeader.Sizeof);
            LocalBuilder offs = il.DeclareLocal(typeof(int));
            il.Emit(OpCodes.Stloc_1, offs);
            LocalBuilder val = il.DeclareLocal(typeof(object));

            ClassDescriptor.FieldDescriptor[] flds = desc.allFields;

            for (int i = 0, n = flds.Length; i < n; i++)
            {
                ClassDescriptor.FieldDescriptor fd = flds[i];
                FieldInfo f = fd.field;
                if (f == null) 
                {
                    switch (fd.type)
                    {
                        case ClassDescriptor.FieldType.tpByte: 
                        case ClassDescriptor.FieldType.tpSByte: 
                        case ClassDescriptor.FieldType.tpBoolean: 
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_1);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpShort: 
                        case ClassDescriptor.FieldType.tpUShort: 
                        case ClassDescriptor.FieldType.tpChar: 
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_2);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpEnum: 
                        case ClassDescriptor.FieldType.tpInt: 
                        case ClassDescriptor.FieldType.tpUInt: 
                        case ClassDescriptor.FieldType.tpFloat: 
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_4);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpLong: 
                        case ClassDescriptor.FieldType.tpULong: 
                        case ClassDescriptor.FieldType.tpDate: 
                        case ClassDescriptor.FieldType.tpDouble: 
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_8);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpDecimal:
                        case ClassDescriptor.FieldType.tpGuid:
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4, 16);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        default:
                            il.Emit(OpCodes.Ldarg_1); // storage
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldnull); // fd
                            il.Emit(OpCodes.Ldc_I4, (int)fd.type);
                            il.Emit(OpCodes.Call, skipField);
                            il.Emit(OpCodes.Stloc_1, offs); // offs
                            continue;
                    }
                }
                else 
                {

                    switch (fd.type)
                    {
                        case ClassDescriptor.FieldType.tpByte: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldelem_U1);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_1);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpSByte: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldelem_U1);
                            il.Emit(OpCodes.Conv_I1);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_1);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpBoolean: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldelem_U1);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_1);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpShort: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackI2);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_2);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpUShort: 
                        case ClassDescriptor.FieldType.tpChar: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackI2);
                            il.Emit(OpCodes.Conv_U2);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_2);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpEnum: 
                        case ClassDescriptor.FieldType.tpInt: 
                        case ClassDescriptor.FieldType.tpUInt: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackI4);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_4);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpLong: 
                        case ClassDescriptor.FieldType.tpULong: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackI8);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_8);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpFloat: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackF4);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_4);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpDouble: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackF8);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_8);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpDecimal:
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackDecimal);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4, 16);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpGuid:
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackGuid);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4, 16);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;

                        case ClassDescriptor.FieldType.tpDate: 
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Call, unpackDate);
                            il.Emit(OpCodes.Stfld, f);
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldc_I4_8);
                            il.Emit(OpCodes.Add);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
					
                        case ClassDescriptor.FieldType.tpString: 
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldflda, f);
                            il.Emit(OpCodes.Ldarg_S, 5); // encoding
                            il.Emit(OpCodes.Call, unpackString);
                            il.Emit(OpCodes.Stloc_1, offs);
                            continue;
                
                        default:
                            il.Emit(OpCodes.Ldarg_1); // storage
                            il.Emit(OpCodes.Ldarg_3); // body
                            il.Emit(OpCodes.Ldloc_1, offs);
                            il.Emit(OpCodes.Ldarg_S, 4); // recursiveLoading
                            il.Emit(OpCodes.Ldloca, val);
                            il.Emit(OpCodes.Ldnull); // fd
                            il.Emit(OpCodes.Ldc_I4, (int)fd.type);
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Call, unpackField);
                            il.Emit(OpCodes.Stloc_1, offs); // offs
                            il.Emit(OpCodes.Ldloc_0, obj);
                            il.Emit(OpCodes.Ldloc, val);
                            il.Emit(OpCodes.Castclass, f.FieldType);
                            il.Emit(OpCodes.Stfld, f);
                            continue;
                    }
                }
            }
            il.Emit(OpCodes.Ret);
        }
 private void generateNewMethod(ClassDescriptor desc, MethodBuilder builder)
 {
     ILGenerator il = builder.GetILGenerator();
     il.Emit(OpCodes.Newobj, desc.defaultConstructor);
     il.Emit(OpCodes.Ret);
 }
 public bool equals(ClassDescriptor cd) 
 { 
     if (cd == null || allFields.Length != cd.allFields.Length) 
     { 
         return false;
     }
     for (int i = 0; i < allFields.Length; i++) 
     { 
         if (!allFields[i].equals(cd.allFields[i])) 
         { 
             return false;
         }
     }
     return true;
 }
Пример #11
0
 public GeneratedSerializer Generate(ClassDescriptor desc)            
 {
     ModuleBuilder module = EmitAssemblyModule();
     Type newCls = EmitClass(module, desc);
     return (GeneratedSerializer)module.Assembly.CreateInstance(newCls.Name);
 }
 internal void resolve() 
 {
     if (!resolved) 
     { 
         StorageImpl classStorage = (StorageImpl)Storage;
         ClassDescriptor desc = new ClassDescriptor(classStorage, cls);
         resolved = true;
         if (!desc.equals(this)) 
         { 
             classStorage.registerClassDescriptor(desc);
         }
     }
 }            
Пример #13
0
        internal int packObject(XMLElement objElem, ClassDescriptor desc, int offs, ByteBuffer buf)
        {
            ClassDescriptor.FieldDescriptor[] flds = desc.allFields;
            for (int i = 0, n = flds.Length; i < n; i++)
            {
                ClassDescriptor.FieldDescriptor fd = flds[i];
                FieldInfo f = fd.field;
                String fieldName = fd.fieldName;
                XMLElement elem = (objElem != null)?objElem.getSibling(fieldName):null;
                ClassDescriptor.FieldType type = fd.type;				
                switch (fd.type)
                {
#if NET_FRAMEWORK_20
                    case ClassDescriptor.FieldType.tpNullableByte: 
                    case ClassDescriptor.FieldType.tpNullableSByte: 
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.extend(offs + 2);
                                buf.arr[offs++] = (byte) 1;
                                buf.arr[offs++] = (byte) elem.IntValue;
                            }
                            else if (elem.isRealValue())
                            {
                                buf.extend(offs + 2);
                                buf.arr[offs++] = (byte) 1;
                                buf.arr[offs++] = (byte) elem.RealValue;
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        } 
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpNullableBoolean: 
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.extend(offs + 2);
                                buf.arr[offs++] = (byte) 1;
                                buf.arr[offs++] = (byte) (elem.IntValue != 0?1:0);
                            }
                            else if (elem.isRealValue())
                            {
                                buf.extend(offs + 2);
                                buf.arr[offs++] = (byte) 1;
                                buf.arr[offs++] = (byte) (elem.RealValue != 0.0?1:0);
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        } 
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpNullableShort: 
                    case ClassDescriptor.FieldType.tpNullableUShort: 
                    case ClassDescriptor.FieldType.tpNullableChar: 
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.extend(offs + 3);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.pack2(buf.arr, offs, (short) elem.IntValue);
                                offs += 2;
                            }
                            else if (elem.isRealValue())
                            {
                                buf.extend(offs + 3);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.pack2(buf.arr, offs, (short) elem.RealValue);
                                offs += 2;
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        } 
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpNullableEnum: 
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.extend(offs + 5);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.pack4(buf.arr, offs, (int) elem.IntValue);        
                                offs += 4;
                            }
                            else if (elem.isRealValue())
                            {
                                buf.extend(offs + 5);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.pack4(buf.arr, offs, (int) elem.RealValue);
                                offs += 4;
                            }
                            else if (elem.isStringValue()) 
                            {
                                try 
                                {
                                    buf.extend(offs + 5);
                                    buf.arr[offs++] = (byte) 1;
                                    Bytes.pack4(buf.arr, offs, (int)ClassDescriptor.parseEnum(f.FieldType, elem.StringValue));
                                } 
                                catch (ArgumentException)
                                {
                                    throwException("Invalid enum value");
                                }
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
					

                    case ClassDescriptor.FieldType.tpNullableInt: 
                    case ClassDescriptor.FieldType.tpNullableUInt: 
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.extend(offs + 5);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.pack4(buf.arr, offs, (int) elem.IntValue);
                                offs += 4;
                            }
                            else if (elem.isRealValue())
                            {
                                buf.extend(offs + 5);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.pack4(buf.arr, offs, (int) elem.RealValue);
                                offs += 4;
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpNullableLong: 
                    case ClassDescriptor.FieldType.tpNullableULong: 
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.extend(offs + 9);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.pack8(buf.arr, offs, elem.IntValue);
                                offs += 9;
                            }
                            else if (elem.isRealValue())
                            {
                                buf.extend(offs + 9);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.pack8(buf.arr, offs, (long) elem.RealValue);
                                offs += 9;
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpNullableFloat: 
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.extend(offs + 5);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.packF4(buf.arr, offs, (float)elem.IntValue);
                                offs += 4;
                            }
                            else if (elem.isRealValue())
                            {
                                buf.extend(offs + 5);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.packF4(buf.arr, offs, (float) elem.RealValue);
                                offs += 4;
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpNullableDouble: 
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.extend(offs + 9);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.packF8(buf.arr, offs, (double) elem.IntValue);
                                offs += 8;
                            }
                            else if (elem.isRealValue())
                            {
                                buf.extend(offs + 9);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.packF8(buf.arr, offs, elem.RealValue);
                                offs += 8;
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpNullableDecimal: 
                        if (elem != null)
                        {
                            decimal d = 0;
                            if (elem.isIntValue())
                            {
                                d = elem.IntValue;
                            }
                            else if (elem.isRealValue())
                            {
                                d = (decimal)elem.RealValue;
                            }
                            else if (elem.isStringValue())
                            {
                                try 
                                { 
                                    d = Decimal.Parse(elem.StringValue);
                                } 
                                catch (FormatException) 
                                {
                                    throwException("Invalid date");
                                }
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                                continue;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                            buf.extend(offs + 17);
                            buf.arr[offs++] = (byte) 1;
                            Bytes.packDecimal(buf.arr, offs, d);
                            offs += 16;
                        }
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
  
                    case ClassDescriptor.FieldType.tpNullableGuid: 
                        if (elem != null)
                        {
                            if (elem.isStringValue())
                            {
                                buf.extend(offs + 17);
                                buf.arr[offs++] = (byte) 1;
                                Guid guid = new Guid(elem.StringValue);
                                byte[] bits = guid.ToByteArray();
                                Array.Copy(bits, 0, buf.arr, offs, 16);
                                offs += 16;
                            }
                            else if (elem.isNullValue())
                            {
                                 buf.extend(offs + 1);
                                 buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;
                    
                    case ClassDescriptor.FieldType.tpNullableDate: 
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.extend(offs + 9);
                                buf.arr[offs++] = (byte) 1;
                                Bytes.pack8(buf.arr, offs, elem.IntValue);
                                offs += 8;
                            }
                            else if (elem.isStringValue())
                            {
                                try 
                                { 
                                    buf.extend(offs + 9);
                                    buf.arr[offs++] = (byte) 1;
                                    Bytes.packDate(buf.arr, offs, DateTime.Parse(elem.StringValue));
                                    offs += 8;
                                } 
                                catch (FormatException) 
                                {
                                    throwException("Invalid date");
                                }
                            }
                            else if (elem.isNullValue())
                            {
                                buf.extend(offs + 1);
                                buf.arr[offs++] = (byte) 0;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        else 
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        }
                        continue;

                    case ClassDescriptor.FieldType.tpNullableValue: 
                        if (elem != null || elem.isNullValue())
                        {
                            buf.extend(offs + 1);
                            buf.arr[offs++] = (byte) 0;
                        } 
                        else                         
                        { 
                            offs = packObject(elem, fd.valueDesc, offs, buf);
                        }
                        continue;
#endif

                    case ClassDescriptor.FieldType.tpByte: 
                    case ClassDescriptor.FieldType.tpSByte: 
                        buf.extend(offs + 1);
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.arr[offs] = (byte) elem.IntValue;
                            }
                            else if (elem.isRealValue())
                            {
                                buf.arr[offs] = (byte) elem.RealValue;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 1;
                        continue;
					
                    case ClassDescriptor.FieldType.tpBoolean: 
                        buf.extend(offs + 1);
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                buf.arr[offs] = (byte) (elem.IntValue != 0?1:0);
                            }
                            else if (elem.isRealValue())
                            {
                                buf.arr[offs] = (byte) (elem.RealValue != 0.0?1:0);
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 1;
                        continue;
					
                    case ClassDescriptor.FieldType.tpShort: 
                    case ClassDescriptor.FieldType.tpUShort: 
                    case ClassDescriptor.FieldType.tpChar: 
                        buf.extend(offs + 2);
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                Bytes.pack2(buf.arr, offs, (short) elem.IntValue);
                            }
                            else if (elem.isRealValue())
                            {
                                Bytes.pack2(buf.arr, offs, (short) elem.RealValue);
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 2;
                        continue;
					
                    case ClassDescriptor.FieldType.tpEnum: 
                        buf.extend(offs + 4);
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                Bytes.pack4(buf.arr, offs, (int) elem.IntValue);
                            }
                            else if (elem.isRealValue())
                            {
                                Bytes.pack4(buf.arr, offs, (int) elem.RealValue);
                            }
                            else if (elem.isStringValue()) 
                            {
                                try
                                {
                                    Bytes.pack4(buf.arr, offs, (int)ClassDescriptor.parseEnum(f.FieldType, elem.StringValue));
                                } 
                                catch (ArgumentException)
                                {
                                    throwException("Invalid enum value");
                                }
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 4;
                        continue;
					

                    case ClassDescriptor.FieldType.tpInt: 
                    case ClassDescriptor.FieldType.tpUInt: 
                        buf.extend(offs + 4);
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                Bytes.pack4(buf.arr, offs, (int) elem.IntValue);
                            }
                            else if (elem.isRealValue())
                            {
                                Bytes.pack4(buf.arr, offs, (int) elem.RealValue);
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 4;
                        continue;
					
                    case ClassDescriptor.FieldType.tpLong: 
                    case ClassDescriptor.FieldType.tpULong: 
                        buf.extend(offs + 8);
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                Bytes.pack8(buf.arr, offs, elem.IntValue);
                            }
                            else if (elem.isRealValue())
                            {
                                Bytes.pack8(buf.arr, offs, (long) elem.RealValue);
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 8;
                        continue;
					
                    case ClassDescriptor.FieldType.tpFloat: 
                        buf.extend(offs + 4);
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                Bytes.packF4(buf.arr, offs, (float)elem.IntValue);
                            }
                            else if (elem.isRealValue())
                            {
                                Bytes.packF4(buf.arr, offs, (float) elem.RealValue);
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 4;
                        continue;
					
                    case ClassDescriptor.FieldType.tpDouble: 
                        buf.extend(offs + 8);
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                Bytes.packF8(buf.arr, offs, (double) elem.IntValue);
                            }
                            else if (elem.isRealValue())
                            {
                                Bytes.packF8(buf.arr, offs, elem.RealValue);
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 8;
                        continue;
					
                    case ClassDescriptor.FieldType.tpDecimal: 
                        buf.extend(offs + 16);
                        if (elem != null)
                        {
                            decimal d = 0;
                            if (elem.isIntValue())
                            {
                                d = elem.IntValue;
                            }
                            else if (elem.isRealValue())
                            {
                                d = (decimal)elem.RealValue;
                            }
                            else if (elem.isStringValue())
                            {
                                try 
                                { 
                                    d = Decimal.Parse(elem.StringValue);
                                } 
                                catch (FormatException) 
                                {
                                    throwException("Invalid date");
                                }
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                            Bytes.packDecimal(buf.arr, offs, d);

                        }
                        offs += 16;
                        continue;
  
                    case ClassDescriptor.FieldType.tpGuid: 
                        buf.extend(offs + 16);
                        if (elem != null)
                        {
                            if (elem.isStringValue())
                            {
                                Guid guid = new Guid(elem.StringValue);
                                byte[] bits = guid.ToByteArray();
                                Array.Copy(bits, 0, buf.arr, offs, 16);
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 16;
                        continue;
                    
                    case ClassDescriptor.FieldType.tpDate: 
                        buf.extend(offs + 8);
                        if (elem != null)
                        {
                            if (elem.isIntValue())
                            {
                                Bytes.pack8(buf.arr, offs, elem.IntValue);
                            }
                            else if (elem.isStringValue())
                            {
                                try 
                                { 
                                    Bytes.packDate(buf.arr, offs, DateTime.Parse(elem.StringValue));
                                } 
                                catch (FormatException) 
                                {
                                    throwException("Invalid date");
                                }
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                        }
                        offs += 8;
                        continue;
					
                    case ClassDescriptor.FieldType.tpString: 
                    case ClassDescriptor.FieldType.tpType: 
                        if (elem != null)
                        {
                            string val = null;
                            if (elem.isIntValue())
                            {
                                val = System.Convert.ToString(elem.IntValue);
                            }
                            else if (elem.isRealValue())
                            {
                                val = elem.RealValue.ToString();
                            }
                            else if (elem.isStringValue())
                            {
                                val = elem.StringValue;
                            }
                            else if (elem.isNullValue())
                            {
                                val = null;
                            }
                            else
                            {
                                throwException("Conversion for field " + fieldName + " is not possible");
                            }
                            offs = buf.packString(offs, val);
                            continue;
                        }
                        offs = buf.packI4(offs, -1);
                        continue;
					
                    case ClassDescriptor.FieldType.tpOid: 
                    case ClassDescriptor.FieldType.tpObject: 
                        offs = importRef(elem, offs, buf);
                        continue;
					
                    case ClassDescriptor.FieldType.tpValue: 
                        offs = packObject(elem, fd.valueDesc, offs, buf);
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfByte: 
                    case ClassDescriptor.FieldType.tpArrayOfSByte: 
                        offs = importBinary(elem, offs, buf, fieldName);
                        continue;
					
                    case ClassDescriptor.FieldType.tpCustom:
                    {
                        if (!elem.isStringValue()) 
                        {
                            throwException("text element expected");
                        }
                        String str = elem.StringValue;                    
                        object obj = storage.serializer.Parse(str);                        
                        storage.serializer.Pack(obj, buf.GetWriter());                    
                        offs = buf.used;
                        break;
                    }

                    case ClassDescriptor.FieldType.tpArrayOfBoolean: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4 + len);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isIntValue())
                                {
                                    buf.arr[offs] = (byte) (item.IntValue != 0?1:0);
                                }
                                else if (item.isRealValue())
                                {
                                    buf.arr[offs] = (byte) (item.RealValue != 0.0?1:0);
                                }
                                else
                                {
                                    throwException("Conversion for field " + fieldName + " is not possible");
                                }
                                item = item.NextSibling;
                                offs += 1;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfChar: 
                    case ClassDescriptor.FieldType.tpArrayOfShort: 
                    case ClassDescriptor.FieldType.tpArrayOfUShort: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4 + len * 2);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isIntValue())
                                {
                                    Bytes.pack2(buf.arr, offs, (short) item.IntValue);
                                }
                                else if (item.isRealValue())
                                {
                                    Bytes.pack2(buf.arr, offs, (short) item.RealValue);
                                }
                                else
                                {
                                    throwException("Conversion for field " + fieldName + " is not possible");
                                }
                                item = item.NextSibling;
                                offs += 2;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfEnum: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            Type elemType = f.FieldType.GetElementType();
                            buf.extend(offs + 4 + len * 4);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isIntValue())
                                {
                                    Bytes.pack4(buf.arr, offs, (int) item.IntValue);
                                }
                                else if (item.isRealValue())
                                {
                                    Bytes.pack4(buf.arr, offs, (int) item.RealValue);
                                }
                                else if (item.isStringValue()) 
                                {
                                    try
                                    {
                                        Bytes.pack4(buf.arr, offs, (int)ClassDescriptor.parseEnum(elemType, item.StringValue));
                                    } 
                                    catch (ArgumentException)
                                    {
                                        throwException("Invalid enum value");
                                    }
                                }
                                else
                                {
                                    throwException("Conversion for field " + fieldName + " is not possible");
                                }
                                item = item.NextSibling;
                                offs += 4;
                            }
                        }
                        continue;
                        

                    case ClassDescriptor.FieldType.tpArrayOfInt: 
                    case ClassDescriptor.FieldType.tpArrayOfUInt: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4 + len * 4);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isIntValue())
                                {
                                    Bytes.pack4(buf.arr, offs, (int) item.IntValue);
                                }
                                else if (item.isRealValue())
                                {
                                    Bytes.pack4(buf.arr, offs, (int) item.RealValue);
                                }
                                else
                                {
                                    throwException("Conversion for field " + fieldName + " is not possible");
                                }
                                item = item.NextSibling;
                                offs += 4;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfLong: 
                    case ClassDescriptor.FieldType.tpArrayOfULong: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4 + len * 8);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isIntValue())
                                {
                                    Bytes.pack8(buf.arr, offs, item.IntValue);
                                }
                                else if (item.isRealValue())
                                {
                                    Bytes.pack8(buf.arr, offs, (long) item.RealValue);
                                }
                                else
                                {
                                    throwException("Conversion for field " + fieldName + " is not possible");
                                }
                                item = item.NextSibling;
                                offs += 8;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfFloat: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4 + len * 4);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isIntValue())
                                {
                                   Bytes.packF4(buf.arr, offs, (float)item.IntValue);
                                }
                                else if (item.isRealValue())
                                {
                                    Bytes.packF4(buf.arr, offs, (float)item.RealValue);
                                }
                                else
                                {
                                    throwException("Conversion for field " + fieldName + " is not possible");
                                }
                                item = item.NextSibling;
                                offs += 4;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfDouble: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4 + len * 8);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isIntValue())
                                {
                                    Bytes.packF8(buf.arr, offs, (double)item.IntValue);
                                }
                                else if (item.isRealValue())
                                {
                                    Bytes.packF8(buf.arr, offs, item.RealValue);
                                }
                                else
                                {
                                    throwException("Conversion for field " + fieldName + " is not possible");
                                }
                                item = item.NextSibling;
                                offs += 8;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfDate: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4 + len * 8);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isNullValue())
                                {
                                    Bytes.pack8(buf.arr, offs, -1);
                                }
                                else if (item.isStringValue())
                                {
                                    try 
                                    { 
                                        Bytes.packDate(buf.arr, offs, DateTime.Parse(item.StringValue));
                                    }
                                    catch (FormatException)
                                    {
                                        throwException("Conversion for field " + fieldName + " is not possible");
                                    }
                                }
                                item = item.NextSibling;
                                offs += 8;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfDecimal: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4 + len * 16);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isStringValue())
                                {
                                    try 
                                    { 
                                        Bytes.packDecimal(buf.arr, offs, Decimal.Parse(item.StringValue));
                                    }
                                    catch (FormatException)
                                    {
                                        throwException("Conversion for field " + fieldName + " is not possible");
                                    }
                                }
                                item = item.NextSibling;
                                offs += 16;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfGuid: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4 + len * 16);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                if (item.isStringValue())
                                {
                                    try 
                                    { 
                                        Bytes.packGuid(buf.arr, offs, new Guid(item.StringValue));
                                    }
                                    catch (FormatException)
                                    {
                                        throwException("Conversion for field " + fieldName + " is not possible");
                                    }
                                }
                                item = item.NextSibling;
                                offs += 16;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfString: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            buf.extend(offs + 4);
                            Bytes.pack4(buf.arr, offs, len);
                            offs += 4;
                            while (--len >= 0)
                            {
                                string val = null;
                                if (item.isIntValue())
                                {
                                    val = System.Convert.ToString(item.IntValue);
                                }
                                else if (item.isRealValue())
                                {
                                    val = item.RealValue.ToString();
                                }
                                else if (item.isStringValue())
                                {
                                    val = item.StringValue;
                                }
                                else if (item.isNullValue())
                                {
                                    val = null;
                                }
                                else
                                {
                                    throwException("Conversion for field " + fieldName + " is not possible");
                                }
                                offs = buf.packString(offs, val);  
                                item = item.NextSibling;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfObject: 
                    case ClassDescriptor.FieldType.tpArrayOfOid: 
                    case ClassDescriptor.FieldType.tpLink: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            offs = buf.packI4(offs, len);
                            while (--len >= 0)
                            {
                                offs = importRef(item, offs, buf);
                                item = item.NextSibling;
                            }
                        }
                        continue;
					
                    case ClassDescriptor.FieldType.tpArrayOfValue: 
                        if (elem == null || elem.isNullValue())
                        {
                            offs = buf.packI4(offs, -1);
                        }
                        else
                        {
                            XMLElement item = elem.getSibling("element");
                            int len = (item == null)?0:item.Counter;
                            offs = buf.packI4(offs, len);
                            ClassDescriptor elemDesc = fd.valueDesc;
                            while (--len >= 0)
                            {
                                offs = packObject(item, elemDesc, offs, buf);
                                item = item.NextSibling;
                            }
                        }
                        continue;					
                }
            }
            return offs;
        }
Пример #14
0
        Key createKey(ClassDescriptor.FieldType type, String val)
        {
            switch (type)
            {
                case ClassDescriptor.FieldType.tpBoolean: 
                    return new Key(Int32.Parse(val) != 0);
					
                case ClassDescriptor.FieldType.tpByte: 
                    return new Key(Byte.Parse(val));
					
                case ClassDescriptor.FieldType.tpSByte: 
                    return new Key(SByte.Parse(val));
					
                case ClassDescriptor.FieldType.tpChar: 
                    return new Key((char)Int32.Parse(val));
					
                case ClassDescriptor.FieldType.tpShort: 
                    return new Key(Int16.Parse(val));
					
                case ClassDescriptor.FieldType.tpUShort: 
                    return new Key(UInt16.Parse(val));
					
                case ClassDescriptor.FieldType.tpInt: 
                    return new Key(Int32.Parse(val));
					
                case ClassDescriptor.FieldType.tpUInt: 
                case ClassDescriptor.FieldType.tpEnum:
                    return new Key(UInt32.Parse(val));
					
                case ClassDescriptor.FieldType.tpOid: 
                    return new Key(ClassDescriptor.FieldType.tpOid, mapId((int)UInt32.Parse(val)));
                case ClassDescriptor.FieldType.tpObject: 
                    return new Key(new PersistentStub(storage, mapId((int)UInt32.Parse(val))));
					
                case ClassDescriptor.FieldType.tpLong: 
                    return new Key(Int64.Parse(val));
					
                case ClassDescriptor.FieldType.tpULong: 
                    return new Key(UInt64.Parse(val));
					
                case ClassDescriptor.FieldType.tpFloat: 
                    return new Key(Single.Parse(val));
					
                case ClassDescriptor.FieldType.tpDouble: 
                    return new Key(Double.Parse(val));
					
                case ClassDescriptor.FieldType.tpDecimal: 
                    return new Key(Decimal.Parse(val));

                case ClassDescriptor.FieldType.tpGuid: 
                    return new Key(new Guid(val));

                case ClassDescriptor.FieldType.tpString: 
                    return new Key(val);
					
                case ClassDescriptor.FieldType.tpArrayOfByte:
                {
                    byte[] buf = new byte[val.Length >> 1];
                    for (int i = 0; i < buf.Length; i++) 
                    { 
                        buf[i] = (byte)((getHexValue(val[i*2]) << 4) | getHexValue(val[i*2+1]));
                    }
                    return new Key(buf);
                }

                case ClassDescriptor.FieldType.tpDate: 
                    return new Key(DateTime.Parse(val));
					
                default: 
                    throwException("Bad key type");
                    break;
					
            }
            return null;
        }
Пример #15
0
 internal static int allocate(StorageImpl db, int root, ClassDescriptor.FieldType type, BtreeKey ins)
 {
     int pageId = db.allocatePage();
     Page pg = db.putPage(pageId);
     setnItems(pg, 1);
     if (type == ClassDescriptor.FieldType.tpString)
     {
         char[] sval = (char[])ins.key.oval;
         int len = sval.Length;
         setSize(pg, len * 2);
         setKeyStrOffs(pg, 0, keySpace - len * 2);
         setKeyStrSize(pg, 0, len);
         setKeyStrOid(pg, 0, ins.oid);
         setKeyStrOid(pg, 1, root);
         setKeyStrChars(pg, keySpace - len * 2, sval);
     }
     else if (type == ClassDescriptor.FieldType.tpArrayOfByte)
     {
         byte[] bval = (byte[])ins.key.oval;
         int len = bval.Length;
         setSize(pg, len);
         setKeyStrOffs(pg, 0, keySpace - len);
         setKeyStrSize(pg, 0, len);
         setKeyStrOid(pg, 0, ins.oid);
         setKeyStrOid(pg, 1, root);
         setKeyBytes(pg, keySpace - len, bval);
     }
     else
     {
         ins.pack(pg, 0);
         setReference(pg, maxItems - 2, root);
     }
     db.pool.unfix(pg);
     return pageId;
 }
Пример #16
0
        private Type EmitClass(ModuleBuilder module, ClassDescriptor desc)
        {
            counter += 1;
            String generatedClassName = "GeneratedSerializerClass" + counter;
            TypeBuilder serializerType = module.DefineType(generatedClassName, TypeAttributes.Public);

            Type serializerInterface = typeof(GeneratedSerializer);
            serializerType.AddInterfaceImplementation(serializerInterface);
            //Add a constructor
            ConstructorBuilder constructor =
                serializerType.DefineDefaultConstructor(MethodAttributes.Public);

            MethodInfo packInterface = serializerInterface.GetMethod("pack");
            MethodBuilder packBuilder = GetBuilder(serializerType, packInterface);
            generatePackMethod(desc, packBuilder);
            serializerType.DefineMethodOverride(packBuilder, packInterface);

            MethodInfo unpackInterface = serializerInterface.GetMethod("unpack");
            MethodBuilder unpackBuilder = GetBuilder(serializerType, unpackInterface);
            generateUnpackMethod(desc, unpackBuilder);
            serializerType.DefineMethodOverride(unpackBuilder, unpackInterface);

            MethodInfo newInterface = serializerInterface.GetMethod("newInstance");
            MethodBuilder newBuilder = GetBuilder(serializerType, newInterface);
            generateNewMethod(desc, newBuilder);
            serializerType.DefineMethodOverride(newBuilder, newInterface);

            serializerType.CreateType();
            return serializerType;
        }
Пример #17
0
        internal void  extract(Page pg, int offs, ClassDescriptor.FieldType type)
        {
            byte[] data = pg.data;
			
            switch (type)
            {
                case ClassDescriptor.FieldType.tpBoolean: 
                    key = new Key(data[offs] != 0);
                    break;
				
                case ClassDescriptor.FieldType.tpSByte: 
                    key = new Key((sbyte)data[offs]);
                    break;
                case ClassDescriptor.FieldType.tpByte: 
                    key = new Key(data[offs]);
                    break;
				
                case ClassDescriptor.FieldType.tpShort: 
                    key = new Key(Bytes.unpack2(data, offs));
                    break;
                case ClassDescriptor.FieldType.tpUShort: 
                    key = new Key((ushort)Bytes.unpack2(data, offs));
                    break;
				
				
                case ClassDescriptor.FieldType.tpChar: 
                    key = new Key((char) Bytes.unpack2(data, offs));
                    break;
				
                case ClassDescriptor.FieldType.tpInt: 
                    key = new Key(Bytes.unpack4(data, offs));
                    break;
                case ClassDescriptor.FieldType.tpEnum: 
                case ClassDescriptor.FieldType.tpUInt: 
                case ClassDescriptor.FieldType.tpObject: 
                case ClassDescriptor.FieldType.tpOid: 
                    key = new Key((uint)Bytes.unpack4(data, offs));
                    break;
				
                case ClassDescriptor.FieldType.tpLong: 
                    key = new Key(Bytes.unpack8(data, offs));
                    break;
                case ClassDescriptor.FieldType.tpDate: 
                case ClassDescriptor.FieldType.tpULong: 
                    key = new Key((ulong)Bytes.unpack8(data, offs));
                    break;
				
                case ClassDescriptor.FieldType.tpFloat: 
                    key = new Key(Bytes.unpackF4(data, offs));
                    break;
				
                case ClassDescriptor.FieldType.tpDouble: 
                    key = new Key(Bytes.unpackF8(data, offs));
                    break;

                case ClassDescriptor.FieldType.tpGuid:
                    key = new Key(Bytes.unpackGuid(data, offs));
                    break;
                
                case ClassDescriptor.FieldType.tpDecimal:
                    key = new Key(Bytes.unpackDecimal(data, offs));
                    break;

                default: 
                    Debug.Assert(false, "Invalid type");
                    break;
				
            }
        }
Пример #18
0
        private void generatePackMethod(ClassDescriptor desc, MethodBuilder builder)
        {
            ILGenerator il = builder.GetILGenerator();
            il.Emit(OpCodes.Ldarg_2); // obj
            il.Emit(OpCodes.Castclass, desc.cls);
            obj = il.DeclareLocal(desc.cls);
            il.Emit(OpCodes.Stloc_0, obj);
            il.Emit(OpCodes.Ldc_I4, ObjectHeader.Sizeof);
            offs = il.DeclareLocal(typeof(int));
            il.Emit(OpCodes.Stloc_1, offs);

            ClassDescriptor.FieldDescriptor[] flds = desc.allFields;

            for (int i = 0, n = flds.Length; i < n; i++)
            {
                ClassDescriptor.FieldDescriptor fd = flds[i];
                FieldInfo f = fd.field;
                switch (fd.type)
                {
                    case ClassDescriptor.FieldType.tpByte: 
                    case ClassDescriptor.FieldType.tpSByte: 
                        generatePackField(il, f, packI1);
                        continue;

                    case ClassDescriptor.FieldType.tpBoolean: 
                        generatePackField(il, f, packBool);
                        continue;
					
                    case ClassDescriptor.FieldType.tpShort: 
                    case ClassDescriptor.FieldType.tpUShort: 
                    case ClassDescriptor.FieldType.tpChar: 
                        generatePackField(il, f, packI2);
                        continue;

                    case ClassDescriptor.FieldType.tpEnum: 
                    case ClassDescriptor.FieldType.tpInt: 
                    case ClassDescriptor.FieldType.tpUInt: 
                        generatePackField(il, f, packI4);
                        continue;
					
                    case ClassDescriptor.FieldType.tpLong: 
                    case ClassDescriptor.FieldType.tpULong: 
                        generatePackField(il, f, packI8);
                        continue;
					
                    case ClassDescriptor.FieldType.tpFloat: 
                        generatePackField(il, f, packF4);
                        continue;
					
                    case ClassDescriptor.FieldType.tpDouble: 
                        generatePackField(il, f, packF8);
                        continue;
					
                    case ClassDescriptor.FieldType.tpDecimal:
                        generatePackField(il, f, packDecimal);
                        continue;

                    case ClassDescriptor.FieldType.tpGuid:
                        generatePackField(il, f, packGuid);
                        continue;

                    case ClassDescriptor.FieldType.tpDate: 
                        generatePackField(il, f, packDate);
                        continue;
					
                    case ClassDescriptor.FieldType.tpString: 
                        generatePackField(il, f, packString);
                        continue;
                
                    default:
                        il.Emit(OpCodes.Ldarg_1); // storage
                        il.Emit(OpCodes.Ldarg_3); // buf
                        il.Emit(OpCodes.Ldloc_1, offs); 
                        il.Emit(OpCodes.Ldloc_0, obj);
                        il.Emit(OpCodes.Ldfld, f);
                        il.Emit(OpCodes.Ldnull); // fd
                        il.Emit(OpCodes.Ldc_I4, (int)fd.type);
                        il.Emit(OpCodes.Call, packField);
                        il.Emit(OpCodes.Stloc_1, offs);
                        continue;
                }
            }
            il.Emit(OpCodes.Ldloc_1, offs);
            il.Emit(OpCodes.Ret);
        }
Пример #19
0
 public override void OnLoad()
 {
     lookupConstructor(ClassDescriptor.lookup(Storage, blockClassName));
 }
Пример #20
0
 internal static BtreeResult handlePageUnderflow(StorageImpl db, Page pg, int r, ClassDescriptor.FieldType type, BtreeKey rem, int height)
 {
     int nItems = getnItems(pg);
     if (type == ClassDescriptor.FieldType.tpString)
     {
         Page a = db.putPage(getKeyStrOid(pg, r));
         int an = getnItems(a);
         if (r < nItems)
         {
             // exists greater page
             Page b = db.getPage(getKeyStrOid(pg, r + 1));
             int bn = getnItems(b);
             int merged_size = (an + bn) * strKeySize + getSize(a) + getSize(b);
             if (height != 1)
             {
                 merged_size += getKeyStrSize(pg, r) * 2 + strKeySize * 2;
             }
             if (merged_size > keySpace)
             {
                 // reallocation of nodes between pages a and b
                 int i, j, k;
                 db.pool.unfix(b);
                 b = db.putPage(getKeyStrOid(pg, r + 1));
                 int size_a = getSize(a);
                 int size_b = getSize(b);
                 int addSize, subSize;
                 if (height != 1)
                 {
                     addSize = getKeyStrSize(pg, r);
                     subSize = getKeyStrSize(b, 0);
                 }
                 else
                 {
                     addSize = subSize = getKeyStrSize(b, 0);
                 }
                 i = 0;
                 int prevDelta = (an * strKeySize + size_a) - (bn * strKeySize + size_b);
                 while (true)
                 {
                     i += 1;
                     int delta = ((an + i) * strKeySize + size_a + addSize * 2) - ((bn - i) * strKeySize + size_b - subSize * 2);
                     if (delta >= 0)
                     {
                         if (delta >= - prevDelta)
                         {
                             i -= 1;
                         }
                         break;
                     }
                     size_a += addSize * 2;
                     size_b -= subSize * 2;
                     prevDelta = delta;
                     if (height != 1)
                     {
                         addSize = subSize;
                         subSize = getKeyStrSize(b, i);
                     }
                     else
                     {
                         addSize = subSize = getKeyStrSize(b, i);
                     }
                 }
                 BtreeResult result = BtreeResult.Done;
                 if (i > 0)
                 {
                     k = i;
                     if (height != 1)
                     {
                         int len = getKeyStrSize(pg, r);
                         setSize(a, getSize(a) + len * 2);
                         setKeyStrOffs(a, an, keySpace - getSize(a));
                         setKeyStrSize(a, an, len);
                         memcpy(a, getKeyStrOffs(a, an), pg, getKeyStrOffs(pg, r), len * 2, 1);
                         k -= 1;
                         an += 1;
                         setKeyStrOid(a, an + k, getKeyStrOid(b, k));
                         setSize(b, getSize(b) - getKeyStrSize(b, k) * 2);
                     }
                     for (j = 0; j < k; j++)
                     {
                         int len = getKeyStrSize(b, j);
                         setSize(a, getSize(a) + len * 2);
                         setSize(b, getSize(b) - len * 2);
                         setKeyStrOffs(a, an, keySpace - getSize(a));
                         setKeyStrSize(a, an, len);
                         setKeyStrOid(a, an, getKeyStrOid(b, j));
                         memcpy(a, getKeyStrOffs(a, an), b, getKeyStrOffs(b, j), len * 2, 1);
                         an += 1;
                     }
                     rem.getStr(b, i - 1);
                     result = replaceStrKey(db, pg, r, rem, height);
                     setnItems(a, an);
                     setnItems(b, compactifyStrings(b, i));
                 }
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 return result;
             }
             else
             {
                 // merge page b to a
                 if (height != 1)
                 {
                     int r_len = getKeyStrSize(pg, r);
                     setKeyStrSize(a, an, r_len);
                     setSize(a, getSize(a) + r_len * 2);
                     setKeyStrOffs(a, an, keySpace - getSize(a));
                     memcpy(a, getKeyStrOffs(a, an), pg, getKeyStrOffs(pg, r), r_len * 2, 1);
                     an += 1;
                     setKeyStrOid(a, an + bn, getKeyStrOid(b, bn));
                 }
                 for (int i = 0; i < bn; i++, an++)
                 {
                     setKeyStrSize(a, an, getKeyStrSize(b, i));
                     setKeyStrOffs(a, an, getKeyStrOffs(b, i) - getSize(a));
                     setKeyStrOid(a, an, getKeyStrOid(b, i));
                 }
                 setSize(a, getSize(a) + getSize(b));
                 setnItems(a, an);
                 memcpy(a, keySpace - getSize(a), b, keySpace - getSize(b), getSize(b), 1);
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 db.freePage(getKeyStrOid(pg, r + 1));
                 setKeyStrOid(pg, r + 1, getKeyStrOid(pg, r));
                 return removeStrKey(pg, r);
             }
         }
         else
         {
             // page b is before a
             Page b = db.getPage(getKeyStrOid(pg, r - 1));
             int bn = getnItems(b);
             int merged_size = (an + bn) * strKeySize + getSize(a) + getSize(b);
             if (height != 1)
             {
                 merged_size += getKeyStrSize(pg, r - 1) * 2 + strKeySize * 2;
             }
             if (merged_size > keySpace)
             {
                 // reallocation of nodes between pages a and b
                 int i, j, k, len;
                 db.pool.unfix(b);
                 b = db.putPage(getKeyStrOid(pg, r - 1));
                 int size_a = getSize(a);
                 int size_b = getSize(b);
                 int addSize, subSize;
                 if (height != 1)
                 {
                     addSize = getKeyStrSize(pg, r - 1);
                     subSize = getKeyStrSize(b, bn - 1);
                 }
                 else
                 {
                     addSize = subSize = getKeyStrSize(b, bn - 1);
                 }
                 i = 0;
                 int prevDelta = (an * strKeySize + size_a) - (bn * strKeySize + size_b);
                 while (true)
                 {
                     i += 1;
                     int delta = ((an + i) * strKeySize + size_a + addSize * 2) - ((bn - i) * strKeySize + size_b - subSize * 2);
                     if (delta >= 0)
                     {
                         if (delta >= - prevDelta)
                         {
                             i -= 1;
                         }
                         break;
                     }
                     prevDelta = delta;
                     size_a += addSize * 2;
                     size_b -= subSize * 2;
                     if (height != 1)
                     {
                         addSize = subSize;
                         subSize = getKeyStrSize(b, bn - i - 1);
                     }
                     else
                     {
                         addSize = subSize = getKeyStrSize(b, bn - i - 1);
                     }
                 }
                 BtreeResult result = BtreeResult.Done;
                 if (i > 0)
                 {
                     k = i;
                     Debug.Assert(i < bn);
                     if (height != 1)
                     {
                         setSize(b, getSize(b) - getKeyStrSize(b, bn - k) * 2);
                         memcpy(a, i, a, 0, an + 1, strKeySize);
                         k -= 1;
                         setKeyStrOid(a, k, getKeyStrOid(b, bn));
                         len = getKeyStrSize(pg, r - 1);
                         setKeyStrSize(a, k, len);
                         setSize(a, getSize(a) + len * 2);
                         setKeyStrOffs(a, k, keySpace - getSize(a));
                         memcpy(a, getKeyStrOffs(a, k), pg, getKeyStrOffs(pg, r - 1), len * 2, 1);
                     }
                     else
                     {
                         memcpy(a, i, a, 0, an, strKeySize);
                     }
                     for (j = 0; j < k; j++)
                     {
                         len = getKeyStrSize(b, bn - k + j);
                         setSize(a, getSize(a) + len * 2);
                         setSize(b, getSize(b) - len * 2);
                         setKeyStrOffs(a, j, keySpace - getSize(a));
                         setKeyStrSize(a, j, len);
                         setKeyStrOid(a, j, getKeyStrOid(b, bn - k + j));
                         memcpy(a, getKeyStrOffs(a, j), b, getKeyStrOffs(b, bn - k + j), len * 2, 1);
                     }
                     an += i;
                     setnItems(a, an);
                     rem.getStr(b, bn - k - 1);
                     result = replaceStrKey(db, pg, r - 1, rem, height);
                     setnItems(b, compactifyStrings(b, - i));
                 }
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 return result;
             }
             else
             {
                 // merge page b to a
                 if (height != 1)
                 {
                     memcpy(a, bn + 1, a, 0, an + 1, strKeySize);
                     int len = getKeyStrSize(pg, r - 1);
                     setKeyStrSize(a, bn, len);
                     setSize(a, getSize(a) + len * 2);
                     setKeyStrOffs(a, bn, keySpace - getSize(a));
                     setKeyStrOid(a, bn, getKeyStrOid(b, bn));
                     memcpy(a, getKeyStrOffs(a, bn), pg, getKeyStrOffs(pg, r - 1), len * 2, 1);
                     an += 1;
                 }
                 else
                 {
                     memcpy(a, bn, a, 0, an, strKeySize);
                 }
                 for (int i = 0; i < bn; i++)
                 {
                     setKeyStrOid(a, i, getKeyStrOid(b, i));
                     setKeyStrSize(a, i, getKeyStrSize(b, i));
                     setKeyStrOffs(a, i, getKeyStrOffs(b, i) - getSize(a));
                 }
                 an += bn;
                 setnItems(a, an);
                 setSize(a, getSize(a) + getSize(b));
                 memcpy(a, keySpace - getSize(a), b, keySpace - getSize(b), getSize(b), 1);
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 db.freePage(getKeyStrOid(pg, r - 1));
                 return removeStrKey(pg, r - 1);
             }
         }
     }
     else if (type == ClassDescriptor.FieldType.tpArrayOfByte)
     {
         Page a = db.putPage(getKeyStrOid(pg, r));
         int an = getnItems(a);
         if (r < nItems)
         {
             // exists greater page
             Page b = db.getPage(getKeyStrOid(pg, r + 1));
             int bn = getnItems(b);
             int merged_size = (an + bn) * strKeySize + getSize(a) + getSize(b);
             if (height != 1)
             {
                 merged_size += getKeyStrSize(pg, r) + strKeySize * 2;
             }
             if (merged_size > keySpace)
             {
                 // reallocation of nodes between pages a and b
                 int i, j, k;
                 db.pool.unfix(b);
                 b = db.putPage(getKeyStrOid(pg, r + 1));
                 int size_a = getSize(a);
                 int size_b = getSize(b);
                 int addSize, subSize;
                 if (height != 1)
                 {
                     addSize = getKeyStrSize(pg, r);
                     subSize = getKeyStrSize(b, 0);
                 }
                 else
                 {
                     addSize = subSize = getKeyStrSize(b, 0);
                 }
                 i = 0;
                 int prevDelta = (an * strKeySize + size_a) - (bn * strKeySize + size_b);
                 while (true)
                 {
                     i += 1;
                     int delta = ((an + i) * strKeySize + size_a + addSize) - ((bn - i) * strKeySize + size_b - subSize);
                     if (delta >= 0)
                     {
                         if (delta >= - prevDelta)
                         {
                             i -= 1;
                         }
                         break;
                     }
                     size_a += addSize;
                     size_b -= subSize;
                     prevDelta = delta;
                     if (height != 1)
                     {
                         addSize = subSize;
                         subSize = getKeyStrSize(b, i);
                     }
                     else
                     {
                         addSize = subSize = getKeyStrSize(b, i);
                     }
                 }
                 BtreeResult result = BtreeResult.Done;
                 if (i > 0)
                 {
                     k = i;
                     if (height != 1)
                     {
                         int len = getKeyStrSize(pg, r);
                         setSize(a, getSize(a) + len);
                         setKeyStrOffs(a, an, keySpace - getSize(a));
                         setKeyStrSize(a, an, len);
                         memcpy(a, getKeyStrOffs(a, an), pg, getKeyStrOffs(pg, r), len, 1);
                         k -= 1;
                         an += 1;
                         setKeyStrOid(a, an + k, getKeyStrOid(b, k));
                         setSize(b, getSize(b) - getKeyStrSize(b, k));
                     }
                     for (j = 0; j < k; j++)
                     {
                         int len = getKeyStrSize(b, j);
                         setSize(a, getSize(a) + len);
                         setSize(b, getSize(b) - len);
                         setKeyStrOffs(a, an, keySpace - getSize(a));
                         setKeyStrSize(a, an, len);
                         setKeyStrOid(a, an, getKeyStrOid(b, j));
                         memcpy(a, getKeyStrOffs(a, an), b, getKeyStrOffs(b, j), len, 1);
                         an += 1;
                     }
                     rem.getByteArray(b, i - 1);
                     result = replaceByteArrayKey(db, pg, r, rem, height);
                     setnItems(a, an);
                     setnItems(b, compactifyByteArrays(b, i));
                 }
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 return result;
             }
             else
             {
                 // merge page b to a
                 if (height != 1)
                 {
                     int r_len = getKeyStrSize(pg, r);
                     setKeyStrSize(a, an, r_len);
                     setSize(a, getSize(a) + r_len);
                     setKeyStrOffs(a, an, keySpace - getSize(a));
                     memcpy(a, getKeyStrOffs(a, an), pg, getKeyStrOffs(pg, r), r_len, 1);
                     an += 1;
                     setKeyStrOid(a, an + bn, getKeyStrOid(b, bn));
                 }
                 for (int i = 0; i < bn; i++, an++)
                 {
                     setKeyStrSize(a, an, getKeyStrSize(b, i));
                     setKeyStrOffs(a, an, getKeyStrOffs(b, i) - getSize(a));
                     setKeyStrOid(a, an, getKeyStrOid(b, i));
                 }
                 setSize(a, getSize(a) + getSize(b));
                 setnItems(a, an);
                 memcpy(a, keySpace - getSize(a), b, keySpace - getSize(b), getSize(b), 1);
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 db.freePage(getKeyStrOid(pg, r + 1));
                 setKeyStrOid(pg, r + 1, getKeyStrOid(pg, r));
                 return removeByteArrayKey(pg, r);
             }
         }
         else
         {
             // page b is before a
             Page b = db.getPage(getKeyStrOid(pg, r - 1));
             int bn = getnItems(b);
             int merged_size = (an + bn) * strKeySize + getSize(a) + getSize(b);
             if (height != 1)
             {
                 merged_size += getKeyStrSize(pg, r - 1) + strKeySize * 2;
             }
             if (merged_size > keySpace)
             {
                 // reallocation of nodes between pages a and b
                 int i, j, k, len;
                 db.pool.unfix(b);
                 b = db.putPage(getKeyStrOid(pg, r - 1));
                 int size_a = getSize(a);
                 int size_b = getSize(b);
                 int addSize, subSize;
                 if (height != 1)
                 {
                     addSize = getKeyStrSize(pg, r - 1);
                     subSize = getKeyStrSize(b, bn - 1);
                 }
                 else
                 {
                     addSize = subSize = getKeyStrSize(b, bn - 1);
                 }
                 i = 0;
                 int prevDelta = (an * strKeySize + size_a) - (bn * strKeySize + size_b);
                 while (true)
                 {
                     i += 1;
                     int delta = ((an + i) * strKeySize + size_a + addSize) - ((bn - i) * strKeySize + size_b - subSize);
                     if (delta >= 0)
                     {
                         if (delta >= - prevDelta)
                         {
                             i -= 1;
                         }
                         break;
                     }
                     prevDelta = delta;
                     size_a += addSize;
                     size_b -= subSize;
                     if (height != 1)
                     {
                         addSize = subSize;
                         subSize = getKeyStrSize(b, bn - i - 1);
                     }
                     else
                     {
                         addSize = subSize = getKeyStrSize(b, bn - i - 1);
                     }
                 }
                 BtreeResult result = BtreeResult.Done;
                 if (i > 0)
                 {
                     k = i;
                     Debug.Assert(i < bn);
                     if (height != 1)
                     {
                         setSize(b, getSize(b) - getKeyStrSize(b, bn - k));
                         memcpy(a, i, a, 0, an + 1, strKeySize);
                         k -= 1;
                         setKeyStrOid(a, k, getKeyStrOid(b, bn));
                         len = getKeyStrSize(pg, r - 1);
                         setKeyStrSize(a, k, len);
                         setSize(a, getSize(a) + len);
                         setKeyStrOffs(a, k, keySpace - getSize(a));
                         memcpy(a, getKeyStrOffs(a, k), pg, getKeyStrOffs(pg, r - 1), len, 1);
                     }
                     else
                     {
                         memcpy(a, i, a, 0, an, strKeySize);
                     }
                     for (j = 0; j < k; j++)
                     {
                         len = getKeyStrSize(b, bn - k + j);
                         setSize(a, getSize(a) + len);
                         setSize(b, getSize(b) - len);
                         setKeyStrOffs(a, j, keySpace - getSize(a));
                         setKeyStrSize(a, j, len);
                         setKeyStrOid(a, j, getKeyStrOid(b, bn - k + j));
                         memcpy(a, getKeyStrOffs(a, j), b, getKeyStrOffs(b, bn - k + j), len, 1);
                     }
                     an += i;
                     setnItems(a, an);
                     rem.getByteArray(b, bn - k - 1);
                     result = replaceByteArrayKey(db, pg, r - 1, rem, height);
                     setnItems(b, compactifyByteArrays(b, - i));
                 }
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 return result;
             }
             else
             {
                 // merge page b to a
                 if (height != 1)
                 {
                     memcpy(a, bn + 1, a, 0, an + 1, strKeySize);
                     int len = getKeyStrSize(pg, r - 1);
                     setKeyStrSize(a, bn, len);
                     setSize(a, getSize(a) + len);
                     setKeyStrOffs(a, bn, keySpace - getSize(a));
                     setKeyStrOid(a, bn, getKeyStrOid(b, bn));
                     memcpy(a, getKeyStrOffs(a, bn), pg, getKeyStrOffs(pg, r - 1), len, 1);
                     an += 1;
                 }
                 else
                 {
                     memcpy(a, bn, a, 0, an, strKeySize);
                 }
                 for (int i = 0; i < bn; i++)
                 {
                     setKeyStrOid(a, i, getKeyStrOid(b, i));
                     setKeyStrSize(a, i, getKeyStrSize(b, i));
                     setKeyStrOffs(a, i, getKeyStrOffs(b, i) - getSize(a));
                 }
                 an += bn;
                 setnItems(a, an);
                 setSize(a, getSize(a) + getSize(b));
                 memcpy(a, keySpace - getSize(a), b, keySpace - getSize(b), getSize(b), 1);
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 db.freePage(getKeyStrOid(pg, r - 1));
                 return removeByteArrayKey(pg, r - 1);
             }
         }
     }
     else
     {
         Page a = db.putPage(getReference(pg, maxItems - r - 1));
         int an = getnItems(a);
         int itemSize = ClassDescriptor.Sizeof[(int)type];
         if (r < nItems)
         {
             // exists greater page
             Page b = db.getPage(getReference(pg, maxItems - r - 2));
             int bn = getnItems(b);
             Debug.Assert(bn >= an);
             if (height != 1)
             {
                 memcpy(a, an, pg, r, 1, itemSize);
                 an += 1;
                 bn += 1;
             }
             int merged_size = (an + bn) * (4 + itemSize);
             if (merged_size > keySpace)
             {
                 // reallocation of nodes between pages a and b
                 int i = bn - ((an + bn) >> 1);
                 db.pool.unfix(b);
                 b = db.putPage(getReference(pg, maxItems - r - 2));
                 memcpy(a, an, b, 0, i, itemSize);
                 memcpy(b, 0, b, i, bn - i, itemSize);
                 memcpy(a, maxItems - an - i, b, maxItems - i, i, 4);
                 memcpy(b, maxItems - bn + i, b, maxItems - bn, bn - i, 4);
                 memcpy(pg, r, a, an + i - 1, 1, itemSize);
                 setnItems(b, getnItems(b) - i);
                 setnItems(a, getnItems(a) + i);
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 return BtreeResult.Done;
             }
             else
             {
                 // merge page b to a  
                 memcpy(a, an, b, 0, bn, itemSize);
                 memcpy(a, maxItems - an - bn, b, maxItems - bn, bn, 4);
                 db.freePage(getReference(pg, maxItems - r - 2));
                 memcpy(pg, maxItems - nItems, pg, maxItems - nItems - 1, nItems - r - 1, 4);
                 memcpy(pg, r, pg, r + 1, nItems - r - 1, itemSize);
                 setnItems(a, getnItems(a) + bn);
                 setnItems(pg, nItems - 1);
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 return nItems * (itemSize + 4) < keySpace / 3 ? BtreeResult.Underflow : BtreeResult.Done;
             }
         }
         else
         {
             // page b is before a
             Page b = db.getPage(getReference(pg, maxItems - r));
             int bn = getnItems(b);
             Debug.Assert(bn >= an);
             if (height != 1)
             {
                 an += 1;
                 bn += 1;
             }
             int merged_size = (an + bn) * (4 + itemSize);
             if (merged_size > keySpace)
             {
                 // reallocation of nodes between pages a and b
                 int i = bn - ((an + bn) >> 1);
                 db.pool.unfix(b);
                 b = db.putPage(getReference(pg, maxItems - r));
                 memcpy(a, i, a, 0, an, itemSize);
                 memcpy(a, 0, b, bn - i, i, itemSize);
                 memcpy(a, maxItems - an - i, a, maxItems - an, an, 4);
                 memcpy(a, maxItems - i, b, maxItems - bn, i, 4);
                 if (height != 1)
                 {
                     memcpy(a, i - 1, pg, r - 1, 1, itemSize);
                 }
                 memcpy(pg, r - 1, b, bn - i - 1, 1, itemSize);
                 setnItems(b, getnItems(b) - i);
                 setnItems(a, getnItems(a) + i);
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 return BtreeResult.Done;
             }
             else
             {
                 // merge page b to a
                 memcpy(a, bn, a, 0, an, itemSize);
                 memcpy(a, 0, b, 0, bn, itemSize);
                 memcpy(a, maxItems - an - bn, a, maxItems - an, an, 4);
                 memcpy(a, maxItems - bn, b, maxItems - bn, bn, 4);
                 if (height != 1)
                 {
                     memcpy(a, bn - 1, pg, r - 1, 1, itemSize);
                 }
                 db.freePage(getReference(pg, maxItems - r));
                 setReference(pg, maxItems - r, getReference(pg, maxItems - r - 1));
                 setnItems(a, getnItems(a) + bn);
                 setnItems(pg, nItems - 1);
                 db.pool.unfix(a);
                 db.pool.unfix(b);
                 return nItems * (itemSize + 4) < keySpace / 3 ? BtreeResult.Underflow : BtreeResult.Done;
             }
         }
     }
 }
Пример #21
0
 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);
 }
Пример #22
0
 internal static void  purge(StorageImpl db, int pageId, ClassDescriptor.FieldType type, int height)
 {
     if (--height != 0)
     {
         Page pg = db.getPage(pageId);
         int n = getnItems(pg) + 1;
         if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte)
         {
             // page of strings
             while (--n >= 0)
             {
                 purge(db, getKeyStrOid(pg, n), type, height);
             }
         }
         else
         {
             while (--n >= 0)
             {
                 purge(db, getReference(pg, maxItems - n - 1), type, height);
             }
         }
         db.pool.unfix(pg);
     }
     db.freePage(pageId);
 }
Пример #23
0
        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;
        }
Пример #24
0
        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)
                {
                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(f.FieldType, 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:
                    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:
                    exportRef(Bytes.unpack4(body, offs));
                    offs += 4;
                    break;

                case ClassDescriptor.FieldType.tpValue:
                    writer.Write('\n');
                    offs = exportObject(fd.valueDesc, body, offs, indent + 1);
                    indentation(indent);
                    break;

#if SUPPORT_RAW_TYPE
                case ClassDescriptor.FieldType.tpRaw:
#endif
                case ClassDescriptor.FieldType.tpArrayOfByte:
                case ClassDescriptor.FieldType.tpArrayOfSByte:
                    offs = exportBinary(body, offs);
                    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 = f.FieldType.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:
                {
                    int len = Bytes.unpack4(body, offs);
                    offs += 4;
                    if (len < 0)
                    {
                        writer.Write("null");
                    }
                    else
                    {
                        writer.Write('\n');
                        while (--len >= 0)
                        {
                            indentation(indent + 1);
                            int oid = Bytes.unpack4(body, offs);
                            if (oid != 0 && (exportedBitmap[oid >> 5] & (1 << (oid & 31))) == 0)
                            {
                                markedBitmap[oid >> 5] |= 1 << (oid & 31);
                            }
                            writer.Write("<element><ref id=\"" + oid + "\"/></element>\n");
                            offs += 4;
                        }
                        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;
                }

#if SUPPORT_RAW_TYPE
                case ClassDescriptor.FieldType.tpArrayOfRaw:
                {
                    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 = exportBinary(body, offs);
                            writer.Write("</element>\n");
                        }
                        indentation(indent);
                    }
                    break;
                }
#endif
                }
                writer.Write("</" + fieldName + ">\n");
            }
            return(offs);
        }