Einzelnen Beitrag anzeigen

Benutzerbild von maximov
maximov

Registriert seit: 2. Okt 2003
Ort: Hamburg
548 Beiträge
 
Delphi 2005 Professional
 
#5

Re: Speicherung von Sets... ?!?

  Alt 28. Feb 2005, 15:25
Ja, ordinal geht es prima, aber am schönsten mit strings. Die unit TypeInfo hat zwei funktionen die das konvertieren von set-properties beherrschen. Leider ist das auf auf properties spezialisiert. Ich hatte das mal entspezialisiert, sodass es mit normalen typeInfos geht:

Delphi-Quellcode:
uses typInfo, RTLConsts;
...

function SetToStr(SetTypeInfo:PTypeInfo;value:integer;Brackets:boolean=true):string;
var
  S: TIntSet;
  TypeInfo: PTypeInfo;
  compTypeDate: PTypeData;
  I: Integer;
begin
   Result := '';
  Integer(S) := Value;
  TypeInfo := GetTypeData(SetTypeInfo)^.CompType^;
  compTypeDate := GetTypeData(TypeInfo);
  for I := compTypeDate.MinValue to compTypeDate.MaxValue do
    if I in s then
    begin
      if Result <> 'then
        Result := Result + ',';
      Result := Result + GetEnumName(TypeInfo, I);
    end;
  if Brackets then Result := '[' + Result + ']';
end;


function StrToSet(SetTypeInfo:PTypeInfo; const Value: string): Integer;
var
  P: PChar;
  EnumName: string;
  EnumValue: Longint;
  EnumInfo: PTypeInfo;

  // grab the next enum name
  function NextWord(var P: PChar): string;
  var
    i: Integer;
  begin
    i := 0;

    // scan til whitespace
    while not (P[i] in [',', ' ', #0,']']) do
      Inc(i);

    SetString(Result, P, i);

    // skip whitespace
    while P[i] in [',', ' ',']'] do
      Inc(i);

    Inc(P, i);
  end;

begin
   Result := 0;
  if Value = 'then Exit;
  P := PChar(Value);

  // skip leading bracket and whitespace
   while P^ in ['[',' '] do
      Inc(P);

   EnumInfo := GetTypeData(SetTypeInfo)^.CompType^;
   EnumName := NextWord(P);
  while EnumName <> 'do
  begin
    EnumValue := GetEnumValue(EnumInfo, EnumName);
    if EnumValue < 0 then
         raise EPropertyConvertError.CreateResFmt(@SInvalidPropertyElement, [EnumName]);
    Include(TIntegerSet(Result), EnumValue);
    EnumName := NextWord(P);
  end;
end;
Damit kann man super leicht konverieren:

Delphi-Quellcode:
type
  T8BitSet = set of (bit_0, bit_1, bit_2, bit_3, bit_4, bit_5, bit_6, bit_7);
...
var
   Bits:T8BitSet;
   s:string;
begin
   Bits := [bit_2, bit_4, bit_7];
   ...
  s := setToStr(typeInfo(T8BitSet), PInteger(@Bits)^, true);
  ..
   PInteger(@Bits)^ := strToSet(typeInfo(T8BitSet), s);
end;
Entsprechend leicht dürfte das speichern in eine datei sein -> stringStream oder so.

Und wenn es hier nicht gebraucht wird, dann sicher später von jemand anderem!


//edit:
PS:@Kedariodakon: Du hast quasi gerade entdeckt, dass jeder eintrag in einem set einem bit entspricht...was auch logisch und effizient ist.
//edit2: blöde pointer
mâxîmôv.

{KDT}
  Mit Zitat antworten Zitat