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