1-- CXA4023.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
28--      Ada.Strings.Wide_Unbounded are available, and that they produce
29--      correct results. Specifically, check the subprograms Delete,
30--      Find_Token, Translate, Trim, and "*".
31--
32-- TEST DESCRIPTION:
33--      This test demonstrates the uses of many of the subprograms defined
34--      in package Ada.Strings.Wide_Unbounded for use with unbounded wide
35--      strings.  The test simulates how unbounded wide strings
36--      will be processed in a user environment, using the subprograms
37--      provided in this package.
38--
39--      This test, when taken in conjunction with tests CXA4021-22, will
40--      constitute a test of the functionality contained in package
41--      Ada.Strings.Wide_Unbounded.  This test uses a variety
42--      of the subprograms defined in the unbounded wide string package
43--      in ways typical of common usage, with different combinations of
44--      available subprograms being used to accomplish similar
45--      unbounded wide string processing goals.
46--
47--
48-- CHANGE HISTORY:
49--      06 Dec 94   SAIC    ACVC 2.0
50--      08 Nov 95   SAIC    Corrected accessibility level and type
51--                          visibility problems for ACVC 2.0.1.
52--
53--!
54
55with Ada.Characters.Handling;
56with Ada.Strings;
57
58package CXA40230 is
59
60   -- The following two functions are used to translate character and string
61   -- values to non-character "Wide" values.  They will be applied to all the
62   -- Wide_Bounded subprogram character and string parameters to simulate the
63   -- use of Wide_Characters and Wide_Strings in actual practice.
64   -- Note: These functions do not actually return "equivalent" wide
65   --       characters to their character inputs, just "non-character"
66   --       wide characters.
67
68   function Equiv (Ch : Character) return Wide_Character;
69
70   function Equiv (Str : String) return Wide_String;
71
72   -- Functions and access-to-subprogram object used to supply mapping
73   -- capability to the appropriate versions of Translate.
74
75   function AB_to_US_Mapping_Function (From : Wide_Character)
76     return Wide_Character;
77
78   function AB_to_Blank_Mapping_Function (From : Wide_Character)
79     return Wide_Character;
80
81end CXA40230;
82
83
84package body CXA40230 is
85
86   function Equiv (Ch : Character) return Wide_Character is
87      C : Character := Ch;
88   begin
89      if Ch = ' ' then
90         return Ada.Characters.Handling.To_Wide_Character(C);
91      else
92         return Wide_Character'Val(Character'Pos(Ch) +
93                Character'Pos(Character'Last) + 1);
94      end if;
95   end Equiv;
96
97
98   function Equiv (Str : String) return Wide_String is
99      WS : Wide_String(Str'First..Str'Last);
100   begin
101      for i in Str'First..Str'Last loop
102         WS(i) := Equiv(Str(i));
103      end loop;
104      return WS;
105   end Equiv;
106
107
108   function AB_to_US_Mapping_Function (From : Wide_Character)
109     return Wide_Character is
110      UnderScore : constant Wide_Character := Equiv('_');
111   begin
112      if From = Equiv('a')  or  From = Equiv('b')  then
113         return UnderScore;
114      else
115         return From;
116      end if;
117   end AB_to_US_Mapping_Function;
118
119
120   function AB_to_Blank_Mapping_Function (From : Wide_Character)
121     return Wide_Character is
122   begin
123      if From = Equiv('a')  or  From = Equiv('b') then
124         return Ada.Strings.Wide_Space;
125      else
126         return From;
127      end if;
128   end AB_to_Blank_Mapping_Function;
129
130end CXA40230;
131
132
133with CXA40230;
134with Report;
135with Ada.Characters.Handling;
136with Ada.Strings.Wide_Maps;
137with Ada.Strings.Wide_Unbounded;
138
139procedure CXA4023 is
140begin
141
142   Report.Test ("CXA4023", "Check that the subprograms defined in "    &
143                           "package Ada.Strings.Wide_Unbounded are "   &
144                           "available, and that they produce correct " &
145                           "results");
146
147   Test_Block:
148   declare
149
150      use CXA40230;
151
152      package ASW renames Ada.Strings.Wide_Unbounded;
153      use Ada.Strings;
154      use type Wide_Maps.Wide_Character_Set;
155      use type ASW.Unbounded_Wide_String;
156
157      Test_String   : ASW.Unbounded_Wide_String;
158      AtoE_Str      : ASW.Unbounded_Wide_String :=
159                        ASW.To_Unbounded_Wide_String(Equiv("abcde"));
160
161      Cad_String    : ASW.Unbounded_Wide_String :=
162                        ASW.To_Unbounded_Wide_String(Equiv("cad"));
163
164      Magic_String  : ASW.Unbounded_Wide_String :=
165                        ASW.To_Unbounded_Wide_String(Equiv("abracadabra"));
166
167      Incantation   : ASW.Unbounded_Wide_String := Magic_String;
168
169
170      A_Small_G : Wide_Character := Equiv('g');
171
172      ABCD_Set  : Wide_Maps.Wide_Character_Set :=
173                    Wide_Maps.To_Set(Equiv("abcd"));
174      B_Set     : Wide_Maps.Wide_Character_Set :=
175                    Wide_Maps.To_Set(Equiv('b'));
176      AB_Set    : Wide_Maps.Wide_Character_Set :=
177                    Wide_Maps."OR"(Wide_Maps.To_Set(Equiv('a')), B_Set);
178
179
180      AB_to_YZ_Map     : Wide_Maps.Wide_Character_Mapping :=
181                           Wide_Maps.To_Mapping(From => Equiv("ab"),
182                                                To   => Equiv("yz"));
183      Code_Map         : Wide_Maps.Wide_Character_Mapping :=
184                           Wide_Maps.To_Mapping(Equiv("abcd"), Equiv("wxyz"));
185      Reverse_Code_Map : Wide_Maps.Wide_Character_Mapping :=
186                           Wide_Maps.To_Mapping(Equiv("wxyz"), Equiv("abcd"));
187      Non_Existent_Map : Wide_Maps.Wide_Character_Mapping :=
188                           Wide_Maps.To_Mapping(Equiv("jkl"), Equiv("mno"));
189
190
191      Token_Start      : Positive;
192      Token_End        : Natural := 0;
193
194      Map_Ptr  : Wide_Maps.Wide_Character_Mapping_Function :=
195                   AB_to_US_Mapping_Function'Access;
196
197
198   begin
199
200      -- Find_Token
201
202      ASW.Find_Token(Magic_String,      -- Find location of first "ab" equiv.
203                     AB_Set,            -- Should be (1..2).
204                     Ada.Strings.Inside,
205                     Token_Start,
206                     Token_End);
207
208      if Natural(Token_Start) /= ASW.To_Wide_String(Magic_String)'First  or
209         Token_End            /= ASW.Index(Magic_String, B_Set)          or
210         Token_End            /= 2
211      then
212         Report.Failed("Incorrect result from Procedure Find_Token - 1");
213      end if;
214
215
216      ASW.Find_Token(Source => Magic_String, -- Find location of char 'r'equiv
217                     Set    => ABCD_Set,     -- in wide str, should be (3..3)
218                     Test   => Ada.Strings.Outside,
219                     First  => Token_Start,
220                     Last   => Token_End);
221
222      if Natural(Token_Start) /= 3  or  Token_End /= 3 then
223         Report.Failed("Incorrect result from Procedure Find_Token - 2");
224      end if;
225
226
227      ASW.Find_Token(Magic_String,                -- No 'g' "equivalent in
228                     Wide_Maps.To_Set(A_Small_G), -- the wide str, so the
229                     Ada.Strings.Inside,          -- result params should be
230                     First => Token_Start,        -- First = Source'First and
231                     Last  => Token_End);         -- Last = 0.
232
233
234      if Token_Start /= ASW.To_Wide_String(Magic_String)'First  or
235         Token_End   /= 0
236      then
237         Report.Failed("Incorrect result from Procedure Find_Token - 3");
238      end if;
239
240
241      ASW.Find_Token(ASW.To_Unbounded_Wide_String(Equiv("abpqpqrttrcpqr")),
242                     Wide_Maps.To_Set(Equiv("trpq")),
243                     Ada.Strings.Inside,
244                     Token_Start,
245                     Token_End);
246
247      if Token_Start /= 3 or
248         Token_End   /= 10
249      then
250         Report.Failed("Incorrect result from Procedure Find_Token - 4");
251      end if;
252
253      ASW.Find_Token(ASW.To_Unbounded_Wide_String(Equiv("abpqpqrttrcpqr")),
254                     Wide_Maps.To_Set(Equiv("abpq")),
255                     Ada.Strings.Outside,
256                     Token_Start,
257                     Token_End);
258
259      if Token_Start /= 7 or
260         Token_End   /= 11
261      then
262         Report.Failed("Incorrect result from Procedure Find_Token - 5");
263      end if;
264
265
266
267      -- Translate
268
269      -- Use a mapping ("abcd" -> "wxyz") to transform the contents of
270      -- the unbounded wide string.
271      -- Magic_String = "abracadabra"
272
273      Incantation := ASW.Translate(Magic_String, Code_Map);
274
275      if Incantation /=
276         ASW.To_Unbounded_Wide_String(Equiv("wxrwywzwxrw"))
277      then
278         Report.Failed("Incorrect result from Function Translate - 1");
279      end if;
280
281      -- (Note: See below for additional testing of Function Translate)
282
283      -- Use the inverse mapping of the one above to return the "translated"
284      -- unbounded wide string to its original form.
285
286      ASW.Translate(Incantation, Reverse_Code_Map);
287
288      -- The map contained in the following call to Translate contains three
289      -- elements, and these elements are not found in the unbounded wide
290      -- string, so this call to Translate should have no effect on it.
291
292      if Incantation /= ASW.Translate(Magic_String, Non_Existent_Map) then
293         Report.Failed("Incorrect result from Procedure Translate - 1");
294      end if;
295
296      -- Partial mapping of source.
297
298      Test_String := ASW.To_Unbounded_Wide_String(Equiv("abcdeabcab"));
299
300      ASW.Translate(Source => Test_String, Mapping => AB_to_YZ_Map);
301
302      if Test_String /= ASW.To_Unbounded_Wide_String(Equiv("yzcdeyzcyz")) then
303         Report.Failed("Incorrect result from Procedure Translate - 2");
304      end if;
305
306      -- Total mapping of source.
307
308      Test_String := ASW.To_Unbounded_Wide_String(Equiv("abbaaababb"));
309
310      ASW.Translate(Source => Test_String, Mapping => AB_to_YZ_Map);
311
312      if Test_String /= ASW.To_Unbounded_Wide_String(Equiv("yzzyyyzyzz")) then
313         Report.Failed("Incorrect result from Procedure Translate - 3");
314      end if;
315
316      -- No mapping of source.
317
318      Test_String := ASW.To_Unbounded_Wide_String(Equiv("xyzsypcc"));
319
320      ASW.Translate(Source => Test_String, Mapping => AB_to_YZ_Map);
321
322      if Test_String /= ASW.To_Unbounded_Wide_String(Equiv("xyzsypcc")) then
323         Report.Failed("Incorrect result from Procedure Translate - 4");
324      end if;
325
326      -- Map > 2 characters, partial mapping.
327
328      Test_String := ASW.To_Unbounded_Wide_String(Equiv("opabcdelmn"));
329
330      ASW.Translate(Test_String,
331                    Wide_Maps.To_Mapping(Equiv("abcde"), Equiv("lmnop")));
332
333      if Test_String /= ASW.To_Unbounded_Wide_String(Equiv("oplmnoplmn")) then
334         Report.Failed("Incorrect result from Procedure Translate - 5");
335      end if;
336
337
338
339      -- Various degrees of mapping of source (full, partial, none) used
340      -- with Function Translate.
341
342      if ASW.Translate(
343               ASW.To_Unbounded_Wide_String(Equiv("abcdeabcabbbaaacaa")),
344                       AB_to_YZ_Map)                               /=
345         ASW.To_Unbounded_Wide_String(Equiv("yzcdeyzcyzzzyyycyy"))   or
346
347         ASW.Translate(
348               ASW.To_Unbounded_Wide_String(Equiv("abbaaababbaaaaba")),
349                       AB_to_YZ_Map)                               /=
350         ASW.To_Unbounded_Wide_String(Equiv("yzzyyyzyzzyyyyzy"))     or
351
352         ASW.Translate(ASW.To_Unbounded_Wide_String(Equiv("cABcABBAc")),
353                       Mapping => AB_to_YZ_Map)                    /=
354         ASW.To_Unbounded_Wide_String(Equiv("cABcABBAc"))            or
355
356         ASW.Translate(ASW.To_Unbounded_Wide_String("opabcdelmnddeaccabec"),
357                       Wide_Maps.To_Mapping("abcde", "lmnop"))     /=
358         ASW.To_Unbounded_Wide_String("oplmnoplmnooplnnlmpn")
359      then
360         Report.Failed("Incorrect result from Function Translate - 2");
361      end if;
362
363
364
365      -- Procedure Translate using access-to-subprogram mapping.
366      -- Partial mapping of source.
367
368      Map_Ptr := AB_to_Blank_Mapping_Function'Access;
369
370      Test_String := ASW.To_Unbounded_Wide_String(Equiv("abABaABbaBAbba"));
371
372      ASW.Translate(Source  => Test_String, -- change equivalent of 'a' and
373                    Mapping => Map_Ptr);    -- 'b' to ' '
374
375      if Test_String /=
376         ASW.To_Unbounded_Wide_String(Equiv("  AB AB  BA   "))
377      then
378         Report.Failed
379           ("Incorrect result from Proc Translate, w/ access value map - 1");
380      end if;
381
382      -- Total mapping of source to blanks.
383
384      Test_String := ASW.To_Unbounded_Wide_String(Equiv("abbbab"));
385
386      ASW.Translate(Source  => Test_String,
387                    Mapping => Map_Ptr);
388
389      if Test_String /=
390         ASW.To_Unbounded_Wide_String(Equiv("      "))
391      then
392         Report.Failed
393           ("Incorrect result from Proc Translate, w/ access value map - 2");
394      end if;
395
396      -- No mapping of source.
397
398      Map_Ptr := AB_to_US_Mapping_Function'Access;
399
400      Test_String := ASW.To_Unbounded_Wide_String(Equiv("xyzsypcc"));
401
402      ASW.Translate(Source  => Test_String,
403                    Mapping => Map_Ptr);
404
405      if Test_String /=
406         ASW.To_Unbounded_Wide_String(Equiv("xyzsypcc"))   -- no change
407      then
408         Report.Failed
409           ("Incorrect result from Proc Translate, w/ access value map - 3");
410      end if;
411
412
413      -- Function Translate using access-to-subprogram mapping value.
414
415      Map_Ptr  := AB_to_Blank_Mapping_Function'Access;
416
417      Test_String := ASW.To_Unbounded_Wide_String(Equiv("abAbBBAabbacD"));
418
419      if ASW.Translate(ASW.Translate(Test_String, Map_Ptr), Map_Ptr)  /=
420         ASW.To_Unbounded_Wide_String(Equiv("  A BBA    cD"))
421      then
422         Report.Failed
423           ("Incorrect result from Function Translate, access value map - 1");
424      end if;
425
426      if ASW.Translate(Source  => ASW.To_Unbounded_Wide_String(Equiv("a")),
427                       Mapping => Map_Ptr)                            /=
428         ASW.To_Unbounded_Wide_String(Equiv(" "))                       or
429         ASW.Translate(ASW.To_Unbounded_Wide_String
430                         (Equiv(" aa Aa A AAaaa a   aA")),
431                       Map_Ptr)                                       /=
432         ASW.To_Unbounded_Wide_String(Equiv("    A  A AA         A"))   or
433         ASW.Translate(Source  => ASW.To_Unbounded_Wide_String(Equiv("a ")),
434                       Mapping => Map_Ptr)                            /=
435         ASW.To_Unbounded_Wide_String(Equiv("  "))                      or
436         ASW.Translate(Source  => ASW.To_Unbounded_Wide_String(Equiv("xyz")),
437                       Mapping => Map_Ptr)                            /=
438         ASW.To_Unbounded_Wide_String(Equiv("xyz"))
439      then
440         Report.Failed
441           ("Incorrect result from Function Translate, access value map - 2");
442      end if;
443
444
445
446      -- Trim
447
448      Trim_Block:
449      declare
450
451         XYZ_Set     : Wide_Maps.Wide_Character_Set :=
452                         Wide_Maps.To_Set(Equiv("xyz"));
453         PQR_Set     : Wide_Maps.Wide_Character_Set :=
454                         Wide_Maps.To_Set(Equiv("pqr"));
455
456         Pad         : constant ASW.Unbounded_Wide_String :=
457                                 ASW.To_Unbounded_Wide_String(Equiv("Pad"));
458
459         The_New_Ada : constant ASW.Unbounded_Wide_String :=
460                                 ASW.To_Unbounded_Wide_String(Equiv("Ada9X"));
461
462         Space_Array : array (1..4) of ASW.Unbounded_Wide_String :=
463                         (ASW.To_Unbounded_Wide_String(Equiv("  Pad    ")),
464                          ASW.To_Unbounded_Wide_String(Equiv("Pad   ")),
465                          ASW.To_Unbounded_Wide_String(Equiv("     Pad")),
466                          Pad);
467
468         String_Array : array (1..5) of ASW.Unbounded_Wide_String :=
469                        (ASW.To_Unbounded_Wide_String(Equiv("xyzxAda9Xpqr")),
470                         ASW.To_Unbounded_Wide_String(Equiv("Ada9Xqqrp")),
471                         ASW.To_Unbounded_Wide_String(Equiv("zxyxAda9Xqpqr")),
472                         ASW.To_Unbounded_Wide_String(Equiv("xxxyAda9X")),
473                         The_New_Ada);
474
475      begin
476
477         -- Examine the version of Trim that removes blanks from
478         -- the left and/or right of a wide string.
479
480         for i in 1..4 loop
481            if ASW.Trim(Space_Array(i), Ada.Strings.Both) /= Pad then
482               Report.Failed("Incorrect result from Trim for spaces - " &
483                             Integer'Image(i));
484            end if;
485         end loop;
486
487         -- Examine the version of Trim that removes set characters from
488         -- the left and right of a wide string.
489
490         for i in 1..5 loop
491            if ASW.Trim(String_Array(i),
492                        Left   => XYZ_Set,
493                        Right  => PQR_Set) /= The_New_Ada then
494               Report.Failed
495                 ("Incorrect result from Trim for set characters - " &
496                  Integer'Image(i));
497            end if;
498         end loop;
499
500         -- No trimming.
501
502         if ASW.Trim(
503              ASW.To_Unbounded_Wide_String(Equiv("prqqprAda9Xyzzxyzzyz")),
504                     XYZ_Set,
505                     PQR_Set)  /=
506            ASW.To_Unbounded_Wide_String(Equiv("prqqprAda9Xyzzxyzzyz"))
507         then
508            Report.Failed
509              ("Incorrect result from Trim for set, no trimming");
510         end if;
511
512      end Trim_Block;
513
514
515
516      -- Delete
517
518      -- Use the Delete function to remove the first four and last four
519      -- characters from the wide string.
520
521      if ASW.Delete(Source  => ASW.Delete(Magic_String,
522                                          8,
523                                          ASW.Length(Magic_String)),
524                    From    => ASW.To_Wide_String(Magic_String)'First,
525                    Through => 4)   /=
526         Cad_String
527      then
528         Report.Failed("Incorrect results from Function Delete");
529      end if;
530
531
532
533      -- Constructors ("*")
534
535      Constructor_Block:
536      declare
537
538         SOS      : ASW.Unbounded_Wide_String;
539
540         Dot      : constant ASW.Unbounded_Wide_String :=
541                               ASW.To_Unbounded_Wide_String(Equiv("Dot_"));
542         Dash     : constant Wide_String := Equiv("Dash_");
543
544         Distress : ASW.Unbounded_Wide_String :=
545                      ASW."&"(ASW.To_Unbounded_Wide_String
546                                (Equiv("Dot_Dot_Dot_")),
547                              ASW."&"(ASW.To_Unbounded_Wide_String
548                                        (Equiv("Dash_Dash_Dash_")),
549                                      ASW.To_Unbounded_Wide_String
550                                        (Equiv("Dot_Dot_Dot"))));
551
552         Repeat        : constant Natural        := 3;
553         Separator     : constant Wide_Character := Equiv('_');
554
555         Separator_Set : Wide_Maps.Wide_Character_Set :=
556                           Wide_Maps.To_Set(Separator);
557
558      begin
559
560         -- Use the following constructor forms to construct the wide string
561         -- "Dot_Dot_Dot_Dash_Dash_Dash_Dot_Dot_Dot".  Note that the
562         -- trailing underscore in the wide string is removed in the call to
563         -- Trim in the If statement condition.
564
565         SOS := ASW."*"(Repeat, Dot);                   -- "*"(#, W Unb Str)
566
567         SOS := ASW."&"(SOS,
568                        ASW."&"(ASW."*"(Repeat, Dash),  -- "*"(#, W Str)
569                                ASW."*"(Repeat, Dot))); -- "*"(#, W Unb Str)
570
571         if ASW.Trim(SOS, Wide_Maps.Null_Set, Separator_Set) /= Distress then
572            Report.Failed("Incorrect results from Function ""*""");
573         end if;
574
575      end Constructor_Block;
576
577
578   exception
579      when others => Report.Failed ("Exception raised in Test_Block");
580   end Test_Block;
581
582
583   Report.Result;
584
585end CXA4023;
586