Browse Source

* fixed tbinaryobjectwrite.writeset/readset on big endian systems
(and made it future proof in case the set format should change
again, as long as the size of all streamed sets is guaranteed
to be 4 bytes and if their packset setting is guaranteed to
be 0).

git-svn-id: trunk@11149 -

Jonas Maebe 17 years ago
parent
commit
b6a8e4343d

+ 1 - 0
.gitattributes

@@ -7716,6 +7716,7 @@ tests/test/uinline4b.pp svneol=native#text/plain
 tests/test/umacpas1.pp svneol=native#text/plain
 tests/test/umacpas1.pp svneol=native#text/plain
 tests/test/umainnam.pp svneol=native#text/plain
 tests/test/umainnam.pp svneol=native#text/plain
 tests/test/units/classes/tmakeobjinst.pp svneol=native#text/plain
 tests/test/units/classes/tmakeobjinst.pp svneol=native#text/plain
+tests/test/units/classes/tsetstream.pp svneol=native#text/plain
 tests/test/units/crt/tcrt.pp svneol=native#text/plain
 tests/test/units/crt/tcrt.pp svneol=native#text/plain
 tests/test/units/crt/tctrlc.pp svneol=native#text/plain
 tests/test/units/crt/tctrlc.pp svneol=native#text/plain
 tests/test/units/dos/hello.pp svneol=native#text/plain
 tests/test/units/dos/hello.pp svneol=native#text/plain

+ 3 - 1
rtl/objpas/classes/reader.inc

@@ -253,6 +253,8 @@ begin
 end;
 end;
 
 
 function TBinaryObjectReader.ReadSet(EnumType: Pointer): Integer;
 function TBinaryObjectReader.ReadSet(EnumType: Pointer): Integer;
+type
+  tset = set of 0..31;
 var
 var
   Name: String;
   Name: String;
   Value: Integer;
   Value: Integer;
@@ -267,7 +269,7 @@ begin
       Value := GetEnumValue(PTypeInfo(EnumType), Name);
       Value := GetEnumValue(PTypeInfo(EnumType), Name);
       if Value = -1 then
       if Value = -1 then
         raise EReadError.Create(SInvalidPropertyValue);
         raise EReadError.Create(SInvalidPropertyValue);
-      Result := Result or (1 shl Value);
+      include(tset(result),Value);
     end;
     end;
   except
   except
     SkipSetBody;
     SkipSetBody;

+ 3 - 4
rtl/objpas/classes/writer.inc

@@ -259,17 +259,16 @@ begin
 end;
 end;
 
 
 procedure TBinaryObjectWriter.WriteSet(Value: LongInt; SetType: Pointer);
 procedure TBinaryObjectWriter.WriteSet(Value: LongInt; SetType: Pointer);
+type
+  tset = set of 0..31;
 var
 var
   i: Integer;
   i: Integer;
-  Mask: LongInt;
 begin
 begin
   WriteValue(vaSet);
   WriteValue(vaSet);
-  Mask := 1;
   for i := 0 to 31 do
   for i := 0 to 31 do
   begin
   begin
-    if (Value and Mask) <> 0 then
+    if (i in tset(Value)) then
       WriteStr(GetEnumName(PTypeInfo(SetType), i));
       WriteStr(GetEnumName(PTypeInfo(SetType), i));
-    Mask := Mask shl 1;
   end;
   end;
   WriteStr('');
   WriteStr('');
 end;
 end;

+ 53 - 0
tests/test/units/classes/tsetstream.pp

@@ -0,0 +1,53 @@
+program storedfalse;
+{$ifdef FPC}{$mode objfpc}{$h+}{$INTERFACES CORBA}{$endif}
+{$ifdef mswindows}{$apptype console}{$endif}
+uses
+ {$ifdef FPC}{$ifdef linux}cthreads,{$endif}{$endif}
+ sysutils,classes;
+
+type
+ tenum = (eena,eenb,eenc,eend,eene,eenf,eeng,eenh,eeni);
+ tset = set of tenum;
+
+ ttestclass1 = class(tcomponent)
+  private
+   fprop1: tset;
+  public
+   property prop1: tset read fprop1 write fprop1 stored true;
+ end;
+
+ ttestclass2 = class(ttestclass1)
+  published
+   property prop1;
+ end;
+
+var
+ testclass2,testclass3: ttestclass2;
+ stream1,stream2: tmemorystream;
+ str1: ansistring;
+begin
+ testclass2:= ttestclass2.create(nil);
+ testclass2.prop1:= [eenb,eend,eene,eenh,eeni];
+ stream1:= tmemorystream.create;
+ try
+  stream1.writecomponent(testclass2);
+  stream2:= tmemorystream.create;
+  try
+   stream1.position:= 0;
+   objectbinarytotext(stream1,stream2);
+   stream1.position:= 0;
+   stream2.position:= 0;
+   setlength(str1,stream2.size);
+   move(stream2.memory^,str1[1],length(str1));
+   writeln(str1);
+   testclass3:=ttestclass2.create(nil);
+   stream1.readcomponent(testclass3);
+   if (testclass3.prop1<>[eenb,eend,eene,eenh,eeni]) then
+     halt(1);
+  finally
+   stream2.free;
+  end;
+ finally
+  stream1.free;
+ end;
+end.