~ubuntu-branches/ubuntu/wily/libspiff/wily

« back to all changes in this revision

Viewing changes to win32/uriparser/UriParse.c

  • Committer: Bazaar Package Importer
  • Author(s): Adeodato Simó
  • Date: 2007-10-11 14:44:38 UTC
  • Revision ID: james.westby@ubuntu.com-20071011144438-zpl4gtvl3bf2ocnx
Tags: upstream-0.8.2
Import upstream version 0.8.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * uriparser - RFC 3986 URI parsing library
 
3
 *
 
4
 * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
 
5
 * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution  and use in source and binary forms, with or without
 
9
 * modification,  are permitted provided that the following conditions
 
10
 * are met:
 
11
 *
 
12
 *     * Redistributions   of  source  code  must  retain  the   above
 
13
 *       copyright  notice, this list of conditions and the  following
 
14
 *       disclaimer.
 
15
 *
 
16
 *     * Redistributions  in  binary  form must  reproduce  the  above
 
17
 *       copyright  notice, this list of conditions and the  following
 
18
 *       disclaimer   in  the  documentation  and/or  other  materials
 
19
 *       provided with the distribution.
 
20
 *
 
21
 *     * Neither  the name of the <ORGANIZATION> nor the names of  its
 
22
 *       contributors  may  be  used to endorse  or  promote  products
 
23
 *       derived  from  this software without specific  prior  written
 
24
 *       permission.
 
25
 *
 
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
27
 * "AS  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT  NOT
 
28
 * LIMITED  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS
 
29
 * FOR  A  PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT  SHALL  THE
 
30
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 
31
 * INCIDENTAL,    SPECIAL,   EXEMPLARY,   OR   CONSEQUENTIAL   DAMAGES
 
32
 * (INCLUDING,  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
33
 * SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
34
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
35
 * STRICT  LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)
 
36
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 
37
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 
38
 */
 
39
 
 
40
/**
 
41
 * @file UriParse.c
 
42
 * Holds the RFC 3986 %URI parsing implementation.
 
43
 * NOTE: This source file includes itself twice.
 
44
 */
 
45
 
 
46
/* What encodings are enabled? */
 
47
#include <uriparser/UriDefsConfig.h>
 
48
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
 
49
/* Include SELF twice */
 
50
# define URI_PASS_ANSI 1
 
51
# include "UriParse.c"
 
52
# undef URI_PASS_ANSI
 
53
# define URI_PASS_UNICODE 1
 
54
# include "UriParse.c"
 
55
# undef URI_PASS_UNICODE
 
56
#else
 
57
# ifdef URI_PASS_ANSI
 
58
#  include <uriparser/UriDefsAnsi.h>
 
59
# else
 
60
#  include <uriparser/UriDefsUnicode.h>
 
61
#  include <wchar.h>
 
62
# endif
 
63
 
 
64
 
 
65
 
 
66
#ifndef URI_DOXYGEN
 
67
# include <uriparser/Uri.h>
 
68
# include <uriparser/UriIp4.h>
 
69
# include "UriCommon.h"
 
70
# include "UriParseBase.h"
 
71
#endif
 
72
 
 
73
 
 
74
 
 
75
#define URI_SET_DIGIT \
 
76
             _UT('0'): \
 
77
        case _UT('1'): \
 
78
        case _UT('2'): \
 
79
        case _UT('3'): \
 
80
        case _UT('4'): \
 
81
        case _UT('5'): \
 
82
        case _UT('6'): \
 
83
        case _UT('7'): \
 
84
        case _UT('8'): \
 
85
        case _UT('9')
 
86
 
 
87
#define URI_SET_HEX_LETTER_UPPER \
 
88
             _UT('A'): \
 
89
        case _UT('B'): \
 
90
        case _UT('C'): \
 
91
        case _UT('D'): \
 
92
        case _UT('E'): \
 
93
        case _UT('F')
 
94
 
 
95
#define URI_SET_HEX_LETTER_LOWER \
 
96
             _UT('a'): \
 
97
        case _UT('b'): \
 
98
        case _UT('c'): \
 
99
        case _UT('d'): \
 
100
        case _UT('e'): \
 
101
        case _UT('f')
 
102
 
 
103
#define URI_SET_HEXDIG \
 
104
        URI_SET_DIGIT: \
 
105
        case URI_SET_HEX_LETTER_UPPER: \
 
106
        case URI_SET_HEX_LETTER_LOWER
 
107
 
 
108
#define URI_SET_ALPHA \
 
109
        URI_SET_HEX_LETTER_UPPER: \
 
110
        case URI_SET_HEX_LETTER_LOWER: \
 
111
        case _UT('g'): \
 
112
        case _UT('G'): \
 
113
        case _UT('h'): \
 
114
        case _UT('H'): \
 
115
        case _UT('i'): \
 
116
        case _UT('I'): \
 
117
        case _UT('j'): \
 
118
        case _UT('J'): \
 
119
        case _UT('k'): \
 
120
        case _UT('K'): \
 
121
        case _UT('l'): \
 
122
        case _UT('L'): \
 
123
        case _UT('m'): \
 
124
        case _UT('M'): \
 
125
        case _UT('n'): \
 
126
        case _UT('N'): \
 
127
        case _UT('o'): \
 
128
        case _UT('O'): \
 
129
        case _UT('p'): \
 
130
        case _UT('P'): \
 
131
        case _UT('q'): \
 
132
        case _UT('Q'): \
 
133
        case _UT('r'): \
 
134
        case _UT('R'): \
 
135
        case _UT('s'): \
 
136
        case _UT('S'): \
 
137
        case _UT('t'): \
 
138
        case _UT('T'): \
 
139
        case _UT('u'): \
 
140
        case _UT('U'): \
 
141
        case _UT('v'): \
 
142
        case _UT('V'): \
 
143
        case _UT('w'): \
 
144
        case _UT('W'): \
 
145
        case _UT('x'): \
 
146
        case _UT('X'): \
 
147
        case _UT('y'): \
 
148
        case _UT('Y'): \
 
149
        case _UT('z'): \
 
150
        case _UT('Z')
 
151
 
 
152
 
 
153
 
 
154
static const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
155
static const URI_CHAR * URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
156
static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
157
static const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
158
static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
159
static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
160
static const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
161
static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
162
static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
163
static const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
164
static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
165
static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
166
static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
167
static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
168
static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
169
static const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
170
static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
171
static const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
172
static const URI_CHAR * URI_FUNC(ParsePathRootless)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
173
static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
174
static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
175
static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
176
static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
177
static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
178
static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
179
static const URI_CHAR * URI_FUNC(ParseSegmentNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
180
static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
181
static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
182
static const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
183
static const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
184
static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
185
 
 
186
static UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first);
 
187
static UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first);
 
188
static UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first);
 
189
static UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first);
 
190
static void URI_FUNC(OnExitPartHelperTwo)(URI_TYPE(ParserState) * state);
 
191
 
 
192
static void URI_FUNC(ResetParserState)(URI_TYPE(ParserState) * state);
 
193
 
 
194
static UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
 
195
 
 
196
static void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state, const URI_CHAR * errorPos);
 
197
static void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state);
 
198
 
 
199
 
 
200
 
 
201
static URI_INLINE void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state,
 
202
                const URI_CHAR * errorPos) {
 
203
        URI_FUNC(FreeUriMembers)(state->uri);
 
204
        state->errorPos = errorPos;
 
205
        state->errorCode = URI_ERROR_SYNTAX;
 
206
}
 
207
 
 
208
 
 
209
 
 
210
static URI_INLINE void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state) {
 
211
        URI_FUNC(FreeUriMembers)(state->uri);
 
212
        state->errorPos = NULL;
 
213
        state->errorCode = URI_ERROR_MALLOC;
 
214
}
 
215
 
 
216
 
 
217
 
 
218
/*
 
219
 * [authority]-><[>[ipLit2][authorityTwo]
 
220
 * [authority]->[ownHostUserInfoNz]
 
221
 * [authority]-><NULL>
 
222
 */
 
223
static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
224
        if (first >= afterLast) {
 
225
                /* "" regname host */
 
226
                state->uri->hostText.first = URI_FUNC(SafeToPointTo);
 
227
                state->uri->hostText.afterLast = URI_FUNC(SafeToPointTo);
 
228
                return afterLast;
 
229
        }
 
230
 
 
231
        switch (*first) {
 
232
        case _UT('['):
 
233
                {
 
234
                        const URI_CHAR * const afterIpLit2
 
235
                                        = URI_FUNC(ParseIpLit2)(state, first + 1, afterLast);
 
236
                        if (afterIpLit2 == NULL) {
 
237
                                return NULL;
 
238
                        }
 
239
                        state->uri->hostText.first = first + 1; /* HOST BEGIN */
 
240
                        return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast);
 
241
                }
 
242
 
 
243
        case _UT('!'):
 
244
        case _UT('$'):
 
245
        case _UT('%'):
 
246
        case _UT('&'):
 
247
        case _UT('('):
 
248
        case _UT(')'):
 
249
        case _UT('-'):
 
250
        case _UT('*'):
 
251
        case _UT(','):
 
252
        case _UT('.'):
 
253
        case _UT(':'):
 
254
        case _UT(';'):
 
255
        case _UT('@'):
 
256
        case _UT('\''):
 
257
        case _UT('_'):
 
258
        case _UT('~'):
 
259
        case _UT('+'):
 
260
        case _UT('='):
 
261
        case URI_SET_DIGIT:
 
262
        case URI_SET_ALPHA:
 
263
                state->uri->userInfo.first = first; /* USERINFO BEGIN */
 
264
                return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast);
 
265
 
 
266
        default:
 
267
                /* "" regname host */
 
268
                state->uri->hostText.first = URI_FUNC(SafeToPointTo);
 
269
                state->uri->hostText.afterLast = URI_FUNC(SafeToPointTo);
 
270
                return first;
 
271
        }
 
272
}
 
273
 
 
274
 
 
275
 
 
276
/*
 
277
 * [authorityTwo]-><:>[port]
 
278
 * [authorityTwo]-><NULL>
 
279
 */
 
280
static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
281
        if (first >= afterLast) {
 
282
                return afterLast;
 
283
        }
 
284
 
 
285
        switch (*first) {
 
286
        case _UT(':'):
 
287
                {
 
288
                        const URI_CHAR * const afterPort = URI_FUNC(ParsePort)(state, first + 1, afterLast);
 
289
                        if (afterPort == NULL) {
 
290
                                return NULL;
 
291
                        }
 
292
                        state->uri->portText.first = first + 1; /* PORT BEGIN */
 
293
                        state->uri->portText.afterLast = afterPort; /* PORT END */
 
294
                        return afterPort;
 
295
                }
 
296
 
 
297
        default:
 
298
                return first;
 
299
        }
 
300
}
 
301
 
 
302
 
 
303
 
 
304
/*
 
305
 * [hexZero]->[HEXDIG][hexZero]
 
306
 * [hexZero]-><NULL>
 
307
 */
 
