home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / misc / dstr2.ada < prev    next >
Encoding:
Text File  |  1988-05-03  |  13.8 KB  |  399 lines

  1.  
  2. -------- SIMTEL20 Ada Software Repository Prologue ------------
  3. --                                                           -*
  4. -- Unit name    : DYNAMIC_STRINGS
  5. -- Version      : 1.0
  6. -- Author       : Mike Linnig et al (see source)
  7. --              : Texas Instruments Ada Technology Branch
  8. --              : PO Box 801, MS 8007
  9. --              : McKinney, TX  75069
  10. -- DDN Address  : linnig%ti-eg at csnet-relay
  11. -- Copyright    : (c) 
  12. -- Date created :  27 June 85
  13. -- Release date :  27 June 85
  14. -- Last update  :  27 June 85
  15. -- Machine/System Compiled/Run on : DG MV 10000 with ROLM ADE
  16. --                    DEC VAX 11/780 with DEC Ada
  17. --                                                           -*
  18. ---------------------------------------------------------------
  19. --                                                           -*
  20. -- Keywords     :  STRINGS, DYNAMIC STRINGS
  21. ----------------:
  22. --
  23. -- Abstract     : Dynamic_Strings is a generic package which
  24. -- provides a set of routines to manipulate dynamic strings.
  25. -- See the documentation in the source code for references
  26. -- to magazine articles et al
  27. --
  28. --                                                           -*
  29. ------------------ Revision history ---------------------------
  30. --                                                           -*
  31. -- DATE         VERSION    AUTHOR                  HISTORY
  32. -- 19850627    1.0    Mike Linnig        Initial Release
  33. --                                                           -*
  34. ------------------ Distribution and Copyright -----------------
  35. --                                                           -*
  36. -- This prologue must be included in all copies of this software.
  37. --
  38. -- This software is released to the Ada community.
  39. -- This software is released to the Public Domain (note:
  40. --   software released to the Public Domain is not subject
  41. --   to copyright protection).
  42. -- Restrictions on use or distribution:  NONE
  43. --                                                           -*
  44. ------------------ Disclaimer ---------------------------------
  45. --                                                           -*
  46. -- This software and its documentation are provided "AS IS" and
  47. -- without any expressed or implied warranties whatsoever.
  48. -- No warranties as to performance, merchantability, or fitness
  49. -- for a particular purpose exist.
  50. --
  51. -- Because of the diversity of conditions and hardware under
  52. -- which this software may be used, no warranty of fitness for
  53. -- a particular purpose is offered.  The user is advised to
  54. -- test the software thoroughly before relying on it.  The user
  55. -- must assume the entire risk and liability of using this
  56. -- software.
  57. --
  58. -- In no event shall any person or organization of people be
  59. -- held responsible for any direct, indirect, consequential
  60. -- or inconsequential damages or lost profits.
  61. --                                                           -*
  62. -------------------END-PROLOGUE--------------------------------
  63.  
  64.  
  65. GENERIC
  66.   Max_Length : Positive := 256;
  67.  
  68.     -- should the package fail gracefully or raise an exception on errors
  69.   Raise_Exception_On_Error : Boolean := False;
  70.  
  71. PACKAGE Dynamic_Strings IS
  72.  
  73. ------------------------------------------------------------------------------
  74. --  This is a package of several string manipulation functions based on     --
  75. -- a built-in dynamic string type DYN_STRING.  It is an adaptation and      --
  76. -- extension of the package proposed by Sylvan Rubin of Ford Aerospace and  --
  77. -- Communications Corporation in the Nov/Dec 1984 issue of the Journal of   --
  78. -- Pascal, Ada and Modula-2.  Some new functions have been added, the       --
  79. -- SUBSTRING function has been modified to permit it to return the right    --
  80. -- part of a string if the third parameter is permitted to default, and     --
  81. -- much of the body code has been rewritten.                                --
  82. ------------------------------------------------------------------------------
  83. -- R.G. Cleaveland 07 December 1984:                                        --
  84. --  Implementation initially with the Telesoft Ada version                  --
  85. -- This required definition of the DYN_STRING type without use of a         --
  86. -- discriminant; an arbitrary maximum string length was chosen.  This       --
  87. -- should be changed when an improved compiler is available.                --
  88. ------------------------------------------------------------------------------
  89. -- Richard Powers 03 January 1985:                                          --
  90. -- changed to be used with a real compiler.                                 --
  91. -- Some of the routines removed by my whim.                                 --
  92. ------------------------------------------------------------------------------
  93. -- Michael J. Linnig          04 Jan 1985                                   --
  94. --  modified to reflect version published in Dec '84                        --
  95. --  edition of Journal of Pascal, Ada and Modula-2                          --
  96. --   (not all functions from original article reproduced here)              --
  97. --  AND MADE IT GENERIC (to prevent need for dynamic allocation of strings) --
  98. ------------------------------------------------------------------------------
  99.  
  100.  
  101.   TYPE Dyn_String IS PRIVATE;
  102.  
  103.   Null_Dstring    : CONSTANT Dyn_String;
  104.   No_Match        : CONSTANT Integer := 0;     -- made constant in spite of
  105.   No_Fit          : CONSTANT Integer := -1;    -- JPAM2 article - mjl
  106.  
  107.   String_Too_Short : EXCEPTION;
  108.   Dynamic_String_Parameter_Error : EXCEPTION;
  109.      -- raised if parameters make no sense
  110.  
  111. -----------------------------------------------------------------------------
  112.  
  113.   FUNCTION D_String (Char : Character) RETURN Dyn_String;
  114.   -- Creates a one-byte dynamic string of contents CHAR.
  115.  
  116.   FUNCTION D_String (Str : String) RETURN Dyn_String;
  117.   -- Creates a dynamic string of contents STR.
  118.  
  119.   FUNCTION Char (Dstr : Dyn_String) RETURN Character;
  120.   FUNCTION Str  (Dstr : Dyn_String) RETURN String;
  121.  
  122.   FUNCTION Length (Dstr : Dyn_String) RETURN Natural;
  123.   FUNCTION "<"    (Ds1, Ds2 : Dyn_String) RETURN Boolean;
  124.   FUNCTION "&"    (Ds1, Ds2 : Dyn_String) RETURN Dyn_String;
  125.  
  126.   FUNCTION Substring (Dstr   : Dyn_String;
  127.                       Start  : Natural;
  128.                       Length : Natural := 0) RETURN Dyn_String;
  129.  
  130.  
  131.  
  132.   FUNCTION Index (Source_String,
  133.                   Pattern_String : Dyn_String;
  134.                   Start_Pos : Integer) RETURN Integer;
  135.  
  136. -- If the source string contains the pattern string starting at or AFTER
  137. -- START_POSITION,  the position of such string is returned.
  138.  
  139.  
  140.  
  141.   FUNCTION Rindex (Source_String,
  142.                    Pattern_String : Dyn_String;
  143.  
  144.                    Start_Pos                     : Integer) RETURN Integer;
  145.  
  146. -- If the source string contains the pattern string starting at or BEFORE
  147. -- START_POSITION,  the position of such string is returned.
  148.  
  149. -----------------------------------------------------------------------
  150. PRIVATE
  151.  
  152.   SUBTYPE String_range IS Natural RANGE 0 .. Max_Length;
  153.   TYPE Internal_Dyn_String (Size : String_range := 0) IS
  154.     RECORD
  155.       Data : String (1 .. Size);
  156.     END RECORD;
  157.  
  158.   TYPE Dyn_String IS
  159.     RECORD
  160.       Dstring : Internal_Dyn_String;
  161.     END RECORD;
  162.  
  163.     Null_Dstring    : CONSTANT Dyn_String := (dstring=> (size=>0,
  164.                                                          data=>""));
  165.  
  166.  
  167.  
  168. END Dynamic_Strings;
  169.  
  170. ----------------------------------------------------------------------------
  171.  
  172. PACKAGE BODY Dynamic_Strings IS
  173.  
  174.   raise_exceptions : CONSTANT Boolean := Raise_Exception_on_Error;
  175.  
  176.  
  177.   FUNCTION "&" (Ds1, Ds2 : Dyn_String) RETURN Dyn_String IS
  178.   BEGIN
  179.     RETURN (Dstring =>
  180.               ((Ds1.Dstring.Size + Ds2.Dstring.Size),
  181.                (Ds1.Dstring.Data & Ds2.Dstring.Data)));
  182.   END "&";
  183.  
  184.  
  185.  
  186.   FUNCTION Length (Dstr : Dyn_String) RETURN Natural IS
  187.   BEGIN
  188.     RETURN Dstr.Dstring.Size;
  189.   END Length;
  190.  
  191.  
  192.   FUNCTION D_String (Char : Character) RETURN Dyn_String IS
  193.   BEGIN
  194.     RETURN (Dstring => (1, (1 => Char)));
  195.   END D_String;
  196.  
  197.   FUNCTION D_String (Str : String) RETURN Dyn_String IS
  198.     First, Last : Natural;
  199.   BEGIN
  200.     First := Str'First;                          -- should always be one -- mjl
  201.     Last := Str'Last;
  202.     RETURN (Dstring => (Last - First + 1, (Str (First .. Last))));
  203.   END D_String;
  204.  
  205.   FUNCTION Char (Dstr : Dyn_String) RETURN Character IS
  206.   BEGIN
  207.     IF Dstr.Dstring.Size = 0 THEN
  208.       If raise_exceptions then
  209.         RAISE String_Too_Short;
  210.       else
  211.         RETURN Ascii.Nul;  -- fail gracefully
  212.       end if;
  213.     ELSE
  214.       RETURN Dstr.Dstring.Data (1);
  215.     END IF;
  216.   END Char;
  217.  
  218.   FUNCTION Str (Dstr : Dyn_String) RETURN String IS
  219.   BEGIN
  220.     RETURN Dstr.Dstring.Data (1 .. Dstr.Dstring.Size);
  221.   END Str;
  222.  
  223.  
  224.   FUNCTION "<" (Ds1, Ds2 : Dyn_String) RETURN Boolean IS
  225. -- this was not changed back to jpam2 implementation - mjl
  226.   BEGIN
  227.     IF Str (Ds1) < Str (Ds2) THEN
  228.       RETURN (True);
  229.     ELSE
  230.       RETURN (False);
  231.     END IF;
  232.   END "<";
  233.  
  234.   FUNCTION Substring (Dstr   : Dyn_String;
  235.                       Start  : Natural;
  236.                       Length : Natural := 0) RETURN Dyn_String IS
  237.  
  238.   BEGIN
  239.     IF (Start < 1)  THEN
  240.       IF raise_Exceptions then
  241.         RAISE Dynamic_String_Parameter_Error;
  242.       Else
  243.         RETURN SUBSTRING(dstr, 1, Length); -- assume start at 1st character
  244.       End if;
  245.  
  246.     ELSIF   (Start > Dstr.Dstring.Size) THEN
  247.       IF raise_Exceptions then
  248.         RAISE Dynamic_String_Parameter_Error;
  249.       Else
  250.         RETURN Null_Dstring; -- since starting point beyond characters in str.
  251.       End if;
  252.  
  253.     ELSIF Dstr.Dstring.Size < (Start + Length - 1) THEN
  254.       IF raise_Exceptions then
  255.         RAISE String_Too_Short;
  256.       Else
  257.         -- return portion of string possible [from START to end of DSTR]
  258.         RETURN (Dstring =>
  259.                  (Dstr.Dstring.Size-Start+1,
  260.                   dstr.Dstring.data(Start..Dstr.Dstring.size)));
  261.       End if;
  262.  
  263.     ELSE
  264.       RETURN (Dstring =>
  265.                 (Length, (Dstr.Dstring.Data (Start .. Start + Length - 1))));
  266.     END IF;
  267.   END Substring;
  268.  
  269.  
  270. ---------------------------------------------------------------------------
  271.   FUNCTION Index (Source_String, Pattern_String : Dyn_String;
  272.                   Start_Pos                     : Integer) RETURN Integer IS
  273.  
  274.     Pos_Index, I, J : Integer;
  275.  
  276.     Source_Length   : Natural;                   -- added since undeclared in
  277.                                                  -- jpam2 article
  278.     Pattern_Length  : Natural;                   -- ditto
  279.  
  280.   BEGIN
  281.     Source_Length := Source_String.Dstring.Size;
  282.     Pattern_Length := Pattern_String.Dstring.Size;
  283.  
  284.     IF Start_Pos + Pattern_Length - 1 > Source_Length THEN
  285.       RETURN No_Fit;
  286.     END IF;
  287.  
  288.     IF Start_Pos = 1 THEN
  289.       RETURN No_Fit;
  290.     END IF;
  291.  
  292.     I := 1;
  293.     J := Start_Pos;
  294.     Pos_Index := Start_Pos;
  295.  
  296.     LOOP
  297. -- if a char in a pattern string matches with
  298. -- a char in a source string...
  299.       IF Pattern_String.Dstring.Data (I) = Source_String.Dstring.Data (J) THEN
  300.  
  301. -- if the index of pattern string equal sthe
  302. -- pattern length then there is  a pattern match
  303. -- within source string
  304.         IF I = Pattern_Length THEN
  305.           RETURN Pos_Index;
  306.         ELSE
  307.           -- look at the next pair of chars..
  308.           I := I + 1;
  309.           J := J + 1;
  310.         END IF;
  311.  
  312.         -- if a character in a pattern string doesn't match
  313.         -- with a character in a sources string..
  314.       ELSE
  315. -- there are not enough characters remaining
  316. -- in the source string to match the pattern, then
  317. -- No match is possible....
  318.         IF Source_Length - Pos_Index < Pattern_Length THEN
  319.           RETURN No_Match;
  320.         ELSE
  321.           -- otherwise, set the pattern string index to 1...
  322.           I := 1;
  323.           -- adjust the postion index of the source string
  324.           -- and keep on comparing...
  325.           Pos_Index := Pos_Index + 1;
  326.           J := Pos_Index;
  327.         END IF;
  328.       END IF;
  329.     END LOOP;
  330.   END Index;
  331.  
  332.  
  333.   FUNCTION Rindex (Source_String, Pattern_String : Dyn_String;
  334.                    Start_Pos                     : Integer) RETURN Integer IS
  335.  
  336.     Pos_Index, I, J : Integer;
  337.  
  338.     Source_Length   : Natural;                   -- added since undeclared in
  339.                                                  -- jpam2 article
  340.     Pattern_Length  : Natural;                   -- ditto
  341.  
  342.  
  343.     No_Match        : CONSTANT Integer := 0;
  344.     No_Fit          : CONSTANT Integer := -1;
  345.  
  346.   BEGIN
  347.     Source_Length := Source_String.Dstring.Size;
  348.     Pattern_Length := Pattern_String.Dstring.Size;
  349.  
  350.     IF Start_Pos < Pattern_Length THEN
  351.       RETURN No_Fit;
  352.     END IF;
  353.  
  354.     IF Start_Pos > Source_Length THEN
  355.       RETURN No_Fit;
  356.     END IF;
  357.  
  358.     I := Pattern_Length;
  359.     J := Start_Pos;
  360.     Pos_Index := Start_Pos;
  361.  
  362.     LOOP
  363. -- if a char in a pattern string matches with
  364. -- a char in a source string...
  365.       IF Pattern_String.Dstring.Data (I) = Source_String.Dstring.Data (J) THEN
  366.  
  367. -- if the index of pattern string equal one
  368. -- then there is  a pattern match
  369. -- within source string
  370.         IF I = 1 THEN
  371.           RETURN Pos_Index;
  372.         ELSE
  373.           -- look at the next pair of chars..
  374.           I := I - 1;
  375.           J := J - 1;
  376.         END IF;
  377.  
  378.         -- if a character in a pattern string doesn't match
  379.         -- with a character in a sources string..
  380.       ELSE
  381. -- if the source string has no more room for the pattern
  382.         IF Pos_Index = Pattern_Length THEN
  383.           RETURN No_Match;
  384.         ELSE
  385.           -- otherwise, set the pattern string index to
  386.           -- the length of the pattern...
  387.           I := Pattern_Length;
  388.           -- adjust the postion index of the source string
  389.           -- and keep on comparing...
  390.           Pos_Index := Pos_Index - 1;
  391.           J := Pos_Index;
  392.         END IF;
  393.       END IF;
  394.     END LOOP;
  395.  
  396.  
  397.   END Rindex;
  398. END Dynamic_Strings;
  399.