home *** CD-ROM | disk | FTP | other *** search
/ Chip 1995 March / CHIP3.mdf / programm / prog2 / dynstrng.ada < prev    next >
Encoding:
Text File  |  1991-07-01  |  14.3 KB  |  386 lines

  1.                                        -- Chapter 16 - Program 3
  2. -- This is a dynamic string package which can be used as an aid
  3. -- in writing string intensive programs.  Ada only has a static
  4. -- string capability, so this package was written as an example of
  5. -- how the Ada programming language can be expanded.  The basis
  6. -- for this package is the dynamic string available with the
  7. -- Borland International implementation of Pascal, TURBO Pascal.
  8.  
  9. -- A dynamic string is defined as an array of characters of maximum
  10. -- length of 255.  The dynamic length of the dynamic string is
  11. -- stored in the string location with index = 0, so the dynamic
  12. -- string must be defined with a lower limit of 0 and an upper
  13. -- limit of whatever the desired maximum length of the string is
  14. -- to be.  The subtype STRING_SIZE below limits the string length
  15. -- when it is defined.
  16.  
  17. -- Put      Outputs a dynamic string to the monitor
  18. -- ConCat   Concatenates two dynamic strings and puts the result
  19. --           into a third dynamic string
  20. -- Copy     Copies a dynamic string to another dynamic string
  21. -- Copy     Copies a static string to a dynamic string
  22. -- Delete   Deletes a group of characters from a dynamic string
  23. -- Insert   Inserts a group of characters into a dynamic string
  24. -- Length   Returns the dynamic length of a dynamic string
  25. -- Size_Of  Returns the static length of a dynamic string
  26. -- Pos      Returns the first location of a dynamic string within
  27. --           another dynamic string
  28.  
  29. with Text_IO; use Text_IO;
  30. package DynStrng is
  31.  
  32.    subtype STRING_SIZE is INTEGER range 0..255;
  33.    type DYNAMIC_STRING is array(STRING_SIZE range <>) of CHARACTER;
  34.  
  35. -- Put : Display a dynamic string on the monitor.
  36. procedure Put(Input_String : in     DYNAMIC_STRING);
  37.  
  38.  
  39. -- ConCat : Concatenation - The First_String is copied into the
  40. --             Result_String, then the Second_String is copied
  41. --             into the Result_String following the First_String.
  42. --             If all characters fit, Result is set to TRUE.
  43. --             If Result_String will not hold all characters,
  44. --             only as many as will fit are copied and Result
  45. --             is set to FALSE.
  46. --             Result = TRUE, complete copy done.
  47. --             Result = FALSE, some or all not copied
  48. procedure ConCat(First_String  : in     DYNAMIC_STRING;
  49.                  Second_String : in     DYNAMIC_STRING;
  50.                  Result_String : in out DYNAMIC_STRING;
  51.                  Result        :    out BOOLEAN);
  52.  
  53.  
  54. -- Copy : The String contained in Input_String is copied into
  55. --             the string Output_String.  This procedure is
  56. --             overloaded to include copying from either dynamic
  57. --             strings or static strings.
  58. --             Result = TRUE, complete copy done
  59. --             Result = FALSE, some or all not copied
  60. procedure Copy(Input_String  : in     DYNAMIC_STRING;
  61.                Output_String : in out DYNAMIC_STRING;
  62.                Result        :    out BOOLEAN);
  63. procedure Copy(Input_String  : in     STRING;
  64.                Output_String :    out DYNAMIC_STRING;
  65.                Result        :    out BOOLEAN);
  66.  
  67.  
  68. -- Delete : Beginning at First_Position, as many characters as are
  69. --             indicated by Number_Of_Characters are deleted from
  70. --             String_To_Modify.  If there are not that many, only
  71. --             as many as are left are deleted.
  72. --             Result = TRUE, deletion was complete
  73. --             Result = FALSE, only a partial deletion was done
  74. procedure Delete(String_To_Modify     : in out DYNAMIC_STRING;
  75.                  First_Position       : in     STRING_SIZE;
  76.                  Number_Of_Characters : in     STRING_SIZE;
  77.                  Result               :    out BOOLEAN);
  78.  
  79.  
  80. -- Insert : The string String_To_Insert is inserted into the string
  81. --             String_To_Modify begining at location Place_To_Insert
  82. --             if there is enough room.
  83. --             Result = TRUE, insert completed in full
  84. --             Result = FALSE, not enough room for full insert
  85. procedure Insert(String_To_Modify : in out DYNAMIC_STRING;
  86.                  String_To_Insert : in     DYNAMIC_STRING;
  87.                  Place_To_Insert  : in     STRING_SIZE;
  88.                  Result           :    out BOOLEAN);
  89.  
  90.  
  91. -- Length : Returns the dynamic length of the string defined by
  92. --             String_To_Measure.
  93. function Length(String_To_Measure : in DYNAMIC_STRING)
  94.                  return STRING_SIZE;
  95.  
  96.  
  97. -- Size_Of : Returns the static length of the string, the actual
  98. --             upper limit of the string definition.
  99. function Size_Of(String_To_Measure : in DYNAMIC_STRING)
  100.                  return STRING_SIZE;
  101.  
  102.  
  103. -- Pos : Position of substring - The string String_To_Search is
  104. --             searched for the string Required_String beginning
  105. --             at Place_To_Start.
  106. --             Result = TRUE, a search was possible
  107. --             Result = FALSE, no search could be made
  108. --             Location_Found = 0, no string found
  109. --             Location_Found = N, start of matching string
  110. procedure Pos(String_To_Search : in     DYNAMIC_STRING;
  111.               Required_String  : in     DYNAMIC_STRING;
  112.               Place_To_Start   : in     STRING_SIZE;
  113.               Location_Found   :    out STRING_SIZE;
  114.               Result           :    out BOOLEAN);
  115.  
  116. end DynStrng;
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124. package body DynStrng is
  125.  
  126.                -- The display procedure overloads the existing
  127.                -- Put procedures to output a dynamic string. Note
  128.                -- that the existing Put is used in this new Put.
  129. procedure Put(Input_String : in     DYNAMIC_STRING) is
  130. begin
  131.    for Index in 1..CHARACTER'POS(Input_String(0)) loop
  132.       Put(Input_String(Index));
  133.    end loop;
  134. end Put;
  135.  
  136.  
  137.  
  138.  
  139. procedure ConCat(First_String  : in     DYNAMIC_STRING;
  140.                  Second_String : in     DYNAMIC_STRING;
  141.                  Result_String : in out DYNAMIC_STRING;
  142.                  Result        :    out BOOLEAN) is
  143. Intermediate_Result : BOOLEAN;
  144. Character_Count     : STRING_SIZE;
  145. Room_Left           : STRING_SIZE;
  146. begin
  147.                        -- Copy the first into the result string
  148.    Copy(First_String,Result_String,Intermediate_Result);
  149.    if Intermediate_Result then
  150.       Character_Count := CHARACTER'POS(Second_String(0));
  151.       Room_Left := Result_String'LAST
  152.                                 - CHARACTER'POS(Result_String(0));
  153.       Result := TRUE;
  154.       if Character_Count > Room_Left then
  155.          Character_Count := Room_Left;
  156.          Result := FALSE;
  157.       end if;
  158.       for Index in 1..Character_Count loop
  159.          Result_String(Index + CHARACTER'POS(Result_String(0))) :=
  160.                                           Second_String(Index);
  161.       end loop;
  162.       Result_String(0) :=
  163.              CHARACTER'VAL(CHARACTER'POS(Result_String(0))
  164.                                                  + Character_Count);
  165.    else
  166.       Result := FALSE;
  167.    end if;
  168. end ConCat;
  169.  
  170.  
  171.  
  172.  
  173.                -- This procedure overloads the name Copy to
  174.                -- copy from one dynamic string to another.
  175. procedure Copy(Input_String  : in     DYNAMIC_STRING;
  176.                Output_String : in out DYNAMIC_STRING;
  177.                Result        :    out BOOLEAN) is
  178. Character_Count : STRING_SIZE;
  179. begin
  180.                        -- First pick the smallest string size
  181.    Character_Count := CHARACTER'POS(Input_String(0));
  182.    if Character_Count > Output_String'LAST then
  183.       Character_Count := Output_String'LAST;
  184.       Result := FALSE; -- The entire string didn't fit
  185.    else
  186.       Result := TRUE;  -- The entire string fit
  187.    end if;
  188.  
  189.    for Index in 0..Character_Count loop
  190.       Output_String(Index) := Input_String(Index);
  191.    end loop;
  192.    Output_String(0) := CHARACTER'VAL(Character_Count);
  193. end Copy;
  194.  
  195.  
  196.  
  197.  
  198.                -- This routine overloads the copy procedure name
  199.                -- to copy a static string into a dynamic string.
  200. procedure Copy(Input_String  : in     STRING;
  201.                Output_String :    out DYNAMIC_STRING;
  202.                Result        :    out BOOLEAN) is
  203. Character_Count : STRING_SIZE;
  204. begin
  205.                        -- First pick the smallest string size
  206.    Character_Count := Input_String'LAST;
  207.    if Character_Count > Output_String'LAST then
  208.       Character_Count := Output_String'LAST;
  209.       Result := FALSE; -- The entire string didn't fit
  210.    else
  211.       Result := TRUE;  -- The entire string fit
  212.    end if;
  213.  
  214.    for Index in 1..Character_Count loop
  215.       Output_String(Index) := Input_String(Index);
  216.    end loop;
  217.    Output_String(0) := CHARACTER'VAL(Character_Count);
  218. end Copy;
  219.  
  220.  
  221.  
  222.  
  223. procedure Delete(String_To_Modify     : in out DYNAMIC_STRING;
  224.                  First_Position       : in     STRING_SIZE;
  225.                  Number_Of_Characters : in     STRING_SIZE;
  226.                  Result               :    out BOOLEAN) is
  227. Number_To_Delete       : STRING_SIZE;
  228. Number_To_Move         : STRING_SIZE;
  229. Last_Dynamic_Character : STRING_SIZE :=
  230.                                 CHARACTER'POS(String_To_Modify(0));
  231. begin
  232.                          -- can we delete any at all?
  233.    if First_Position > Last_Dynamic_Character then
  234.       Result := FALSE;
  235.       return;
  236.    end if;
  237.                          -- Decide how many to delete
  238.    if (First_Position + Number_Of_Characters)
  239.                                    > Last_Dynamic_Character then
  240.       Number_To_Delete := Last_Dynamic_Character
  241.                                              - First_Position + 1;
  242.       Result := FALSE;
  243.    else
  244.       Number_To_Delete := Number_Of_Characters;
  245.       Result := TRUE;
  246.    end if;
  247.  
  248.                   -- find out how many to move back
  249.    if (Last_Dynamic_Character - (First_Position + Number_To_Delete))
  250.                                                            >= 0 then
  251.       Number_To_Move := 1 + Last_Dynamic_Character
  252.                            - (First_Position + Number_To_Delete);
  253.    else
  254.       Number_To_Move := 0;
  255.    end if;
  256.  
  257.                   -- now delete the characters by moving them back
  258.    for Index in First_Position..
  259.                           (First_Position + Number_To_Move - 1) loop
  260.       String_To_Modify(Index) := String_To_Modify(Index
  261.                                                 + Number_To_Delete);
  262.    end loop;
  263.    String_To_Modify(0) :=
  264.             CHARACTER'VAL(CHARACTER'POS(String_To_Modify(0))
  265.                                                - Number_To_Delete);
  266. end Delete;
  267.  
  268.  
  269.  
  270.  
  271. procedure Insert(String_To_Modify : in out DYNAMIC_STRING;
  272.                  String_To_Insert : in     DYNAMIC_STRING;
  273.                  Place_To_Insert  : in     STRING_SIZE;
  274.                  Result           :    out BOOLEAN) is
  275. Number_To_Add  : STRING_SIZE;
  276. Number_To_Move : STRING_SIZE;
  277. Room_Left      : STRING_SIZE;
  278. begin
  279.                         -- Can we add any at all?
  280.    if (Place_To_Insert > String_To_Modify'LAST) or
  281.      (Place_To_Insert > CHARACTER'POS(String_To_Modify(0)) + 1) then
  282.       Result := FALSE;
  283.       return;
  284.    end if;
  285.    Result := TRUE;
  286.  
  287.                         -- How many can we add?
  288.    Number_To_Add := String_To_Modify'LAST - Place_To_Insert + 1;
  289.    if Number_To_Add > CHARACTER'POS(String_To_Insert(0)) then
  290.       Number_To_Add := CHARACTER'POS(String_To_Insert(0));
  291.    end if;
  292.  
  293.                         -- Find how many to move forward
  294.    Number_To_Move := CHARACTER'POS(String_To_Modify(0))
  295.                                              - Place_To_Insert + 1;
  296.    Room_Left := String_To_Modify'LAST - Place_To_Insert + 1;
  297.    if Room_Left < Number_To_Move then
  298.       Number_To_Move := Room_Left;
  299.    end if;
  300.  
  301.                         -- Move them forward
  302.    for Index in reverse Place_To_Insert..Place_To_Insert
  303.                                          + Number_To_Move - 1 loop
  304.       String_To_Modify(Index + Number_To_Add) :=
  305.                                            String_To_Modify(Index);
  306.    end loop;
  307.    for Index in 1..Number_To_Add loop
  308.       String_To_Modify(Index + Place_To_Insert - 1) :=
  309.                                            String_To_Insert(Index);
  310.    end loop;
  311.  
  312.                         -- Increase the length of the string
  313.    String_To_Modify(0) := CHARACTER'VAL(
  314.              CHARACTER'POS(String_To_Modify(0)) + Number_To_Add);
  315.    if CHARACTER'POS(String_To_Modify(0)) > String_To_Modify'LAST
  316.                                                                then
  317.       String_To_Modify(0) := CHARACTER'VAL(String_To_Modify'LAST);
  318.    end if;
  319.  
  320. end Insert;
  321.  
  322.  
  323.  
  324.  
  325.                -- This returns the dynamic length of a string
  326. function Length(String_To_Measure : in DYNAMIC_STRING)
  327.                  return STRING_SIZE is
  328. begin
  329.    return CHARACTER'POS(String_To_Measure(0));
  330. end Length;
  331.  
  332.  
  333.  
  334.  
  335.                -- This returns the static length of a string
  336. function Size_Of(String_To_Measure : in DYNAMIC_STRING)
  337.                  return STRING_SIZE is
  338. begin
  339.    return String_To_Measure'LAST;
  340. end Size_Of;
  341.  
  342.  
  343.  
  344.  
  345. procedure Pos(String_To_Search : in     DYNAMIC_STRING;
  346.               Required_String  : in     DYNAMIC_STRING;
  347.               Place_To_Start   : in     STRING_SIZE;
  348.               Location_Found   :    out STRING_SIZE;
  349.               Result           :    out BOOLEAN) is
  350. End_Search             : STRING_SIZE;
  351. Characters_All_Compare : BOOLEAN;
  352. begin
  353.    Location_Found := 0;
  354.                           -- can we search the string at all?
  355.    if (Place_To_Start < CHARACTER'POS(String_To_Search(0))) and
  356.                      (Place_To_Start < String_To_Search'LAST) then
  357.       Result := TRUE;
  358.    else
  359.       Result := FALSE;
  360.       return;
  361.    end if;
  362.  
  363.                           -- search the loop for the string now
  364.    End_Search := CHARACTER'POS(String_To_Search(0)) -
  365.                          CHARACTER'POS(Required_String(0)) + 1;
  366.  
  367.    for Index in Place_To_Start..End_Search loop      -- search loop
  368.       Characters_All_Compare := TRUE;
  369.       for Count in 1..CHARACTER'POS(Required_String(0)) loop
  370.          if Required_String(Count) /=
  371.                            String_To_Search(Count + Index - 1) then
  372.             Characters_All_Compare := FALSE;
  373.             exit;         -- exit loop, a character did not match
  374.          end if;
  375.       end loop;
  376.       if Characters_All_Compare then
  377.          Location_Found := Index;
  378.          return;             -- string match found, return location
  379.       end if;
  380.    end loop;  -- end search loop
  381.  
  382. end Pos;
  383.  
  384. end DynStrng;
  385.  
  386.