308
static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
309
        if (first >= afterLast) {
 
310
                return afterLast;
 
311
        }
 
312
 
 
313
        switch (*first) {
 
314
        case URI_SET_HEXDIG:
 
315
                return URI_FUNC(ParseHexZero)(state, first + 1, afterLast);
 
316
 
 
317
        default:
 
318
                return first;
 
319
        }
 
320
}
 
321
 
 
322
 
 
323
 
 
324
/*
 
325
 * [hierPart]->[pathRootless]
 
326
 * [hierPart]-></>[partHelperTwo]
 
327
 * [hierPart]-><NULL>
 
328
 */
 
329
static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
330
        if (first >= afterLast) {
 
331
                return afterLast;
 
332
        }
 
333
 
 
334
        switch (*first) {
 
335
        case _UT('!'):
 
336
        case _UT('$'):
 
337
        case _UT('%'):
 
338
        case _UT('&'):
 
339
        case _UT('('):
 
340
        case _UT(')'):
 
341
        case _UT('-'):
 
342
        case _UT('*'):
 
343
        case _UT(','):
 
344
        case _UT('.'):
 
345
        case _UT(':'):
 
346
        case _UT(';'):
 
347
        case _UT('@'):
 
348
        case _UT('\''):
 
349
        case _UT('_'):
 
350
        case _UT('~'):
 
351
        case _UT('+'):
 
352
        case _UT('='):
 
353
        case URI_SET_DIGIT:
 
354
        case URI_SET_ALPHA:
 
355
                return URI_FUNC(ParsePathRootless)(state, first, afterLast);
 
356
 
 
357
        case _UT('/'):
 
358
                return URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast);
 
359
 
 
360
        default:
 
361
                return first;
 
362
        }
 
363
}
 
364
 
 
365
 
 
366
 
 
367
/*
 
368
 * [ipFutLoop]->[subDelims][ipFutStopGo]
 
369
 * [ipFutLoop]->[unreserved][ipFutStopGo]
 
370
 * [ipFutLoop]-><:>[ipFutStopGo]
 
371
 */
 
372
static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
373
        if (first >= afterLast) {
 
374
                URI_FUNC(StopSyntax)(state, first);
 
375
                return NULL;
 
376
        }
 
377
 
 
378
        switch (*first) {
 
379
        case _UT('!'):
 
380
        case _UT('$'):
 
381
        case _UT('&'):
 
382
        case _UT('('):
 
383
        case _UT(')'):
 
384
        case _UT('-'):
 
385
        case _UT('*'):
 
386
        case _UT(','):
 
387
        case _UT('.'):
 
388
        case _UT(':'):
 
389
        case _UT(';'):
 
390
        case _UT('\''):
 
391
        case _UT('_'):
 
392
        case _UT('~'):
 
393
        case _UT('+'):
 
394
        case _UT('='):
 
395
        case URI_SET_DIGIT:
 
396
        case URI_SET_ALPHA:
 
397
                return URI_FUNC(ParseIpFutStopGo)(state, first + 1, afterLast);
 
398
 
 
399
        default:
 
400
                URI_FUNC(StopSyntax)(state, first);
 
401
                return NULL;
 
402
        }
 
403
}
 
404
 
 
405
 
 
406
 
 
407
/*
 
408
 * [ipFutStopGo]->[ipFutLoop]
 
409
 * [ipFutStopGo]-><NULL>
 
410
 */
 
411
static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
412
        if (first >= afterLast) {
 
413
                return afterLast;
 
414
        }
 
415
 
 
416
        switch (*first) {
 
417
        case _UT('!'):
 
418
        case _UT('$'):
 
419
        case _UT('&'):
 
420
        case _UT('('):
 
421
        case _UT(')'):
 
422
        case _UT('-'):
 
423
        case _UT('*'):
 
424
        case _UT(','):
 
425
        case _UT('.'):
 
426
        case _UT(':'):
 
427
        case _UT(';'):
 
428
        case _UT('\''):
 
429
        case _UT('_'):
 
430
        case _UT('~'):
 
431
        case _UT('+'):
 
432
        case _UT('='):
 
433
        case URI_SET_DIGIT:
 
434
        case URI_SET_ALPHA:
 
435
                return URI_FUNC(ParseIpFutLoop)(state, first, afterLast);
 
436
 
 
437
        default:
 
438
                return first;
 
439
        }
 
440
}
 
441
 
 
442
 
 
443
 
 
444
/*
 
445
 * [ipFuture]-><v>[HEXDIG][hexZero]<.>[ipFutLoop]
 
446
 */
 
447
static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
448
        if (first >= afterLast) {
 
449
                URI_FUNC(StopSyntax)(state, first);
 
450
                return NULL;
 
451
        }
 
452
 
 
453
        /*
 
454
        First character has already been
 
455
        checked before entering this rule.
 
456
 
 
457
        switch (*first) {
 
458
        case _UT('v'):
 
459
        */
 
460
                if (first + 1 >= afterLast) {
 
461
                        URI_FUNC(StopSyntax)(state, first + 1);
 
462
                        return NULL;
 
463
                }
 
464
 
 
465
                switch (first[1]) {
 
466
                case URI_SET_HEXDIG:
 
467
                        {
 
468
                                const URI_CHAR * afterIpFutLoop;
 
469
                                const URI_CHAR * const afterHexZero
 
470
                                                = URI_FUNC(ParseHexZero)(state, first + 2, afterLast);
 
471
                                if (afterHexZero == NULL) {
 
472
                                        return NULL;
 
473
                                }
 
474
                                if ((afterHexZero >= afterLast)
 
475
                                                || (*afterHexZero != _UT('.'))) {
 
476
                                        URI_FUNC(StopSyntax)(state, afterHexZero);
 
477
                                        return NULL;
 
478
                                }
 
479
                                state->uri->hostText.first = first; /* HOST BEGIN */
 
480
                                state->uri->hostData.ipFuture.first = first; /* IPFUTURE BEGIN */
 
481
                                afterIpFutLoop = URI_FUNC(ParseIpFutLoop)(state, afterHexZero + 1, afterLast);
 
482
                                if (afterIpFutLoop == NULL) {
 
483
                                        return NULL;
 
484
                                }
 
485
                                state->uri->hostText.afterLast = afterIpFutLoop; /* HOST END */
 
486
                                state->uri->hostData.ipFuture.afterLast = afterIpFutLoop; /* IPFUTURE END */
 
487
                                return afterIpFutLoop;
 
488
                        }
 
489
 
 
490
                default:
 
491
                        URI_FUNC(StopSyntax)(state, first + 1);
 
492
                        return NULL;
 
493
                }
 
494
 
 
495
        /*
 
496
        default:
 
497
                URI_FUNC(StopSyntax)(state, first);
 
498
                return NULL;
 
499
        }
 
500
        */
 
501
}
 
502
 
 
503
 
 
504
 
 
505
/*
 
506
 * [ipLit2]->[ipFuture]<]>
 
507
 * [ipLit2]->[IPv6address2]
 
508
 */
 
509
static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
510
        if (first >= afterLast) {
 
511
                URI_FUNC(StopSyntax)(state, first);
 
512
                return NULL;
 
513
        }
 
514
 
 
515
        switch (*first) {
 
516
        case _UT('v'):
 
517
                {
 
518
                        const URI_CHAR * const afterIpFuture
 
519
                                        = URI_FUNC(ParseIpFuture)(state, first, afterLast);
 
520
                        if (afterIpFuture == NULL) {
 
521
                                return NULL;
 
522
                        }
 
523
                        if ((afterIpFuture >= afterLast)
 
524
                                        || (*afterIpFuture != _UT(']'))) {
 
525
                                URI_FUNC(StopSyntax)(state, first);
 
526
                                return NULL;
 
527
                        }
 
528
                        return afterIpFuture + 1;
 
529
                }
 
530
 
 
531
        case _UT(':'):
 
532
        case _UT(']'):
 
533
        case URI_SET_HEXDIG:
 
534
                state->uri->hostData.ip6 = malloc(1 * sizeof(UriIp6)); /* Freed when stopping on parse error */
 
535
                if (state->uri->hostData.ip6 == NULL) {
 
536
                        URI_FUNC(StopMalloc)(state);
 
537
                        return NULL;
 
538
                }
 
539
                return URI_FUNC(ParseIPv6address2)(state, first, afterLast);
 
540
 
 
541
        default:
 
542
                URI_FUNC(StopSyntax)(state, first);
 
543
                return NULL;
 
544
        }
 
545
}
 
546
 
 
547
 
 
548
 
 
549
/*
 
550
 * [IPv6address2]->..<]>
 
551
 */
 
552
static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
553
        int zipperEver = 0;
 
554
        int quadsDone = 0;
 
555
        int digitCount = 0;
 
556
        unsigned char digitHistory[4];
 
557
        int ip4OctetsDone = 0;
 
558
 
 
559
        unsigned char quadsAfterZipper[14];
 
560
        int quadsAfterZipperCount = 0;
 
