Changeset 172


Ignore:
Timestamp:
Feb 22, 2011, 1:53:47 PM (13 years ago)
Author:
george
Message:
  • Fixed: Writing and reading Unicode characters in string.
  • Added: Demo for VarBlockSerializer.
  • Added: Write and read array of string.
Location:
CoolStreaming
Files:
7 added
3 edited

Legend:

Unmodified
Added
Removed
  • CoolStreaming/CoolStreaming.lpk

    r125 r172  
    66    <Author Value="Chronos"/>
    77    <CompilerOptions>
    8       <Version Value="9"/>
     8      <Version Value="10"/>
    99      <PathDelim Value="\"/>
    1010      <SearchPaths>
     
    4949    </Files>
    5050    <Type Value="RunAndDesignTime"/>
    51     <RequiredPkgs Count="2">
     51    <RequiredPkgs Count="3">
    5252      <Item1>
    53         <PackageName Value="TemplateGenerics"/>
     53        <PackageName Value="MicroThreading"/>
    5454      </Item1>
    5555      <Item2>
     56        <PackageName Value="TemplateGenerics"/>
     57      </Item2>
     58      <Item3>
    5659        <PackageName Value="FCL"/>
    5760        <MinVersion Major="1" Valid="True"/>
    58       </Item2>
     61      </Item3>
    5962    </RequiredPkgs>
    6063    <UsageOptions>
  • CoolStreaming/UStreamHelper.pas

    r117 r172  
    66
    77uses
    8   Classes, DateUtils, syncobjs;
     8  Classes, DateUtils, syncobjs, UMicroThreading;
    99
    1010type
     
    6363
    6464  TThreadStreamHelper = class(TStreamHelper)
    65     Lock: TCriticalSection;
     65    Lock: TMicroThreadCriticalSection;
    6666    procedure Clear;
    6767    constructor Create;
     
    363363begin
    364364  inherited Create;
    365   Lock := TCriticalSection.Create;
     365  Lock := TMicroThreadCriticalSection.Create;
    366366end;
    367367
  • CoolStreaming/UVarBlockSerializer.pas

    r125 r172  
    1 // 2010-03-30
     1// 2011-02-22
    22
    33unit UVarBlockSerializer;
     
    55{$mode Delphi}{$H+}
    66
    7 // One recursive VarInt size level supported
     7// One level of recursive VarInt size supported
    88// Biggest UInt type is QWord (64-bit)
    99
     
    1212uses
    1313  Classes, DateUtils, UStreamHelper, Math, SysUtils, USubStream,
    14   Contnrs, SpecializedList;
     14  Contnrs, SpecializedList, LCLProc;
    1515
    1616const
    1717  BitAlignment = 8;
    18   RealBase = 2;
    1918
    2019type
     
    4443    procedure WriteVarSInt(Value: Int64);
    4544    function ReadVarSInt: Int64;
    46     procedure WriteVarFloat(Value: Double);
    47     function ReadVarFloat: Double;
     45    procedure WriteVarFloat(Value: Double; Base: Integer = 2);
     46    function ReadVarFloat(Base: Integer = 2): Double;
    4847    procedure WriteVarString(Value: string);
    4948    function ReadVarString: string;
     
    8786    procedure WriteVarString(Index: Integer; Value: string);
    8887    function ReadVarString(Index: Integer): string;
    89     procedure WriteVarIntegerArray(Index: Integer; List: TListInteger);
    90     procedure ReadVarIntegerArray(Index: Integer; List: TListInteger);
     88    procedure WriteVarUIntArray(Index: Integer; List: TListInteger);
     89    procedure ReadVarUIntArray(Index: Integer; List: TListInteger);
     90    procedure WriteVarStringArray(Index: Integer; List: TListString);
     91    procedure ReadVarStringArray(Index: Integer; List: TListString);
    9192
    9293    procedure Clear;
     
    198199    Data := Stream.ReadByte;
    199200    if I = 0 then begin
    200       Length := DecodeUnaryLength(Data);
    201       if Length > (BitAlignment) then
    202         raise Exception.Create(SUInt64Overflow);
    203       LengthMask := GetUnaryLengthMask(Length);
    204       Data := Data and (LengthMask xor $ff);
     201      if Data = $ff then begin
     202        // Read recursive length
     203        Length := ReadVarUInt;
     204        if Length > BitAlignment then
     205          raise Exception.Create(SUInt64Overflow);
     206        if Length > 0 then Data := Stream.ReadByte else
     207          Data := 0;
     208      end else begin
     209        Length := DecodeUnaryLength(Data);
     210        LengthMask := GetUnaryLengthMask(Length);
     211        Data := Data and (LengthMask xor $ff);
     212      end;
    205213    end;
    206214    Result := Result or (QWord(Data) shl ((Length - I - 1) * BitAlignment));
     
    219227end;
    220228
    221 procedure TVarBlockSerializer.WriteVarFloat(Value: Double);
     229procedure TVarBlockSerializer.WriteVarFloat(Value: Double; Base: Integer = 2);
    222230var
    223231  Exponent: Integer;
     
    229237    // Normalize to integer number with base 10 exponent
    230238    Exponent := 0;
    231     while Frac(Value) > 0 do begin
    232       Value := Value * RealBase;
    233       Dec(Exponent);
    234     end;
    235     while Frac(Value / RealBase) = 0 do begin
    236       Value := Value / RealBase;
    237       Inc(Exponent);
     239    if Value <> 0 then begin
     240      if Frac(Value) > 0 then begin
     241        while Frac(Value) > 0 do begin
     242          Value := Value * Base;
     243          Dec(Exponent);
     244        end;
     245      end else
     246      while Frac(Value / Base) = 0 do begin
     247        Value := Value / Base;
     248        Inc(Exponent);
     249      end;
    238250    end;
    239251    Block.WriteVarSInt(Trunc(Value));
     
    245257end;
    246258
    247 function TVarBlockSerializer.ReadVarFloat: Double;
     259function TVarBlockSerializer.ReadVarFloat(Base: Integer = 2): Double;
    248260var
    249261  Significant: Int64;
     
    256268    Significant := Block.ReadVarSInt;
    257269    Exponent := Block.ReadVarSInt;
    258     Result := Significant * IntPower(RealBase, Exponent);
     270    Result := Significant * IntPower(Base, Exponent);
    259271  finally
    260272    Block.Free;
     
    266278  Stream: TVarBlockSerializer;
    267279  I: Integer;
     280  P: PChar;
     281  Unicode: Cardinal;
     282  CharLen: Integer;
    268283begin
    269284  try
    270285    Stream := TVarBlockSerializer.Create;
    271     for I := 1 to Length(Value) do
    272       Stream.WriteVarUInt(Integer(Value[I]));
     286    P := PChar(Value);
     287    for I := 0 to UTF8Length(Value) - 1 do begin
     288      Unicode := UTF8CharacterToUnicode(P, CharLen);
     289      Stream.WriteVarUInt(Unicode);
     290      Inc(P, CharLen);
     291    end;
    273292    WriteVarBlock(Stream);
    274293  finally
     
    288307    while Block.Stream.Position < Block.Stream.Size do begin
    289308      Character := Block.ReadVarUInt;
    290       Result := Result + Char(Character);
     309      Result := Result + UnicodeToUTF8(Character);
    291310    end;
    292311  finally
     
    352371  I := 0;
    353372  Length := 1;
    354   while I < Length do begin
     373
    355374    Data := Stream.ReadByte;
    356     if I = 0 then begin
    357375      if Data = $ff then begin
    358376        // Read recursive length
    359377        Length := ReadVarUInt;
    360378        AStream.Size := Length;
    361         Data := Stream.ReadByte;
    362         AStream.WriteByte(Data);
     379        if Length > 0 then begin
     380          Data := Stream.ReadByte;
     381          AStream.WriteByte(Data);
     382        end;
    363383      end else begin
    364384        // Read unary length
     
    367387        LengthMask := GetUnaryLengthMask(Length);
    368388        Data := Data and (LengthMask xor $ff);
    369         // Drop first byte if first data zero
     389        // Drop first byte if first data is zero
    370390        if Data <> 0 then AStream.WriteByte(Data)
    371391          else begin
     
    378398          end;
    379399      end;
    380     end else AStream.WriteByte(Data);
    381     Inc(I);
    382   end;
     400
     401  // If CopyFrom parameter count is zero then whole source is copied
     402  if Length > 1 then
     403    AStream.CopyFrom(Stream, Length - 1);
    383404  AStream.Position := 0;
    384405end;
     
    572593procedure TVarBlockIndexed.ReadVarBlock(Index: Integer; Block: TVarBlockSerializer);
    573594begin
    574   TVarBlockSerializer(Items[Index]).Stream.Position := 0;
    575   TVarBlockSerializer(Items[Index]).ReadVarBlock(Block);
     595  with TVarBlockSerializer(Items[Index]) do begin
     596    Stream.Position := 0;
     597    ReadVarBlock(Block);
     598  end;
    576599end;
    577600
     
    650673function TVarBlockIndexed.ReadVarString(Index: Integer):string;
    651674begin
    652   TVarBlockSerializer(Items[Index]).Stream.Position := 0;
    653   Result := TVarBlockSerializer(Items[Index]).ReadVarString;
    654 end;
    655 
    656 procedure TVarBlockIndexed.WriteVarIntegerArray(Index: Integer;
     675  with TVarBlockSerializer(Items[Index]) do begin
     676    Stream.Position := 0;
     677    Result := ReadVarString;
     678  end;
     679end;
     680
     681procedure TVarBlockIndexed.WriteVarUIntArray(Index: Integer;
    657682  List: TListInteger);
    658683var
     
    670695end;
    671696
    672 procedure TVarBlockIndexed.ReadVarIntegerArray(Index: Integer;
     697procedure TVarBlockIndexed.ReadVarUIntArray(Index: Integer;
    673698  List: TListInteger);
    674699var
     
    681706    while Temp.Stream.Position < Temp.Stream.Size do begin
    682707      List.Add(Temp.ReadVarUInt);
     708    end;
     709  finally
     710    Temp.Free;
     711  end;
     712end;
     713
     714procedure TVarBlockIndexed.WriteVarStringArray(Index: Integer;
     715  List: TListString);
     716var
     717  I: Integer;
     718  Temp: TVarBlockSerializer;
     719begin
     720  try
     721    Temp := TVarBlockSerializer.Create;
     722    for I := 0 to List.Count - 1 do
     723      Temp.WriteVarString(List[I]);
     724    WriteVarBlock(Index, Temp);
     725  finally
     726    Temp.Free;
     727  end;
     728end;
     729
     730procedure TVarBlockIndexed.ReadVarStringArray(Index: Integer; List: TListString
     731  );
     732var
     733  Temp: TVarBlockSerializer;
     734begin
     735  try
     736    Temp := TVarBlockSerializer.Create;
     737    List.Clear;
     738    ReadVarBlock(Index, Temp);
     739    while Temp.Stream.Position < Temp.Stream.Size do begin
     740      List.Add(Temp.ReadVarString);
    683741    end;
    684742  finally
Note: See TracChangeset for help on using the changeset viewer.