Конференция "KOL" » format function for freepascal (revisited)
 
  • Thaddy © (27.08.14 11:01) [0]
    This one seems to pass compatibility, but you have to be careful.


    // format function that also works for Freepascal.
    // limited, but easy to extend.
    function Format(Format: KolString; const Args: array of const): KolString;
    type
    TVAList = array[0..$FFFF] of Pointer;
    var
    VA:TVAList;
    I: integer;
    begin
    Result :='';
    If length(Args) > 0 then
    begin
      SetLength(Result,1024);
      for I := Low(Args) to High(Args) do
        with Args[I] do
          case VType of
            vtInteger: VA[I] := Pointer(VInteger);
            vtPChar,
            vtAnsiString:VA[i]:=PKolChar(VPCHAR);
            vtPWideChar,
            vtWideString:VA[i]:=PKolChar(VPWIDECHAR);
          else
            VA[i] := nil;
          end;
      end;
      SetLength(Result, wvsprintf(PKolChar(Result), PKolChar(Format), @VA));
    end;



    If your code compiles and works in Delphi, this will also compile and work in Freepascal 32/64.

    Nothing more is promised!
  • Awkward © (27.08.14 14:08) [1]
    not so good decision coz result text can be longer than 1024 symbols
  • Thaddy © (27.08.14 18:04) [2]
    No! See MSDN. The limit is 1024 symbols. Even on 64 bit platforms.
  • Awkward © (27.08.14 21:28) [3]
    pity. then better to use custom implementation without limits :(
  • Thaddy © (28.08.14 00:00) [4]
    Do you need it? Then change it! Pointer array is big enough.... ;)
  • Thaddy © (28.08.14 00:06) [5]
    But wsprintf will fail....
  • Awkward © (28.08.14 08:19) [6]
    i made surrogate functions for me which works with text (%s only) and text with integers (%s, %d and %u substitutes) and replace it "by hands". And trying to use these functions where possible. (first part calculates length of final text, second makes replaces)
  • Thaddy © (04.09.14 13:09) [7]
    You can also use this trick from Andreas Hausladen:

    function _FormatC(const Format: string): string; cdecl;
    const
     StackSlotSize = SizeOf(Pointer);
    var
     Args: va_list;
     Buffer: array[0..1024] of Char;
    begin
     // va_start(Args, Format)
     Args := va_list(PAnsiChar(@Format) + ((SizeOf(Format) + StackSlotSize - 1) and not (StackSlotSize - 1)));
     SetString(Result, Buffer, wvsprintf(Buffer, PChar(Format), Args));
    end;

    const // allows us to use "varargs" in Delphi
     FormatC: function(const Format: string): string; cdecl varargs = _FormatC;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
     MsgOk(FormatC('%s %03d', 'Hallo', 3));
    end;
  • Thaddy © (04.09.14 13:10) [8]
    procedure TForm1.Button1Click(Sender: PObj);  // <smile>
    begin
    MsgOk(FormatC('%s %03d', 'Hallo', 3));
    end;
  • Vladimir Kladov © (10.09.14 20:56) [9]
    I used Format ONLY because it is already present in Windows API (wsprintf), so calling it is cheaper then creating several formatting functions. It is useful to make some number-to-string conversions like %.03d (gives 002, not 2). In any other case it is cheaper to create several small functions like
    function Int2Z(i, digits): String;
    begin
       Result := Int2Str(Abs(i));
       while Length(Result) < digits do
           Result := '0' + Result;
       if i < 0 then Result := '-' + Result;
    end;

 
Конференция "KOL" » format function for freepascal (revisited)
Есть новые Нет новых   [134427   +35][b:0][p:0.001]