561
 
 
562
 
 
563
        for (;;) {
 
564
                if (first >= afterLast) {
 
565
                        URI_FUNC(StopSyntax)(state, first);
 
566
                        return NULL;
 
567
                }
 
568
 
 
569
                /* Inside IPv4 part? */
 
570
                if (ip4OctetsDone > 0) {
 
571
                        /* Eat rest of IPv4 address */
 
572
                        for (;;) {
 
573
                                switch (*first) {
 
574
                                case URI_SET_DIGIT:
 
575
                                        if (digitCount == 4) {
 
576
                                                URI_FUNC(StopSyntax)(state, first);
 
577
                                                return NULL;
 
578
                                        }
 
579
                                        digitHistory[digitCount++] = (unsigned char)(9 + *first - _UT('9'));
 
580
                                        break;
 
581
 
 
582
                                case _UT('.'):
 
583
                                        if ((ip4OctetsDone == 4) /* NOTE! */
 
584
                                                        || (digitCount == 0)
 
585
                                                        || (digitCount == 4)) {
 
586
                                                /* Invalid digit or octet count */
 
587
                                                URI_FUNC(StopSyntax)(state, first);
 
588
                                                return NULL;
 
589
                                        } else if ((digitCount > 1)
 
590
                                                        && (digitHistory[0] == 0)) {
 
591
                                                /* Leading zero */
 
592
                                                URI_FUNC(StopSyntax)(state, first - digitCount);
 
593
                                                return NULL;
 
594
                                        } else if ((digitCount > 2)
 
595
                                                        && (digitHistory[1] == 0)) {
 
596
                                                /* Leading zero */
 
597
                                                URI_FUNC(StopSyntax)(state, first - digitCount + 1);
 
598
                                                return NULL;
 
599
                                        } else if ((digitCount == 3)
 
600
                                                        && (100 * digitHistory[0]
 
601
                                                                + 10 * digitHistory[1]
 
602
                                                                + digitHistory[2] > 255)) {
 
603
                                                /* Octet value too large */
 
604
                                                if (digitHistory[0] > 2) {
 
605
                                                        URI_FUNC(StopSyntax)(state, first - 3);
 
606
                                                } else if (digitHistory[1] > 5) {
 
607
                                                        URI_FUNC(StopSyntax)(state, first - 2);
 
608
                                                } else {
 
609
                                                        URI_FUNC(StopSyntax)(state, first - 1);
 
610
                                                }
 
611
                                                return NULL;
 
612
                                        }
 
613
 
 
614
                                        /* Copy IPv4 octet */
 
615
                                        state->uri->hostData.ip6->data[16 - 4 + ip4OctetsDone] = uriGetOctetValue(digitHistory, digitCount);
 
616
                                        digitCount = 0;
 
617
                                        ip4OctetsDone++;
 
618
                                        break;
 
619
 
 
620
                                case _UT(']'):
 
621
                                        if ((ip4OctetsDone != 3) /* NOTE! */
 
622
                                                        || (digitCount == 0)
 
623
                                                        || (digitCount == 4)) {
 
624
                                                /* Invalid digit or octet count */
 
625
                                                URI_FUNC(StopSyntax)(state, first);
 
626
                                                return NULL;
 
627
                                        } else if ((digitCount > 1)
 
628
                                                        && (digitHistory[0] == 0)) {
 
629
                                                /* Leading zero */
 
630
                                                URI_FUNC(StopSyntax)(state, first - digitCount);
 
631
                                                return NULL;
 
632
                                        } else if ((digitCount > 2)
 
633
                                                        && (digitHistory[1] == 0)) {
 
634
                                                /* Leading zero */
 
635
                                                URI_FUNC(StopSyntax)(state, first - digitCount + 1);
 
636
                                                return NULL;
 
637
                                        } else if ((digitCount == 3)
 
638
                                                        && (100 * digitHistory[0]
 
639
                                                                + 10 * digitHistory[1]
 
640
                                                                + digitHistory[2] > 255)) {
 
641
                                                /* Octet value too large */
 
642
                                                if (digitHistory[0] > 2) {
 
643
                                                        URI_FUNC(StopSyntax)(state, first - 3);
 
644
                                                } else if (digitHistory[1] > 5) {
 
645
                                                        URI_FUNC(StopSyntax)(state, first - 2);
 
646
                                                } else {
 
647
                                                        URI_FUNC(StopSyntax)(state, first - 1);
 
648
                                                }
 
649
                                                return NULL;
 
650
                                        }
 
651
 
 
652
                                        state->uri->hostText.afterLast = first; /* HOST END */
 
653
 
 
654
                                        /* Copy missing quads right before IPv4 */
 
655
                                        memcpy(state->uri->hostData.ip6->data + 16 - 4 - 2 * quadsAfterZipperCount,
 
656
                                                                quadsAfterZipper, 2 * quadsAfterZipperCount);
 
657
 
 
658
                                        /* Copy last IPv4 octet */
 
659
                                        state->uri->hostData.ip6->data[16 - 4 + 3] = uriGetOctetValue(digitHistory, digitCount);
 
660
 
 
661
                                        return first + 1;
 
662
 
 
663
                                default:
 
664
                                        URI_FUNC(StopSyntax)(state, first);
 
665
                                        return NULL;
 
666
                                }
 
667
                                first++;
 
668
                        }
 
669
                } else {
 
670
                        /* Eat while no dot in sight */
 
671
                        int letterAmong = 0;
 
672
                        int walking = 1;
 
673
                        do {
 
674
                                switch (*first) {
 
675
                                case URI_SET_HEX_LETTER_LOWER:
 
676
                                        letterAmong = 1;
 
677
                                        if (digitCount == 4) {
 
678
                                                URI_FUNC(StopSyntax)(state, first);
 
679
                                                return NULL;
 
680
                                        }
 
681
                                        digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('f'));
 
682
                                        digitCount++;
 
683
                                        break;
 
684
 
 
685
                                case URI_SET_HEX_LETTER_UPPER:
 
686
                                        letterAmong = 1;
 
687
                                        if (digitCount == 4) {
 
688
                                                URI_FUNC(StopSyntax)(state, first);
 
689
                                                return NULL;
 
690
                                        }
 
691
                                        digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('F'));
 
692
                                        digitCount++;
 
693
                                        break;
 
694
 
 
695
                                case URI_SET_DIGIT:
 
696
                                        if (digitCount == 4) {
 
697
                                                URI_FUNC(StopSyntax)(state, first);
 
698
                                                return NULL;
 
699
                                        }
 
700
                                        digitHistory[digitCount] = (unsigned char)(9 + *first - _UT('9'));
 
701
                                        digitCount++;
 
702
                                        break;
 
703
 
 
704
                                case _UT(':'):
 
705
                                        {
 
706
                                                int setZipper = 0;
 
707
 
 
708
                                                /* Too many quads? */
 
709
                                                if (quadsDone > 8 - zipperEver) {
 
710
                                                        URI_FUNC(StopSyntax)(state, first);
 
711
                                                        return NULL;
 
712
                                                }
 
713
 
 
714
                                                /* "::"? */
 
715
                                                if (first + 1 >= afterLast) {
 
716
                                                        URI_FUNC(StopSyntax)(state, first + 1);
 
717
                                                        return NULL;
 
718
                                                }
 
719
                                                if (first[1] == _UT(':')) {
 
720
                                                        const int resetOffset = 2 * (quadsDone + (digitCount > 0));
 
721
 
 
722
                                                        first++;
 
723
                                                        if (zipperEver) {
 
724
                                                                URI_FUNC(StopSyntax)(state, first);
 
725
                                                                return NULL; /* "::.+::" */
 
726
                                                        }
 
727
 
 
728
                                                        /* Zero everything after zipper */
 
729
                                                        memset(state->uri->hostData.ip6->data + resetOffset, 0, 16 - resetOffset);
 
730
                                                        setZipper = 1;
 
731
 
 
732
                                                        /* ":::+"? */
 
733
                                                        if (first + 1 >= afterLast) {
 
734
                                                                URI_FUNC(StopSyntax)(state, first + 1);
 
735
                                                                return NULL; /* No ']' yet */
 
736
                                                        }
 
737
                                                        if (first[1] == _UT(':')) {
 
738
                                                                URI_FUNC(StopSyntax)(state, first + 1);
 
739
                                                                return NULL; /* ":::+ "*/
 
740
                                                        }
 
741
                                                }
 
742
                                                if (digitCount > 0) {
 
743
                                                        if (zipperEver) {
 
744
                                                                uriWriteQuadToDoubleByte(digitHistory, digitCount, quadsAfterZipper + 2 * quadsAfterZipperCount);
 
745
                                                                quadsAfterZipperCount++;
 
746
                                                        } else {
 
747
                                                                uriWriteQuadToDoubleByte(digitHistory, digitCount, state->uri->hostData.ip6->data + 2 * quadsDone);
 
748
                                                        }
 
749
                                                        quadsDone++;
 
750
                                                        digitCount = 0;
 
751
                                                }
 
752
                                                letterAmong = 0;
 
753
 
 
754
                                                if (setZipper) {
 
755
                                                        zipperEver = 1;
 
756
                                                }
 
757
                                        }
 
758
                                        break;
 
759
 
 
760
                                case _UT('.'):
 
761
                                        if ((quadsDone > 6) /* NOTE */
 
762
                                                        || (!zipperEver && (quadsDone < 6))
 
763
                                                        || letterAmong
 
764
                                                        || (digitCount == 0)
 
765
                                                        || (digitCount == 4)) {
 
766
                                                /* Invalid octet before */
 
767
                                                URI_FUNC(StopSyntax)(state, first);
 
768
                                                return NULL;
 
769
                                        } else if ((digitCount > 1)
 
770
                                                        && (digitHistory[0] == 0)) {
 
771
                                                /* Leading zero */
 
772
                                                URI_FUNC(StopSyntax)(state, first - digitCount);
 
773
                                                return NULL;
 
774
                                        } else if ((digitCount > 2)
 
775
                                                        && (digitHistory[1] == 0)) {
 
776
                                                /* Leading zero */
 
777
                                                URI_FUNC(StopSyntax)(state, first - digitCount + 1);
 
778
                                                return NULL;
 
779
                                        } else if ((digitCount == 3)
 
780
                                                        && (100 * digitHistory[0]
 
781
                                                                + 10 * digitHistory[1]
 
782
                                                                + digitHistory[2] > 255)) {
 
783
                                                /* Octet value too large */
 
784
                                                if (digitHistory[0] > 2) {
 
785
                                                        URI_FUNC(StopSyntax)(state, first - 3);
 
786
                                                } else if (digitHistory[1] > 5) {
 
787
                                                        URI_FUNC(StopSyntax)(state, first - 2);
 
788
                                                } else {
 
789
                                                        URI_FUNC(StopSyntax)(state, first - 1);
 
790
                                                }
 
791
                                                return NULL;
 
792
                                        }
 
793
 
 
794
                                        /* Copy first IPv4 octet */
 
795
                                        state->uri->hostData.ip6->data[16 - 4] = uriGetOctetValue(digitHistory, digitCount);
 
796
                                        digitCount = 0;
 
797
 
 
798
                                        /* Switch over to IPv4 loop */
 
799
                                        ip4OctetsDone = 1;
 
800
                                        walking = 0;
 
801
                                        break;
 
802
 
 
803
                                case _UT(']'):
 
804
                                        /* Too little quads? */
 
805
                                        if (!zipperEver && !((quadsDone == 7) && (digitCount > 0))) {
 
806
                                                URI_FUNC(StopSyntax)(state, first);
 
807
                                                return NULL;
 
808
                                        }
 
809
 
 
810
                                        if (digitCount > 0) {
 
811
                                                if (zipperEver) {
 
812
                                                        uriWriteQuadToDoubleByte(digitHistory, digitCount, quadsAfterZipper + 2 * quadsAfterZipperCount);
 
813
                                                        quadsAfterZipperCount++;
 
814
                                                } else {
 
815
                                                        uriWriteQuadToDoubleByte(digitHistory, digitCount, state->uri->hostData.ip6->data + 2 * quadsDone);
 
816
                                                }
 
817
                                                /*
 
818
                                                quadsDone++;
 
819
                                                digitCount = 0;
 
820
                                                */
 
821
                                        }
 
822
 
 
823
                                        /* Copy missing quads to the end */
 
824
                                        memcpy(state->uri->hostData.ip6->data + 16 - 2 * quadsAfterZipperCount,
 
825
                                                                quadsAfterZipper, 2 * quadsAfterZipperCount);
 
826
 
 
827
                                        state->uri->hostText.afterLast = first; /* HOST END */
 
828
                                        return first + 1; /* Fine */
 
829
 
 
830
                                default:
 
831
                                        URI_FUNC(StopSyntax)(state, first);
 
832
                                        return NULL;
 
833
                                }
 
834
                                first++;
 
835
 
 
836
                                if (first >= afterLast) {
 
837
                                        URI_FUNC(StopSyntax)(state, first);
 
838
                                        return NULL; /* No ']' yet */
 
839
                                }
 
840
                        } while (walking);
 
