1-- CXA4014.A
2--
3--                             Grant of Unlimited Rights
4--
5--     Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
6--     F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
7--     unlimited rights in the software and documentation contained herein.
8--     Unlimited rights are defined in DFAR 252.227-7013(a)(19).  By making
9--     this public release, the Government intends to confer upon all
10--     recipients unlimited rights  equal to those held by the Government.
11--     These rights include rights to use, duplicate, release or disclose the
12--     released technical data and computer software in whole or in part, in
13--     any manner and for any purpose whatsoever, and to have or permit others
14--     to do so.
15--
16--                                    DISCLAIMER
17--
18--     ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
19--     DISCLOSED ARE AS IS.  THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
20--     WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
21--     SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
22--     OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
23--     PARTICULAR PURPOSE OF SAID MATERIAL.
24--*
25--
26-- OBJECTIVE:
27--      Check that the subprograms defined in package Ada.Strings.Wide_Fixed
28--      are available, and that they produce correct results.  Specifically,
29--      check the subprograms Find_Token, Head, Index, Index_Non_Blank, Move,
30--      Overwrite, and Replace_Slice, Tail, and Translate.
31--      Use the access-to-subprogram mapping version of Translate (function
32--      and procedure).
33--
34-- TEST DESCRIPTION:
35--      This test demonstrates how certain wide fixed string operations could
36--      be used in wide string information processing.  A procedure is defined
37--      that will extract portions of a 50 character string that correspond to
38--      certain data items (i.e., name, address, state, zip code). These
39--      parsed items will then be added to the appropriate fields of data
40--      base elements.  These data base elements are then compared for
41--      accuracy against a similar set of predefined data base
42--      elements.
43--      A variety of wide fixed string processing subprograms are used in this
44--      test.  Each parsing operation attempts to use a different combination
45--      of the available subprograms to accomplish the same goal, therefore
46--      continuity of approach to wide string parsing is not seen in this
47--      test.
48--      However, a wide variety of possible approaches are demonstrated, while
49--      exercising a large number of the total predefined subprograms of
50--      package Ada.Strings.Wide_Fixed.
51--
52--
53-- CHANGE HISTORY:
54--      06 Dec 94   SAIC    ACVC 2.0
55--      02 Nov 95   SAIC    Update and repair for ACVC 2.0.1.
56--
57--!
58
59package CXA40140 is
60
61   UnderScore  : Wide_Character := '_';
62   Blank       : Wide_Character := ' ';
63
64   -- Function providing a mapping to a blank Wide_Character.
65   function US_to_Blank_Map (From : Wide_Character) return Wide_Character;
66
67end CXA40140;
68
69package body CXA40140 is
70
71   function US_to_Blank_Map (From : Wide_Character) return Wide_Character is
72   begin
73      if From = UnderScore then
74         return Blank;
75      else
76         return From;
77      end if;
78   end US_to_Blank_Map;
79
80end CXA40140;
81
82
83with CXA40140;
84with Ada.Strings.Wide_Fixed;
85with Ada.Strings.Wide_Maps;
86with Report;
87
88procedure CXA4014 is
89   use CXA40140;
90begin
91
92   Report.Test ("CXA4014", "Check that the subprograms defined in package "  &
93                           "Ada.Strings.Wide_Fixed are available, and that " &
94                           "they produce correct results");
95
96   Test_Block:
97   declare
98
99      Number_Of_Info_Strings : constant Natural := 3;
100      DB_Size                : constant Natural := Number_Of_Info_Strings;
101      Count                  : Natural          := 0;
102      Finished_Processing    : Boolean          := False;
103      Blank_Wide_String      : constant Wide_String  := " ";
104
105      subtype Info_Wide_String_Type         is Wide_String (1..50);
106      type    Info_Wide_String_Storage_Type is
107                array (1..Number_Of_Info_Strings) of Info_Wide_String_Type;
108
109
110      subtype Name_Type                is Wide_String (1..10);
111      subtype Street_Number_Type       is Wide_String (1..5);
112      subtype Street_Name_Type         is Wide_String (1..10);
113      subtype City_Type                is Wide_String (1..10);
114      subtype State_Type               is Wide_String (1..2);
115      subtype Zip_Code_Type            is Wide_String (1..5);
116
117      type Data_Base_Element_Type is
118         record
119            Name          : Name_Type          := (others => ' ');
120            Street_Number : Street_Number_Type := (others => ' ');
121            Street_Name   : Street_Name_Type   := (others => ' ');
122            City          : City_Type          := (others => ' ');
123            State         : State_Type         := (others => ' ');
124            Zip_Code      : Zip_Code_Type      := (others => ' ');
125         end record;
126
127      type Data_Base_Type is array (1..DB_Size) of Data_Base_Element_Type;
128
129      Data_Base : Data_Base_Type;
130
131      ---
132
133      Info_String_1 : Info_Wide_String_Type :=
134        "Joe_Jones 123   Sixth_St   San_Diego    CA   98765";
135
136      Info_String_2 : Info_Wide_String_Type :=
137        "Sam_Smith 56789  S._Seventh   Carlsbad  CA   92177";
138
139      Info_String_3 : Info_Wide_String_Type :=
140        "Jane_Brown 1219   Info_Lane  Tuscon     AZ   85643";
141
142
143      Info_Strings : Info_Wide_String_Storage_Type :=
144                       (1 => Info_String_1,
145                        2 => Info_String_2,
146                        3 => Info_String_3);
147
148
149
150      TC_DB_Element_1 : Data_Base_Element_Type :=
151        ("Joe Jones ", "123  ", "Sixth St  ", "San Diego ", "CA", "98765");
152
153      TC_DB_Element_2 : Data_Base_Element_Type :=
154        ("Sam Smith ", "56789", "S. Seventh", "Carlsbad  ", "CA", "92177");
155
156      TC_DB_Element_3 : Data_Base_Element_Type :=
157        ("Jane Brown", "1219 ", "Info Lane ", "Tuscon    ", "AZ", "85643");
158
159      TC_Data_Base : Data_Base_Type := (TC_DB_Element_1,
160                                        TC_DB_Element_2,
161                                        TC_DB_Element_3);
162
163      ---
164
165
166      procedure Store_Information
167         (Info_String : in     Info_Wide_String_Type;
168          DB_Record   : in out Data_Base_Element_Type) is
169
170         package  AS renames Ada.Strings;
171         use type AS.Wide_Maps.Wide_Character_Set;
172
173         Start,
174         Stop        : Natural := 0;
175
176         Numeric_Set    : constant AS.Wide_Maps.Wide_Character_Set :=
177                            AS.Wide_Maps.To_Set("0123456789");
178
179         Cal            : constant
180                            AS.Wide_Maps.Wide_Character_Sequence := "CA";
181         California_Set : constant AS.Wide_Maps.Wide_Character_Set :=
182                            AS.Wide_Maps.To_Set(Cal);
183         Arizona_Set    : constant AS.Wide_Maps.Wide_Character_Set :=
184                            AS.Wide_Maps.To_Set("AZ");
185         Nevada_Set     : constant AS.Wide_Maps.Wide_Character_Set :=
186                            AS.Wide_Maps.To_Set("NV");
187
188         Blank_Ftn_Ptr : AS.Wide_Maps.Wide_Character_Mapping_Function :=
189                           US_to_Blank_Map'Access;
190
191      begin
192
193         -- Find the starting position of the name field (first non-blank),
194         -- then, from that position, find the end of the name field (first
195         -- blank).
196
197         Start := AS.Wide_Fixed.Index_Non_Blank(Info_String);
198         Stop  := AS.Wide_Fixed.Index (Info_String(Start..Info_String'Length),
199                                       AS.Wide_Maps.To_Set(Blank),
200                                       AS.Inside,
201                                       AS.Forward) - 1 ;
202
203         -- Store the name field in the data base element field for "Name".
204
205         DB_Record.Name := AS.Wide_Fixed.Head(Info_String(1..Stop),
206                                         DB_Record.Name'Length);
207
208         -- Replace any underscore characters in the name field
209         -- that were used to separate first/middle/last names.
210         -- Use the overloaded version of Translate that takes an
211         -- access-to-subprogram value.
212
213         AS.Wide_Fixed.Translate (DB_Record.Name, Blank_Ftn_Ptr);
214
215
216         -- Continue the extraction process; now find the position of
217         -- the street number in the string.
218
219         Start := Stop + 1;
220
221         AS.Wide_Fixed.Find_Token(Info_String(Start..Info_String'Length),
222                                  Numeric_Set,
223                                  AS.Inside,
224                                  Start,
225                                  Stop);
226
227         -- Store the street number field in the appropriate data base
228         -- element.
229         -- No modification of the default parameters of procedure Move
230         -- is required.
231
232         AS.Wide_Fixed.Move(Source => Info_String(Start..Stop),
233                            Target => DB_Record.Street_Number);
234
235
236         -- Continue the extraction process; find the street name in the
237         -- info string.  Skip blanks to the start of the street name, then
238         -- search for the index of the next blank character in the string.
239
240         Start := AS.Wide_Fixed.Index_Non_Blank
241                                  (Info_String(Stop+1..Info_String'Length));
242
243         Stop :=
244           AS.Wide_Fixed.Index(Info_String(Start..Info_String'Length),
245                               Blank_Wide_String) - 1;
246
247         -- Store the street name in the appropriate data base element field.
248
249         AS.Wide_Fixed.Overwrite(DB_Record.Street_Name,
250                                 1,
251                                 Info_String(Start..Stop));
252
253         -- Replace any underscore characters in the street name field
254         -- that were used as word separation with blanks.  Again, use the
255         -- access-to-subprogram value to provide the mapping.
256
257         DB_Record.Street_Name :=
258           AS.Wide_Fixed.Translate(DB_Record.Street_Name,
259                                   Blank_Ftn_Ptr);
260
261
262         -- Continue the extraction; remove the city name from the string.
263
264         Start := AS.Wide_Fixed.Index_Non_Blank
265                                  (Info_String(Stop+1..Info_String'Length));
266
267         Stop :=
268           AS.Wide_Fixed.Index(Info_String(Start..Info_String'Length),
269                               Blank_Wide_String) - 1;
270
271         -- Store the city name field in the appropriate data base element.
272
273         AS.Wide_Fixed.Replace_Slice(DB_Record.City,
274                                     1,
275                                     DB_Record.City'Length,
276                                     Info_String(Start..Stop));
277
278         -- Replace any underscore characters in the city name field
279         -- that were used as word separation.
280
281         AS.Wide_Fixed.Translate (DB_Record.City,
282                                  Blank_Ftn_Ptr);
283
284
285         -- Continue the extraction; remove the state identifier from the
286         -- info string.
287
288         Start := Stop + 1;
289
290         AS.Wide_Fixed.Find_Token(Info_String(Start..Info_String'Length),
291                                  AS.Wide_Maps."OR"(California_Set,
292                                    AS.Wide_Maps."OR"(Nevada_Set,
293                                                      Arizona_Set)),
294                                  AS.Inside,
295                                  Start,
296                                  Stop);
297
298         -- Store the state indicator into the data base element.
299
300         AS.Wide_Fixed.Move(Source  => Info_String(Start..Stop),
301                            Target  => DB_Record.State,
302                            Drop    => Ada.Strings.Right,
303                            Justify => Ada.Strings.Left,
304                            Pad     => AS.Wide_Space);
305
306
307         -- Continue the extraction process; remove the final data item in
308         -- the info string, the zip code, and place it into the
309         -- corresponding data base element.
310
311         DB_Record.Zip_Code :=
312           AS.Wide_Fixed.Tail(Info_String, DB_Record.Zip_Code'Length);
313
314      exception
315         when AS.Length_Error      =>
316            Report.Failed ("Length_Error raised in procedure");
317         when AS.Pattern_Error     =>
318            Report.Failed ("Pattern_Error raised in procedure");
319         when AS.Translation_Error =>
320            Report.Failed ("Translation_Error raised in procedure");
321         when others            =>
322            Report.Failed ("Exception raised in procedure");
323      end Store_Information;
324
325
326   begin
327
328      -- Loop thru the information strings, extract the name and address
329      -- information, place this info into elements of the data base.
330
331      while not Finished_Processing loop
332
333         Count := Count + 1;
334
335         Store_Information (Info_Strings(Count), Data_Base(Count));
336
337         Finished_Processing := (Count = Number_Of_Info_Strings);
338
339      end loop;
340
341
342      -- Verify that the string processing was successful.
343
344      for i in 1..DB_Size loop
345         if Data_Base(i) /= TC_Data_Base(i) then
346            Report.Failed
347              ("Data processing error on record " & Integer'Image(i));
348         end if;
349      end loop;
350
351
352   exception
353      when others => Report.Failed ("Exception raised in Test_Block");
354   end Test_Block;
355
356
357   Report.Result;
358
359end CXA4014;
360