"Fossies" - the Fresh Open Source Software Archive

Member "uriparser-0.9.7/src/UriParse.c" (5 Oct 2022, 65805 Bytes) of package /linux/www/uriparser-0.9.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "UriParse.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.9.6_vs_0.9.7.

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