841
                }
 
842
        }
 
843
}
 
844
 
 
845
 
 
846
 
 
847
/*
 
848
 * [mustBeSegmentNzNc]->[pctEncoded][mustBeSegmentNzNc]
 
849
 * [mustBeSegmentNzNc]->[subDelims][mustBeSegmentNzNc]
 
850
 * [mustBeSegmentNzNc]->[unreserved][mustBeSegmentNzNc]
 
851
 * [mustBeSegmentNzNc]->[uriTail] // can take <NULL>
 
852
 * [mustBeSegmentNzNc]-></>[segment][zeroMoreSlashSegs][uriTail]
 
853
 * [mustBeSegmentNzNc]-><@>[mustBeSegmentNzNc]
 
854
 */
 
855
static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
856
        if (first >= afterLast) {
 
857
                if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */
 
858
                        URI_FUNC(StopMalloc)(state);
 
859
                        return NULL;
 
860
                }
 
861
                state->uri->scheme.first = NULL; /* Not a scheme, reset */
 
862
                return afterLast;
 
863
        }
 
864
 
 
865
        switch (*first) {
 
866
        case _UT('%'):
 
867
                {
 
868
                        const URI_CHAR * const afterPctEncoded
 
869
                                        = URI_FUNC(ParsePctEncoded)(state, first, afterLast);
 
870
                        if (afterPctEncoded == NULL) {
 
871
                                return NULL;
 
872
                        }
 
873
                        return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast);
 
874
                }
 
875
 
 
876
        case _UT('@'):
 
877
        case _UT('!'):
 
878
        case _UT('$'):
 
879
        case _UT('&'):
 
880
        case _UT('('):
 
881
        case _UT(')'):
 
882
        case _UT('*'):
 
883
        case _UT(','):
 
884
        case _UT(';'):
 
885
        case _UT('\''):
 
886
        case _UT('+'):
 
887
        case _UT('='):
 
888
        case _UT('-'):
 
889
        case _UT('.'):
 
890
        case _UT('_'):
 
891
        case _UT('~'):
 
892
        case URI_SET_DIGIT:
 
893
        case URI_SET_ALPHA:
 
894
                return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast);
 
895
 
 
896
        case _UT('/'):
 
897
                {
 
898
                        const URI_CHAR * afterZeroMoreSlashSegs;
 
899
                        const URI_CHAR * afterSegment;
 
900
                        if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */
 
901
                                URI_FUNC(StopMalloc)(state);
 
902
                                return NULL;
 
903
                        }
 
904
                        state->uri->scheme.first = NULL; /* Not a scheme, reset */
 
905
                        afterSegment = URI_FUNC(ParseSegment)(state, first + 1, afterLast);
 
906
                        if (afterSegment == NULL) {
 
907
                                return NULL;
 
908
                        }
 
909
                        if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */
 
910
                                URI_FUNC(StopMalloc)(state);
 
911
                                return NULL;
 
912
                        }
 
913
                        afterZeroMoreSlashSegs
 
914
                                        = URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast);
 
915
                        if (afterZeroMoreSlashSegs == NULL) {
 
916
                                return NULL;
 
917
                        }
 
918
                        return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast);
 
919
                }
 
920
 
 
921
        default:
 
922
                if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */
 
923
                        URI_FUNC(StopMalloc)(state);
 
924
                        return NULL;
 
925
                }
 
926
                state->uri->scheme.first = NULL; /* Not a scheme, reset */
 
927
                return URI_FUNC(ParseUriTail)(state, first, afterLast);
 
928
        }
 
929
}
 
930
 
 
931
 
 
932
 
 
933
/*
 
934
 * [ownHost]-><[>[ipLit2][authorityTwo]
 
935
 * [ownHost]->[ownHost2] // can take <NULL>
 
936
 */
 
937
static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHost)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
938
        if (first >= afterLast) {
 
939
                return afterLast;
 
940
        }
 
941
 
 
942
        switch (*first) {
 
943
        case _UT('['):
 
944
                {
 
945
                        const URI_CHAR * const afterIpLit2
 
946
                                        = URI_FUNC(ParseIpLit2)(state, first + 1, afterLast);
 
947
                        if (afterIpLit2 == NULL) {
 
948
                                return NULL;
 
949
                        }
 
950
                        state->uri->hostText.first = first + 1; /* HOST BEGIN */
 
951
                        return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast);
 
952
                }
 
953
 
 
954
        default:
 
955
                return URI_FUNC(ParseOwnHost2)(state, first, afterLast);
 
956
        }
 
957
}
 
958
 
 
959
 
 
960
 
 
961
static URI_INLINE UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first) {
 
962
        state->uri->hostText.afterLast = first; /* HOST END */
 
963
 
 
964
        /* Valid IPv4 or just a regname? */
 
965
        state->uri->hostData.ip4 = malloc(1 * sizeof(UriIp4)); /* Freed when stopping on parse error */
 
966
        if (state->uri->hostData.ip4 == NULL) {
 
967
                return URI_FALSE; /* Raises malloc error */
 
968
        }
 
969
        if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,
 
970
                        state->uri->hostText.first, state->uri->hostText.afterLast)) {
 
971
                /* Not IPv4 */
 
972
                free(state->uri->hostData.ip4);
 
973
                state->uri->hostData.ip4 = NULL;
 
974
        }
 
975
        return URI_TRUE; /* Success */
 
976
}
 
977
 
 
978
 
 
979
 
 
980
/*
 
981
 * [ownHost2]->[authorityTwo] // can take <NULL>
 
982
 * [ownHost2]->[pctSubUnres][ownHost2]
 
983
 */
 
984
static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
985
        if (first >= afterLast) {
 
986
                if (!URI_FUNC(OnExitOwnHost2)(state, first)) {
 
987
                        URI_FUNC(StopMalloc)(state);
 
988
                        return NULL;
 
989
                }
 
990
                return afterLast;
 
991
        }
 
992
 
 
993
        switch (*first) {
 
994
        case _UT('!'):
 
995
        case _UT('$'):
 
996
        case _UT('%'):
 
997
        case _UT('&'):
 
998
        case _UT('('):
 
999
        case _UT(')'):
 
1000
        case _UT('-'):
 
1001
        case _UT('*'):
 
1002
        case _UT(','):
 
1003
        case _UT('.'):
 
1004
        case _UT(';'):
 
1005
        case _UT('\''):
 
1006
        case _UT('_'):
 
1007
        case _UT('~'):
 
1008
        case _UT('+'):
 
1009
        case _UT('='):
 
1010
        case URI_SET_DIGIT:
 
1011
        case URI_SET_ALPHA:
 
1012
                {
 
1013
                        const URI_CHAR * const afterPctSubUnres
 
1014
                                        = URI_FUNC(ParsePctSubUnres)(state, first, afterLast);
 
1015
                        if (afterPctSubUnres == NULL) {
 
1016
                                return NULL;
 
1017
                        }
 
1018
                        return URI_FUNC(ParseOwnHost2)(state, afterPctSubUnres, afterLast);
 
1019
                }
 
1020
 
 
1021
        default:
 
1022
                if (!URI_FUNC(OnExitOwnHost2)(state, first)) {
 
1023
                        URI_FUNC(StopMalloc)(state);
 
1024
                        return NULL;
 
1025
                }
 
1026
                return URI_FUNC(ParseAuthorityTwo)(state, first, afterLast);
 
1027
        }
 
1028
}
 
1029
 
 
1030
 
 
1031
 
 
1032
static URI_INLINE UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first) {
 
1033
        state->uri->hostText.first = state->uri->userInfo.first; /* Host instead of userInfo, update */
 
1034
        state->uri->userInfo.first = NULL; /* Not a userInfo, reset */
 
1035
        state->uri->hostText.afterLast = first; /* HOST END */
 
1036
 
 
1037
        /* Valid IPv4 or just a regname? */
 
1038
        state->uri->hostData.ip4 = malloc(1 * sizeof(UriIp4)); /* Freed when stopping on parse error */
 
1039
        if (state->uri->hostData.ip4 == NULL) {
 
1040
                return URI_FALSE; /* Raises malloc error */
 
1041
        }
 
1042
        if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,
 
1043
                        state->uri->hostText.first, state->uri->hostText.afterLast)) {
 
1044
                /* Not IPv4 */
 
1045
                free(state->uri->hostData.ip4);
 
1046
                state->uri->hostData.ip4 = NULL;
 
1047
        }
 
1048
        return URI_TRUE; /* Success */
 
1049
}
 
1050
 
 
1051
 
 
1052
 
 
1053
/*
 
1054
 * [ownHostUserInfo]->[ownHostUserInfoNz]
 
1055
 * [ownHostUserInfo]-><NULL>
 
1056
 */
 
1057
static URI_INLINE const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1058
        if (first >= afterLast) {
 
1059
                if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first)) {
 
1060
                        URI_FUNC(StopMalloc)(state);
 
1061
                        return NULL;
 
1062
                }
 
1063
                return afterLast;
 
1064
        }
 
1065
 
 
1066
        switch (*first) {
 
1067
        case _UT('!'):
 
1068
        case _UT('$'):
 
1069
        case _UT('%'):
 
1070
        case _UT('&'):
 
1071
        case _UT('('):
 
1072
        case _UT(')'):
 
1073
        case _UT('-'):
 
1074
        case _UT('*'):
 
1075
        case _UT(','):
 
1076
        case _UT('.'):
 
1077
        case _UT(':'):
 
1078
        case _UT(';'):
 
1079
        case _UT('@'):
 
1080
        case _UT('\''):
 
1081
        case _UT('_'):
 
1082
        case _UT('~'):
 
1083
        case _UT('+'):
 
1084
        case _UT('='):
 
1085
        case URI_SET_DIGIT:
 
1086
        case URI_SET_ALPHA:
 
1087
                return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast);
 
1088
 
 
1089
        default:
 
1090
                if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first)) {
 
1091
                        URI_FUNC(StopMalloc)(state);
 
1092
                        return NULL;
 
1093
                }
 
1094
                return first;
 
1095
        }
 
1096
}
 
1097
 
 
1098
 
 
1099
 
 
1100
/*
 
1101
 * [ownHostUserInfoNz]->[pctSubUnres][ownHostUserInfo]
 
1102
 * [ownHostUserInfoNz]-><:>[ownPortUserInfo]
 
1103
 * [ownHostUserInfoNz]-><@>[ownHost]
 
1104
 */
 
1105
static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1106
        if (first >= afterLast) {
 
1107
                URI_FUNC(StopSyntax)(state, first);
 
1108
                return NULL;
 
1109
        }
 
