[Back to STRINGS SWAG index]  [Back to Main SWAG index]  [Original]

{$O-}
UNIT Strings;
INTERFACE

  FUNCTION Dupe(C : Char; Len : Byte) : String;
  FUNCTION ADupe(C : Char; Len : Byte) : String;
  FUNCTION Pad(S : String; C : Char;
                           Len : Byte) : String;
  FUNCTION APad(S : String; C : Char;
                            Len : Byte) : String;
  FUNCTION LeftPad(S : String; C : Char;
                               Len : Byte) : String;
  FUNCTION ALeftPad(S : String; C : Char;
                                Len : Byte) : String;
  FUNCTION Chop(S : String; len: Byte): String;
  FUNCTION AChop(S : String; len: Byte): String;
  FUNCTION LeftChop(S : String; len: Byte): String;
  FUNCTION ALeftChop(S : String; len: Byte): String;
  PROCEDURE Trim(VAR S : String; C : Char);
  PROCEDURE TrimLead(VAR S : String; C : Char);

IMPLEMENTATION

  FUNCTION Dupe(C : Char; Len : Byte) : String;
  VAR Temp : String;
  BEGIN
    FillChar(Temp[1], Len, C);
    Temp[0] := Char(Len);
    Dupe := Temp;
  END;

  FUNCTION ADupe(C : Char;
                 Len : Byte) : String; Assembler;
  ASM
    LES DI, @Result
    CLD
    XOR CH, CH
    MOV CL, Len       {length in CX}
    MOV AX, CX        {and in AX}
    STOSB             {store length byte}
    MOV AL, C
    REP STOSB         {fill string with char}
  END;

  FUNCTION Pad(S : String; C : Char; Len : Byte) : String;
  BEGIN
    IF length(S) < len THEN
      FillChar(S[succ(length(S))], Len-length(S), C);
    S[0] := char(Len);
    Pad := S;
  END;

  FUNCTION APad(S : String; C : Char;
                Len : Byte) : String; Assembler;
  ASM
    PUSH DS
    LDS SI, S        {DS:SI points to S}
    LES DI, @Result  {ES:DI points to result}
    LODSB            {read existing length}
    XOR AH, AH
    MOV CX, AX
    MOV AL, Len      {Set result to desired length}
    STOSB            {Transfer length to result}
    MOV BX, CX
    REP MOVSB        {Now S is in @Result}
    XOR CH, CH
    MOV CL, Len      {Get desired length in CX}
    SUB CX, BX       {Subtract current length}
    JLE @NoPad       {If difference < 0, no pad}
      MOV AL, C      {Put char in AL}
      REP STOSB      {Fill rest of string}
    @NoPad:
    POP DS
  END;

  FUNCTION LeftPad(S : String; C : Char;
                               Len : Byte) : String;
  BEGIN
    IF length(S) < Len THEN
      BEGIN
        MOVE(S[1], S[succ(Len - length(S))], length(S));
        FillChar(S[1], Len - length(S), C);
      END;
    S[0] := Char(Len);
    LeftPad := S;
  END;

  FUNCTION ALeftPad(S : String; C : Char;
                    Len : Byte) : String; Assembler;
  ASM
    PUSH DS
    CLD
    LES DI, @Result  {ES:DI points to result}
    MOV AL, Len
    XOR AH, AH
    MOV CX, AX       {Desired length in CX}
    STOSB            {length byte of result}
    LDS SI, S        {DS:SI points to S}
    LODSB            {AL has length of S}
    MOV BL, AL       {remember length of S}
    SUB CX, AX       {subtract actual from desired}
    JLE @NoPad       {if diff < 0, don't pad}
      MOV AL, C      {fill at start of string}
      REP STOSB
    @NoPad:
    MOV CL, BL       {get back length of S}
    REP MOVSB        {copy rest of S}
    POP DS
  END;

  FUNCTION Chop(S : String; len : Byte): String;
  BEGIN
    IF length(S) > len THEN
      S[0] := Char(Len);
    Chop := S;
  END;

  FUNCTION AChop(S : String;
                 len: Byte): String; Assembler;
  ASM
    PUSH DS
    LDS SI, S
    LES DI, @Result
    LODSB
    XOR AH, AH
    XCHG AX, CX
    CMP CL, Len       {if length > len,...}
    JB @NoChop
      MOV CL, Len     {... set length to len}
    @NoCHop:
    MOV AL, CL        {store length}
    STOSB
    REP MOVSB         {copy Len chars to result}
    POP DS
  END;

  FUNCTION LeftChop(S : String; len: Byte): String;
  BEGIN
    IF length(S) > len THEN
      BEGIN
        MOVE(S[succ(length(S) - len)],
             S[1], Len);
        S[0] := Char(Len);
      END;
    LeftChop := S;
  END;

  FUNCTION ALeftChop(S : String;
                 len: Byte): String; Assembler;
  ASM
    PUSH DS
    LDS SI, S
    LES DI, @Result
    LODSB
    XOR AH, AH
    XCHG AX, CX
    CMP CL, Len       {if length > len,...}
    JB @NoChop
      ADD SI, CX      {point to end of string}
      MOV CL, Len     {set length to len}
      SUB SI, CX      {point to new start of string}
    @NoCHop:
    MOV AL, CL        {store length}
    STOSB
    REP MOVSB         {copy Len chars to result}
    POP DS
  END;

  PROCEDURE Trim(VAR S : String; C : Char);
  BEGIN
    WHILE S[length(S)] = C DO Dec(S[0]);
  END;

  PROCEDURE TrimLead(VAR S : String; C : Char);
  VAR P : Byte;
  BEGIN
    P := 1;
    WHILE (S[P] = C) AND (P <= length(S)) DO Inc(P);
    CASE P OF
      0 : S[0] := #0; {string was 255 of C!}
      1 : ; {not found}
      ELSE
        Move(S[P], S[1], succ(length(S) - P));
        Dec(S[0], pred(P));
    END;
  END;

END.

[Back to STRINGS SWAG index]  [Back to Main SWAG index]  [Original]