1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru**********************************************************************
3b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   Copyright (c) 2001-2011, International Business Machines
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru**********************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Date        Name        Description
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   11/19/2001  aliu        Creation.
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru**********************************************************************
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uchar.h"
1283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#include "unicode/utf16.h"
13b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "patternprops.h"
14b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "util.h"
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Parse an integer at pos, either of the form \d+ or of the form
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 0x[0-9A-Fa-f]+ or 0[0-7]+, that is, in standard decimal, hex,
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * or octal format.
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param pos INPUT-OUTPUT parameter.  On input, the first
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * character to parse.  On output, the character after the last
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * parsed character.
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t ICU_Utility::parseInteger(const UnicodeString& rule, int32_t& pos, int32_t limit) {
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t count = 0;
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t value = 0;
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t p = pos;
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int8_t radix = 10;
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (p < limit && rule.charAt(p) == 48 /*0*/) {
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (p+1 < limit && (rule.charAt(p+1) == 0x78 /*x*/ || rule.charAt(p+1) == 0x58 /*X*/)) {
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            p += 2;
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            radix = 16;
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            p++;
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            count = 1;
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            radix = 8;
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (p < limit) {
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t d = u_digit(rule.charAt(p++), radix);
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (d < 0) {
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            --p;
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++count;
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t v = (value * radix) + d;
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (v <= value) {
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // If there are too many input digits, at some point
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the value will go negative, e.g., if we have seen
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // "0x8000000" already and there is another '0', when
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // we parse the next 0 the value will go negative.
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        value = v;
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (count > 0) {
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pos = p;
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return value;
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Parse a pattern string starting at offset pos.  Keywords are
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * matched case-insensitively.  Spaces may be skipped and may be
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * optional or required.  Integer values may be parsed, and if
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * they are, they will be returned in the given array.  If
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * successful, the offset of the next non-space character is
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * returned.  On failure, -1 is returned.
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param pattern must only contain lowercase characters, which
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * will match their uppercase equivalents as well.  A space
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * character matches one or more required spaces.  A '~' character
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * matches zero or more optional spaces.  A '#' character matches
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * an integer and stores it in parsedInts, which the caller must
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * ensure has enough capacity.
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param parsedInts array to receive parsed integers.  Caller
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * must ensure that parsedInts.length is >= the number of '#'
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * signs in 'pattern'.
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the position after the last character parsed, or -1 if
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the parse failed
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t ICU_Utility::parsePattern(const UnicodeString& rule, int32_t pos, int32_t limit,
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString& pattern, int32_t* parsedInts) {
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO Update this to handle surrogates
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t p;
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t intCount = 0; // number of integers parsed
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int32_t i=0; i<pattern.length(); ++i) {
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar cpat = pattern.charAt(i);
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar c;
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch (cpat) {
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 32 /*' '*/:
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (pos >= limit) {
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return -1;
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            c = rule.charAt(pos++);
100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!PatternProps::isWhiteSpace(c)) {
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return -1;
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // FALL THROUGH to skipWhitespace
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 126 /*'~'*/:
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pos = skipWhitespace(rule, pos);
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 35 /*'#'*/:
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            p = pos;
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            parsedInts[intCount++] = parseInteger(rule, p, limit);
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (p == pos) {
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // Syntax error; failed to parse integer
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return -1;
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pos = p;
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        default:
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (pos >= limit) {
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return -1;
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            c = (UChar) u_tolower(rule.charAt(pos++));
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (c != cpat) {
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return -1;
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return pos;
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Parse a Unicode identifier from the given string at the given
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * position.  Return the identifier, or an empty string if there
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is no identifier.
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param str the string to parse
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param pos INPUT-OUPUT parameter.  On INPUT, pos is the
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * first character to examine.  It must be less than str.length(),
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and it must not point to a whitespace character.  That is, must
138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * have pos < str.length().  On
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * OUTPUT, the position after the last parsed character.
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the Unicode identifier, or an empty string if there is
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * no valid identifier at pos.
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString ICU_Utility::parseUnicodeIdentifier(const UnicodeString& str, int32_t& pos) {
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // assert(pos < str.length());
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString buf;
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int p = pos;
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (p < str.length()) {
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar32 ch = str.char32At(p);
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (buf.length() == 0) {
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (u_isIDStart(ch)) {
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                buf.append(ch);
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                buf.truncate(0);
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return buf;
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (u_isIDPart(ch)) {
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                buf.append(ch);
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
16383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius        p += U16_LENGTH(ch);
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pos = p;
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return buf;
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Parse an unsigned 31-bit integer at the given offset.  Use
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * UCharacter.digit() to parse individual characters into digits.
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param text the text to be parsed
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param pos INPUT-OUTPUT parameter.  On entry, pos[0] is the
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * offset within text at which to start parsing; it should point
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to a valid digit.  On exit, pos[0] is the offset after the last
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * parsed character.  If the parse failed, it will be unchanged on
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * exit.  Must be >= 0 on entry.
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param radix the radix in which to parse; must be >= 2 and <=
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 36.
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return a non-negative parsed number, or -1 upon parse failure.
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Parse fails if there are no digits, that is, if pos[0] does not
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * point to a valid digit on entry, or if the number to be parsed
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * does not fit into a 31-bit unsigned integer.
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t ICU_Utility::parseNumber(const UnicodeString& text,
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 int32_t& pos, int8_t radix) {
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // assert(pos[0] >= 0);
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // assert(radix >= 2);
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // assert(radix <= 36);
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t n = 0;
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t p = pos;
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (p < text.length()) {
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar32 ch = text.char32At(p);
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t d = u_digit(ch, radix);
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (d < 0) {
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        n = radix*n + d;
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // ASSUME that when a 32-bit integer overflows it becomes
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // negative.  E.g., 214748364 * 10 + 8 => negative value.
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (n < 0) {
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return -1;
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++p;
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (p == pos) {
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return -1;
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pos = p;
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return n;
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
215