1110
 
 
1111
        switch (*first) {
 
1112
        case _UT('!'):
 
1113
        case _UT('$'):
 
1114
        case _UT('%'):
 
1115
        case _UT('&'):
 
1116
        case _UT('('):
 
1117
        case _UT(')'):
 
1118
        case _UT('-'):
 
1119
        case _UT('*'):
 
1120
        case _UT(','):
 
1121
        case _UT('.'):
 
1122
        case _UT(';'):
 
1123
        case _UT('\''):
 
1124
        case _UT('_'):
 
1125
        case _UT('~'):
 
1126
        case _UT('+'):
 
1127
        case _UT('='):
 
1128
        case URI_SET_DIGIT:
 
1129
        case URI_SET_ALPHA:
 
1130
                {
 
1131
                        const URI_CHAR * const afterPctSubUnres
 
1132
                                        = URI_FUNC(ParsePctSubUnres)(state, first, afterLast);
 
1133
                        if (afterPctSubUnres == NULL) {
 
1134
                                return NULL;
 
1135
                        }
 
1136
                        return URI_FUNC(ParseOwnHostUserInfo)(state, afterPctSubUnres, afterLast);
 
1137
                }
 
1138
 
 
1139
        case _UT(':'):
 
1140
                state->uri->hostText.afterLast = first; /* HOST END */
 
1141
                state->uri->portText.first = first + 1; /* PORT BEGIN */
 
1142
                return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast);
 
1143
 
 
1144
        case _UT('@'):
 
1145
                state->uri->userInfo.afterLast = first; /* USERINFO END */
 
1146
                state->uri->hostText.first = first + 1; /* HOST BEGIN */
 
1147
                return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast);
 
1148
 
 
1149
        default:
 
1150
                URI_FUNC(StopSyntax)(state, first);
 
1151
                return NULL;
 
1152
        }
 
1153
}
 
1154
 
 
1155
 
 
1156
 
 
1157
static URI_INLINE UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first) {
 
1158
        state->uri->hostText.first = state->uri->userInfo.first; /* Host instead of userInfo, update */
 
1159
        state->uri->userInfo.first = NULL; /* Not a userInfo, reset */
 
1160
        state->uri->portText.afterLast = first; /* PORT END */
 
1161
 
 
1162
        /* Valid IPv4 or just a regname? */
 
1163
        state->uri->hostData.ip4 = malloc(1 * sizeof(UriIp4)); /* Freed when stopping on parse error */
 
1164
        if (state->uri->hostData.ip4 == NULL) {
 
1165
                return URI_FALSE; /* Raises malloc error */
 
1166
        }
 
1167
        if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,
 
1168
                        state->uri->hostText.first, state->uri->hostText.afterLast)) {
 
1169
                /* Not IPv4 */
 
1170
                free(state->uri->hostData.ip4);
 
1171
                state->uri->hostData.ip4 = NULL;
 
1172
        }
 
1173
        return URI_TRUE; /* Success */
 
1174
}
 
1175
 
 
1176
 
 
1177
 
 
1178
/*
 
1179
 * [ownPortUserInfo]->[ALPHA][ownUserInfo]
 
1180
 * [ownPortUserInfo]->[DIGIT][ownPortUserInfo]
 
1181
 * [ownPortUserInfo]-><.>[ownUserInfo]
 
1182
 * [ownPortUserInfo]-><_>[ownUserInfo]
 
1183
 * [ownPortUserInfo]-><~>[ownUserInfo]
 
1184
 * [ownPortUserInfo]-><->[ownUserInfo]
 
1185
 * [ownPortUserInfo]-><NULL>
 
1186
 */
 
1187
static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1188
        if (first >= afterLast) {
 
1189
                if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first)) {
 
1190
                        URI_FUNC(StopMalloc)(state);
 
1191
                        return NULL;
 
1192
                }
 
1193
                return afterLast;
 
1194
        }
 
1195
 
 
1196
        switch (*first) {
 
1197
        case _UT('.'):
 
1198
        case _UT('_'):
 
1199
        case _UT('~'):
 
1200
        case _UT('-'):
 
1201
        case URI_SET_ALPHA:
 
1202
                state->uri->hostText.afterLast = NULL; /* Not a host, reset */
 
1203
                state->uri->portText.first = NULL; /* Not a port, reset */
 
1204
                return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast);
 
1205
 
 
1206
        case URI_SET_DIGIT:
 
1207
                return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast);
 
1208
 
 
1209
        default:
 
1210
                if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first)) {
 
1211
                        URI_FUNC(StopMalloc)(state);
 
1212
                        return NULL;
 
1213
                }
 
1214
                return first;
 
1215
        }
 
1216
}
 
1217
 
 
1218
 
 
1219
 
 
1220
/*
 
1221
 * [ownUserInfo]->[pctSubUnres][ownUserInfo]
 
1222
 * [ownUserInfo]-><:>[ownUserInfo]
 
1223
 * [ownUserInfo]-><@>[ownHost]
 
1224
 */
 
1225
static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1226
        if (first >= afterLast) {
 
1227
                URI_FUNC(StopSyntax)(state, first);
 
1228
                return NULL;
 
1229
        }
 
1230
 
 
1231
        switch (*first) {
 
1232
        case _UT('!'):
 
1233
        case _UT('$'):
 
1234
        case _UT('%'):
 
1235
        case _UT('&'):
 
1236
        case _UT('('):
 
1237
        case _UT(')'):
 
1238
        case _UT('-'):
 
1239
        case _UT('*'):
 
1240
        case _UT(','):
 
1241
        case _UT('.'):
 
1242
        case _UT(';'):
 
1243
        case _UT('\''):
 
1244
        case _UT('_'):
 
1245
        case _UT('~'):
 
1246
        case _UT('+'):
 
1247
        case _UT('='):
 
1248
        case URI_SET_DIGIT:
 
1249
        case URI_SET_ALPHA:
 
1250
                {
 
1251
                        const URI_CHAR * const afterPctSubUnres
 
1252
                                        = URI_FUNC(ParsePctSubUnres)(state, first, afterLast);
 
1253
                        if (afterPctSubUnres == NULL) {
 
1254
                                return NULL;
 
1255
                        }
 
1256
                        return URI_FUNC(ParseOwnUserInfo)(state, afterPctSubUnres, afterLast);
 
1257
                }
 
1258
 
 
1259
        case _UT(':'):
 
1260
                return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast);
 
1261
 
 
1262
        case _UT('@'):
 
1263
                /* SURE */
 
1264
                state->uri->userInfo.afterLast = first; /* USERINFO END */
 
1265
                state->uri->hostText.first = first + 1; /* HOST BEGIN */
 
1266
                return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast);
 
1267
 
 
1268
        default:
 
1269
                URI_FUNC(StopSyntax)(state, first);
 
1270
                return NULL;
 
1271
        }
 
1272
}
 
1273
 
 
1274
 
 
1275
 
 
1276
static URI_INLINE void URI_FUNC(OnExitPartHelperTwo)(URI_TYPE(ParserState) * state) {
 
1277
        state->uri->absolutePath = URI_TRUE;
 
1278
}
 
1279
 
 
1280
 
 
1281
 
 
1282
/*
 
1283
 * [partHelperTwo]->[pathAbsNoLeadSlash] // can take <NULL>
 
1284
 * [partHelperTwo]-></>[authority][pathAbsEmpty]
 
1285
 */
 
1286
static URI_INLINE const URI_CHAR * URI_FUNC(ParsePartHelperTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1287
        if (first >= afterLast) {
 
1288
                URI_FUNC(OnExitPartHelperTwo)(state);
 
1289
                return afterLast;
 
1290
        }
 
1291
 
 
1292
        switch (*first) {
 
1293
        case _UT('/'):
 
1294
                {
 
1295
                        const URI_CHAR * const afterAuthority
 
1296
                                        = URI_FUNC(ParseAuthority)(state, first + 1, afterLast);
 
1297
                        const URI_CHAR * afterPathAbsEmpty;
 
1298
                        if (afterAuthority == NULL) {
 
1299
                                return NULL;
 
1300
                        }
 
1301
                        afterPathAbsEmpty = URI_FUNC(ParsePathAbsEmpty)(state, afterAuthority, afterLast);
 
1302
 
 
1303
                        /* Fix path if only one empty segment */
 
1304
                        if ((state->uri->pathHead != NULL)
 
1305
                                        && (state->uri->pathHead->next == NULL)
 
1306
                                        && (state->uri->pathHead->text.first == state->uri->pathHead->text.afterLast)) {
 
1307
                                free(state->uri->pathHead);
 
1308
                                state->uri->pathHead = NULL;
 
1309
                                state->uri->pathTail = NULL;
 
1310
                        }
 
1311
 
 
1312
                        return afterPathAbsEmpty;
 
1313
                }
 
1314
 
 
1315
        default:
 
1316
                URI_FUNC(OnExitPartHelperTwo)(state);
 
1317
                return URI_FUNC(ParsePathAbsNoLeadSlash)(state, first, afterLast);
 
1318
        }
 
1319
}
 
1320
 
 
1321
 
 
1322
 
 
1323
/*
 
1324
 * [pathAbsEmpty]-></>[segment][pathAbsEmpty]
 
1325
 * [pathAbsEmpty]-><NULL>
 
1326
 */
 
1327
static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1328
        if (first >= afterLast) {
 
1329
                return afterLast;
 
1330
        }
 
1331
 
 
1332
        switch (*first) {
 
1333
        case _UT('/'):
 
1334
                {
 
1335
                        const URI_CHAR * const afterSegment
 
1336
                                        = URI_FUNC(ParseSegment)(state, first + 1, afterLast);
 
1337
                        if (afterSegment == NULL) {
 
1338
                                return NULL;
 
1339
                        }
 
1340
                        if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */
 
1341
                                URI_FUNC(StopMalloc)(state);
 
1342
                                return NULL;
 
1343
                        }
 
1344
                        return URI_FUNC(ParsePathAbsEmpty)(state, afterSegment, afterLast);
 
1345
                }
 
1346
 
 
1347
        default:
 
1348
                return first;
 
1349
        }
 
1350
}
 
1351
 
 
1352
 
 
1353
 
 
1354
/*
 
1355
 * [pathAbsNoLeadSlash]->[segmentNz][zeroMoreSlashSegs]
 
1356
 * [pathAbsNoLeadSlash]-><NULL>
 
1357
 */
 
1358
static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1359
        if (first >= afterLast) {
 
1360
                return afterLast;
 
1361
        }
 
1362
 
 
1363
        switch (*first) {
 
1364
        case _UT('!'):
 
1365
        case _UT('$'):
 
1366
        case _UT('%'):
 
1367
        case _UT('&'):
 
1368
        case _UT('('):
 
1369
        case _UT(')'):
 
1370
        case _UT('-'):
 
1371
        case _UT('*'):
 
1372
        case _UT(','):
 
1373
        case _UT('.'):
 
1374
        case _UT(':'):
 
1375
        case _UT(';'):
 
1376
        case _UT('@'):
 
1377
        case _UT('\''):
 
1378
        case _UT('_'):
 
1379
        case _UT('~'):
 
1380
        case _UT('+'):
 
1381
        case _UT('='):
 
1382
        case URI_SET_DIGIT:
 
1383
        case URI_SET_ALPHA:
 
1384
                {
 
1385
                        const URI_CHAR * const afterSegmentNz
 
1386
                                        = URI_FUNC(ParseSegmentNz)(state, first, afterLast);
 
1387
                        if (afterSegmentNz == NULL) {
 
1388
                                return NULL;
 
1389
                        }
 
1390
                        if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz)) { /* SEGMENT BOTH */
 
1391
                                URI_FUNC(StopMalloc)(state);
 
1392
                                return NULL;
 
1393
                        }
 
