Update concepts branch to revision 131834
[official-gcc.git] / gcc / ada / g-decstr.adb
blobe7c8a2612f4048d03cd3c65f226f050f9b6f2d5b
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME COMPONENTS --
4 -- --
5 -- G N A T . D E C O D E _ S T R I N G --
6 -- --
7 -- S p e c --
8 -- --
9 -- Copyright (C) 2007-2008, AdaCore --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
21 -- --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
28 -- --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 -- --
32 ------------------------------------------------------------------------------
34 -- This package provides a utility routine for converting from an encoded
35 -- string to a corresponding Wide_String or Wide_Wide_String value.
37 with Interfaces; use Interfaces;
39 with System.WCh_Cnv; use System.WCh_Cnv;
40 with System.WCh_Con; use System.WCh_Con;
42 package body GNAT.Decode_String is
44 -----------------------
45 -- Local Subprograms --
46 -----------------------
48 procedure Bad;
49 pragma No_Return (Bad);
50 -- Raise error for bad encoding
52 procedure Past_End;
53 pragma No_Return (Past_End);
54 -- Raise error for off end of string
56 ---------
57 -- Bad --
58 ---------
60 procedure Bad is
61 begin
62 raise Constraint_Error with
63 "bad encoding or character out of range";
64 end Bad;
66 ---------------------------
67 -- Decode_Wide_Character --
68 ---------------------------
70 procedure Decode_Wide_Character
71 (Input : String;
72 Ptr : in out Natural;
73 Result : out Wide_Character)
75 Char : Wide_Wide_Character;
76 begin
77 Decode_Wide_Wide_Character (Input, Ptr, Char);
79 if Wide_Wide_Character'Pos (Char) > 16#FFFF# then
80 Bad;
81 else
82 Result := Wide_Character'Val (Wide_Wide_Character'Pos (Char));
83 end if;
84 end Decode_Wide_Character;
86 ------------------------
87 -- Decode_Wide_String --
88 ------------------------
90 function Decode_Wide_String (S : String) return Wide_String is
91 Result : Wide_String (1 .. S'Length);
92 Length : Natural;
93 begin
94 Decode_Wide_String (S, Result, Length);
95 return Result (1 .. Length);
96 end Decode_Wide_String;
98 procedure Decode_Wide_String
99 (S : String;
100 Result : out Wide_String;
101 Length : out Natural)
103 Ptr : Natural;
105 begin
106 Ptr := S'First;
107 Length := 0;
108 while Ptr <= S'Last loop
109 if Length >= Result'Last then
110 Past_End;
111 end if;
113 Length := Length + 1;
114 Decode_Wide_Character (S, Ptr, Result (Length));
115 end loop;
116 end Decode_Wide_String;
118 --------------------------------
119 -- Decode_Wide_Wide_Character --
120 --------------------------------
122 procedure Decode_Wide_Wide_Character
123 (Input : String;
124 Ptr : in out Natural;
125 Result : out Wide_Wide_Character)
127 C : Character;
129 function In_Char return Character;
130 pragma Inline (In_Char);
131 -- Function to get one input character
133 -------------
134 -- In_Char --
135 -------------
137 function In_Char return Character is
138 begin
139 if Ptr <= Input'Last then
140 Ptr := Ptr + 1;
141 return Input (Ptr - 1);
142 else
143 Past_End;
144 end if;
145 end In_Char;
147 -- Start of processing for Decode_Wide_Wide_Character
149 begin
150 C := In_Char;
152 -- Special fast processing for UTF-8 case
154 if Encoding_Method = WCEM_UTF8 then
155 UTF8 : declare
156 U : Unsigned_32;
157 W : Unsigned_32;
159 procedure Get_UTF_Byte;
160 pragma Inline (Get_UTF_Byte);
161 -- Used to interpret 2#10xxxxxx# continuation byte in UTF-8 mode.
162 -- Reads a byte, and raises CE if the first two bits are not 10.
163 -- Otherwise shifts W 6 bits left and or's in the 6 xxxxxx bits.
165 ------------------
166 -- Get_UTF_Byte --
167 ------------------
169 procedure Get_UTF_Byte is
170 begin
171 U := Unsigned_32 (Character'Pos (In_Char));
173 if (U and 2#11000000#) /= 2#10_000000# then
174 Bad;
175 end if;
177 W := Shift_Left (W, 6) or (U and 2#00111111#);
178 end Get_UTF_Byte;
180 -- Start of processing for UTF8 case
182 begin
183 -- Note: for details of UTF8 encoding see RFC 3629
185 U := Unsigned_32 (Character'Pos (C));
187 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
189 if (U and 2#10000000#) = 2#00000000# then
190 Result := Wide_Wide_Character'Val (Character'Pos (C));
192 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
194 elsif (U and 2#11100000#) = 2#110_00000# then
195 W := U and 2#00011111#;
196 Get_UTF_Byte;
197 Result := Wide_Wide_Character'Val (W);
199 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
201 elsif (U and 2#11110000#) = 2#1110_0000# then
202 W := U and 2#00001111#;
203 Get_UTF_Byte;
204 Get_UTF_Byte;
205 Result := Wide_Wide_Character'Val (W);
207 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
209 elsif (U and 2#11111000#) = 2#11110_000# then
210 W := U and 2#00000111#;
212 for K in 1 .. 3 loop
213 Get_UTF_Byte;
214 end loop;
216 Result := Wide_Wide_Character'Val (W);
218 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx 10xxxxxx
219 -- 10xxxxxx 10xxxxxx
221 elsif (U and 2#11111100#) = 2#111110_00# then
222 W := U and 2#00000011#;
224 for K in 1 .. 4 loop
225 Get_UTF_Byte;
226 end loop;
228 Result := Wide_Wide_Character'Val (W);
230 -- All other cases are invalid, note that this includes:
232 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx 10xxxxxx
233 -- 10xxxxxx 10xxxxxx 10xxxxxx
235 -- since Wide_Wide_Character does not include code values
236 -- greater than 16#03FF_FFFF#.
238 else
239 Bad;
240 end if;
241 end UTF8;
243 -- All encoding functions other than UTF-8
245 else
246 Non_UTF8 : declare
247 function Char_Sequence_To_UTF is
248 new Char_Sequence_To_UTF_32 (In_Char);
250 begin
251 -- For brackets, must test for specific case of [ not followed by
252 -- quotation, where we must not call Char_Sequence_To_UTF, but
253 -- instead just return the bracket unchanged.
255 if Encoding_Method = WCEM_Brackets
256 and then C = '['
257 and then (Ptr > Input'Last or else Input (Ptr) /= '"')
258 then
259 Result := '[';
261 -- All other cases including [" with Brackets
263 else
264 Result :=
265 Wide_Wide_Character'Val
266 (Char_Sequence_To_UTF (C, Encoding_Method));
267 end if;
268 end Non_UTF8;
269 end if;
270 end Decode_Wide_Wide_Character;
272 -----------------------------
273 -- Decode_Wide_Wide_String --
274 -----------------------------
276 function Decode_Wide_Wide_String (S : String) return Wide_Wide_String is
277 Result : Wide_Wide_String (1 .. S'Length);
278 Length : Natural;
279 begin
280 Decode_Wide_Wide_String (S, Result, Length);
281 return Result (1 .. Length);
282 end Decode_Wide_Wide_String;
284 procedure Decode_Wide_Wide_String
285 (S : String;
286 Result : out Wide_Wide_String;
287 Length : out Natural)
289 Ptr : Natural;
291 begin
292 Ptr := S'First;
293 Length := 0;
294 while Ptr <= S'Last loop
295 if Length >= Result'Last then
296 Past_End;
297 end if;
299 Length := Length + 1;
300 Decode_Wide_Wide_Character (S, Ptr, Result (Length));
301 end loop;
302 end Decode_Wide_Wide_String;
304 -------------------------
305 -- Next_Wide_Character --
306 -------------------------
308 procedure Next_Wide_Character (Input : String; Ptr : in out Natural) is
309 begin
310 if Ptr < Input'First then
311 Past_End;
312 end if;
314 -- Special efficient encoding for UTF-8 case
316 if Encoding_Method = WCEM_UTF8 then
317 UTF8 : declare
318 U : Unsigned_32;
320 procedure Getc;
321 pragma Inline (Getc);
322 -- Gets the character at Input (Ptr) and returns code in U as
323 -- Unsigned_32 value. On return Ptr is bumped past the character.
325 procedure Skip_UTF_Byte;
326 pragma Inline (Skip_UTF_Byte);
327 -- Skips past one encoded byte which must be 2#10xxxxxx#
329 ----------
330 -- Getc --
331 ----------
333 procedure Getc is
334 begin
335 if Ptr > Input'Last then
336 Past_End;
337 else
338 U := Unsigned_32 (Character'Pos (Input (Ptr)));
339 Ptr := Ptr + 1;
340 end if;
341 end Getc;
343 -------------------
344 -- Skip_UTF_Byte --
345 -------------------
347 procedure Skip_UTF_Byte is
348 begin
349 Getc;
351 if (U and 2#11000000#) /= 2#10_000000# then
352 Bad;
353 end if;
354 end Skip_UTF_Byte;
356 -- Start of processing for UTF-8 case
358 begin
359 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
361 Getc;
363 if (U and 2#10000000#) = 2#00000000# then
364 return;
366 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
368 elsif (U and 2#11100000#) = 2#110_00000# then
369 Skip_UTF_Byte;
371 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
373 elsif (U and 2#11110000#) = 2#1110_0000# then
374 Skip_UTF_Byte;
375 Skip_UTF_Byte;
377 -- Any other code is invalid, note that this includes:
379 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
381 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx 10xxxxxx
382 -- 10xxxxxx 10xxxxxx
384 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx 10xxxxxx
385 -- 10xxxxxx 10xxxxxx 10xxxxxx
387 -- since Wide_Character does not allow codes > 16#FFFF#
389 else
390 Bad;
391 end if;
392 end UTF8;
394 -- Non-UTF-8 case
396 else
397 declare
398 Discard : Wide_Character;
399 begin
400 Decode_Wide_Character (Input, Ptr, Discard);
401 end;
402 end if;
403 end Next_Wide_Character;
405 ------------------------------
406 -- Next_Wide_Wide_Character --
407 ------------------------------
409 procedure Next_Wide_Wide_Character (Input : String; Ptr : in out Natural) is
410 begin
411 -- Special efficient encoding for UTF-8 case
413 if Encoding_Method = WCEM_UTF8 then
414 UTF8 : declare
415 U : Unsigned_32;
417 procedure Getc;
418 pragma Inline (Getc);
419 -- Gets the character at Input (Ptr) and returns code in U as
420 -- Unsigned_32 value. On return Ptr is bumped past the character.
422 procedure Skip_UTF_Byte;
423 pragma Inline (Skip_UTF_Byte);
424 -- Skips past one encoded byte which must be 2#10xxxxxx#
426 ----------
427 -- Getc --
428 ----------
430 procedure Getc is
431 begin
432 if Ptr > Input'Last then
433 Past_End;
434 else
435 U := Unsigned_32 (Character'Pos (Input (Ptr)));
436 Ptr := Ptr + 1;
437 end if;
438 end Getc;
440 -------------------
441 -- Skip_UTF_Byte --
442 -------------------
444 procedure Skip_UTF_Byte is
445 begin
446 Getc;
448 if (U and 2#11000000#) /= 2#10_000000# then
449 Bad;
450 end if;
451 end Skip_UTF_Byte;
453 -- Start of processing for UTF-8 case
455 begin
456 if Ptr < Input'First then
457 Past_End;
458 end if;
460 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
462 Getc;
464 if (U and 2#10000000#) = 2#00000000# then
465 null;
467 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
469 elsif (U and 2#11100000#) = 2#110_00000# then
470 Skip_UTF_Byte;
472 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
474 elsif (U and 2#11110000#) = 2#1110_0000# then
475 Skip_UTF_Byte;
476 Skip_UTF_Byte;
478 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
480 elsif (U and 2#11111000#) = 2#11110_000# then
481 for K in 1 .. 3 loop
482 Skip_UTF_Byte;
483 end loop;
485 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx 10xxxxxx
486 -- 10xxxxxx 10xxxxxx
488 elsif (U and 2#11111100#) = 2#111110_00# then
489 for K in 1 .. 4 loop
490 Skip_UTF_Byte;
491 end loop;
493 -- Any other code is invalid, note that this includes:
495 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx 10xxxxxx
496 -- 10xxxxxx 10xxxxxx 10xxxxxx
498 -- since Wide_Wide_Character does not allow codes > 16#03FF_FFFF#
500 else
501 Bad;
502 end if;
503 end UTF8;
505 -- Non-UTF-8 case
507 else
508 declare
509 Discard : Wide_Wide_Character;
510 begin
511 Decode_Wide_Wide_Character (Input, Ptr, Discard);
512 end;
513 end if;
514 end Next_Wide_Wide_Character;
516 --------------
517 -- Past_End --
518 --------------
520 procedure Past_End is
521 begin
522 raise Constraint_Error with "past end of string";
523 end Past_End;
525 -------------------------
526 -- Prev_Wide_Character --
527 -------------------------
529 procedure Prev_Wide_Character (Input : String; Ptr : in out Natural) is
530 begin
531 if Ptr > Input'Last + 1 then
532 Past_End;
533 end if;
535 -- Special efficient encoding for UTF-8 case
537 if Encoding_Method = WCEM_UTF8 then
538 UTF8 : declare
539 U : Unsigned_32;
541 procedure Getc;
542 pragma Inline (Getc);
543 -- Gets the character at Input (Ptr - 1) and returns code in U as
544 -- Unsigned_32 value. On return Ptr is decremented by one.
546 procedure Skip_UTF_Byte;
547 pragma Inline (Skip_UTF_Byte);
548 -- Checks that U is 2#10xxxxxx# and then calls Get
550 ----------
551 -- Getc --
552 ----------
554 procedure Getc is
555 begin
556 if Ptr <= Input'First then
557 Past_End;
558 else
559 Ptr := Ptr - 1;
560 U := Unsigned_32 (Character'Pos (Input (Ptr)));
561 end if;
562 end Getc;
564 -------------------
565 -- Skip_UTF_Byte --
566 -------------------
568 procedure Skip_UTF_Byte is
569 begin
570 if (U and 2#11000000#) = 2#10_000000# then
571 Getc;
572 else
573 Bad;
574 end if;
575 end Skip_UTF_Byte;
577 -- Start of processing for UTF-8 case
579 begin
580 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
582 Getc;
584 if (U and 2#10000000#) = 2#00000000# then
585 return;
587 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
589 else
590 Skip_UTF_Byte;
592 if (U and 2#11100000#) = 2#110_00000# then
593 return;
595 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
597 else
598 Skip_UTF_Byte;
600 if (U and 2#11110000#) = 2#1110_0000# then
601 return;
603 -- Any other code is invalid, note that this includes:
605 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx
606 -- 10xxxxxx
608 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx
609 -- 10xxxxxx 10xxxxxx
610 -- 10xxxxxx
612 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx
613 -- 10xxxxxx 10xxxxxx
614 -- 10xxxxxx 10xxxxxx
616 -- since Wide_Character does not allow codes > 16#FFFF#
618 else
619 Bad;
620 end if;
621 end if;
622 end if;
623 end UTF8;
625 -- Special efficient encoding for brackets case
627 elsif Encoding_Method = WCEM_Brackets then
628 Brackets : declare
629 P : Natural;
630 S : Natural;
632 begin
633 -- See if we have "] at end positions
635 if Ptr > Input'First + 1
636 and then Input (Ptr - 1) = ']'
637 and then Input (Ptr - 2) = '"'
638 then
639 P := Ptr - 2;
641 -- Loop back looking for [" at start
643 while P >= Ptr - 10 loop
644 if P <= Input'First + 1 then
645 Bad;
647 elsif Input (P - 1) = '"'
648 and then Input (P - 2) = '['
649 then
650 -- Found ["..."], scan forward to check it
652 S := P - 2;
653 P := S;
654 Next_Wide_Character (Input, P);
656 -- OK if at original pointer, else error
658 if P = Ptr then
659 Ptr := S;
660 return;
661 else
662 Bad;
663 end if;
664 end if;
666 P := P - 1;
667 end loop;
669 -- Falling through loop means more than 8 chars between the
670 -- enclosing brackets (or simply a missing left bracket)
672 Bad;
674 -- Here if no bracket sequence present
676 else
677 if Ptr = Input'First then
678 Past_End;
679 else
680 Ptr := Ptr - 1;
681 end if;
682 end if;
683 end Brackets;
685 -- Non-UTF-8/Brackets. These are the inefficient cases where we have to
686 -- go to the start of the string and skip forwards till Ptr matches.
688 else
689 Non_UTF_Brackets : declare
690 Discard : Wide_Character;
691 PtrS : Natural;
692 PtrP : Natural;
694 begin
695 PtrS := Input'First;
697 if Ptr <= PtrS then
698 Past_End;
699 end if;
701 loop
702 PtrP := PtrS;
703 Decode_Wide_Character (Input, PtrS, Discard);
705 if PtrS = Ptr then
706 Ptr := PtrP;
707 return;
709 elsif PtrS > Ptr then
710 Bad;
711 end if;
712 end loop;
714 exception
715 when Constraint_Error =>
716 Bad;
717 end Non_UTF_Brackets;
718 end if;
719 end Prev_Wide_Character;
721 ------------------------------
722 -- Prev_Wide_Wide_Character --
723 ------------------------------
725 procedure Prev_Wide_Wide_Character (Input : String; Ptr : in out Natural) is
726 begin
727 if Ptr > Input'Last + 1 then
728 Past_End;
729 end if;
731 -- Special efficient encoding for UTF-8 case
733 if Encoding_Method = WCEM_UTF8 then
734 UTF8 : declare
735 U : Unsigned_32;
737 procedure Getc;
738 pragma Inline (Getc);
739 -- Gets the character at Input (Ptr - 1) and returns code in U as
740 -- Unsigned_32 value. On return Ptr is decremented by one.
742 procedure Skip_UTF_Byte;
743 pragma Inline (Skip_UTF_Byte);
744 -- Checks that U is 2#10xxxxxx# and then calls Get
746 ----------
747 -- Getc --
748 ----------
750 procedure Getc is
751 begin
752 if Ptr <= Input'First then
753 Past_End;
754 else
755 Ptr := Ptr - 1;
756 U := Unsigned_32 (Character'Pos (Input (Ptr)));
757 end if;
758 end Getc;
760 -------------------
761 -- Skip_UTF_Byte --
762 -------------------
764 procedure Skip_UTF_Byte is
765 begin
766 if (U and 2#11000000#) = 2#10_000000# then
767 Getc;
768 else
769 Bad;
770 end if;
771 end Skip_UTF_Byte;
773 -- Start of processing for UTF-8 case
775 begin
776 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
778 Getc;
780 if (U and 2#10000000#) = 2#00000000# then
781 return;
783 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
785 else
786 Skip_UTF_Byte;
788 if (U and 2#11100000#) = 2#110_00000# then
789 return;
791 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
793 else
794 Skip_UTF_Byte;
796 if (U and 2#11110000#) = 2#1110_0000# then
797 return;
799 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx
800 -- 10xxxxxx
802 else
803 Skip_UTF_Byte;
805 if (U and 2#11111000#) = 2#11110_000# then
806 return;
808 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx
809 -- 10xxxxxx 10xxxxxx
810 -- 10xxxxxx
812 else
813 Skip_UTF_Byte;
815 if (U and 2#11111100#) = 2#111110_00# then
816 return;
818 -- Any other code is invalid, note that this includes:
820 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx
821 -- 10xxxxxx 10xxxxxx
822 -- 10xxxxxx 10xxxxxx
824 -- since Wide_Wide_Character does not allow codes
825 -- greater than 16#03FF_FFFF#
827 else
828 Bad;
829 end if;
830 end if;
831 end if;
832 end if;
833 end if;
834 end UTF8;
836 -- Special efficient encoding for brackets case
838 elsif Encoding_Method = WCEM_Brackets then
839 Brackets : declare
840 P : Natural;
841 S : Natural;
843 begin
844 -- See if we have "] at end positions
846 if Ptr > Input'First + 1
847 and then Input (Ptr - 1) = ']'
848 and then Input (Ptr - 2) = '"'
849 then
850 P := Ptr - 2;
852 -- Loop back looking for [" at start
854 while P >= Ptr - 10 loop
855 if P <= Input'First + 1 then
856 Bad;
858 elsif Input (P - 1) = '"'
859 and then Input (P - 2) = '['
860 then
861 -- Found ["..."], scan forward to check it
863 S := P - 2;
864 P := S;
865 Next_Wide_Wide_Character (Input, P);
867 -- OK if at original pointer, else error
869 if P = Ptr then
870 Ptr := S;
871 return;
872 else
873 Bad;
874 end if;
875 end if;
877 P := P - 1;
878 end loop;
880 -- Falling through loop means more than 8 chars between the
881 -- enclosing brackets (or simply a missing left bracket)
883 Bad;
885 -- Here if no bracket sequence present
887 else
888 if Ptr = Input'First then
889 Past_End;
890 else
891 Ptr := Ptr - 1;
892 end if;
893 end if;
894 end Brackets;
896 -- Non-UTF-8/Brackets. These are the inefficient cases where we have to
897 -- go to the start of the string and skip forwards till Ptr matches.
899 else
900 Non_UTF8_Brackets : declare
901 Discard : Wide_Wide_Character;
902 PtrS : Natural;
903 PtrP : Natural;
905 begin
906 PtrS := Input'First;
908 if Ptr <= PtrS then
909 Past_End;
910 end if;
912 loop
913 PtrP := PtrS;
914 Decode_Wide_Wide_Character (Input, PtrS, Discard);
916 if PtrS = Ptr then
917 Ptr := PtrP;
918 return;
920 elsif PtrS > Ptr then
921 Bad;
922 end if;
923 end loop;
925 exception
926 when Constraint_Error =>
927 Bad;
928 end Non_UTF8_Brackets;
929 end if;
930 end Prev_Wide_Wide_Character;
932 --------------------------
933 -- Validate_Wide_String --
934 --------------------------
936 function Validate_Wide_String (S : String) return Boolean is
937 Ptr : Natural;
939 begin
940 Ptr := S'First;
941 while Ptr <= S'Last loop
942 Next_Wide_Character (S, Ptr);
943 end loop;
945 return True;
947 exception
948 when Constraint_Error =>
949 return False;
950 end Validate_Wide_String;
952 -------------------------------
953 -- Validate_Wide_Wide_String --
954 -------------------------------
956 function Validate_Wide_Wide_String (S : String) return Boolean is
957 Ptr : Natural;
959 begin
960 Ptr := S'First;
961 while Ptr <= S'Last loop
962 Next_Wide_Wide_Character (S, Ptr);
963 end loop;
965 return True;
967 exception
968 when Constraint_Error =>
969 return False;
970 end Validate_Wide_Wide_String;
972 end GNAT.Decode_String;