2
* uriparser - RFC 3986 URI parsing library
4
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
5
* Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
12
* * Redistributions of source code must retain the above
13
* copyright notice, this list of conditions and the following
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.
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
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.
42
* Holds the RFC 3986 %URI parsing implementation.
43
* NOTE: This source file includes itself twice.
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"
53
# define URI_PASS_UNICODE 1
54
# include "UriParse.c"
55
# undef URI_PASS_UNICODE
58
# include <uriparser/UriDefsAnsi.h>
60
# include <uriparser/UriDefsUnicode.h>
67
# include <uriparser/Uri.h>
68
# include <uriparser/UriIp4.h>
69
# include "UriCommon.h"
70
# include "UriParseBase.h"
75
#define URI_SET_DIGIT \
87
#define URI_SET_HEX_LETTER_UPPER \
95
#define URI_SET_HEX_LETTER_LOWER \
103
#define URI_SET_HEXDIG \
105
case URI_SET_HEX_LETTER_UPPER: \
106
case URI_SET_HEX_LETTER_LOWER
108
#define URI_SET_ALPHA \
109
URI_SET_HEX_LETTER_UPPER: \
110
case URI_SET_HEX_LETTER_LOWER: \
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);
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);
192
static void URI_FUNC(ResetParserState)(URI_TYPE(ParserState) * state);
194
static UriBool URI_FUNC(PushPathSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast);
196
static void URI_FUNC(StopSyntax)(URI_TYPE(ParserState) * state, const URI_CHAR * errorPos);
197
static void URI_FUNC(StopMalloc)(URI_TYPE(ParserState) * state);
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;
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;
219
* [authority]-><[>[ipLit2][authorityTwo]
220
* [authority]->[ownHostUserInfoNz]
221
* [authority]-><NULL>
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);
234
const URI_CHAR * const afterIpLit2
235
= URI_FUNC(ParseIpLit2)(state, first + 1, afterLast);
236
if (afterIpLit2 == NULL) {
239
state->uri->hostText.first = first + 1; /* HOST BEGIN */
240
return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast);
263
state->uri->userInfo.first = first; /* USERINFO BEGIN */
264
return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast);
267
/* "" regname host */
268
state->uri->hostText.first = URI_FUNC(SafeToPointTo);
269
state->uri->hostText.afterLast = URI_FUNC(SafeToPointTo);
277
* [authorityTwo]-><:>[port]
278
* [authorityTwo]-><NULL>
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) {
288
const URI_CHAR * const afterPort = URI_FUNC(ParsePort)(state, first + 1, afterLast);
289
if (afterPort == NULL) {
292
state->uri->portText.first = first + 1; /* PORT BEGIN */
293
state->uri->portText.afterLast = afterPort; /* PORT END */
305
* [hexZero]->[HEXDIG][hexZero]
308
static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
309
if (first >= afterLast) {
315
return URI_FUNC(ParseHexZero)(state, first + 1, afterLast);
325
* [hierPart]->[pathRootless]
326
* [hierPart]-></>[partHelperTwo]
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) {
355
return URI_FUNC(ParsePathRootless)(state, first, afterLast);
358
return URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast);
368
* [ipFutLoop]->[subDelims][ipFutStopGo]
369
* [ipFutLoop]->[unreserved][ipFutStopGo]
370
* [ipFutLoop]-><:>[ipFutStopGo]
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);
397
return URI_FUNC(ParseIpFutStopGo)(state, first + 1, afterLast);
400
URI_FUNC(StopSyntax)(state, first);
408
* [ipFutStopGo]->[ipFutLoop]
409
* [ipFutStopGo]-><NULL>
411
static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
412
if (first >= afterLast) {
435
return URI_FUNC(ParseIpFutLoop)(state, first, afterLast);
445
* [ipFuture]-><v>[HEXDIG][hexZero]<.>[ipFutLoop]
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);
454
First character has already been
455
checked before entering this rule.
460
if (first + 1 >= afterLast) {
461
URI_FUNC(StopSyntax)(state, first + 1);
468
const URI_CHAR * afterIpFutLoop;
469
const URI_CHAR * const afterHexZero
470
= URI_FUNC(ParseHexZero)(state, first + 2, afterLast);
471
if (afterHexZero == NULL) {
474
if ((afterHexZero >= afterLast)
475
|| (*afterHexZero != _UT('.'))) {
476
URI_FUNC(StopSyntax)(state, afterHexZero);
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) {
485
state->uri->hostText.afterLast = afterIpFutLoop; /* HOST END */
486
state->uri->hostData.ipFuture.afterLast = afterIpFutLoop; /* IPFUTURE END */
487
return afterIpFutLoop;
491
URI_FUNC(StopSyntax)(state, first + 1);
497
URI_FUNC(StopSyntax)(state, first);
506
* [ipLit2]->[ipFuture]<]>
507
* [ipLit2]->[IPv6address2]
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);
518
const URI_CHAR * const afterIpFuture
519
= URI_FUNC(ParseIpFuture)(state, first, afterLast);
520
if (afterIpFuture == NULL) {
523
if ((afterIpFuture >= afterLast)
524
|| (*afterIpFuture != _UT(']'))) {
525
URI_FUNC(StopSyntax)(state, first);
528
return afterIpFuture + 1;
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);
539
return URI_FUNC(ParseIPv6address2)(state, first, afterLast);
542
URI_FUNC(StopSyntax)(state, first);
550
* [IPv6address2]->..<]>
552
static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
556
unsigned char digitHistory[4];
557
int ip4OctetsDone = 0;
559
unsigned char quadsAfterZipper[14];
560
int quadsAfterZipperCount = 0;
564
if (first >= afterLast) {
565
URI_FUNC(StopSyntax)(state, first);
569
/* Inside IPv4 part? */
570
if (ip4OctetsDone > 0) {
571
/* Eat rest of IPv4 address */
575
if (digitCount == 4) {
576
URI_FUNC(StopSyntax)(state, first);
579
digitHistory[digitCount++] = (unsigned char)(9 + *first - _UT('9'));
583
if ((ip4OctetsDone == 4) /* NOTE! */
585
|| (digitCount == 4)) {
586
/* Invalid digit or octet count */
587
URI_FUNC(StopSyntax)(state, first);
589
} else if ((digitCount > 1)
590
&& (digitHistory[0] == 0)) {
592
URI_FUNC(StopSyntax)(state, first - digitCount);
594
} else if ((digitCount > 2)
595
&& (digitHistory[1] == 0)) {
597
URI_FUNC(StopSyntax)(state, first - digitCount + 1);
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);
609
URI_FUNC(StopSyntax)(state, first - 1);
614
/* Copy IPv4 octet */
615
state->uri->hostData.ip6->data[16 - 4 + ip4OctetsDone] = uriGetOctetValue(digitHistory, digitCount);
621
if ((ip4OctetsDone != 3) /* NOTE! */
623
|| (digitCount == 4)) {
624
/* Invalid digit or octet count */
625
URI_FUNC(StopSyntax)(state, first);
627
} else if ((digitCount > 1)
628
&& (digitHistory[0] == 0)) {
630
URI_FUNC(StopSyntax)(state, first - digitCount);
632
} else if ((digitCount > 2)
633
&& (digitHistory[1] == 0)) {
635
URI_FUNC(StopSyntax)(state, first - digitCount + 1);
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);
647
URI_FUNC(StopSyntax)(state, first - 1);
652
state->uri->hostText.afterLast = first; /* HOST END */
654
/* Copy missing quads right before IPv4 */
655
memcpy(state->uri->hostData.ip6->data + 16 - 4 - 2 * quadsAfterZipperCount,
656
quadsAfterZipper, 2 * quadsAfterZipperCount);
658
/* Copy last IPv4 octet */
659
state->uri->hostData.ip6->data[16 - 4 + 3] = uriGetOctetValue(digitHistory, digitCount);
664
URI_FUNC(StopSyntax)(state, first);
670
/* Eat while no dot in sight */
675
case URI_SET_HEX_LETTER_LOWER:
677
if (digitCount == 4) {
678
URI_FUNC(StopSyntax)(state, first);
681
digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('f'));
685
case URI_SET_HEX_LETTER_UPPER:
687
if (digitCount == 4) {
688
URI_FUNC(StopSyntax)(state, first);
691
digitHistory[digitCount] = (unsigned char)(15 + *first - _UT('F'));
696
if (digitCount == 4) {
697
URI_FUNC(StopSyntax)(state, first);
700
digitHistory[digitCount] = (unsigned char)(9 + *first - _UT('9'));
708
/* Too many quads? */
709
if (quadsDone > 8 - zipperEver) {
710
URI_FUNC(StopSyntax)(state, first);
715
if (first + 1 >= afterLast) {
716
URI_FUNC(StopSyntax)(state, first + 1);
719
if (first[1] == _UT(':')) {
720
const int resetOffset = 2 * (quadsDone + (digitCount > 0));
724
URI_FUNC(StopSyntax)(state, first);
725
return NULL; /* "::.+::" */
728
/* Zero everything after zipper */
729
memset(state->uri->hostData.ip6->data + resetOffset, 0, 16 - resetOffset);
733
if (first + 1 >= afterLast) {
734
URI_FUNC(StopSyntax)(state, first + 1);
735
return NULL; /* No ']' yet */
737
if (first[1] == _UT(':')) {
738
URI_FUNC(StopSyntax)(state, first + 1);
739
return NULL; /* ":::+ "*/
742
if (digitCount > 0) {
744
uriWriteQuadToDoubleByte(digitHistory, digitCount, quadsAfterZipper + 2 * quadsAfterZipperCount);
745
quadsAfterZipperCount++;
747
uriWriteQuadToDoubleByte(digitHistory, digitCount, state->uri->hostData.ip6->data + 2 * quadsDone);
761
if ((quadsDone > 6) /* NOTE */
762
|| (!zipperEver && (quadsDone < 6))
765
|| (digitCount == 4)) {
766
/* Invalid octet before */
767
URI_FUNC(StopSyntax)(state, first);
769
} else if ((digitCount > 1)
770
&& (digitHistory[0] == 0)) {
772
URI_FUNC(StopSyntax)(state, first - digitCount);
774
} else if ((digitCount > 2)
775
&& (digitHistory[1] == 0)) {
777
URI_FUNC(StopSyntax)(state, first - digitCount + 1);
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);
789
URI_FUNC(StopSyntax)(state, first - 1);
794
/* Copy first IPv4 octet */
795
state->uri->hostData.ip6->data[16 - 4] = uriGetOctetValue(digitHistory, digitCount);
798
/* Switch over to IPv4 loop */
804
/* Too little quads? */
805
if (!zipperEver && !((quadsDone == 7) && (digitCount > 0))) {
806
URI_FUNC(StopSyntax)(state, first);
810
if (digitCount > 0) {
812
uriWriteQuadToDoubleByte(digitHistory, digitCount, quadsAfterZipper + 2 * quadsAfterZipperCount);
813
quadsAfterZipperCount++;
815
uriWriteQuadToDoubleByte(digitHistory, digitCount, state->uri->hostData.ip6->data + 2 * quadsDone);
823
/* Copy missing quads to the end */
824
memcpy(state->uri->hostData.ip6->data + 16 - 2 * quadsAfterZipperCount,
825
quadsAfterZipper, 2 * quadsAfterZipperCount);
827
state->uri->hostText.afterLast = first; /* HOST END */
828
return first + 1; /* Fine */
831
URI_FUNC(StopSyntax)(state, first);
836
if (first >= afterLast) {
837
URI_FUNC(StopSyntax)(state, first);
838
return NULL; /* No ']' yet */
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]
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);
861
state->uri->scheme.first = NULL; /* Not a scheme, reset */
868
const URI_CHAR * const afterPctEncoded
869
= URI_FUNC(ParsePctEncoded)(state, first, afterLast);
870
if (afterPctEncoded == NULL) {
873
return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast);
894
return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast);
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);
904
state->uri->scheme.first = NULL; /* Not a scheme, reset */
905
afterSegment = URI_FUNC(ParseSegment)(state, first + 1, afterLast);
906
if (afterSegment == NULL) {
909
if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */
910
URI_FUNC(StopMalloc)(state);
913
afterZeroMoreSlashSegs
914
= URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast);
915
if (afterZeroMoreSlashSegs == NULL) {
918
return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast);
922
if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */
923
URI_FUNC(StopMalloc)(state);
926
state->uri->scheme.first = NULL; /* Not a scheme, reset */
927
return URI_FUNC(ParseUriTail)(state, first, afterLast);
934
* [ownHost]-><[>[ipLit2][authorityTwo]
935
* [ownHost]->[ownHost2] // can take <NULL>
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) {
945
const URI_CHAR * const afterIpLit2
946
= URI_FUNC(ParseIpLit2)(state, first + 1, afterLast);
947
if (afterIpLit2 == NULL) {
950
state->uri->hostText.first = first + 1; /* HOST BEGIN */
951
return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast);
955
return URI_FUNC(ParseOwnHost2)(state, first, afterLast);
961
static URI_INLINE UriBool URI_FUNC(OnExitOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first) {
962
state->uri->hostText.afterLast = first; /* HOST END */
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 */
969
if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,
970
state->uri->hostText.first, state->uri->hostText.afterLast)) {
972
free(state->uri->hostData.ip4);
973
state->uri->hostData.ip4 = NULL;
975
return URI_TRUE; /* Success */
981
* [ownHost2]->[authorityTwo] // can take <NULL>
982
* [ownHost2]->[pctSubUnres][ownHost2]
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);
1013
const URI_CHAR * const afterPctSubUnres
1014
= URI_FUNC(ParsePctSubUnres)(state, first, afterLast);
1015
if (afterPctSubUnres == NULL) {
1018
return URI_FUNC(ParseOwnHost2)(state, afterPctSubUnres, afterLast);
1022
if (!URI_FUNC(OnExitOwnHost2)(state, first)) {
1023
URI_FUNC(StopMalloc)(state);
1026
return URI_FUNC(ParseAuthorityTwo)(state, first, afterLast);
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 */
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 */
1042
if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,
1043
state->uri->hostText.first, state->uri->hostText.afterLast)) {
1045
free(state->uri->hostData.ip4);
1046
state->uri->hostData.ip4 = NULL;
1048
return URI_TRUE; /* Success */
1054
* [ownHostUserInfo]->[ownHostUserInfoNz]
1055
* [ownHostUserInfo]-><NULL>
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);
1087
return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast);
1090
if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first)) {
1091
URI_FUNC(StopMalloc)(state);
1101
* [ownHostUserInfoNz]->[pctSubUnres][ownHostUserInfo]
1102
* [ownHostUserInfoNz]-><:>[ownPortUserInfo]
1103
* [ownHostUserInfoNz]-><@>[ownHost]
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);
1131
const URI_CHAR * const afterPctSubUnres
1132
= URI_FUNC(ParsePctSubUnres)(state, first, afterLast);
1133
if (afterPctSubUnres == NULL) {
1136
return URI_FUNC(ParseOwnHostUserInfo)(state, afterPctSubUnres, afterLast);
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);
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);
1150
URI_FUNC(StopSyntax)(state, first);
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 */
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 */
1167
if (URI_FUNC(ParseIpFourAddress)(state->uri->hostData.ip4->data,
1168
state->uri->hostText.first, state->uri->hostText.afterLast)) {
1170
free(state->uri->hostData.ip4);
1171
state->uri->hostData.ip4 = NULL;
1173
return URI_TRUE; /* Success */
1179
* [ownPortUserInfo]->[ALPHA][ownUserInfo]
1180
* [ownPortUserInfo]->[DIGIT][ownPortUserInfo]
1181
* [ownPortUserInfo]-><.>[ownUserInfo]
1182
* [ownPortUserInfo]-><_>[ownUserInfo]
1183
* [ownPortUserInfo]-><~>[ownUserInfo]
1184
* [ownPortUserInfo]-><->[ownUserInfo]
1185
* [ownPortUserInfo]-><NULL>
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);
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);
1207
return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast);
1210
if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first)) {
1211
URI_FUNC(StopMalloc)(state);
1221
* [ownUserInfo]->[pctSubUnres][ownUserInfo]
1222
* [ownUserInfo]-><:>[ownUserInfo]
1223
* [ownUserInfo]-><@>[ownHost]
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);
1251
const URI_CHAR * const afterPctSubUnres
1252
= URI_FUNC(ParsePctSubUnres)(state, first, afterLast);
1253
if (afterPctSubUnres == NULL) {
1256
return URI_FUNC(ParseOwnUserInfo)(state, afterPctSubUnres, afterLast);
1260
return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast);
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);
1269
URI_FUNC(StopSyntax)(state, first);
1276
static URI_INLINE void URI_FUNC(OnExitPartHelperTwo)(URI_TYPE(ParserState) * state) {
1277
state->uri->absolutePath = URI_TRUE;
1283
* [partHelperTwo]->[pathAbsNoLeadSlash] // can take <NULL>
1284
* [partHelperTwo]-></>[authority][pathAbsEmpty]
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);
1295
const URI_CHAR * const afterAuthority
1296
= URI_FUNC(ParseAuthority)(state, first + 1, afterLast);
1297
const URI_CHAR * afterPathAbsEmpty;
1298
if (afterAuthority == NULL) {
1301
afterPathAbsEmpty = URI_FUNC(ParsePathAbsEmpty)(state, afterAuthority, afterLast);
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;
1312
return afterPathAbsEmpty;
1316
URI_FUNC(OnExitPartHelperTwo)(state);
1317
return URI_FUNC(ParsePathAbsNoLeadSlash)(state, first, afterLast);
1324
* [pathAbsEmpty]-></>[segment][pathAbsEmpty]
1325
* [pathAbsEmpty]-><NULL>
1327
static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
1328
if (first >= afterLast) {
1335
const URI_CHAR * const afterSegment
1336
= URI_FUNC(ParseSegment)(state, first + 1, afterLast);
1337
if (afterSegment == NULL) {
1340
if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */
1341
URI_FUNC(StopMalloc)(state);
1344
return URI_FUNC(ParsePathAbsEmpty)(state, afterSegment, afterLast);
1355
* [pathAbsNoLeadSlash]->[segmentNz][zeroMoreSlashSegs]
1356
* [pathAbsNoLeadSlash]-><NULL>
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) {
1385
const URI_CHAR * const afterSegmentNz
1386
= URI_FUNC(ParseSegmentNz)(state, first, afterLast);
1387
if (afterSegmentNz == NULL) {
1390
if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz)) { /* SEGMENT BOTH */
1391
URI_FUNC(StopMalloc)(state);
1394
return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast);
1405
* [pathRootless]->[segmentNz][zeroMoreSlashSegs]
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) {
1413
if (!URI_FUNC(PushPathSegment)(state, first, afterSegmentNz)) { /* SEGMENT BOTH */
1414
URI_FUNC(StopMalloc)(state);
1418
return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegmentNz, afterLast);
1424
* [pchar]->[pctEncoded]
1425
* [pchar]->[subDelims]
1426
* [pchar]->[unreserved]
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);
1438
return URI_FUNC(ParsePctEncoded)(state, first, afterLast);
1462
URI_FUNC(StopSyntax)(state, first);
1470
* [pctEncoded]-><%>[HEXDIG][HEXDIG]
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);
1479
First character has already been
1480
checked before entering this rule.
1485
if (first + 1 >= afterLast) {
1486
URI_FUNC(StopSyntax)(state, first + 1);
1491
case URI_SET_HEXDIG:
1492
if (first + 2 >= afterLast) {
1493
URI_FUNC(StopSyntax)(state, first + 2);
1498
case URI_SET_HEXDIG:
1502
URI_FUNC(StopSyntax)(state, first + 2);
1507
URI_FUNC(StopSyntax)(state, first + 1);
1513
URI_FUNC(StopSyntax)(state, first);
1522
* [pctSubUnres]->[pctEncoded]
1523
* [pctSubUnres]->[subDelims]
1524
* [pctSubUnres]->[unreserved]
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);
1534
return URI_FUNC(ParsePctEncoded)(state, first, afterLast);
1556
URI_FUNC(StopSyntax)(state, first);
1564
* [port]->[DIGIT][port]
1567
static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
1568
if (first >= afterLast) {
1574
return URI_FUNC(ParsePort)(state, first + 1, afterLast);
1584
* [queryFrag]->[pchar][queryFrag]
1585
* [queryFrag]-></>[queryFrag]
1586
* [queryFrag]-><?>[queryFrag]
1587
* [queryFrag]-><NULL>
1589
static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
1590
if (first >= afterLast) {
1616
const URI_CHAR * const afterPchar
1617
= URI_FUNC(ParsePchar)(state, first, afterLast);
1618
if (afterPchar == NULL) {
1621
return URI_FUNC(ParseQueryFrag)(state, afterPchar, afterLast);
1626
return URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast);
1636
* [segment]->[pchar][segment]
1639
static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
1640
if (first >= afterLast) {
1666
const URI_CHAR * const afterPchar
1667
= URI_FUNC(ParsePchar)(state, first, afterLast);
1668
if (afterPchar == NULL) {
1671
return URI_FUNC(ParseSegment)(state, afterPchar, afterLast);
1682
* [segmentNz]->[pchar][segment]
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) {
1690
return URI_FUNC(ParseSegment)(state, afterPchar, afterLast);
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*/
1699
state->uri->scheme.first = NULL; /* Not a scheme, reset */
1700
return URI_TRUE; /* Success */
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]
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);
1744
return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast);
1748
const URI_CHAR * const afterPctEncoded
1749
= URI_FUNC(ParsePctEncoded)(state, first, afterLast);
1750
if (afterPctEncoded == NULL) {
1753
return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast);
1769
return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast);
1773
const URI_CHAR * afterZeroMoreSlashSegs;
1774
const URI_CHAR * const afterSegment
1775
= URI_FUNC(ParseSegment)(state, first + 1, afterLast);
1776
if (afterSegment == NULL) {
1779
if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first)) { /* SEGMENT BOTH */
1780
URI_FUNC(StopMalloc)(state);
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);
1788
afterZeroMoreSlashSegs
1789
= URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast);
1790
if (afterZeroMoreSlashSegs == NULL) {
1793
return URI_FUNC(ParseUriTail)(state, afterZeroMoreSlashSegs, afterLast);
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) {
1804
return URI_FUNC(ParseUriTail)(state, afterHierPart, afterLast);
1808
if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first)) {
1809
URI_FUNC(StopMalloc)(state);
1812
return URI_FUNC(ParseUriTail)(state, first, afterLast);
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]
1831
static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
1832
if (first >= afterLast) {
1838
state->uri->scheme.first = first; /* SCHEME BEGIN */
1839
return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast);
1858
state->uri->scheme.first = first; /* SCHEME BEGIN */
1859
return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast);
1863
const URI_CHAR * const afterPctEncoded
1864
= URI_FUNC(ParsePctEncoded)(state, first, afterLast);
1865
if (afterPctEncoded == NULL) {
1868
state->uri->scheme.first = first; /* SCHEME BEGIN */
1869
return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast);
1874
const URI_CHAR * const afterPartHelperTwo
1875
= URI_FUNC(ParsePartHelperTwo)(state, first + 1, afterLast);
1876
if (afterPartHelperTwo == NULL) {
1879
return URI_FUNC(ParseUriTail)(state, afterPartHelperTwo, afterLast);
1883
return URI_FUNC(ParseUriTail)(state, first, afterLast);
1890
* [uriTail]-><#>[queryFrag]
1891
* [uriTail]-><?>[queryFrag][uriTailTwo]
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) {
1902
const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast);
1903
if (afterQueryFrag == NULL) {
1906
state->uri->fragment.first = first + 1; /* FRAGMENT BEGIN */
1907
state->uri->fragment.afterLast = afterQueryFrag; /* FRAGMENT END */
1908
return afterQueryFrag;
1913
const URI_CHAR * const afterQueryFrag
1914
= URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast);
1915
if (afterQueryFrag == NULL) {
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);
1931
* [uriTailTwo]-><#>[queryFrag]
1932
* [uriTailTwo]-><NULL>
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) {
1942
const URI_CHAR * const afterQueryFrag = URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast);
1943
if (afterQueryFrag == NULL) {
1946
state->uri->fragment.first = first + 1; /* FRAGMENT BEGIN */
1947
state->uri->fragment.afterLast = afterQueryFrag; /* FRAGMENT END */
1948
return afterQueryFrag;
1959
* [zeroMoreSlashSegs]-></>[segment][zeroMoreSlashSegs]
1960
* [zeroMoreSlashSegs]-><NULL>
1962
static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast) {
1963
if (first >= afterLast) {
1970
const URI_CHAR * const afterSegment
1971
= URI_FUNC(ParseSegment)(state, first + 1, afterLast);
1972
if (afterSegment == NULL) {
1975
if (!URI_FUNC(PushPathSegment)(state, first + 1, afterSegment)) { /* SEGMENT BOTH */
1976
URI_FUNC(StopMalloc)(state);
1979
return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast);
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;
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 */
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);
2007
segment->text.first = first;
2008
segment->text.afterLast = afterLast;
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;
2017
/* Append, update tail */
2018
state->uri->pathTail->next = segment;
2019
state->uri->pathTail = segment;
2022
return URI_TRUE; /* Success */
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;
2032
if ((state == NULL) || (state == NULL) || (state == NULL)) {
2033
return URI_ERROR_NULL;
2038
URI_FUNC(ResetParserState)(state);
2039
URI_FUNC(ResetUri)(uri);
2042
afterUriReference = URI_FUNC(ParseUriReference)(state, first, afterLast);
2043
if (afterUriReference == NULL) {
2044
return state->errorCode;
2046
if (afterUriReference != afterLast) {
2047
return URI_ERROR_SYNTAX;
2054
int URI_FUNC(ParseUri)(URI_TYPE(ParserState) * state, const URI_CHAR * text) {
2055
if ((state == NULL) || (text == NULL)) {
2056
return URI_ERROR_NULL;
2058
return URI_FUNC(ParseUriEx)(state, text, text + URI_STRLEN(text));
2063
void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri) {
2070
if (uri->scheme.first != NULL) {
2071
free((URI_CHAR *)uri->scheme.first);
2072
uri->scheme.first = NULL;
2073
uri->scheme.afterLast = NULL;
2077
if (uri->userInfo.first != NULL) {
2078
free((URI_CHAR *)uri->userInfo.first);
2079
uri->userInfo.first = NULL;
2080
uri->userInfo.afterLast = NULL;
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;
2092
/* Host text (if regname, after IPvFuture!) */
2093
if ((uri->hostText.first != NULL)
2094
&& (uri->hostData.ip4 == NULL)
2095
&& (uri->hostData.ip6 == NULL)) {
2097
free((URI_CHAR *)uri->hostText.first);
2098
uri->hostText.first = NULL;
2099
uri->hostText.afterLast = NULL;
2103
/* Host data - IPv4 */
2104
if (uri->hostData.ip4 != NULL) {
2105
free(uri->hostData.ip4);
2106
uri->hostData.ip4 = NULL;
2109
/* Host data - IPv6 */
2110
if (uri->hostData.ip6 != NULL) {
2111
free(uri->hostData.ip6);
2112
uri->hostData.ip6 = NULL;
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;
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);
2135
uri->pathHead = NULL;
2136
uri->pathTail = NULL;
2141
if (uri->query.first != NULL) {
2142
free((URI_CHAR *)uri->query.first);
2143
uri->query.first = NULL;
2144
uri->query.afterLast = NULL;
2148
if (uri->fragment.first != NULL) {
2149
free((URI_CHAR *)uri->fragment.first);
2150
uri->fragment.first = NULL;
2151
uri->fragment.afterLast = NULL;
2158
UriBool URI_FUNC(_TESTING_ONLY_ParseIpSix)(const URI_CHAR * text) {
2160
URI_TYPE(ParserState) parser;
2161
const URI_CHAR * const afterIpSix = text + URI_STRLEN(text);
2162
const URI_CHAR * res;
2164
URI_FUNC(ResetParserState)(&parser);
2165
URI_FUNC(ResetUri)(&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;
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;
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