1394
                        return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast);
 
1395
                }
 
1396
 
 
1397
        default:
 
1398
                return first;
 
1399
        }
 
1400
}
 
1401
 
 
1402
 
 
1403
 
 
1404
/*
 
1405
 * [pathRootless]->[segmentNz][zeroMoreSlashSegs]
 
1406
 */
 
1407
static URI_INLINE const URI_CHAR * URI_FUNC(ParsePathRootless)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1408
        const URI_CHAR * const afterSegmentNz
 
1409
                        = URI_FUNC(ParseSegmentNz)(state, first, afterLast);
 
1410
        if (afterSegmentNz == NULL) {
 
1411
                return NULL;
 
1412
        } else {
 
1413
                if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz)) { /* SEGMENT BOTH */
 
1414
                        URI_FUNC(StopMalloc)(state);
 
1415
                        return NULL;
 
1416
                }
 
1417
        }
 
1418
        return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast);
 
1419
}
 
1420
 
 
1421
 
 
1422
 
 
1423
/*
 
1424
 * [pchar]->[pctEncoded]
 
1425
 * [pchar]->[subDelims]
 
1426
 * [pchar]->[unreserved]
 
1427
 * [pchar]-><:>
 
1428
 * [pchar]-><@>
 
1429
 */
 
1430
static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1431
        if (first >= afterLast) {
 
1432
                URI_FUNC(StopSyntax)(state, first);
 
1433
                return NULL;
 
1434
        }
 
1435
 
 
1436
        switch (*first) {
 
1437
        case _UT('%'):
 
1438
                return URI_FUNC(ParsePctEncoded)(state, first, afterLast);
 
1439
 
 
1440
        case _UT(':'):
 
1441
        case _UT('@'):
 
1442
        case _UT('!'):
 
1443
        case _UT('$'):
 
1444
        case _UT('&'):
 
1445
        case _UT('('):
 
1446
        case _UT(')'):
 
1447
        case _UT('*'):
 
1448
        case _UT(','):
 
1449
        case _UT(';'):
 
1450
        case _UT('\''):
 
1451
        case _UT('+'):
 
1452
        case _UT('='):
 
1453
        case _UT('-'):
 
1454
        case _UT('.'):
 
1455
        case _UT('_'):
 
1456
        case _UT('~'):
 
1457
        case URI_SET_DIGIT:
 
1458
        case URI_SET_ALPHA:
 
1459
                return first + 1;
 
1460
 
 
1461
        default:
 
1462
                URI_FUNC(StopSyntax)(state, first);
 
1463
                return NULL;
 
1464
        }
 
1465
}
 
1466
 
 
1467
 
 
1468
 
 
1469
/*
 
1470
 * [pctEncoded]-><%>[HEXDIG][HEXDIG]
 
1471
 */
 
1472
static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1473
        if (first >= afterLast) {
 
1474
                URI_FUNC(StopSyntax)(state, first);
 
1475
                return NULL;
 
1476
        }
 
1477
 
 
1478
        /*
 
1479
        First character has already been
 
1480
        checked before entering this rule.
 
1481
 
 
1482
        switch (*first) {
 
1483
        case _UT('%'):
 
1484
        */
 
1485
                if (first + 1 >= afterLast) {
 
1486
                        URI_FUNC(StopSyntax)(state, first + 1);
 
1487
                        return NULL;
 
1488
                }
 
1489
 
 
1490
                switch (first[1]) {
 
1491
                case URI_SET_HEXDIG:
 
1492
                        if (first + 2 >= afterLast) {
 
1493
                                URI_FUNC(StopSyntax)(state, first + 2);
 
1494
                                return NULL;
 
1495
                        }
 
1496
 
 
1497
                        switch (first[2]) {
 
1498
                        case URI_SET_HEXDIG:
 
1499
                                return first + 3;
 
1500
 
 
1501
                        default:
 
1502
                                URI_FUNC(StopSyntax)(state, first + 2);
 
1503
                                return NULL;
 
1504
                        }
 
1505
 
 
1506
                default:
 
1507
                        URI_FUNC(StopSyntax)(state, first + 1);
 
1508
                        return NULL;
 
1509
                }
 
1510
 
 
1511
        /*
 
1512
        default:
 
1513
                URI_FUNC(StopSyntax)(state, first);
 
1514
                return NULL;
 
1515
        }
 
1516
        */
 
1517
}
 
1518
 
 
1519
 
 
1520
 
 
1521
/*
 
1522
 * [pctSubUnres]->[pctEncoded]
 
1523
 * [pctSubUnres]->[subDelims]
 
1524
 * [pctSubUnres]->[unreserved]
 
1525
 */
 
1526
static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1527
        if (first >= afterLast) {
 
1528
                URI_FUNC(StopSyntax)(state, first);
 
1529
                return NULL;
 
1530
        }
 
1531
 
 
1532
        switch (*first) {
 
1533
        case _UT('%'):
 
1534
                return URI_FUNC(ParsePctEncoded)(state, first, afterLast);
 
1535
 
 
1536
        case _UT('!'):
 
1537
        case _UT('$'):
 
1538
        case _UT('&'):
 
1539
        case _UT('('):
 
1540
        case _UT(')'):
 
1541
        case _UT('*'):
 
1542
        case _UT(','):
 
1543
        case _UT(';'):
 
1544
        case _UT('\''):
 
1545
        case _UT('+'):
 
1546
        case _UT('='):
 
1547
        case _UT('-'):
 
1548
        case _UT('.'):
 
1549
        case _UT('_'):
 
1550
        case _UT('~'):
 
1551
        case URI_SET_DIGIT:
 
1552
        case URI_SET_ALPHA:
 
1553
                return first + 1;
 
1554
 
 
1555
        default:
 
1556
                URI_FUNC(StopSyntax)(state, first);
 
1557
                return NULL;
 
1558
        }
 
1559
}
 
1560
 
 
1561
 
 
1562
 
 
1563
/*
 
1564
 * [port]->[DIGIT][port]
 
1565
 * [port]-><NULL>
 
1566
 */
 
1567
static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1568
        if (first >= afterLast) {
 
1569
                return afterLast;
 
1570
        }
 
1571
 
 
1572
        switch (*first) {
 
1573
        case URI_SET_DIGIT:
 
1574
                return URI_FUNC(ParsePort)(state, first + 1, afterLast);
 
1575
 
 
1576
        default:
 
1577
                return first;
 
1578
        }
 
1579
}
 
1580
 
 
1581
 
 
1582
 
 
1583
/*
 
1584
 * [queryFrag]->[pchar][queryFrag]
 
1585
 * [queryFrag]-></>[queryFrag]
 
1586
 * [queryFrag]-><?>[queryFrag]
 
1587
 * [queryFrag]-><NULL>
 
1588
 */
 
1589
static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1590
        if (first >= afterLast) {
 
1591
                return afterLast;
 
1592
        }
 
1593
 
 
1594
        switch (*first) {
 
1595
        case _UT('!'):
 
1596
        case _UT('$'):
 
1597
        case _UT('%'):
 
1598
        case _UT('&'):
 
1599
        case _UT('('):
 
1600
        case _UT(')'):
 
1601
        case _UT('-'):
 
1602
        case _UT('*'):
 
1603
        case _UT(','):
 
1604
        case _UT('.'):
 
1605
        case _UT(':'):
 
1606
        case _UT(';'):
 
1607
        case _UT('@'):
 
1608
        case _UT('\''):
 
1609
        case _UT('_'):
 
1610
        case _UT('~'):
 
1611
        case _UT('+'):
 
1612
        case _UT('='):
 
1613
        case URI_SET_DIGIT:
 
1614
        case URI_SET_ALPHA:
 
1615
                {
 
1616
                        const URI_CHAR * const afterPchar
 
1617
                                        = URI_FUNC(ParsePchar)(state, first, afterLast);
 
1618
                        if (afterPchar == NULL) {
 
1619
                                return NULL;
 
1620
                        }
 
1621
                        return URI_FUNC(ParseQueryFrag)(state, afterPchar, afterLast);
 
1622
                }
 
1623
 
 
1624
        case _UT('/'):
 
1625
        case _UT('?'):
 
1626
                return URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast);
 
1627
 
 
1628
        default:
 
1629
                return first;
 
1630
        }
 
1631
}
 
1632
 
 
1633
 
 
1634
 
 
1635
/*
 
1636
 * [segment]->[pchar][segment]
 
1637
 * [segment]-><NULL>
 
1638
 */
 
1639
static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1640
        if (first >= afterLast) {
 
1641
                return afterLast;
 
1642
        }
 
1643
 
 
1644
        switch (*first) {
 
1645
        case _UT('!'):
 
1646
        case _UT('$'):
 
1647
        case _UT('%'):
 
1648
        case _UT('&'):
 
1649
        case _UT('('):
 
1650
        case _UT(')'):
 
1651
        case _UT('-'):
 
1652
        case _UT('*'):
 
1653
        case _UT(','):
 
1654
        case _UT('.'):
 
1655
        case _UT(':'):
 
1656
        case _UT(';'):
 
1657
        case _UT('@'):
 
1658
        case _UT('\''):
 
1659
        case _UT('_'):
 
1660
        case _UT('~'):
 
1661
        case _UT('+'):
 
1662
        case _UT('='):
 
1663
        case URI_SET_DIGIT:
 
1664
        case URI_SET_ALPHA:
 
1665
                {
 
1666
                        const URI_CHAR * const afterPchar
 
1667
                                        = URI_FUNC(ParsePchar)(state, first, afterLast);
 
1668
                        if (afterPchar == NULL) {
 
1669
                                return NULL;
 
1670
                        }
 
1671
                        return URI_FUNC(ParseSegment)(state, afterPchar, afterLast);
 
1672
                }
 
1673
 
 
1674
        default:
 
1675
                return first;
 
1676
        }
 
1677
}
 
1678
 
 
1679
 
 
1680
 
 
1681
/*
 
1682
 * [segmentNz]->[pchar][segment]
 
1683
 */
 
1684
static URI_INLINE const URI_CHAR * URI_FUNC(ParseSegmentNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1685
        const URI_CHAR * const afterPchar
 
1686
                        = URI_FUNC(ParsePchar)(state, first, afterLast);
 
1687
        if (afterPchar == NULL) {
 
1688
                return NULL;
 
1689
        }
 
1690
        return URI_FUNC(ParseSegment)(state, afterPchar, afterLast);
 
1691
}
 
1692
 
 
1693
 
 
1694
 
 
1695
static URI_INLINE UriBool URI_FUNC(OnExitSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first) {
 
1696
        if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */
 
1697
                return URI_FALSE; /* Raises malloc error*/
 
1698
        }
 
