View Issue Details

IDProjectCategoryView StatusLast Update
0004586JEDI VCL00 JVCL Componentspublic2008-12-22 07:27
ReporterwessonAssigned Toobones 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product VersionDaily / GIT 
Target VersionFixed in Version3.36 
Summary0004586: JvAppStorage: No longer load/save char property
DescriptionSince Delphi 2009, the default proptype for a CHAR property is TkWchar (it was TkChar before)

TkWchar typed properties are ignored by the loadproperty / saveproperty
Additional InformationPatch included to solve the issue

(the patch also include another small change, introducing DoReadWideString and DoWriteWideString virtual method that may be overriden by descendant classes. This allow to solve a potential issue with storage of unicode strings in registry under D2007 and japanese version of Windows, as UTF-8 string doesn't travel safely under this OS, so the normal UTF <-> Unicode conversion may not work)
TagsNo tags attached.

Relationships

related to 0004635 resolvedobones Under non unicode versions of Delphi AppStorage classes may fail to properly save / reload unicode strings 

Activities

2008-11-17 03:19

 

AppStorage_charprop_fix.patch (3,859 bytes)
Index: JvAppStorage.pas
===================================================================
--- JvAppStorage.pas	(revision 12048)
+++ JvAppStorage.pas	(working copy)
@@ -347,6 +347,14 @@
     function DoReadString(const Path: string; const Default: string): string; virtual; abstract;
     { Stores an string value. }
     procedure DoWriteString(const Path: string; const Value: string); virtual; abstract;
+
+    { Retrieves the specified string value. If the value is not found, the Default will be
+      returned. If the value is not a string (or can't be converted to a string an EConvertError
+      exception will be raised. }
+    function DoReadWideString(const Path: string; const Default: Widestring): Widestring; virtual;
+    { Stores an string value. }
+    procedure DoWriteWideString(const Path: string; const Value: Widestring); virtual;
+
     { Retrieves the specified value into a buffer. The result holds the number of bytes actually
       retrieved. }
     function DoReadBinary(const Path: string; Buf: TJvBytes; BufSize: Integer): Integer; virtual; abstract;
@@ -1727,11 +1735,27 @@
   Result := DoReadFloat(Path, Default);
 end;
 
+function TJvCustomAppStorage.DoReadWideString(const Path: string;
+  const Default: Widestring): Widestring;
+begin
+  {$IFDEF COMPILER12_UP}
+  Result := UTF8ToWideString(RawByteString(ReadString(Path, string(UTF8Encode(Default)))));
+  {$ELSE}
+  Result := UTF8Decode(ReadString(Path, UTF8Encode(Default)));
+  {$ENDIF COMPILER12_UP}
+end;
+
 procedure TJvCustomAppStorage.DoWriteDateTime(const Path: string; Value: TDateTime);
 begin
   DoWriteFloat(Path, Value);
 end;
 
+procedure TJvCustomAppStorage.DoWriteWideString(const Path: string;
+  const Value: Widestring);
+begin
+  DoWriteString(Path,string(UTF8Encode(Value)));
+end;
+
 procedure TJvCustomAppStorage.DoError(const msg: string);
 begin
   if Assigned(OnError) then
@@ -2374,7 +2398,7 @@
     else
     begin
       try
-        if TypeInfo.Kind = tkChar then
+        if TypeInfo.Kind in [tkChar,tkWChar] then
           OrdValue := ReadIntegerInt(Path, OrdValue)
         else
           if TypeInfo.Kind = tkInteger then
@@ -2449,7 +2473,7 @@
       WriteBooleanInt(Path, OrdOfEnum(Value, GetTypeData(TypeInfo).OrdType) <> 0)
   {$ENDIF CLR}
     else
-      if TypeInfo.Kind = tkChar then
+      if TypeInfo.Kind in [tkChar, tkWchar] then
         WriteIntegerInt(Path, OrdOfEnum(Value, GetTypeData(TypeInfo).OrdType))
       else
         if TypeInfo.Kind = tkInteger then
@@ -2661,7 +2685,7 @@
         ReadSet(Path, GetPropInfo(PersObj, PropName).PropType{$IFNDEF CLR}^{$ENDIF}, TmpValue, TmpValue);
         SetOrdProp(PersObj, PropName, TmpValue);
       end;
-    tkChar, tkInteger:
+    tkChar, tkWchar, tkInteger:
       begin
         TmpValue := GetOrdProp(PersObj, PropName);
         ReadEnumeration(Path, GetPropInfo(PersObj, PropName).PropType{$IFNDEF CLR}^{$ENDIF}, TmpValue, TmpValue);
@@ -2805,7 +2829,7 @@
           WriteSet(Path, P.PropType{$IFNDEF CLR}^{$ENDIF}, TmpValue);
         end;
       end;
-    tkChar, tkInteger:
+    tkChar, tkWchar, tkInteger:
       begin
         if StorageOptions.StoreDefaultValues or not IsDefaultOrdProp(P) then
         begin
@@ -3156,17 +3180,13 @@
 function TJvCustomAppStorage.ReadWideString(const Path: string;
   const Default: WideString = ''): WideString;
 begin
-  {$IFDEF COMPILER12_UP}
-  Result := UTF8ToWideString(RawByteString(ReadString(Path, string(UTF8Encode(Default)))));
-  {$ELSE}
-  Result := UTF8Decode(ReadString(Path, UTF8Encode(Default)));
-  {$ENDIF COMPILER12_UP}
+  Result := DoReadWideString(Path,Default);
 end;
 
 procedure TJvCustomAppStorage.WriteWideString(const Path: string;
   const Value: WideString);
 begin
-  WriteString(Path, string(UTF8Encode(Value)));
+  DoWriteWideString(Path,Value);
 end;
 {$ENDIF COMPILER6_UP}
 

obones

2008-11-18 08:24

administrator   ~0015015

Please provide the zipped sources of a sample application showing this.

2008-11-19 18:27

 

unicode_storage_test.zip (496,421 bytes)

wesson

2008-11-19 18:33

reporter   ~0015036

Here you have:

A test application showing various issues storing unicode strings with AppStorage classes . Binaries included

Also included a slight modification of JvSimpleXml (TJvSimpleXML) to pass the test app.

2008-11-20 03:12

 

JvSimpleXml_Unicodefix.patch (565 bytes)
Index: JvSimpleXml.pas
===================================================================
--- JvSimpleXml.pas	(revision 12030)
+++ JvSimpleXml.pas	(working copy)
@@ -216,6 +216,9 @@
 
 implementation
 
+uses
+  JclStreams;
+
 function EntityEncode(const S: string): string;
 begin
   Result := JclSimpleXml.EntityEncode(S);
@@ -404,7 +407,7 @@
 
 procedure TJvSimpleXML.SaveToFile(FileName: TFileName);
 begin
-  FJclSimpleXML.SaveToFile(FileName);
+  FJclSimpleXML.SaveToFile(FileName,SeUtf8);
 end;
 
 procedure TJvSimpleXML.SaveToStream(Stream: TStream);

obones

2008-12-22 05:01

administrator   ~0015145

The default should be tkUChar under D2009, but I added tkWChar anyway.
As to the ReadWideString/WriteWriteString functions, please create a new issue with more details for them

jfudickar

2008-12-22 06:36

developer   ~0015168

Hi Olivier,

your change didn't work in my D2009 installation.

I didn't have a tkUChar Datatype ?

Greetings
Jens

obones

2008-12-22 07:27

administrator   ~0015170

My bad, I mixed that up with tkUString, I fixed it in SVN

Issue History

Date Modified Username Field Change
2008-11-17 03:19 wesson New Issue
2008-11-17 03:19 wesson File Added: AppStorage_charprop_fix.patch
2008-11-18 08:24 obones Note Added: 0015015
2008-11-18 08:24 obones Status new => feedback
2008-11-19 18:27 wesson File Added: unicode_storage_test.zip
2008-11-19 18:33 wesson Note Added: 0015036
2008-11-20 03:12 wesson File Added: JvSimpleXml_Unicodefix.patch
2008-12-22 05:01 obones Note Added: 0015145
2008-12-22 05:01 obones Status feedback => resolved
2008-12-22 05:01 obones Fixed in Version => Daily / SVN
2008-12-22 05:01 obones Resolution open => fixed
2008-12-22 05:01 obones Assigned To => obones
2008-12-22 06:36 jfudickar Note Added: 0015168
2008-12-22 06:36 jfudickar Status resolved => feedback
2008-12-22 06:36 jfudickar Resolution fixed => reopened
2008-12-22 07:27 obones Note Added: 0015170
2008-12-22 07:27 obones Status feedback => resolved
2008-12-22 07:27 obones Resolution reopened => fixed
2008-12-23 00:41 obones Relationship added related to 0004635