tags:

views:

112

answers:

2

I have a set of enumeration values that have 138 values. Something like:

type
  TSomething = (sOne, sTwo, sThree, ..., ..., sOnehundredAndThirtyeight);
  TSomethings = set of TSomething;

....

  TSomething = class(TPersistent)
  private
    fSomethings: TSomethings;
  published
    property Somethings: TSomethings read fSomethings write fSomethings;
  end;

When compiling this I get the following error message:

[DCC Error] uProfilesManagement.pas(20): E2187 Size of published set 'Something' is >4 bytes

Any idea on how I can include a set of this size inside a published property?

I need to include this set on the published section because I'm using OmniXMLPersistent to save the class into a XML and it only saves published properties.

+1  A: 

Unfortunately the compiler does not allow sets greater than 32 bits to be contained in a published section. The size, in bytes, of a set can be calculated by High(set) div 8 - Low(set) div 8 + 1.

You can either reduce the set size, or use a custom class instead of a set, or you can split the enumeration into a few sets that each has a size of 32 bits.

Kornel Kisielewicz
Thanks for the reply. Splitting the enumeration would involve a great number of changes to the application code so it's out of the question. Any idea how I could create a custom class that would replicate the set?
smartins
@smartin : Unfortunately you need 18 bytes. Maybe typecast it onto a big enough byte array?
Kornel Kisielewicz
+1  A: 

May be you need the following trick (I am not using OmniXML and can't check it):

type
  TSomething = (sOne, sTwo, sThree, ..., sOnehundredAndThirtyeight);
  TSomethings = set of TSomething;

  TSomethingClass = class(TPersistent)
  private
    fSomethings: TSomethings;
    function GetSomethings: string;
    procedure SetSomethings(const Value: string);
  published
    property Somethings: string read GetSomethings write SetSomethings;
  end;


{ TSomethingClass }

function TSomethingClass.GetSomethings: string;
var
  thing: TSomeThing;
begin
  Result:= '';
  for thing:= Low(TSomething) to High(TSomething) do begin
    if thing in fSomethings then Result:= Result+'1'
    else Result:= Result+'0';
  end;
end;

procedure TSomethingClass.SetSomethings(const Value: string);
var
  I: Integer;
  thing: TSomeThing;
begin
  fSomethings:= [];
  for I:= 0 to length(Value) - 1 do begin
    if Value[I+1] = '1' then Include(fSomethings, TSomething(I));
  end;
end;
Serg
Thanks for the reply. Any idea on how to use GetSetProp and SetSetProp (from TypInfo unit) to automatically get the set as a string and set it back to the original state from the string? I just created another question specifically for this: http://stackoverflow.com/questions/2127079/how-to-use-getsetprop-and-setsetprop-from-typinfo-unit
smartins