1699
        state->uri->scheme.first = NULL; /* Not a scheme, reset */
 
1700
        return URI_TRUE; /* Success */
 
1701
}
 
1702
 
 
1703
 
 
1704
 
 
1705
/*
 
1706
 * [segmentNzNcOrScheme2]->[ALPHA][segmentNzNcOrScheme2]
 
1707
 * [segmentNzNcOrScheme2]->[DIGIT][segmentNzNcOrScheme2]
 
1708
 * [segmentNzNcOrScheme2]->[pctEncoded][mustBeSegmentNzNc]
 
1709
 * [segmentNzNcOrScheme2]->[uriTail] // can take <NULL>
 
1710
 * [segmentNzNcOrScheme2]-><!>[mustBeSegmentNzNc]
 
1711
 * [segmentNzNcOrScheme2]-><$>[mustBeSegmentNzNc]
 
1712
 * [segmentNzNcOrScheme2]-><&>[mustBeSegmentNzNc]
 
1713
 * [segmentNzNcOrScheme2]-><(>[mustBeSegmentNzNc]
 
1714
 * [segmentNzNcOrScheme2]-><)>[mustBeSegmentNzNc]
 
1715
 * [segmentNzNcOrScheme2]-><*>[mustBeSegmentNzNc]
 
1716
 * [segmentNzNcOrScheme2]-><,>[mustBeSegmentNzNc]
 
1717
 * [segmentNzNcOrScheme2]-><.>[segmentNzNcOrScheme2]
 
1718
 * [segmentNzNcOrScheme2]-></>[segment][zeroMoreSlashSegs][uriTail]
 
1719
 * [segmentNzNcOrScheme2]-><:>[hierPart][uriTail]
 
1720
 * [segmentNzNcOrScheme2]-><;>[mustBeSegmentNzNc]
 
1721
 * [segmentNzNcOrScheme2]-><@>[mustBeSegmentNzNc]
 
1722
 * [segmentNzNcOrScheme2]-><_>[mustBeSegmentNzNc]
 
1723
 * [segmentNzNcOrScheme2]-><~>[mustBeSegmentNzNc]
 
1724
 * [segmentNzNcOrScheme2]-><+>[segmentNzNcOrScheme2]
 
1725
 * [segmentNzNcOrScheme2]-><=>[mustBeSegmentNzNc]
 
1726
 * [segmentNzNcOrScheme2]-><'>[mustBeSegmentNzNc]
 
1727
 * [segmentNzNcOrScheme2]-><->[segmentNzNcOrScheme2]
 
1728
 */
 
1729
static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1730
        if (first >= afterLast) {
 
1731
                if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first)) {
 
1732
                        URI_FUNC(StopMalloc)(state);
 
1733
                        return NULL;
 
1734
                }
 
1735
                return afterLast;
 
1736
        }
 
1737
 
 
1738
        switch (*first) {
 
1739
        case _UT('.'):
 
1740
        case _UT('+'):
 
1741
        case _UT('-'):
 
1742
        case URI_SET_ALPHA:
 
1743
        case URI_SET_DIGIT:
 
1744
                return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast);
 
1745
 
 
1746
        case _UT('%'):
 
1747
                {
 
1748
                        const URI_CHAR * const afterPctEncoded
 
1749
                                        = URI_FUNC(ParsePctEncoded)(state, first, afterLast);
 
1750
                        if (afterPctEncoded == NULL) {
 
1751
                                return NULL;
 
1752
                        }
 
1753
                        return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast);
 
1754
                }
 
1755
 
 
1756
        case _UT('!'):
 
1757
        case _UT('$'):
 
1758
        case _UT('&'):
 
1759
        case _UT('('):
 
1760
        case _UT(')'):
 
1761
        case _UT('*'):
 
1762
        case _UT(','):
 
1763
        case _UT(';'):
 
1764
        case _UT('@'):
 
1765
        case _UT('_'):
 
1766
        case _UT('~'):
 
1767
        case _UT('='):
 
1768
        case _UT('\''):
 
1769
                return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast);
 
1770
 
 
1771
        case _UT('/'):
 
1772
                {
 
1773
                        const URI_CHAR * afterZeroMoreSlashSegs;
 
1774
                        const URI_CHAR * const afterSegment
 
1775
                                        = URI_FUNC(ParseSegment)(state, first + 1, afterLast);
 
1776
                        if (afterSegment == NULL) {
 
1777
                                return NULL;
 
1778
                        }
 
1779
                        if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */
 
1780
                                URI_FUNC(StopMalloc)(state);
 
1781
                                return NULL;
 
1782
                        }
 
1783
                        state->uri->scheme.first = NULL; /* Not a scheme, reset */
 
1784
                        if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */
 
1785
                                URI_FUNC(StopMalloc)(state);
 
1786
                                return NULL;
 
1787
                        }
 
1788
                        afterZeroMoreSlashSegs
 
1789
                                        = URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast);
 
1790
                        if (afterZeroMoreSlashSegs == NULL) {
 
1791
                                return NULL;
 
1792
                        }
 
1793
                        return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast);
 
1794
                }
 
1795
 
 
1796
        case _UT(':'):
 
1797
                {
 
1798
                        const URI_CHAR * const afterHierPart
 
1799
                                        = URI_FUNC(ParseHierPart)(state, first + 1, afterLast);
 
1800
                        state->uri->scheme.afterLast = first; /* SCHEME END */
 
1801
                        if (afterHierPart == NULL) {
 
1802
                                return NULL;
 
1803
                        }
 
1804
                        return URI_FUNC(ParseUriTail)(state, afterHierPart, afterLast);
 
1805
                }
 
1806
 
 
1807
        default:
 
1808
                if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first)) {
 
1809
                        URI_FUNC(StopMalloc)(state);
 
1810
                        return NULL;
 
1811
                }
 
1812
                return URI_FUNC(ParseUriTail)(state, first, afterLast);
 
1813
        }
 
1814
}
 
1815
 
 
1816
 
 
1817
 
 
1818
/*
 
1819
 * [uriReference]->[ALPHA][segmentNzNcOrScheme2]
 
1820
 * [uriReference]->[DIGIT][mustBeSegmentNzNc]
 
1821
 * [uriReference]->[pctEncoded][mustBeSegmentNzNc]
 
1822
 * [uriReference]->[subDelims][mustBeSegmentNzNc]
 
1823
 * [uriReference]->[uriTail] // can take <NULL>
 
1824
 * [uriReference]-><.>[mustBeSegmentNzNc]
 
1825
 * [uriReference]-></>[partHelperTwo][uriTail]
 
1826
 * [uriReference]-><@>[mustBeSegmentNzNc]
 
1827
 * [uriReference]-><_>[mustBeSegmentNzNc]
 
1828
 * [uriReference]-><~>[mustBeSegmentNzNc]
 
1829
 * [uriReference]-><->[mustBeSegmentNzNc]
 
1830
 */
 
1831
static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1832
        if (first >= afterLast) {
 
1833
                return afterLast;
 
1834
        }
 
1835
 
 
1836
        switch (*first) {
 
1837
        case URI_SET_ALPHA:
 
1838
                state->uri->scheme.first = first; /* SCHEME BEGIN */
 
1839
                return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast);
 
1840
 
 
1841
        case URI_SET_DIGIT:
 
1842
        case _UT('!'):
 
1843
        case _UT('$'):
 
1844
        case _UT('&'):
 
1845
        case _UT('('):
 
1846
        case _UT(')'):
 
1847
        case _UT('*'):
 
1848
        case _UT(','):
 
1849
        case _UT(';'):
 
1850
        case _UT('\''):
 
1851
        case _UT('+'):
 
1852
        case _UT('='):
 
1853
        case _UT('.'):
 
1854
        case _UT('_'):
 
1855
        case _UT('~'):
 
1856
        case _UT('-'):
 
1857
        case _UT('@'):
 
1858
                state->uri->scheme.first = first; /* SCHEME BEGIN */
 
1859
                return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast);
 
1860
 
 
1861
        case _UT('%'):
 
1862
                {
 
1863
                        const URI_CHAR * const afterPctEncoded
 
1864
                                        = URI_FUNC(ParsePctEncoded)(state, first, afterLast);
 
1865
                        if (afterPctEncoded == NULL) {
 
1866
                                return NULL;
 
1867
                        }
 
1868
                        state->uri->scheme.first = first; /* SCHEME BEGIN */
 
1869
                        return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast);
 
1870
                }
 
1871
 
 
1872
        case _UT('/'):
 
1873
                {
 
1874
                        const URI_CHAR * const afterPartHelperTwo
 
1875
                                        = URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast);
 
1876
                        if (afterPartHelperTwo == NULL) {
 
1877
                                return NULL;
 
1878
                        }
 
1879
                        return URI_FUNC(ParseUriTail)(state, afterPartHelperTwo, afterLast);
 
1880
                }
 
1881
 
 
1882
        default:
 
1883
                return URI_FUNC(ParseUriTail)(state, first, afterLast);
 
1884
        }
 
1885
}
 
1886
 
 
1887
 
 
1888
 
 
1889
/*
 
1890
 * [uriTail]-><#>[queryFrag]
 
1891
 * [uriTail]-><?>[queryFrag][uriTailTwo]
 
1892
 * [uriTail]-><NULL>
 
1893
 */
 
1894
static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTail)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1895
        if (first >= afterLast) {
 
1896
                return afterLast;
 
1897
        }
 
1898
 
 
1899
        switch (*first) {
 
1900
        case _UT('#'):
 
1901
                {
 
1902
                        const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast);
 
1903
                        if (afterQueryFrag == NULL) {
 
1904
                                return NULL;
 
1905
                        }
 
1906
                        state->uri->fragment.first = first + 1; /* FRAGMENT BEGIN */
 
1907
                        state->uri->fragment.afterLast = afterQueryFrag; /* FRAGMENT END */
 
1908
                        return afterQueryFrag;
 
1909
                }
 
1910
 
 
1911
        case _UT('?'):
 
1912
                {
 
1913
                        const URI_CHAR * const afterQueryFrag
 
1914
                                        = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast);
 
1915
                        if (afterQueryFrag == NULL) {
 
1916
                                return NULL;
 
1917
                        }
 
1918
                        state->uri->query.first = first + 1; /* QUERY BEGIN */
 
1919
                        state->uri->query.afterLast = afterQueryFrag; /* QUERY END */
 
1920
                        return URI_FUNC(ParseUriTailTwo)(state, afterQueryFrag, afterLast);
 
1921
                }
 
1922
 
 
1923
        default:
 
1924
                return first;
 
1925
        }
 
1926
}
 
1927
 
 
1928
 
 
1929
 
 
1930
/*
 
1931
 * [uriTailTwo]-><#>[queryFrag]
 
1932
 * [uriTailTwo]-><NULL>
 
1933
 */
 
