[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]