internal static int allocate(DatabaseImpl db, int root, ClassDescriptor.FieldType type, OldBtreeKey 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; }
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; switch (fd.type) { 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 { #if CF Bytes.pack4(buf.arr, offs, (int)ClassDescriptor.parseEnum(f.FieldType, elem.StringValue)); #else Bytes.pack4(buf.arr, offs, (int)Enum.Parse(f.FieldType, elem.StringValue)); #endif } 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.isNullValue()) { Bytes.pack8(buf.arr, offs, -1); } 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: if (elem != null) { System.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; } buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; continue; case ClassDescriptor.FieldType.tpOid: case ClassDescriptor.FieldType.tpObject: { int oid = 0; if (elem != null) { XMLElement refElem = elem.getSibling("ref"); if (refElem == null) { throwException("<ref> element expected"); } oid = mapId(getIntAttribute(refElem, "id")); } buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, oid); offs += 4; continue; } case ClassDescriptor.FieldType.tpValue: offs = packObject(elem, fd.valueDesc, offs, buf); continue; case ClassDescriptor.FieldType.tpRaw: case ClassDescriptor.FieldType.tpArrayOfByte: case ClassDescriptor.FieldType.tpArrayOfSByte: offs = importBinary(elem, offs, buf, fieldName); continue; case ClassDescriptor.FieldType.tpArrayOfBoolean: if (elem == null || elem.isNullValue()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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 { #if CF Bytes.pack4(buf.arr, offs, (int)ClassDescriptor.parseEnum(elemType, item.StringValue)); #else Bytes.pack4(buf.arr, offs, (int)Enum.Parse(elemType, item.StringValue)); #endif } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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) { System.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()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } 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) { XMLElement href = item.getSibling("ref"); if (href == null) { throwException("<ref> element expected"); } int oid = mapId(getIntAttribute(href, "id")); Bytes.pack4(buf.arr, offs, oid); item = item.NextSibling; offs += 4; } } continue; case ClassDescriptor.FieldType.tpArrayOfValue: if (elem == null || elem.isNullValue()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } else { XMLElement item = elem.getSibling("element"); int len = (item == null) ? 0 : item.Counter; Bytes.pack4(buf.arr, offs, len); offs += 4; ClassDescriptor elemDesc = fd.valueDesc; while (--len >= 0) { offs = packObject(item, elemDesc, offs, buf); item = item.NextSibling; } } continue; case ClassDescriptor.FieldType.tpArrayOfRaw: if (elem == null || elem.isNullValue()) { buf.extend(offs + 4); Bytes.pack4(buf.arr, offs, -1); offs += 4; } else { XMLElement item = elem.getSibling("element"); int len = (item == null) ? 0 : item.Counter; Bytes.pack4(buf.arr, offs, len); offs += 4; while (--len >= 0) { offs = importBinary(item, offs, buf, fieldName); item = item.NextSibling; } } continue; } } return offs; }
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(db, 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; }
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: 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()); }
internal static void purge(DatabaseImpl 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); }
public GeneratedSerializer Generate(ClassDescriptor desc) { ModuleBuilder module = EmitAssemblyModule(); Type newCls = EmitClass(module, desc); return (GeneratedSerializer)module.Assembly.CreateInstance(newCls.Name); }
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); // db 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.Ldloc_0, obj); il.Emit(OpCodes.Call, packField); il.Emit(OpCodes.Stloc_1, offs); continue; } } il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ret); }
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; } }
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: case ClassDescriptor.FieldType.tpOid: 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; case ClassDescriptor.FieldType.tpRaw: 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: 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); 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; } 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; } } writer.Write("</" + fieldName + ">\n"); } return offs; }
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"); }
internal static OldBtreeResult handlePageUnderflow(DatabaseImpl db, Page pg, int r, ClassDescriptor.FieldType type, OldBtreeKey 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); } } OldBtreeResult result = OldBtreeResult.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); } } OldBtreeResult result = OldBtreeResult.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); } } OldBtreeResult result = OldBtreeResult.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); } } OldBtreeResult result = OldBtreeResult.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 OldBtreeResult.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 / 2 ? OldBtreeResult.Underflow : OldBtreeResult.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 OldBtreeResult.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 / 2 ? OldBtreeResult.Underflow : OldBtreeResult.Done; } } } }
internal static void exportPage(DatabaseImpl 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, OldBtreePage.firstKeyOffs + OldBtreePage.getKeyStrOffs(pg, i), OldBtreePage.getKeyStrSize(pg, i), type); } } else { // page of scalars for (i = 0; i < n; i++) { exporter.exportAssoc(getReference(pg, maxItems - 1 - i), pg.data, OldBtreePage.firstKeyOffs + i * ClassDescriptor.Sizeof[(int)type], ClassDescriptor.Sizeof[(int)type], type); } } } } finally { db.pool.unfix(pg); } }
internal static int traverseForward(DatabaseImpl db, int pageId, ClassDescriptor.FieldType type, int height, IPersistent[] 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); } }
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; }
void exportCompoundKey(byte[] body, int offs, int size, ClassDescriptor.FieldType type) { Debug.Assert(type == ClassDescriptor.FieldType.tpArrayOfByte); int end = offs + size; for (int i = 0; i < compoundKeyTypes.Length; i++) { type = compoundKeyTypes[i]; if (type == ClassDescriptor.FieldType.tpArrayOfByte || type == ClassDescriptor.FieldType.tpString) { size = Bytes.unpack4(body, offs); offs += 4; } writer.Write(" key" + i + "=\""); offs = exportKey(body, offs, size, type); writer.Write("\""); } Debug.Assert(offs == end); }
internal void resolve() { if (resolved) return; DatabaseImpl classStorage = (DatabaseImpl)Database; ClassDescriptor desc = new ClassDescriptor(classStorage, cls); resolved = true; if (!desc.equals(this)) { classStorage.registerClassDescriptor(desc); } }
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: if (size < 0) { string s; offs = Bytes.unpackString(body, offs - 4, out s); for (int i = 0; i < s.Length; i++) { exportChar(s[i]); } } else { 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 generateNewMethod(ClassDescriptor desc, MethodBuilder builder) { ILGenerator il = builder.GetILGenerator(); il.Emit(OpCodes.Newobj, desc.defaultConstructor); il.Emit(OpCodes.Ret); }
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); // db 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.Call, unpackString); il.Emit(OpCodes.Stloc_1, offs); continue; default: il.Emit(OpCodes.Ldarg_1); // db 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 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 //TODO: wasn't used, figure out if was needed //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; }
internal static int markPage(DatabaseImpl db, int pageId, ClassDescriptor.FieldType type, int height) { 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; }