1934
static URI_INLINE const URI_CHAR * URI_FUNC(ParseUriTailTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1935
        if (first >= afterLast) {
 
1936
                return afterLast;
 
1937
        }
 
1938
 
 
1939
        switch (*first) {
 
1940
        case _UT('#'):
 
1941
                {
 
1942
                        const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast);
 
1943
                        if (afterQueryFrag == NULL) {
 
1944
                                return NULL;
 
1945
                        }
 
1946
                        state->uri->fragment.first = first + 1; /* FRAGMENT BEGIN */
 
1947
                        state->uri->fragment.afterLast = afterQueryFrag; /* FRAGMENT END */
 
1948
                        return afterQueryFrag;
 
1949
                }
 
1950
 
 
1951
        default:
 
1952
                return first;
 
1953
        }
 
1954
}
 
1955
 
 
1956
 
 
1957
 
 
1958
/*
 
1959
 * [zeroMoreSlashSegs]-></>[segment][zeroMoreSlashSegs]
 
1960
 * [zeroMoreSlashSegs]-><NULL>
 
1961
 */
 
1962
static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1963
        if (first >= afterLast) {
 
1964
                return afterLast;
 
1965
        }
 
1966
 
 
1967
        switch (*first) {
 
1968
        case _UT('/'):
 
1969
                {
 
1970
                        const URI_CHAR * const afterSegment
 
1971
                                        = URI_FUNC(ParseSegment)(state, first + 1, afterLast);
 
1972
                        if (afterSegment == NULL) {
 
1973
                                return NULL;
 
1974
                        }
 
1975
                        if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */
 
1976
                                URI_FUNC(StopMalloc)(state);
 
1977
                                return NULL;
 
1978
                        }
 
1979
                        return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast);
 
1980
                }
 
1981
 
 
1982
        default:
 
1983
                return first;
 
1984
        }
 
1985
}
 
1986
 
 
1987
 
 
1988
 
 
1989
static URI_INLINE void URI_FUNC(ResetParserState)(URI_TYPE(ParserState) * state) {
 
1990
        URI_TYPE(Uri) * const uriBackup = state->uri;
 
1991
        memset(state, 0, sizeof(URI_TYPE(ParserState)));
 
1992
        state->uri = uriBackup;
 
1993
}
 
1994
 
 
1995
 
 
1996
 
 
1997
static URI_INLINE UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
1998
        URI_TYPE(PathSegment) * segment = malloc(1 * sizeof(URI_TYPE(PathSegment)));
 
1999
        if (segment == NULL) {
 
2000
                return URI_FALSE; /* Raises malloc error */
 
2001
        }
 
2002
        memset(segment, 0, sizeof(URI_TYPE(PathSegment)));
 
2003
        if (first == afterLast) {
 
2004
                segment->text.first = URI_FUNC(SafeToPointTo);
 
2005
                segment->text.afterLast = URI_FUNC(SafeToPointTo);
 
2006
        } else {
 
2007
                segment->text.first = first;
 
2008
                segment->text.afterLast = afterLast;
 
2009
        }
 
2010
 
 
2011
        /* First segment ever? */
 
2012
        if (state->uri->pathHead == NULL) {
 
2013
                /* First segement ever, set head and tail */
 
2014
                state->uri->pathHead = segment;
 
2015
                state->uri->pathTail = segment;
 
2016
        } else {
 
2017
                /* Append, update tail */
 
2018
                state->uri->pathTail->next = segment;
 
2019
                state->uri->pathTail = segment;
 
2020
        }
 
2021
 
 
2022
        return URI_TRUE; /* Success */
 
2023
}
 
2024
 
 
2025
 
 
2026
 
 
2027
int URI_FUNC(ParseUriEx)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
 
2028
        const URI_CHAR * afterUriReference;
 
2029
        URI_TYPE(Uri) * uri;
 
2030
 
 
2031
        /* Check params */
 
2032
        if ((state == NULL) || (state == NULL) || (state == NULL)) {
 
2033
                return URI_ERROR_NULL;
 
2034
        }
 
2035
        uri = state->uri;
 
2036
 
 
2037
        /* Init parser */
 
2038
        URI_FUNC(ResetParserState)(state);
 
2039
        URI_FUNC(ResetUri)(uri);
 
2040
 
 
2041
        /* Parse */
 
2042
        afterUriReference = URI_FUNC(ParseUriReference)(state, first, afterLast);
 
2043
        if (afterUriReference == NULL) {
 
2044
                return state->errorCode;
 
2045
        }
 
2046
        if (afterUriReference != afterLast) {
 
2047
                return URI_ERROR_SYNTAX;
 
2048
        }
 
2049
        return URI_SUCCESS;
 
2050
}
 
2051
 
 
2052
 
 
2053
 
 
2054
int URI_FUNC(ParseUri)(URI_TYPE(ParserState) * state, const URI_CHAR * text) {
 
2055
        if ((state == NULL) || (text == NULL)) {
 
2056
                return URI_ERROR_NULL;
 
2057
        }
 
2058
        return URI_FUNC(ParseUriEx)(state, text, text + URI_STRLEN(text));
 
2059
}
 
2060
 
 
2061
 
 
2062
 
 
2063
void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) {
 
2064
        if (uri == NULL) {
 
2065
                return;
 
2066
        }
 
2067
 
 
2068
        if (uri->owner) {
 
2069
                /* Scheme */
 
2070
                if (uri->scheme.first != NULL) {
 
2071
                        free((URI_CHAR *)uri->scheme.first);
 
2072
                        uri->scheme.first = NULL;
 
2073
                        uri->scheme.afterLast = NULL;
 
2074
                }
 
2075
 
 
2076
                /* User info */
 
2077
                if (uri->userInfo.first != NULL) {
 
2078
                        free((URI_CHAR *)uri->userInfo.first);
 
2079
                        uri->userInfo.first = NULL;
 
2080
                        uri->userInfo.afterLast = NULL;
 
2081
                }
 
2082
 
 
2083
                /* Host data - IPvFuture */
 
2084
                if (uri->hostData.ipFuture.first != NULL) {
 
2085
                        free((URI_CHAR *)uri->hostData.ipFuture.first);
 
2086
                        uri->hostData.ipFuture.first = NULL;
 
2087
                        uri->hostData.ipFuture.afterLast = NULL;
 
2088
                        uri->hostText.first = NULL;
 
2089
                        uri->hostText.afterLast = NULL;
 
2090
                }
 
2091
 
 
2092
                /* Host text (if regname, after IPvFuture!) */
 
2093
                if ((uri->hostText.first != NULL)
 
2094
                                && (uri->hostData.ip4 == NULL)
 
2095
                                && (uri->hostData.ip6 == NULL)) {
 
2096
                        /* Real regname */
 
2097
                        free((URI_CHAR *)uri->hostText.first);
 
2098
                        uri->hostText.first = NULL;
 
2099
                        uri->hostText.afterLast = NULL;
 
2100
                }
 
2101
        }
 
2102
 
 
2103
        /* Host data - IPv4 */
 
2104
        if (uri->hostData.ip4 != NULL) {
 
2105
                free(uri->hostData.ip4);
 
2106
                uri->hostData.ip4 = NULL;
 
2107
        }
 
2108
 
 
2109
        /* Host data - IPv6 */
 
2110
        if (uri->hostData.ip6 != NULL) {
 
2111
                free(uri->hostData.ip6);
 
2112
                uri->hostData.ip6 = NULL;
 
2113
        }
 
2114
 
 
2115
        /* Port text */
 
2116
        if (uri->owner && (uri->portText.first != NULL)) {
 
2117
                free((URI_CHAR *)uri->portText.first);
 
2118
                uri->portText.first = NULL;
 
2119
                uri->portText.afterLast = NULL;
 
2120
        }
 
2121
 
 
2122
        /* Path */
 
2123
        if (uri->pathHead != NULL) {
 
2124
                URI_TYPE(PathSegment) * segWalk = uri->pathHead;
 
2125
                while (segWalk != NULL) {
 
2126
                        URI_TYPE(PathSegment) * const next = segWalk->next;
 
2127
                        if (uri->owner && (segWalk->text.first != NULL)
 
2128
                                        && (segWalk->text.afterLast != NULL)
 
2129
                                        && (segWalk->text.afterLast > segWalk->text.first)) {
 
2130
                                free((URI_CHAR *)segWalk->text.first);
 
2131
                        }
 
2132
                        free(segWalk);
 
2133
                        segWalk = next;
 
2134
                }
 
2135
                uri->pathHead = NULL;
 
2136
                uri->pathTail = NULL;
 
2137
        }
 
2138
 
 
2139
        if (uri->owner) {
 
2140
                /* Query */
 
2141
                if (uri->query.first != NULL) {
 
2142
                        free((URI_CHAR *)uri->query.first);
 
2143
                        uri->query.first = NULL;
 
2144
                        uri->query.afterLast = NULL;
 
2145
                }
 
2146
 
 
2147
                /* Fragment */
 
2148
                if (uri->fragment.first != NULL) {
 
2149
                        free((URI_CHAR *)uri->fragment.first);
 
2150
                        uri->fragment.first = NULL;
 
2151
                        uri->fragment.afterLast = NULL;
 
2152
                }
 
2153
        }
 
2154
}
 
2155
 
 
2156
 
 
2157
 
 
2158
UriBool URI_FUNC(_TESTING_ONLY_ParseIpSix)(const URI_CHAR * text) {
 
2159
        URI_TYPE(Uri) uri;
 
2160
        URI_TYPE(ParserState) parser;
 
2161
        const URI_CHAR * const afterIpSix = text + URI_STRLEN(text);
 
2162
        const URI_CHAR * res;
 
2163
 
 
2164
        URI_FUNC(ResetParserState)(&parser);
 
2165
        URI_FUNC(ResetUri)(&uri);
 
2166
        parser.uri = &uri;
 
2167
        parser.uri->hostData.ip6 = malloc(1 * sizeof(UriIp6));
 
2168
        res = URI_FUNC(ParseIPv6address2)(&parser, text, afterIpSix);
 
2169
        URI_FUNC(FreeUriMembers)(&uri);
 
2170
        return res == afterIpSix ? URI_TRUE : URI_FALSE;
 
2171
}
 
2172
 
 
2173
 
 
2174
 
 
2175
UriBool URI_FUNC(_TESTING_ONLY_ParseIpFour)(const URI_CHAR * text) {
 
2176
        unsigned char octets[4];
 
2177
        int res = URI_FUNC(ParseIpFourAddress)(octets, text, text + URI_STRLEN(text));
 
2178
        return (res == URI_SUCCESS) ? URI_TRUE : URI_FALSE;
 
2179
}
 
2180
 
 
2181
 
 
2182
 
 
2183
#undef URI_SET_DIGIT
 
2184
#undef URI_SET_HEX_LETTER_UPPER
 
2185
#undef URI_SET_HEX_LETTER_LOWER
 
2186
#undef URI_SET_HEXDIG
 
2187
#undef URI_SET_ALPHA
 
2188
 
 
2189
 
 
2190
 
 
2191
#endif