home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Snippets / PStrings / PStrings.c next >
Encoding:
C/C++ Source or Header  |  1994-05-07  |  7.1 KB  |  288 lines  |  [TEXT/KAHL]

  1. #include "PStrings.h"
  2.  
  3. /*
  4. *
  5. *        PStrings
  6. *   hueras@world.std.com (Jon Hueras)
  7. *        
  8. *            This is a set of routines for manipulating Pascal strings. The routines are
  9. *            designed not only to be (reasonably) fast, but also robust when presented
  10. *            with unusual arguments.
  11. *            
  12. *            In those routines that reference substrings by index (indices begin at one,
  13. *            by the way) and/or length, there is the possibility that the specified
  14. *            substring is not wholly contained in the target string. Take, for example,
  15. *            the string S = "abc". DeleteSubStr(S, 2, 3) is not literally possible here.
  16. *            Likewise, DeleteSubStr(S, -5, 10). However, both of these calls are valid.
  17. *            
  18. *            What happens is that the target string is treated as though it were extended
  19. *            indefinitely from either end for the purpose of determining the start and
  20. *            end points of the substring. Then the arguments are "pinned" to values that
  21. *            actually fall within the target string's boundaries.
  22. *            
  23. *            Thus, DeleteSubStr(S, 2, 3) would behave the same as DeleteSubStr(S, 2, 2)
  24. *            and DeleteSubStr(S, -5, 10) would behave the same as DeleteSubStr(S, 1, 3).
  25. *            More interesting is that DeleteSubStr(S, -5, 7) would behave the same as
  26. *            DeleteSubStr(S, 1, 1) (why this is true is left as an exercise to the
  27. *            reader).
  28. *            
  29. *            All operations assume that any string variable that is modified is capable
  30. *            of containing 255 characters (i.e., Str255). If the result of an operation
  31. *            would result in overflow, the result is truncated. If you wish to modify a
  32. *            smaller string but cannot be certain the result will not overflow, you
  33. *            should work with a Str255 temporary variable (if necessary) and use
  34. *            CopySubStr to truncate the final result.
  35. *        
  36. *        CopyStr(SrcStr, DstStr)
  37. *        
  38. *            A simple string to string copy from SrcSrt to DstStr.
  39. *        
  40. *        AppendStr(SrcStr, DstStr)
  41. *        
  42. *            A copy of SrcStr is appended to the end of DstStr.
  43. *        
  44. *        EqualStr(Str1, Str2, CaseSens)
  45. *        
  46. *            Tests whether Str1 and Str2 are the same length and contain the same sequence
  47. *            of characters. CaseSens determines whether upper- and lower-case alphabetics
  48. *            are considered equivalent.
  49. *        
  50. *        FindSubStr(Pat, Str)
  51. *        
  52. *            Searches Str for an occurrence of Pat. If found, the index of the first
  53. *            matching character in Str is returned, otherwise zero is returned. Note that
  54. *            if Pat is a null string or has a length greater than that of Str, then zero is
  55. *            necessarily returned.
  56. *        
  57. *        CopySubStr(SrcStr, Index, Count, DstStr)
  58. *        
  59. *            Copies the specified substring within SrcStr to DstStr.
  60. *        
  61. *        EqualSubStr(SrcStr, Index, Count, CompStr, CaseSens)
  62. *        
  63. *            Tests whether the specified substring in SrcStr and CompStr are the same
  64. *            length and contain the same sequence of characters. CaseSens determines
  65. *            whether upper- and lower-case alphabetics are considered equivalent.
  66. *        
  67. *        InsertSubStr(SrcStr, DstStr, Index)
  68. *        
  69. *            Inserts SrcStr into DstStr at the given index position in DstStr.
  70. *        
  71. *        DeleteSubStr(Str, Index, Count)
  72. *        
  73. *            Deletes the specifies substring within Str.
  74. *        
  75. *        ReplaceSubStr(Pat, SrcStr, DstStr)
  76. *        
  77. *            Literally does a FindSubStr(Pat, DstStr) and, if Pat is found, deletes Pat
  78. *            from DstStr and inserts SrcStr at the same position.
  79. *
  80. */
  81.  
  82. pascal void CopyStr(StringPtr    SrcStr,
  83.                                         StringPtr    DstStr)
  84.     {
  85.         BlockMove(SrcStr, DstStr, *SrcStr+1);
  86.     }
  87.  
  88. pascal void AppendStr(register StringPtr    SrcStr,
  89.                                             register StringPtr    DstStr)
  90.     {
  91.         register int    SrcStrLen = *SrcStr;
  92.         register int    DstStrLen = *DstStr;
  93.         
  94.         if (DstStrLen + SrcStrLen > 255)
  95.             SrcStrLen = 255 - DstStrLen;
  96.         
  97.         if (SrcStrLen) {
  98.             BlockMove(SrcStr+1, DstStr+1+DstStrLen, SrcStrLen);
  99.             *DstStr += SrcStrLen;
  100.         }
  101.     }
  102.  
  103. static Boolean EqualChars(register unsigned char    *CharPtr1, 
  104.                                                     register unsigned char    *CharPtr2,
  105.                                                     register int                        NumChars,
  106.                                                     Boolean                                    CaseSens)
  107.     {
  108.         register unsigned char Char1, Char2;
  109.         
  110.         if (!CaseSens)
  111.             while (--NumChars >= 0) {
  112.                 
  113.                 Char1 = *CharPtr1++;
  114.                 
  115.                 if (Char1 >= 'a' && Char1 <= 'z')
  116.                     Char1 -= 'a' - 'A';
  117.                     
  118.                 Char2 = *CharPtr2++;
  119.                     
  120.                 if (Char2 >= 'a' && Char2 <= 'z')
  121.                     Char2 -= 'a' - 'A';
  122.                     
  123.                 if (Char1 != Char2)
  124.                     return(false);
  125.             
  126.             }
  127.         else
  128.             while (--NumChars >= 0)
  129.                 if (*CharPtr1++ != *CharPtr2++)
  130.                     return(false);
  131.         
  132.         return(true);
  133.     }
  134.  
  135. pascal Boolean EqualStr(StringPtr    Str1,
  136.                                                 StringPtr    Str2,
  137.                                                 Boolean        CaseSens)
  138.     {
  139.         if (*Str1 != *Str2)
  140.             return(false);
  141.         
  142.         return(EqualChars(Str1+1, Str2+1, *Str1, CaseSens));
  143.     }
  144.  
  145. pascal int FindSubStr(StringPtr    Pat,
  146.                                             StringPtr    Str)
  147.     {
  148.         register StringPtr    p, s;
  149.         register int                pl, sl;
  150.         register char                fc;
  151.         
  152.         p = Pat;
  153.         s = Str;
  154.         
  155.         pl = *p++;
  156.         sl = *s++;
  157.         
  158.         if ((sl -= pl - 1) <= 0)
  159.             return(0);
  160.         
  161.         if (--pl < 0)
  162.             return(0);
  163.         
  164.         fc = *p++;
  165.         
  166.         while (--sl >= 0) {
  167.             if (*s++ != fc)
  168.                 continue;
  169.             if (pl && !EqualChars(p, s, pl, true))
  170.                 continue;
  171.             return(s - Str - 1);
  172.         }
  173.         
  174.         return(0);
  175.     }
  176.  
  177. pascal void CopySubStr(register StringPtr    SrcStr,
  178.                                              register int                Index1,
  179.                                              register int                Count,
  180.                                              register StringPtr    DstStr)
  181.     {
  182.         register int    Index2, SrcLen = *SrcStr;
  183.         
  184.         Index2 = Index1 + Count;
  185.                 
  186.         if (Index1 < 1)
  187.             Index1 = 1;
  188.         
  189.         if (Index2 > SrcLen + 1)
  190.             Index2 = SrcLen + 1;
  191.         
  192.         if ((Count = Index2 - Index1) <= 0) {
  193.             *DstStr = 0;
  194.             return;
  195.         }
  196.         
  197.         *DstStr++ = Count;
  198.         
  199.         BlockMove(SrcStr+Index1, DstStr, Count);
  200.     }
  201.  
  202. pascal Boolean EqualSubStr(register StringPtr    SrcStr,
  203.                                                      register int                Index1,
  204.                                                      register int                Count,
  205.                                                      register StringPtr    CompStr,
  206.                                                      Boolean                        CaseSens)
  207.     {
  208.         register int    Index2, SrcLen = *SrcStr;
  209.         
  210.         Index2 = Index1 + Count;
  211.                 
  212.         if (Index1 < 1)
  213.             Index1 = 1;
  214.         
  215.         if (Index2 > SrcLen + 1)
  216.             Index2 = SrcLen + 1;
  217.         
  218.         if ((Count = Index2 - Index1) <= 0)
  219.             return(!*CompStr);
  220.         
  221.         return(EqualChars(SrcStr+Index1, CompStr+1, Count, CaseSens));
  222.     }
  223.  
  224. pascal void InsertSubStr(register StringPtr    SrcStr,
  225.                                                  register StringPtr    DstStr,
  226.                                                  register int                Index1)
  227.     {
  228.         register int    SrcLen = *SrcStr;
  229.         register int    DstLen = *DstStr;
  230.         register int    Index2, Index3;
  231.         
  232.         if (!SrcLen)
  233.             return;
  234.         
  235.         if (Index1 < 1)
  236.             Index1 = 1;
  237.         
  238.         if (Index1 > DstLen + 1)
  239.             Index1 = DstLen + 1;
  240.                 
  241.         if ((Index2 = Index1 + SrcLen) > 256)
  242.             Index2 = 256;
  243.         
  244.         if ((Index3 = DstLen + SrcLen + 1) > 256)
  245.             Index3 = 256;
  246.         
  247.         *DstStr = Index3 - 1;
  248.         
  249.         BlockMove(DstStr+Index1, DstStr+Index2, Index3-Index2);
  250.         BlockMove(SrcStr+1, DstStr+Index1, Index2-Index1);
  251.     }
  252.  
  253. pascal void DeleteSubStr(register StringPtr    Str,
  254.                                                  register int                Index1,
  255.                                                  register int                Count)
  256.     {
  257.         register int    Index2, StrLen = *Str;
  258.         
  259.         Index2 = Index1 + Count;
  260.                 
  261.         if (Index1 < 1)
  262.             Index1 = 1;
  263.         
  264.         if (Index2 > StrLen + 1)
  265.             Index2 = StrLen + 1;
  266.         
  267.         if ((Count = Index2 - Index1) <= 0)
  268.             return;
  269.         
  270.         *Str -= Count;
  271.         
  272.         BlockMove(Str+Index2, Str+Index1, StrLen-Index2+1);
  273.     }
  274.  
  275. pascal int ReplaceSubStr(StringPtr    Pat,
  276.                                                  StringPtr    SrcStr,
  277.                                                  StringPtr    DstStr)
  278.     {
  279.         register int i;
  280.         
  281.         if (i = FindSubStr(Pat, DstStr)) {
  282.             DeleteSubStr(DstStr, i, *Pat);
  283.             InsertSubStr(SrcStr, DstStr, i);
  284.         }
  285.         
  286.         return(i);
  287.     }
  288.