anchor.diff:      Result := CompareStr(Item, Value) = 0
   {$ENDIF}
     else
  -    Result := VarEquals(Item, Value)
  +*)
  +    Result := VarEquals(Item, Value);
   end;
   
   function THashedList.IndexOf(const Value: Variant): Integer;
  
positive.code:     else if (L^.VType = varUnknown or varByRef) and
              (R^.VType = varUnknown or varByRef) then
        Result := Pointer(L^.VPointer^) = Pointer(R^.VPointer^)
      else
        try
          Result := Left = Right;
        except
          Result := False;
        end;
    end;
  end;
  
  function VarIsObj(const Value: Variant): Boolean;
  begin
    Result := VarIsObj(Value, TObject);
  end;
  
  function VarIsObj(const Value: Variant; AClass: TClass): Boolean;
  var
    P: PVarData;
  begin
    Result := True;
    try
      P := FindVarData(Value);
      if P^.VType = varObject then
        Result := TObject(P^.VPointer) is AClass
      else if P^.VType <> varNull then
        Result := False;
    except
      Result := False;
    end;
  end;
  
  function VarIsList(const Value: Variant): Boolean;
  begin
    Result := (FindVarData(Value)^.VType = varUnknown) and
              Supports(IInterface(Value), IList) or
              VarIsObj(Value, TAbstractList);
  end;
  
  function VarToList(const Value: Variant): IList;
  begin
    if FindVarData(Value)^.VType = varUnknown then
      Supports(IInterface(Value), IList, Result)
    else if VarIsObj(Value, TAbstractList) then
      VarToObj(Value, TAbstractList, Result)
    else
      Error(reInvalidCast);
  end;
  
  function VarIsMap(const Value: Variant): Boolean;
  begin
    Result := (FindVarData(Value)^.VType = varUnknown) and
              Supports(IInterface(Value), IMap) or
              VarIsObj(Value, TAbstractMap);
  end;
  
  function VarToMap(const Value: Variant): IMap;
  begin
    if FindVarData(Value)^.VType = varUnknown then
      Supports(IInterface(Value), IMap, Result)
    else if VarIsObj(Value, TAbstractMap) then
      VarToObj(Value, TAbstractMap, Result)
    else
      Error(reInvalidCast);
  end;
  
  function VarIsIntf(const Value: Variant): Boolean;
  begin
    Result := (FindVarData(Value)^.VType = varUnknown);
  end;
  
  function VarIsIntf(const Value: Variant; const IID: TGUID): Boolean;
  begin
    Result := (FindVarData(Value)^.VType = varUnknown) and
              Supports(IInterface(Value), IID);
  end;
  
  function VarToIntf(const Value: Variant; const IID: TGUID; out AIntf): Boolean;
  begin
    if FindVarData(Value)^.VType = varUnknown then
      Result := Supports(IInterface(Value), IID, AIntf)
    else
      Result := false;
  end;
  
  {$IFNDEF DELPHI2010_UP}
  type
    TObjectFromInterfaceStub = packed record
      Stub: cardinal;
      case integer of
      0: (ShortJmp: ShortInt);
      1: (LongJmp: LongInt)
    end;
    PObjectFromInterfaceStub = ^TObjectFromInterfaceStub;
  {$ENDIF}
  
  function IntfToObj(const Intf: IInterface): TInterfacedObject; {$IFDEF DELPHI2010_UP}inline;{$ENDIF}
  begin
    if Intf = nil then
      result := nil
    else begin
  {$IFDEF DELPHI2010_UP}
      result := Intf as TInterfacedObject; // slower but always working
  {$ELSE}
      with PObjectFromInterfaceStub(PPointer(PPointer(Intf)^)^)^ do
      case Stub of
        $04244483: result := Pointer(NativeInt(Intf) + ShortJmp);
        $04244481: result := Pointer(NativeInt(Intf) + LongJmp);
        else       result := nil;
      end;
  {$ENDIF}
    end;
  end;
  
  { GetPropValue/SetPropValue }
  
  procedure PropertyNotFound(const Name: string);
  begin
    raise EPropertyError.CreateResFmt(@SUnknownProperty, [Name]);
  end;
  
  procedure PropertyConvertError(const Name: string);
  begin
    raise EPropertyConvertError.CreateResFmt(@SInvalidPropertyType, [Name]);
  end;
  
  {$IFNDEF FPC}
  {$IFNDEF DELPHI2007_UP}
  type
    TAccessStyle = (asFieldData, asAccessor, asIndexedAccessor);
  
  function GetAccessToProperty(Instance: TObject; PropInfo: PPropInfo;
    AccessorProc: Longint; out FieldData: Pointer;
    out Accessor: TMethod): TAccessStyle;
  begin
    if (AccessorProc and $FF000000) = $FF000000 then
    begin  // field - Getter is the field's offset in the instance data
      FieldData := Pointer(Integer(Instance) + (AccessorProc and $00FFFFFF));
      Result := asFieldData;
    end
    else
    begin
      if (AccessorProc and $FF000000) = $FE000000 then
        // virtual method  - Getter is a signed 2 byte integer VMT offset
        Accessor.Code := Pointer(PInteger(PInteger(Instance)^ + SmallInt(AccessorProc))^)
      else
        // static method - Getter is the actual address
        Accessor.Code := Pointer(AccessorProc);
  
      Accessor.Data := Instance;
      if PropInfo^.Index = Integer($80000000) then  // no index
        Result := asAccessor
      else
        Result := asIndexedAccessor;
    end;
  end;
  
  function GetDynArrayProp(Instance: TObject; PropInfo: PPropInfo): Pointer;
  type
    { Need a(ny) dynamic array type to force correct call setup.
      (Address of result passed in EDX) }
    TDynamicArray = array of Byte;
  type
    TDynArrayGetProc = function: TDynamicArray of object;
    TDynArrayIndexedGetProc = function (Index: Integer): TDynamicArray of object;
  var
    M: TMethod;
  begin
    case GetAccessToProperty(Instance, PropInfo, Longint(PropInfo^.GetProc),
      Result, M) of
      asFieldData:
        Result := PPointer(Result)^;
      asAccessor:
        Result := Pointer(TDynArrayGetProc(M)());
      asIndexedAccessor:
        Result := Pointer(TDynArrayIndexedGetProc(M)(PropInfo^.Index));
    end;
  end;
  
  procedure SetDynArrayProp(Instance: TObject; PropInfo: PPropInfo;
    const Value: Pointer);
  type
    TDynArraySetProc = procedure (const Value: Pointer) of object;
    TDynArrayIndexedSetProc = procedure (Index: Integer;
                                         const Value: Pointer) of object;
  var
    P: Pointer;
    M: TMethod;
  begin
    case GetAccessToProperty(Instance, PropInfo, Longint(PropInfo^.SetProc),
      P, M) of
      asFieldData:
        asm
          MOV    ECX, PropInfo
          MOV    ECX, [ECX].TPropInfo.PropType
          MOV    ECX, [ECX]
  
          MOV    EAX, [P]
          MOV    EDX, Value
          CALL   System.@DynArrayAsg
        end;
      asAccessor:
        TDynArraySetProc(M)(Value);
      asIndexedAccessor:
        TDynArrayIndexedSetProc(M)(PropInfo^.Index, Value);
    end;
  end;
  {$ENDIF}
  {$ELSE}
  function GetDynArrayProp(Instance: TObject; PropInfo: PPropInfo): Pointer;
  type
    { Need a(ny) dynamic array type to force correct call setup.
      (Address of result passed in EDX) }
    TDynamicArray = array of Byte;
  type
    TDynArrayGetProc = function: TDynamicArray of object;
    TDynArrayIndexedGetProc = function (Index: Integer): TDynamicArray of object;
  var
    AMethod: TMethod;
  begin
    case (PropInfo^.PropProcs) and 3 of
      ptfield:
        Result := PPointer(Pointer(Instance) + PtrUInt(PropInfo^.GetProc))^;
      ptstatic,
      ptvirtual:
      begin
        if (PropInfo^.PropProcs and 3) = ptStatic then
          AMethod.Code := PropInfo^.GetProc
        else
          AMethod.Code := PPointer(Pointer(Instance.ClassType) + PtrUInt(PropInfo^.GetProc))^;
        AMethod.Data := Instance;
        if ((PropInfo^.PropProcs shr 6) and 1) <> 0 then
          Result := TDynArrayIndexedGetProc(AMethod)(PropInfo^.Index)
        else
          Result := TDynArrayGetProc(AMethod)();
      end;
    end;
  end;
  
  procedure SetDynArrayProp(Instance: TObject; PropInfo: PPropInfo;
    const Value: Pointer);
  type
    TDynArraySetProc = procedure (const Value: Pointer) of object;
    TDynArrayIndexedSetProc = procedure (Index: Integer;
                                         const Value: Pointer) of object;
  var
    AMethod: TMethod;
  begin
    case (PropInfo^.PropProcs shr 2) and 3 of
      ptfield:
        PPointer(Pointer(Instance) + PtrUInt(PropInfo^.SetProc))^ := Value;
      ptstatic,
      ptvirtual:
      begin
        if ((PropInfo^.PropProcs shr 2) and 3) = ptStatic then
          AMethod.Code := PropInfo^.SetProc
        else
          AMethod.Code := PPointer(Pointer(Instance.ClassType) + PtrUInt(PropInfo^.SetProc))^;
        AMethod.Data := Instance;
        if ((PropInfo^.PropProcs shr 6) and 1) <> 0 then
          TDynArrayIndexedSetProc(AMethod)(PropInfo^.Index, Value)
        else
          TDynArraySetProc(AMethod)(Value);
      end;
    end;
  end;
  {$ENDIF}
  
  function GetPropValue(Instance: TObject; PropInfo: PPropInfo): Variant;
  var
    PropType: PTypeInfo;
    DynArray: Pointer;
  begin
    // assume failure
    Result := Null;
    PropType := PropInfo^.PropType{$IFNDEF FPC}^{$ENDIF};
    case PropType^.Kind of
      tkInteger:
        Result := GetOrdProp(Instance, PropInfo);
      tkWChar:
  {$IFNDEF NEXTGEN}
        Result := WideString(WideChar(GetOrdProp(Instance, PropInfo)));
  {$ELSE}
        Result := string(WideChar(GetOrdProp(Instance, PropInfo)));
  {$ENDIF}
      tkEnumeration:
        if GetTypeData(PropType)^.BaseType{$IFNDEF FPC}^{$ENDIF} = TypeInfo(Boolean) then
          Result := Boolean(GetOrdProp(Instance, PropInfo))
        else
          Result := GetOrdProp(Instance, PropInfo);
      tkSet:
        Result := GetOrdProp(Instance, PropInfo);
      tkFloat:
        if ((GetTypeName(PropType) = 'TDateTime') or
            (GetTypeName(PropType) = 'TDate') or
            (GetTypeName(PropType) = 'TTime')) then
          Result := VarAsType(GetFloatProp(Instance, PropInfo), varDate)
        else
          Result := GetFloatProp(Instance, PropInfo);
  {$IFNDEF NEXTGEN}
      tkString, {$IFDEF FPC}tkAString, {$ENDIF}tkLString:
        Result := GetStrProp(Instance, PropInfo);
      tkChar:
        Result := Char(GetOrdProp(Instance, PropInfo));
      tkWString:
        Result := GetWideStrProp(Instance, PropInfo);
  {$IFDEF Supports_Unicode}
      tkUString:
        Result := GetUnicodeStrProp(Instance, PropInfo);
  {$ENDIF}
  {$ELSE}
      tkUString:
        Result := GetStrProp(Instance, PropInfo);
  {$ENDIF}
      tkVariant:
        Result := GetVariantProp(Instance, PropInfo);
      tkInt64:
  {$IFDEF DELPHI2009_UP}
      if (GetTypeName(PropType) = 'UInt64') then
        Result := UInt64(GetInt64Prop(Instance, PropInfo))
      else
  {$ENDIF}
        Result := GetInt64Prop(Instance, PropInfo);
  {$IFDEF FPC}
      tkBool:
        Result := Boolean(GetOrdProp(Instance, PropInfo));
      tkQWord:
        Result := QWord(GetInt64Prop(Instance, PropInfo));
  {$ENDIF}
      tkInterface:
        Result := GetInterfaceProp(Instance, PropInfo);
      tkDynArray:
        begin
          DynArray := GetDynArrayProp(Instance, PropInfo);
          DynArrayToVariant(Result, DynArray, PropType);
        end;
      tkClass:
        Result := ObjToVar(GetObjectProp(Instance, PropInfo));
    else
      PropertyConvertError(GetTypeName(PropType));
    end;
  end;
  
  function GetPropValue(Instance: TObject; const Name: string): Variant;
  begin
    Result := GetPropValue(Instance, GetPropInfo(Instance, Name));
  end;
  
  procedure SetPropValue(Instance: TObject; PropInfo: PPropInfo;
    const Value: Variant);
  var
    PropType: PTypeInfo;
    TypeData: PTypeData;
    Obj: TObject;
    DynArray: Pointer;
  begin
    PropType := PropInfo^.PropType{$IFNDEF FPC}^{$ENDIF};
    TypeData := GetTypeData(PropType);
    // set the right type
    case PropType^.Kind of
      tkInteger, {$IFNDEF NEXTGEN}tkChar, {$ENDIF}tkWChar, tkEnumeration, tkSet:
        SetOrdProp(Instance, PropInfo, Value);
  {$IFDEF FPC}
      tkBool:
        SetOrdProp(Instance, PropInfo, Value);
      tkQWord:
        SetInt64Prop(Instance, PropInfo, QWord(Value));
  {$ENDIF}
      tkFloat:
        SetFloatProp(Instance, PropInfo, Value);
  {$IFNDEF NEXTGEN}
      tkString, {$IFDEF FPC}tkAString, {$ENDIF}tkLString:
        SetStrProp(Instance, PropInfo, VarToStr(Value));
      tkWString:
        SetWideStrProp(Instance, PropInfo, VarToWideStr(Value));
  {$IFDEF Supports_Unicode}
      tkUString:
    {$IFDEF FPC}
        SetUnicodeStrProp(Instance, PropInfo, VarToUnicodeStr(Value)); //SB: ??
    {$ELSE}
        SetUnicodeStrProp(Instance, PropInfo, VarToStr(Value)); //SB: ??
    {$ENDIF}
  {$ENDIF}
  {$ELSE}
      tkUString:
        SetStrProp(Instance, PropInfo, VarToStr(Value)); //SB: ??
  {$ENDIF}
  {$IFDEF DELPHI2009_UP}
      tkInt64:
        SetInt64Prop(Instance, PropInfo, Value);
  {$ELSE}
      tkInt64:
        SetInt64Prop(Instance, PropInfo, TVarData(VarAsType(Value, varInt64)).VInt64);
  {$ENDIF}
      tkVariant:
        SetVariantProp(Instance, PropInfo, Value);
      tkInterface:
          SetInterfaceProp(Instance, PropInfo, Value);
      tkDynArray:
        begin
          DynArray := nil; // "nil array"
          if VarIsNull(Value) or (VarArrayHighBound(Value, 1) >= 0) then begin
            DynArrayFromVariant(DynArray, Value, PropType);
          end;
          SetDynArrayProp(Instance, PropInfo, DynArray);
  {$IFNDEF FPC}
          DynArrayClear(DynArray, PropType);
  {$ENDIF}
        end;
      tkClass:
        if VarIsNull(Value) then
          SetOrdProp(Instance, PropInfo, 0)
        else if VarIsObj(Value) then begin
          Obj := VarToObj(Value);
          if (Obj.ClassType.InheritsFrom(TypeData^.ClassType)) then
            SetObjectProp(Instance, PropInfo, Obj)
          else
            PropertyConvertError(GetTypeName(PropType));
        end
        else
          PropertyConvertError(GetTypeName(PropType));
    else
      PropertyConvertError(GetTypeName(PropType));
    end;
  end;
  
  procedure SetPropValue(Instance: TObject; const Name: string;
    const Value: Variant);
  begin
    SetPropValue(Instance, GetPropInfo(Instance, Name), Value);
  end;
  
  function GetStoredPropList(Instance: TObject; out PropList: PPropList): Integer;
  var
    I, J, Count: Integer;
    TempList: PPropList;
  begin
    Count := GetPropList(PTypeInfo(Instance.ClassInfo), TempList);
    PropList := nil;
    Result := 0;
    if Count > 0 then
      try
        for I := 0 to Count - 1 do
          if IsStoredProp(Instance, TempList^[I]) then
            Inc(Result);
        GetMem(PropList, Result * SizeOf(Pointer));
        J := 0;
        for I := 0 to Count - 1 do
          if IsStoredProp(Instance, TempList^[I]) then begin
            PropList^[J] := TempList^[I];
            Inc(J);
          end;
      finally
        FreeMem(TempList);
      end;
  end;
  
  function GetProperties(Instance: TObject): IMap;
  var
    I, Count: Integer;
    TempList: PPropList;
    PropInfo: PPropInfo;
  begin
    Count := GetPropList(PTypeInfo(Instance.ClassInfo), TempList);
    Result := THashMap.create;
    if Count > 0 then
      try
        for I := 0 to Count - 1 do begin
          PropInfo := TempList^[I];
          Result[PropInfo^.Name] := GetPropValue(Instance, PropInfo);
        end;
      finally
        FreeMem(TempList);
      end;
  end;
  
  function GetStoredProperties(Instance: TObject): IMap;
  var
    I, Count: Integer;
    TempList: PPropList;
    PropInfo: PPropInfo;
  begin
    Count := GetPropList(PTypeInfo(Instance.ClassInfo), TempList);
    Result := THashMap.create;
    if Count > 0 then
      try
        for I := 0 to Count - 1 do begin
          PropInfo := TempList^[I];
          if IsStoredProp(Instance, PropInfo) then begin
            Result[PropInfo^.Name] := GetPropValue(Instance, PropInfo);
          end;
        end;
      finally
        FreeMem(TempList);
      end;
  end;
  
  procedure SetProperties(Instance: TObject; const Properties: IMap);
  var
    I, Count: Integer;
  begin
    Count := Properties.Count;
    if (Count > 0) then
      for I := 0 to Count - 1 do
        SetPropValue(Instance, VarToStr(Properties.Keys[I]), Properties.Values[I]);
  end;
  
  const
    htNull    = $00000000;
    htBoolean = $10000000;
    htInteger = $20000000;
    htInt64   = $30000000;
    htDouble  = $40000000;
    htOleStr  = $50000000;
    htDate    = $60000000;
    htObject  = $70000000;
    htArray   = $80000000;
  
  {$IFDEF NEXTGEN}
  function HashOfString(const Value: string): Integer;
  
negative.code: var
    Item: Variant;
  begin
    Item := FList[Index];
  (*
    if VarIsStr(Item) and VarIsStr(Value) then
  {$IFNDEF NEXTGEN}
      Result := WideCompareStr(Item, Value) = 0
  