Browse Source

* TStringStream now observes encoding, bug ID #30508

git-svn-id: trunk@36758 -
michael 8 years ago
parent
commit
2b1bb6a5f5
2 changed files with 110 additions and 56 deletions
  1. 23 12
      rtl/objpas/classes/classesh.inc
  2. 87 44
      rtl/objpas/classes/streams.inc

+ 23 - 12
rtl/objpas/classes/classesh.inc

@@ -1012,28 +1012,39 @@ type
   protected
   protected
     function Realloc(var NewCapacity: PtrInt): Pointer; override;
     function Realloc(var NewCapacity: PtrInt): Pointer; override;
   public
   public
-    constructor Create(const ABytes: TBytes); overload;
+    constructor Create(const ABytes: TBytes); virtual; overload;
     property Bytes: TBytes read FBytes;
     property Bytes: TBytes read FBytes;
   end;
   end;
 
 
 { TStringStream }
 { TStringStream }
 
 
-  TStringStream = class(TStream)
+  TStringStream = class(TBytesStream)
   private
   private
-    FDataString: string;
-    FPosition: Integer;
+    FEncoding: TEncoding;
+    FOwnsEncoding : Boolean;
+    function GetDataString: string;
+    function GetUnicodeDataString: String;
   protected
   protected
-    Function GetSize : Int64; Override;
-    function GetPosition: Int64; Override;
-    procedure SetSize(NewSize: Longint); override;
   public
   public
-    constructor Create(const AString: string = '');
-    function Read(var Buffer; Count: Longint): Longint; override;
+    constructor Create(const ABytes: TBytes); override; overload;
+    constructor Create(const AString: string = ''); overload;
+    constructor Create(const AString: RawByteString); overload;
+    constructor Create(const AString: string; AEncoding: TEncoding; AOwnsEncoding: Boolean = True); overload;
+    constructor Create(const AString: string; ACodePage: Integer); overload;
+    // UnicodeString versions
+    constructor Create(const AString: UnicodeString); overload;
+    constructor Create(const AString: UnicodeString; AEncoding: TEncoding; AOwnsEncoding: Boolean = True); overload;
+    constructor Create(const AString: UnicodeString; ACodePage: Integer); overload;
+    function ReadUnicodeString(Count: Longint): UnicodeString;
+    procedure WriteUnicodeString(const AString: UnicodeString);
+    function ReadAnsiString(Count: Longint): AnsiString;
+    procedure WriteAnsiString(const AString: AnsiString);
     function ReadString(Count: Longint): string;
     function ReadString(Count: Longint): string;
-    function Seek(Offset: Longint; Origin: Word): Longint; override;
-    function Write(const Buffer; Count: Longint): Longint; override;
     procedure WriteString(const AString: string);
     procedure WriteString(const AString: string);
-    property DataString: string read FDataString;
+    property DataString: string read GetDataString;
+    Property UnicodeDataString : String Read GetUnicodeDataString;
+    Property OwnsEncoding : Boolean Read FOwnsEncoding;
+    Property Encoding : TEncoding Read FEncoding;
   end;
   end;
 
 
 { TResourceStream }
 { TResourceStream }

+ 87 - 44
rtl/objpas/classes/streams.inc

@@ -796,95 +796,138 @@ begin
     end;
     end;
 end;
 end;
 
 
+
 {****************************************************************************}
 {****************************************************************************}
 {*                             TStringStream                                *}
 {*                             TStringStream                                *}
 {****************************************************************************}
 {****************************************************************************}
 
 
-function TStringStream.GetSize: Int64;
+function TStringStream.GetDataString: string;
 begin
 begin
-  Result:=Length(FDataString);
+  Result:=FEncoding.GetAnsiString(Bytes,0,Size);
 end;
 end;
 
 
-function TStringStream.GetPosition: Int64;
+function TStringStream.GetUnicodeDataString: String;
 begin
 begin
-  Result:=FPosition;
+  Result:=FEncoding.GetString(Bytes, 0, Size);
 end;
 end;
 
 
-procedure TStringStream.SetSize(NewSize: Longint);
+constructor TStringStream.Create(const AString: string = '');
 
 
 begin
 begin
- Setlength(FDataString,NewSize);
- If FPosition>NewSize then FPosition:=NewSize;
+  Create(AString,TEncoding.Default, False);
 end;
 end;
 
 
+constructor TStringStream.Create(const ABytes: TBytes);
+begin
+  inherited Create(ABytes);
+  FEncoding:=TEncoding.Default;
+  FOwnsEncoding:=False;
+end;
 
 
-constructor TStringStream.Create(const AString: string = '');
+constructor TStringStream.Create(const AString: RawByteString);
+
+var
+  CP: TSystemCodePage;
+
+begin
+  CP:=StringCodePage(AString);
+  if (CP=CP_ACP) or (CP=TEncoding.Default.CodePage) then
+    begin
+    FEncoding:=TEncoding.Default;
+    FOwnsEncoding:=False;
+    end
+  else
+    begin
+    FEncoding:=TEncoding.GetEncoding(CP);
+    FOwnsEncoding:=True;
+    end;
+  inherited Create(BytesOf(AString));
+end;
 
 
+constructor TStringStream.Create(const AString: string; AEncoding: TEncoding; AOwnsEncoding: Boolean);
 begin
 begin
