Implement -mmemcpy-strategy= and -mmemset-strategy= options
[official-gcc.git] / gcc / ada / g-decstr.adb
bloba08584f22e368c4ca193cd6f21d92df958251efe
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-2010, 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 3, 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. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
32 -- This package provides a utility routine for converting from an encoded
33 -- string to a corresponding Wide_String or Wide_Wide_String value.
35 with Interfaces; use Interfaces;
37 with System.WCh_Cnv; use System.WCh_Cnv;
38 with System.WCh_Con; use System.WCh_Con;
40 package body GNAT.Decode_String is
42 -----------------------
43 -- Local Subprograms --
44 -----------------------
46 procedure Bad;
47 pragma No_Return (Bad);
48 -- Raise error for bad encoding
50 procedure Past_End;
51 pragma No_Return (Past_End);
52 -- Raise error for off end of string
54 ---------
55 -- Bad --
56 ---------
58 procedure Bad is
59 begin
60 raise Constraint_Error with
61 "bad encoding or character out of range";
62 end Bad;
64 ---------------------------
65 -- Decode_Wide_Character --
66 ---------------------------
68 procedure Decode_Wide_Character
69 (Input : String;
70 Ptr : in out Natural;
71 Result : out Wide_Character)
73 Char : Wide_Wide_Character;
74 begin
75 Decode_Wide_Wide_Character (Input, Ptr, Char);
77 if Wide_Wide_Character'Pos (Char) > 16#FFFF# then
78 Bad;
79 else
80 Result := Wide_Character'Val (Wide_Wide_Character'Pos (Char));
81 end if;
82 end Decode_Wide_Character;
84 ------------------------
85 -- Decode_Wide_String --
86 ------------------------
88 function Decode_Wide_String (S : String) return Wide_String is
89 Result : Wide_String (1 .. S'Length);
90 Length : Natural;
91 begin
92 Decode_Wide_String (S, Result, Length);
93 return Result (1 .. Length);
94 end Decode_Wide_String;
96 procedure Decode_Wide_String
97 (S : String;
98 Result : out Wide_String;
99 Length : out Natural)
101 Ptr : Natural;
103 begin
104 Ptr := S'First;
105 Length := 0;
106 while Ptr <= S'Last loop
107 if Length >= Result'Last then
108 Past_End;
109 end if;
111 Length := Length + 1;
112 Decode_Wide_Character (S, Ptr, Result (Length));
113 end loop;
114 end Decode_Wide_String;
116 --------------------------------
117 -- Decode_Wide_Wide_Character --
118 --------------------------------
120 procedure Decode_Wide_Wide_Character
121 (Input : String;
122 Ptr : in out Natural;
123 Result : out Wide_Wide_Character)
125 C : Character;
127 function In_Char return Character;
128 pragma Inline (In_Char);
129 -- Function to get one input character
131 -------------
132 -- In_Char --
133 -------------
135 function In_Char return Character is
136 begin
137 if Ptr <= Input'Last then
138 Ptr := Ptr + 1;
139 return Input (Ptr - 1);
140 else
141 Past_End;
142 end if;
143 end In_Char;
145 -- Start of processing for Decode_Wide_Wide_Character
147 begin
148 C := In_Char;
150 -- Special fast processing for UTF-8 case
152 if Encoding_Method = WCEM_UTF8 then
153 UTF8 : declare
154 U : Unsigned_32;
155 W : Unsigned_32;
157 procedure Get_UTF_Byte;
158 pragma Inline (Get_UTF_Byte);
159 -- Used to interpret 2#10xxxxxx# continuation byte in UTF-8 mode.
160 -- Reads a byte, and raises CE if the first two bits are not 10.
161 -- Otherwise shifts W 6 bits left and or's in the 6 xxxxxx bits.
163 ------------------
164 -- Get_UTF_Byte --
165 ------------------
167 procedure Get_UTF_Byte is
168 begin
169 U := Unsigned_32 (Character'Pos (In_Char));
171 if (U and 2#11000000#) /= 2#10_000000# then
172 Bad;
173 end if;
175 W := Shift_Left (W, 6) or (U and 2#00111111#);
176 end Get_UTF_Byte;
178 -- Start of processing for UTF8 case
180 begin
181 -- Note: for details of UTF8 encoding see RFC 3629
183 U := Unsigned_32 (Character'Pos (C));
185 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
187 if (U and 2#10000000#) = 2#00000000# then
188 Result := Wide_Wide_Character'Val (Character'Pos (C));
190 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
192 elsif (U and 2#11100000#) = 2#110_00000# then
193 W := U and 2#00011111#;
194 Get_UTF_Byte;
195 Result := Wide_Wide_Character'Val (W);
197 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
199 elsif (U and 2#11110000#) = 2#1110_0000# then
200 W := U and 2#00001111#;
201 Get_UTF_Byte;
202 Get_UTF_Byte;
203 Result := Wide_Wide_Character'Val (W);
205 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
207 elsif (U and 2#11111000#) = 2#11110_000# then
208 W := U and 2#00000111#;
210 for K in 1 .. 3 loop
211 Get_UTF_Byte;
212 end loop;
214 Result := Wide_Wide_Character'Val (W);
216 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx 10xxxxxx
217 -- 10xxxxxx 10xxxxxx
219 elsif (U and 2#11111100#) = 2#111110_00# then
220 W := U and 2#00000011#;
222 for K in 1 .. 4 loop
223 Get_UTF_Byte;
224 end loop;
226 Result := Wide_Wide_Character'Val (W);
228 -- All other cases are invalid, note that this includes:
230 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx 10xxxxxx
231 -- 10xxxxxx 10xxxxxx 10xxxxxx
233 -- since Wide_Wide_Character does not include code values
234 -- greater than 16#03FF_FFFF#.
236 else
237 Bad;
238 end if;
239 end UTF8;
241 -- All encoding functions other than UTF-8
243 else
244 Non_UTF8 : declare
245 function Char_Sequence_To_UTF is
246 new Char_Sequence_To_UTF_32 (In_Char);
248 begin
249 -- For brackets, must test for specific case of [ not followed by
250 -- quotation, where we must not call Char_Sequence_To_UTF, but
251 -- instead just return the bracket unchanged.
253 if Encoding_Method = WCEM_Brackets
254 and then C = '['
255 and then (Ptr > Input'Last or else Input (Ptr) /= '"')
256 then
257 Result := '[';
259 -- All other cases including [" with Brackets
261 else
262 Result :=
263 Wide_Wide_Character'Val
264 (Char_Sequence_To_UTF (C, Encoding_Method));
265 end if;
266 end Non_UTF8;
267 end if;
268 end Decode_Wide_Wide_Character;
270 -----------------------------
271 -- Decode_Wide_Wide_String --
272 -----------------------------
274 function Decode_Wide_Wide_String (S : String) return Wide_Wide_String is
275 Result : Wide_Wide_String (1 .. S'Length);
276 Length : Natural;
277 begin
278 Decode_Wide_Wide_String (S, Result, Length);
279 return Result (1 .. Length);
280 end Decode_Wide_Wide_String;
282 procedure Decode_Wide_Wide_String
283 (S : String;
284 Result : out Wide_Wide_String;
285 Length : out Natural)
287 Ptr : Natural;
289 begin
290 Ptr := S'First;
291 Length := 0;
292 while Ptr <= S'Last loop
293 if Length >= Result'Last then
294 Past_End;
295 end if;
297 Length := Length + 1;
298 Decode_Wide_Wide_Character (S, Ptr, Result (Length));
299 end loop;
300 end Decode_Wide_Wide_String;
302 -------------------------
303 -- Next_Wide_Character --
304 -------------------------
306 procedure Next_Wide_Character (Input : String; Ptr : in out Natural) is
307 begin
308 if Ptr < Input'First then
309 Past_End;
310 end if;
312 -- Special efficient encoding for UTF-8 case
314 if Encoding_Method = WCEM_UTF8 then
315 UTF8 : declare
316 U : Unsigned_32;
318 procedure Getc;
319 pragma Inline (Getc);
320 -- Gets the character at Input (Ptr) and returns code in U as
321 -- Unsigned_32 value. On return Ptr is bumped past the character.
323 procedure Skip_UTF_Byte;
324 pragma Inline (Skip_UTF_Byte);
325 -- Skips past one encoded byte which must be 2#10xxxxxx#
327 ----------
328 -- Getc --
329 ----------
331 procedure Getc is
332 begin
333 if Ptr > Input'Last then
334 Past_End;
335 else
336 U := Unsigned_32 (Character'Pos (Input (Ptr)));
337 Ptr := Ptr + 1;
338 end if;
339 end Getc;
341 -------------------
342 -- Skip_UTF_Byte --
343 -------------------
345 procedure Skip_UTF_Byte is
346 begin
347 Getc;
349 if (U and 2#11000000#) /= 2#10_000000# then
350 Bad;
351 end if;
352 end Skip_UTF_Byte;
354 -- Start of processing for UTF-8 case
356 begin
357 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
359 Getc;
361 if (U and 2#10000000#) = 2#00000000# then
362 return;
364 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
366 elsif (U and 2#11100000#) = 2#110_00000# then
367 Skip_UTF_Byte;
369 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
371 elsif (U and 2#11110000#) = 2#1110_0000# then
372 Skip_UTF_Byte;
373 Skip_UTF_Byte;
375 -- Any other code is invalid, note that this includes:
377 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
379 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx 10xxxxxx
380 -- 10xxxxxx 10xxxxxx
382 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx 10xxxxxx
383 -- 10xxxxxx 10xxxxxx 10xxxxxx
385 -- since Wide_Character does not allow codes > 16#FFFF#
387 else
388 Bad;
389 end if;
390 end UTF8;
392 -- Non-UTF-8 case
394 else
395 declare
396 Discard : Wide_Character;
397 begin
398 Decode_Wide_Character (Input, Ptr, Discard);
399 end;
400 end if;
401 end Next_Wide_Character;
403 ------------------------------
404 -- Next_Wide_Wide_Character --
405 ------------------------------
407 procedure Next_Wide_Wide_Character (Input : String; Ptr : in out Natural) is
408 begin
409 -- Special efficient encoding for UTF-8 case
411 if Encoding_Method = WCEM_UTF8 then
412 UTF8 : declare
413 U : Unsigned_32;
415 procedure Getc;
416 pragma Inline (Getc);
417 -- Gets the character at Input (Ptr) and returns code in U as
418 -- Unsigned_32 value. On return Ptr is bumped past the character.
420 procedure Skip_UTF_Byte;
421 pragma Inline (Skip_UTF_Byte);
422 -- Skips past one encoded byte which must be 2#10xxxxxx#
424 ----------
425 -- Getc --
426 ----------
428 procedure Getc is
429 begin
430 if Ptr > Input'Last then
431 Past_End;
432 else
433 U := Unsigned_32 (Character'Pos (Input (Ptr)));
434 Ptr := Ptr + 1;
435 end if;
436 end Getc;
438 -------------------
439 -- Skip_UTF_Byte --
440 -------------------
442 procedure Skip_UTF_Byte is
443 begin
444 Getc;
446 if (U and 2#11000000#) /= 2#10_000000# then
447 Bad;
448 end if;
449 end Skip_UTF_Byte;
451 -- Start of processing for UTF-8 case
453 begin
454 if Ptr < Input'First then
455 Past_End;
456 end if;
458 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
460 Getc;
462 if (U and 2#10000000#) = 2#00000000# then
463 null;
465 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
467 elsif (U and 2#11100000#) = 2#110_00000# then
468 Skip_UTF_Byte;
470 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
472 elsif (U and 2#11110000#) = 2#1110_0000# then
473 Skip_UTF_Byte;
474 Skip_UTF_Byte;
476 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
478 elsif (U and 2#11111000#) = 2#11110_000# then
479 for K in 1 .. 3 loop
480 Skip_UTF_Byte;
481 end loop;
483 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx 10xxxxxx
484 -- 10xxxxxx 10xxxxxx
486 elsif (U and 2#11111100#) = 2#111110_00# then
487 for K in 1 .. 4 loop
488 Skip_UTF_Byte;
489 end loop;
491 -- Any other code is invalid, note that this includes:
493 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx 10xxxxxx
494 -- 10xxxxxx 10xxxxxx 10xxxxxx
496 -- since Wide_Wide_Character does not allow codes > 16#03FF_FFFF#
498 else
499 Bad;
500 end if;
501 end UTF8;
503 -- Non-UTF-8 case
505 else
506 declare
507 Discard : Wide_Wide_Character;
508 begin
509 Decode_Wide_Wide_Character (Input, Ptr, Discard);
510 end;
511 end if;
512 end Next_Wide_Wide_Character;
514 --------------
515 -- Past_End --
516 --------------
518 procedure Past_End is
519 begin
520 raise Constraint_Error with "past end of string";
521 end Past_End;
523 -------------------------
524 -- Prev_Wide_Character --
525 -------------------------
527 procedure Prev_Wide_Character (Input : String; Ptr : in out Natural) is
528 begin
529 if Ptr > Input'Last + 1 then
530 Past_End;
531 end if;
533 -- Special efficient encoding for UTF-8 case
535 if Encoding_Method = WCEM_UTF8 then
536 UTF8 : declare
537 U : Unsigned_32;
539 procedure Getc;
540 pragma Inline (Getc);
541 -- Gets the character at Input (Ptr - 1) and returns code in U as
542 -- Unsigned_32 value. On return Ptr is decremented by one.
544 procedure Skip_UTF_Byte;
545 pragma Inline (Skip_UTF_Byte);
546 -- Checks that U is 2#10xxxxxx# and then calls Get
548 ----------
549 -- Getc --
550 ----------
552 procedure Getc is
553 begin
554 if Ptr <= Input'First then
555 Past_End;
556 else
557 Ptr := Ptr - 1;
558 U := Unsigned_32 (Character'Pos (Input (Ptr)));
559 end if;
560 end Getc;
562 -------------------
563 -- Skip_UTF_Byte --
564 -------------------
566 procedure Skip_UTF_Byte is
567 begin
568 if (U and 2#11000000#) = 2#10_000000# then
569 Getc;
570 else
571 Bad;
572 end if;
573 end Skip_UTF_Byte;
575 -- Start of processing for UTF-8 case
577 begin
578 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
580 Getc;
582 if (U and 2#10000000#) = 2#00000000# then
583 return;
585 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
587 else
588 Skip_UTF_Byte;
590 if (U and 2#11100000#) = 2#110_00000# then
591 return;
593 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
595 else
596 Skip_UTF_Byte;
598 if (U and 2#11110000#) = 2#1110_0000# then
599 return;
601 -- Any other code is invalid, note that this includes:
603 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx
604 -- 10xxxxxx
606 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx
607 -- 10xxxxxx 10xxxxxx
608 -- 10xxxxxx
610 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx
611 -- 10xxxxxx 10xxxxxx
612 -- 10xxxxxx 10xxxxxx
614 -- since Wide_Character does not allow codes > 16#FFFF#
616 else
617 Bad;
618 end if;
619 end if;
620 end if;
621 end UTF8;
623 -- Special efficient encoding for brackets case
625 elsif Encoding_Method = WCEM_Brackets then
626 Brackets : declare
627 P : Natural;
628 S : Natural;
630 begin
631 -- See if we have "] at end positions
633 if Ptr > Input'First + 1
634 and then Input (Ptr - 1) = ']'
635 and then Input (Ptr - 2) = '"'
636 then
637 P := Ptr - 2;
639 -- Loop back looking for [" at start
641 while P >= Ptr - 10 loop
642 if P <= Input'First + 1 then
643 Bad;
645 elsif Input (P - 1) = '"'
646 and then Input (P - 2) = '['
647 then
648 -- Found ["..."], scan forward to check it
650 S := P - 2;
651 P := S;
652 Next_Wide_Character (Input, P);
654 -- OK if at original pointer, else error
656 if P = Ptr then
657 Ptr := S;
658 return;
659 else
660 Bad;
661 end if;
662 end if;
664 P := P - 1;
665 end loop;
667 -- Falling through loop means more than 8 chars between the
668 -- enclosing brackets (or simply a missing left bracket)
670 Bad;
672 -- Here if no bracket sequence present
674 else
675 if Ptr = Input'First then
676 Past_End;
677 else
678 Ptr := Ptr - 1;
679 end if;
680 end if;
681 end Brackets;
683 -- Non-UTF-8/Brackets. These are the inefficient cases where we have to
684 -- go to the start of the string and skip forwards till Ptr matches.
686 else
687 Non_UTF_Brackets : declare
688 Discard : Wide_Character;
689 PtrS : Natural;
690 PtrP : Natural;
692 begin
693 PtrS := Input'First;
695 if Ptr <= PtrS then
696 Past_End;
697 end if;
699 loop
700 PtrP := PtrS;
701 Decode_Wide_Character (Input, PtrS, Discard);
703 if PtrS = Ptr then
704 Ptr := PtrP;
705 return;
707 elsif PtrS > Ptr then
708 Bad;
709 end if;
710 end loop;
712 exception
713 when Constraint_Error =>
714 Bad;
715 end Non_UTF_Brackets;
716 end if;
717 end Prev_Wide_Character;
719 ------------------------------
720 -- Prev_Wide_Wide_Character --
721 ------------------------------
723 procedure Prev_Wide_Wide_Character (Input : String; Ptr : in out Natural) is
724 begin
725 if Ptr > Input'Last + 1 then
726 Past_End;
727 end if;
729 -- Special efficient encoding for UTF-8 case
731 if Encoding_Method = WCEM_UTF8 then
732 UTF8 : declare
733 U : Unsigned_32;
735 procedure Getc;
736 pragma Inline (Getc);
737 -- Gets the character at Input (Ptr - 1) and returns code in U as
738 -- Unsigned_32 value. On return Ptr is decremented by one.
740 procedure Skip_UTF_Byte;
741 pragma Inline (Skip_UTF_Byte);
742 -- Checks that U is 2#10xxxxxx# and then calls Get
744 ----------
745 -- Getc --
746 ----------
748 procedure Getc is
749 begin
750 if Ptr <= Input'First then
751 Past_End;
752 else
753 Ptr := Ptr - 1;
754 U := Unsigned_32 (Character'Pos (Input (Ptr)));
755 end if;
756 end Getc;
758 -------------------
759 -- Skip_UTF_Byte --
760 -------------------
762 procedure Skip_UTF_Byte is
763 begin
764 if (U and 2#11000000#) = 2#10_000000# then
765 Getc;
766 else
767 Bad;
768 end if;
769 end Skip_UTF_Byte;
771 -- Start of processing for UTF-8 case
773 begin
774 -- 16#00_0000#-16#00_007F#: 0xxxxxxx
776 Getc;
778 if (U and 2#10000000#) = 2#00000000# then
779 return;
781 -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
783 else
784 Skip_UTF_Byte;
786 if (U and 2#11100000#) = 2#110_00000# then
787 return;
789 -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
791 else
792 Skip_UTF_Byte;
794 if (U and 2#11110000#) = 2#1110_0000# then
795 return;
797 -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx
798 -- 10xxxxxx
800 else
801 Skip_UTF_Byte;
803 if (U and 2#11111000#) = 2#11110_000# then
804 return;
806 -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx
807 -- 10xxxxxx 10xxxxxx
808 -- 10xxxxxx
810 else
811 Skip_UTF_Byte;
813 if (U and 2#11111100#) = 2#111110_00# then
814 return;
816 -- Any other code is invalid, note that this includes:
818 -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx
819 -- 10xxxxxx 10xxxxxx
820 -- 10xxxxxx 10xxxxxx
822 -- since Wide_Wide_Character does not allow codes
823 -- greater than 16#03FF_FFFF#
825 else
826 Bad;
827 end if;
828 end if;
829 end if;
830 end if;
831 end if;
832 end UTF8;
834 -- Special efficient encoding for brackets case
836 elsif Encoding_Method = WCEM_Brackets then
837 Brackets : declare
838 P : Natural;
839 S : Natural;
841 begin
842 -- See if we have "] at end positions
844 if Ptr > Input'First + 1
845 and then Input (Ptr - 1) = ']'
846 and then Input (Ptr - 2) = '"'
847 then
848 P := Ptr - 2;
850 -- Loop back looking for [" at start
852 while P >= Ptr - 10 loop
853 if P <= Input'First + 1 then
854 Bad;
856 elsif Input (P - 1) = '"'
857 and then Input (P - 2) = '['
858 then
859 -- Found ["..."], scan forward to check it
861 S := P - 2;
862 P := S;
863 Next_Wide_Wide_Character (Input, P);
865 -- OK if at original pointer, else error
867 if P = Ptr then
868 Ptr := S;
869 return;
870 else
871 Bad;
872 end if;
873 end if;
875 P := P - 1;
876 end loop;
878 -- Falling through loop means more than 8 chars between the
879 -- enclosing brackets (or simply a missing left bracket)
881 Bad;
883 -- Here if no bracket sequence present
885 else
886 if Ptr = Input'First then
887 Past_End;
888 else
889 Ptr := Ptr - 1;
890 end if;
891 end if;
892 end Brackets;
894 -- Non-UTF-8/Brackets. These are the inefficient cases where we have to
895 -- go to the start of the string and skip forwards till Ptr matches.
897 else
898 Non_UTF8_Brackets : declare
899 Discard : Wide_Wide_Character;
900 PtrS : Natural;
901 PtrP : Natural;
903 begin
904 PtrS := Input'First;
906 if Ptr <= PtrS then
907 Past_End;
908 end if;
910 loop
911 PtrP := PtrS;
912 Decode_Wide_Wide_Character (Input, PtrS, Discard);
914 if PtrS = Ptr then
915 Ptr := PtrP;
916 return;
918 elsif PtrS > Ptr then
919 Bad;
920 end if;
921 end loop;
923 exception
924 when Constraint_Error =>
925 Bad;
926 end Non_UTF8_Brackets;
927 end if;
928 end Prev_Wide_Wide_Character;
930 --------------------------
931 -- Validate_Wide_String --
932 --------------------------
934 function Validate_Wide_String (S : String) return Boolean is
935 Ptr : Natural;
937 begin
938 Ptr := S'First;
939 while Ptr <= S'Last loop
940 Next_Wide_Character (S, Ptr);
941 end loop;
943 return True;
945 exception
946 when Constraint_Error =>
947 return False;
948 end Validate_Wide_String;
950 -------------------------------
951 -- Validate_Wide_Wide_String --
952 -------------------------------
954 function Validate_Wide_Wide_String (S : String) return Boolean is
955 Ptr : Natural;
957 begin
958 Ptr := S'First;
959 while Ptr <= S'Last loop
960 Next_Wide_Wide_Character (S, Ptr);
961 end loop;
963 return True;
965 exception
966 when Constraint_Error =>
967 return False;
968 end Validate_Wide_Wide_String;
970 end GNAT.Decode_String;