-  Inherited create;
-  FDataString:=AString;
-  UniqueString(FDataString);
+  FOwnsEncoding:=AOwnsEncoding and not TEncoding.IsStandardEncoding(AEncoding);
+  FEncoding:=AEncoding;
+  Inherited Create(AEncoding.GetAnsiBytes(AString));
 end;
 end;
 
 
+constructor TStringStream.Create(const AString: string; ACodePage: Integer);
+begin
+  Create(AString,TEncoding.GetEncoding(ACodePage),true);
+end;
 
 
-function TStringStream.Read(var Buffer; Count: Longint): Longint;
+constructor TStringStream.Create(const AString: UnicodeString);
+begin
+  Create(AString,TEncoding.Unicode,false);
+end;
 
 
+constructor TStringStream.Create(const AString: UnicodeString; AEncoding: TEncoding; AOwnsEncoding: Boolean);
 begin
 begin
-  Result:=Length(FDataString)-FPosition;
-  If Result>Count then Result:=Count;
-  // This supposes FDataString to be of type AnsiString !
-  if Result>0 then
-   begin
-   Move (Pchar(FDataString)[FPosition],Buffer,Result);
-   FPosition:=FPosition+Result;
-   end;
+  FOwnsEncoding:=AOwnsEncoding and not TEncoding.IsStandardEncoding(AEncoding);
+  FEncoding:=AEncoding;
+  Inherited Create(AEncoding.GetBytes(AString));
+end;
+
+constructor TStringStream.Create(const AString: UnicodeString; ACodePage: Integer);
+
+begin
+  Create(AString,TEncoding.GetEncoding(ACodePage),true);
 end;
 end;
 
 
 
 
 function TStringStream.ReadString(Count: Longint): string;
 function TStringStream.ReadString(Count: Longint): string;
 
 
-Var NewLen : Longint;
+begin
+  Result:=ReadAnsiString(Count);
+end;
+
+function TStringStream.ReadUnicodeString(Count: Longint): UnicodeString;
+
+Var
+  NewLen,SLen : Longint;
 
 
 begin
 begin
-  NewLen:=Length(FDataString)-FPosition;
+  NewLen:=Size-FPosition;
   If NewLen>Count then NewLen:=Count;
   If NewLen>Count then NewLen:=Count;
-  SetLength(Result,NewLen);
-  Read (Pointer(Result)^,NewLen);
+  Result:=FEncoding.GetString(FBytes,FPosition,NewLen);
 end;
 end;
 
 
+procedure TStringStream.WriteString(const AString: string);
 
 
-function TStringStream.Seek(Offset: Longint; Origin: Word): Longint;
+begin
+  WriteAnsiString(AString);
+end;
+
+procedure TStringStream.WriteUnicodeString(const AString: UnicodeString);
+Var
+  B: TBytes;
 
 
 begin
 begin
-  Case Origin of
-    soFromBeginning : FPosition:=Offset;
-    soFromEnd       : FPosition:=Length(FDataString)+Offset;
-    soFromCurrent   : FPosition:=FPosition+Offset;
-  end;
-  If FPosition>Length(FDataString) then
-    FPosition:=Length(FDataString)
-  else If FPosition<0 then
-    FPosition:=0;
-  Result:=FPosition;
+  B:=FEncoding.GetBytes(AString);
+  if Length(B)>0 then
+    WriteBuffer(B[0],Length(Bytes));
 end;
 end;
 
 
+function TStringStream.ReadAnsiString(Count: Longint): AnsiString;
 
 
-function TStringStream.Write(const Buffer; Count: Longint): Longint;
+Var
+  NewLen : Longint;
 
 
 begin
 begin
-  Result:=Count;
-  if FPosition+Count>Size then
-    SetSize(FPosition+Count);
-  // This supposes that FDataString is of type AnsiString)
-  Move (Buffer,PChar(FDataString)[Fposition],Count);
-  FPosition:=FPosition+Count;
+  NewLen:=Size-FPosition;
+  If NewLen>Count then NewLen:=Count;
+  Result:=FEncoding.GetAnsiString(FBytes,FPosition,NewLen);
 end;
 end;
 
 
+procedure TStringStream.WriteAnsiString(const AString: AnsiString);
 
 
-procedure TStringStream.WriteString(const AString: string);
+Var
+  B: TBytes;
 
 
 begin
 begin
-  Write (PChar(Astring)[0],Length(AString));
+  B:=FEncoding.GetAnsiBytes(AString);
+  if Length(B)>0 then
+    WriteBuffer(B[0],Length(B));
 end;
 end;