summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/dependabot.yml15
-rw-r--r--.github/workflows/build-and-test.yml116
-rw-r--r--.travis.yml86
-rw-r--r--CMakeLists.txt146
-rw-r--r--ChangeLog41
-rw-r--r--README.md11
-rw-r--r--THANKS6
-rw-r--r--appveyor.yml1
-rw-r--r--doc/Mainpage.txt41
-rw-r--r--include/uriparser/Uri.h2
-rw-r--r--include/uriparser/UriBase.h2
-rw-r--r--include/uriparser/UriDefsConfig.h8
-rw-r--r--include/uriparser/UriDefsUnicode.h2
-rw-r--r--liburiparser.pc.in6
-rw-r--r--src/UriCommon.c96
-rw-r--r--src/UriCommon.h2
-rw-r--r--test/MemoryManagerSuite.cpp4
-rw-r--r--test/test.cpp57
18 files changed, 430 insertions, 212 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..b149019
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,15 @@
+# Copyright (C) 2021 Sebastian Pipping <sebastian@pipping.org>
+# Licensed under the MIT license
+
+version: 2
+updates:
+
+ - package-ecosystem: "github-actions"
+ commit-message:
+ include: "scope"
+ prefix: "Actions"
+ directory: "/"
+ labels:
+ - "enhancement"
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
new file mode 100644
index 0000000..ba5cb84
--- /dev/null
+++ b/.github/workflows/build-and-test.yml
@@ -0,0 +1,116 @@
+# Copyright (C) 2021 Sebastian Pipping <sebastian@pipping.org>
+# Licensed under the MIT license
+
+name: Build and test
+
+on:
+ pull_request:
+ push:
+ schedule:
+ - cron: '0 4 * * 5' # Every Friday at 4am
+
+jobs:
+ build_and_test:
+ name: Build and test
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2.3.4
+
+ - name: Add Clang/LLVM repositories
+ run: |-
+ wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
+ sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main'
+
+ - name: Install build dependencies
+ run: |-
+ sudo apt-get install --yes --no-install-recommends -V \
+ clang-11 \
+ cmake \
+ doxygen \
+ graphviz \
+ llvm-11 \
+ lzip \
+ qhelpgenerator-qt5 \
+ qtchooser
+
+ - name: Build, test and install
+ run: |-
+ sed 's,:,\n,g' <<<"${PATH}"
+ clang --version
+
+ GTEST_VERSION=1.8.1
+ GTEST_PREFIX=~/.local/
+
+ wget https://github.com/google/googletest/archive/release-${GTEST_VERSION}.tar.gz
+ tar xf release-${GTEST_VERSION}.tar.gz
+ (
+ cd googletest-release-${GTEST_VERSION}/
+ cmake \
+ -DBUILD_SHARED_LIBS=ON \
+ -DCVF_VERSION=${GTEST_VERSION} \
+ -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} \
+ .
+ make
+ make install
+ )
+
+ mkdir build
+ pushd build
+ compile_flags=(
+ -pipe
+
+ -O1
+ -g
+ -fsanitize=address,undefined,leak
+ -fno-sanitize-recover=all
+ -fno-omit-frame-pointer
+
+ -Wall
+ -Wextra
+ -pedantic
+ )
+ CFLAGS="${compile_flags[*]} -std=c89"
+ CXXFLAGS="${compile_flags[*]} -std=c++98"
+ LDFLAGS='-g -fsanitize=address'
+ cmake_args=(
+ -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX}
+
+ -Wdev
+ -Werror=dev
+ -Wdeprecated
+ -Werror=deprecated
+
+ -DCMAKE_C_COMPILER=clang-11
+ -DCMAKE_CXX_COMPILER=clang++-11
+ -DCMAKE_C_FLAGS="${CFLAGS}"
+ -DCMAKE_CXX_FLAGS="${CXXFLAGS}"
+ -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}"
+ -DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}"
+ -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}"
+
+ -DURIPARSER_WARNINGS_AS_ERRORS=ON
+ )
+ cmake "${cmake_args[@]}" -DCMAKE_INSTALL_INCLUDEDIR=include123 ..
+
+ make VERBOSE=1 all
+
+ make VERBOSE=1 test ARGS=--verbose
+ cat Testing/Temporary/LastTest.log
+
+ make install
+ make DESTDIR="${PWD}"/ROOT/ install
+ find ROOT | sort
+
+ ./doc/release.sh
+ popd
+ pushd cmake/test_find_package
+ cmake "${cmake_args[@]}" .
+ make VERBOSE=1
+ ./hello
+ popd
+
+ git fetch --tags --unshallow origin # for "git describe" in make-distcheck.sh
+
+ ./make-distcheck.sh -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} # without AddressSanitizer
+
+ ! git status | fgrep -A100 'Untracked files:' # works best at the very end
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 0096384..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright (C) 2018 Sebastian Pipping <sebastian@pipping.org>
-# Licensed under the MIT license
-
-language: cpp
-dist: xenial
-
-addons:
- apt:
- sources:
- # Clang 8:
- - llvm-toolchain-xenial-8
- - ubuntu-toolchain-r-test
- packages:
- - clang-8
- - cmake
- - lzip
- # Documentation:
- - doxygen
- - graphviz
- - qt4-dev-tools
- - qtchooser
-
-script:
- - set -e
- - GTEST_VERSION=1.8.1
- ; GTEST_PREFIX=~/.local/
- ; wget https://github.com/google/googletest/archive/release-${GTEST_VERSION}.tar.gz
- && tar xf release-${GTEST_VERSION}.tar.gz
- && ( cd googletest-release-${GTEST_VERSION}/
- && cmake
- -DBUILD_SHARED_LIBS=ON
- -DCVF_VERSION=${GTEST_VERSION}
- -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX}
- .
- && make
- && make install )
- - mkdir build
- - pushd build
- - compile_flags=(
- -pipe
-
- -O1
- -g
- -fsanitize=address
- -fno-omit-frame-pointer
-
- -Wall
- -Wextra
- -pedantic
- )
- && CFLAGS="${compile_flags[*]} -std=c89"
- && CXXFLAGS="${compile_flags[*]} -std=c++98"
- && LDFLAGS='-g -fsanitize=address'
- && cmake_args=(
- -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX}
-
- -Wdev
- -Werror=dev
- -Wdeprecated
- -Werror=deprecated
-
- -DCMAKE_C_COMPILER=clang-8
- -DCMAKE_CXX_COMPILER=clang++-8
- -DCMAKE_C_FLAGS="${CFLAGS}"
- -DCMAKE_CXX_FLAGS="${CXXFLAGS}"
- -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}"
- -DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}"
- -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}"
- )
- && cmake "${cmake_args[@]}" -DCMAKE_INSTALL_INCLUDEDIR=include123 .. # -Werror would fail checks!
- - make VERBOSE=1 C_FLAGS="${CFLAGS} -fPIC -Werror" CXX_FLAGS="${CXXFLAGS} -Werror" all
- - make VERBOSE=1 C_FLAGS="${CFLAGS} -fPIC -Werror" CXX_FLAGS="${CXXFLAGS} -Werror" test ARGS=--verbose
- - cat Testing/Temporary/LastTest.log
- - make install
- - ./doc/release.sh
- - make DESTDIR="${PWD}"/ROOT/ install
- - find ROOT | sort
- - popd
- - pushd cmake/test_find_package
- - cmake "${cmake_args[@]}" .
- - make VERBOSE=1
- - ./hello
- - popd
- - git fetch --tags --unshallow origin # for "git describe" in make-distcheck.sh
- - ./make-distcheck.sh -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} # without AddressSanitizer
- - "! git status | fgrep -A100 'Untracked files:' # works best at the very end"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 70088b1..4b1ce44 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,14 +38,14 @@ cmake_minimum_required(VERSION 3.3)
project(uriparser
VERSION
- 0.9.4
+ 0.9.5
LANGUAGES
C
)
-# See https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
+# See https://verbump.de/ for what these numbers do
set(URIPARSER_SO_CURRENT 1)
-set(URIPARSER_SO_REVISION 27)
+set(URIPARSER_SO_REVISION 28)
set(URIPARSER_SO_AGE 0)
include(CheckCCompilerFlag)
@@ -65,6 +65,7 @@ option(URIPARSER_BUILD_TOOLS "Build tools (e.g. CLI \"uriparse\")" ON)
option(URIPARSER_BUILD_CHAR "Build code supporting data type 'char'" ON)
option(URIPARSER_BUILD_WCHAR_T "Build code supporting data type 'wchar_t'" ON)
option(URIPARSER_ENABLE_INSTALL "Enable installation of uriparser" ON)
+option(URIPARSER_WARNINGS_AS_ERRORS "Treat all compiler warnings as errors" OFF)
set(URIPARSER_MSVC_RUNTIME "" CACHE STRING "Use of specific runtime library (/MT /MTd /MD /MDd) with MSVC")
if(NOT URIPARSER_BUILD_CHAR AND NOT URIPARSER_BUILD_WCHAR_T)
@@ -103,6 +104,14 @@ if(URIPARSER_COMPILER_SUPPORTS_VISIBILITY)
set(URIPARSER_EXTRA_COMPILE_FLAGS "${URIPARSER_EXTRA_COMPILE_FLAGS} -fvisibility=hidden")
endif()
+if(URIPARSER_WARNINGS_AS_ERRORS)
+ if(MSVC)
+ add_definitions(/WX)
+ else()
+ set(URIPARSER_EXTRA_COMPILE_FLAGS "${URIPARSER_EXTRA_COMPILE_FLAGS} -Werror")
+ endif()
+endif()
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${URIPARSER_EXTRA_COMPILE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${URIPARSER_EXTRA_COMPILE_FLAGS}")
@@ -111,40 +120,40 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${URIPARSER_EXTRA_COMPILE_FLAGS}")
#
check_symbol_exists(wprintf wchar.h HAVE_WPRINTF)
check_function_exists(reallocarray HAVE_REALLOCARRAY) # no luck with CheckSymbolExists
-configure_file(src/UriConfig.h.in config.h)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/UriConfig.h.in config.h)
#
# C library
#
set(API_HEADER_FILES
- include/uriparser/UriBase.h
- include/uriparser/UriDefsAnsi.h
- include/uriparser/UriDefsConfig.h
- include/uriparser/UriDefsUnicode.h
- include/uriparser/Uri.h
- include/uriparser/UriIp4.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriBase.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriDefsAnsi.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriDefsConfig.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriDefsUnicode.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/Uri.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/uriparser/UriIp4.h
)
set(LIBRARY_CODE_FILES
- src/UriCommon.c
- src/UriCommon.h
- src/UriCompare.c
- src/UriEscape.c
- src/UriFile.c
- src/UriIp4Base.c
- src/UriIp4Base.h
- src/UriIp4.c
- src/UriMemory.c
- src/UriMemory.h
- src/UriNormalizeBase.c
- src/UriNormalizeBase.h
- src/UriNormalize.c
- src/UriParseBase.c
- src/UriParseBase.h
- src/UriParse.c
- src/UriQuery.c
- src/UriRecompose.c
- src/UriResolve.c
- src/UriShorten.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriCommon.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriCommon.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriCompare.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriEscape.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriFile.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriIp4Base.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriIp4Base.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriIp4.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriMemory.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriMemory.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriNormalizeBase.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriNormalizeBase.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriNormalize.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriParseBase.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriParseBase.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriParse.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriQuery.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriRecompose.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriResolve.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UriShorten.c
)
add_library(uriparser
@@ -157,7 +166,10 @@ if(NOT MSVC)
set_property(TARGET uriparser PROPERTY VERSION ${URIPARSER_SO_CURRENT_MINUS_AGE}.${URIPARSER_SO_AGE}.${URIPARSER_SO_REVISION})
set_property(TARGET uriparser PROPERTY SOVERSION ${URIPARSER_SO_CURRENT_MINUS_AGE})
if(WIN32)
- set_property(TARGET uriparser PROPERTY SUFFIX "-${URIPARSER_SO_CURRENT_MINUS_AGE}${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ set_target_properties(uriparser PROPERTIES
+ OUTPUT_NAME uriparser
+ RUNTIME_OUTPUT_NAME uriparser-${URIPARSER_SO_CURRENT_MINUS_AGE}
+ ARCHIVE_OUTPUT_NAME uriparser)
endif()
endif()
@@ -214,7 +226,7 @@ uriparser_install(
#
if(URIPARSER_BUILD_TOOLS)
add_executable(uriparse
- tool/uriparse.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/tool/uriparse.c
)
target_link_libraries(uriparse PUBLIC uriparser)
@@ -260,10 +272,10 @@ if(URIPARSER_BUILD_TESTS)
find_package(GTest 1.8.0 REQUIRED)
add_executable(testrunner
- test/FourSuite.cpp
- test/MemoryManagerSuite.cpp
- test/test.cpp
- test/VersionSuite.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/FourSuite.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/MemoryManagerSuite.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/test.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/VersionSuite.cpp
# These library code files have non-public symbols that the test suite
# needs to link to, so they appear here as well:
@@ -290,6 +302,15 @@ if(URIPARSER_BUILD_TESTS)
${GTEST_BOTH_LIBRARIES}
)
+ # NOTE: uriparser does not use pthreads itself but gtest does
+ find_package(Threads REQUIRED)
+ target_link_libraries(testrunner PRIVATE Threads::Threads)
+
+ if(MSVC)
+ # Specify unwind semantics so that MSVC knowns how to handle exceptions
+ target_compile_options(testrunner PRIVATE /EHsc)
+ endif()
+
add_test(
NAME
test
@@ -305,11 +326,20 @@ endif()
#
if(URIPARSER_BUILD_DOCS)
find_package(Doxygen REQUIRED dot doxygen)
- find_program(QHG_LOCATION
- NAMES
- qhelpgenerator
- qhelpgenerator-qt5 # e.g. CentOS 7
- )
+
+ set(QHG_LOCATION "" CACHE FILEPATH "Path to qhelpgenerator program (default: auto-detect)")
+ if(NOT QHG_LOCATION)
+ find_package(Qt5Help QUIET)
+ if(TARGET Qt5::qhelpgenerator)
+ get_target_property(QHG_LOCATION Qt5::qhelpgenerator LOCATION)
+ mark_as_advanced(Qt5Core_DIR)
+ mark_as_advanced(Qt5Gui_DIR)
+ mark_as_advanced(Qt5Help_DIR)
+ mark_as_advanced(Qt5Sql_DIR)
+ mark_as_advanced(Qt5Widgets_DIR)
+ endif()
+ endif()
+
include(FindHTMLHelp)
# Generate Doxyfile
@@ -323,8 +353,8 @@ if(URIPARSER_BUILD_DOCS)
else()
set(GENERATE_QHP NO)
endif()
- configure_file(doc/Doxyfile.in doc/Doxyfile @ONLY)
- configure_file(doc/release.sh.in doc/release.sh @ONLY)
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in doc/Doxyfile @ONLY)
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/release.sh.in doc/release.sh @ONLY)
add_custom_target(doc
ALL
@@ -358,7 +388,7 @@ endif()
# CMake files for find_package(uriparser [..] CONFIG [..])
#
configure_package_config_file(
- cmake/uriparser-config.cmake.in
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/uriparser-config.cmake.in
cmake/uriparser-config.cmake
INSTALL_DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/uriparser-${PROJECT_VERSION}/
@@ -393,7 +423,7 @@ uriparser_install(
# pkg-config file
#
if(NOT MSVC)
- configure_file(liburiparser.pc.in liburiparser.pc @ONLY)
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/liburiparser.pc.in liburiparser.pc @ONLY)
uriparser_install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/liburiparser.pc
@@ -408,13 +438,25 @@ endif()
message(STATUS "===========================================================================")
message(STATUS "")
message(STATUS "Configuration")
-message(STATUS " Prefix ............... ${CMAKE_INSTALL_PREFIX}")
-message(STATUS " Shared libraries ..... ${BUILD_SHARED_LIBS}")
-message(STATUS " Code for char * ...... ${URIPARSER_BUILD_CHAR}")
-message(STATUS " Code for wchar_t * ... ${URIPARSER_BUILD_WCHAR_T}")
-message(STATUS " Tools ................ ${URIPARSER_BUILD_TOOLS}")
-message(STATUS " Test suite ........... ${URIPARSER_BUILD_TESTS}")
-message(STATUS " Documentation ........ ${URIPARSER_BUILD_DOCS}")
+message(STATUS " Build type ............. ${CMAKE_BUILD_TYPE}")
+message(STATUS " Shared libraries ....... ${BUILD_SHARED_LIBS}")
+message(STATUS " Compiler flags")
+message(STATUS " C .................... ${CMAKE_C_FLAGS}")
+message(STATUS " C++ .................. ${CMAKE_CXX_FLAGS}")
+message(STATUS " Linker flags")
+message(STATUS " Executable ........... ${CMAKE_EXE_LINKER_FLAGS}")
+message(STATUS " Module ............... ${CMAKE_MODULE_LINKER_FLAGS}")
+message(STATUS " Shared ............... ${CMAKE_SHARED_LINKER_FLAGS}")
+message(STATUS " Paths")
+message(STATUS " Prefix ............... ${CMAKE_INSTALL_PREFIX}")
+message(STATUS " qhelpgenerator ....... ${QHG_LOCATION}")
+message(STATUS "")
+message(STATUS " Features")
+message(STATUS " Code for char * ...... ${URIPARSER_BUILD_CHAR}")
+message(STATUS " Code for wchar_t * ... ${URIPARSER_BUILD_WCHAR_T}")
+message(STATUS " Tools ................ ${URIPARSER_BUILD_TOOLS}")
+message(STATUS " Test suite ........... ${URIPARSER_BUILD_TESTS}")
+message(STATUS " Documentation ........ ${URIPARSER_BUILD_DOCS}")
message(STATUS "")
if(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
message(STATUS "Continue with")
diff --git a/ChangeLog b/ChangeLog
index f1d3533..a3d7844 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,43 @@ NOTE: uriparser is looking for help with a few things:
https://github.com/uriparser/uriparser/labels/help%20wanted
If you can help, please get in touch. Thanks!
+2021-03-18 -- 0.9.5
+
+ * Fixed: Fix a bug regarding section "5.2.4. Remove Dot Segments"
+ of RFC 3986 that affected both normalization and reference resolution
+ with regard to trailing slashes (GitHub #92, #97)
+ Thanks to Dan Pape for the report!
+ * Fixed: MinGW: Fix name of static library (GitHub #90)
+ Thanks to SpaceIm for the patch and Sandro Mani for review!
+ * Fixed: Use correct inline marker "__forceinline" for Intel C++ Compiler
+ (GitHub #93)
+ Thanks to jensenrichardson for the patch!
+ * Fixed: Link against pthreads for (default) -DURIPARSER_BUILD_TESTS=ON
+ (GitHub #99, #100)
+ * Fixed: When integrated using CMake function add_subdirectory, installation
+ could fail due to lack of prefix ${CMAKE_CURRENT_SOURCE_DIR} (GitHub #98)
+ Thanks for the patch to Shehzan Mohammed!
+ * Fixed: Addressed MSVC compile warning about lack of /EHsc when compiling
+ the C++ test suite code (GitHub #102)
+ * Fixed: Stopped misadvertising wide characters as Unicode support
+ (GitHub #104)
+ * Added: CMake option URIPARSER_WARNINGS_AS_ERRORS=(ON|OFF)
+ to turn compile warnings into errors, defaults to "OFF" (GitHub #102)
+ * Improved: pkg-config: Use ${prefix} and ${exec_prefix} to ease
+ overriding variables using --define-variable=NAME=VALUE,
+ e.g. as done on OpenWRT (GitHub #91)
+ Thanks to Karel Kočí for the pull request!
+ * Improved: Auto-detection of the qhelpgenerator command based on CMake
+ package "Qt5Help" when available. CMake option "QHG_LOCATION" can still
+ be used to enforce a specific location (GitHub #103)
+ Thanks for his help to Andreas Sturmlechner!
+ * Improved: Make documentation use pkg-config in example on how to
+ check for uriparser from within configure.ac (GNU Autoconf)
+ (GitHub #37, #106)
+ * Improved: In testing code, add a missing 'extern "C"' (GitHub #109)
+ Thanks to Jørgen Ibsen for the patch!
+ * Soname: 1:28:0 — see https://verbump.de/ for what these numbers do
+
2020-05-31 -- 0.9.4
* Fixed: testrunner: No longer crashes when compiled with NDEBUG (GitHub #67)
@@ -22,7 +59,7 @@ NOTE: uriparser is looking for help with a few things:
* Added: CMake option URIPARSER_ENABLE_INSTALL to toggle installation of
files, defaults to "ON" (GitHub #74, #75)
Thanks to Scott Donelan for the patch!
- * Soname: 1:26:0
+ * Soname: 1:27:0
2019-04-28 -- 0.9.3
@@ -487,7 +524,7 @@ NOTE: uriparser is looking for help with a few things:
2007-03-26 -- 0.3.0
* Added: New API, old marked deprecated
- * Added: Unicode support (think wchar_t)
+ * Added: Added support for wide strings (think wchar_t)
* Added: Doxygen code documentation
* Added: Test suite using CppTest
* Changed: Library code is now licensed under the new BSD license.
diff --git a/README.md b/README.md
index ded8fd0..3f92bfc 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[![Travis CI Build Status](https://travis-ci.org/uriparser/uriparser.svg?branch=master)](https://travis-ci.org/uriparser/uriparser)
+[![Build and test](https://github.com/uriparser/uriparser/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/uriparser/uriparser/actions/workflows/build-and-test.yml)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/uriparseradmin/uriparser?svg=true)](https://ci.appveyor.com/project/uriparseradmin/uriparser)
@@ -10,7 +10,7 @@ URI parsing and handling library
written in C89 ("ANSI C").
uriparser is cross-platform,
fast,
-supports Unicode, and
+supports both `char` and `wchar_t`, and
is licensed under the [New BSD license](https://github.com/uriparser/uriparser/blob/master/COPYING).
To learn more about uriparser,
@@ -55,8 +55,8 @@ CMAKE_BUILD_TYPE:STRING=
// Install path prefix, prepended onto install directories.
CMAKE_INSTALL_PREFIX:PATH=/usr/local
-// Path to a program.
-QHG_LOCATION:FILEPATH=/usr/bin/qhelpgenerator
+// Path to qhelpgenerator program (default: auto-detect)
+QHG_LOCATION:FILEPATH=
// Build code supporting data type 'char'
URIPARSER_BUILD_CHAR:BOOL=ON
@@ -78,4 +78,7 @@ URIPARSER_ENABLE_INSTALL:BOOL=ON
// Use of specific runtime library (/MT /MTd /MD /MDd) with MSVC
URIPARSER_MSVC_RUNTIME:STRING=
+
+// Treat all compiler warnings as errors
+URIPARSER_WARNINGS_AS_ERRORS:BOOL=OFF
```
diff --git a/THANKS b/THANKS
index 8f34990..90e371b 100644
--- a/THANKS
+++ b/THANKS
@@ -4,9 +4,11 @@ Adeodato Sim
Adrian Manrique
Alexander Klink
Arkadiusz Miskiewicz
+Andreas Sturmlechner
Blair Sadewitz
Chris Hills
Cristian Rodriguez
+Dan Pape
Daniel Chapiesky
Daniel Solano Gómez
David Demelier
@@ -22,11 +24,13 @@ Friedrich Delgado Friedrichs
Gary Mazzaferro
Graham Percival
Harvey Vrsalovic
+jensenrichardson
Jerome Custodio
Joel Cunningham
Jørgen Ibsen
Juan Pablo Gonzlez Tognarelli
KangLin
+Karel Kočí
Kouhei Sutou
Kurt Schwehr
Marc Novakowski
@@ -51,6 +55,8 @@ Sandro Mani
Schrijvers Luc
Scott Donelan
Sezai Tekin
+Shehzan Mohammed
+SpaceIm
Valentin Haenel
Vitaly Lipatov
Yang Yu
diff --git a/appveyor.yml b/appveyor.yml
index 09890c0..7e36cdb 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -88,6 +88,7 @@ before_build:
-DGTEST_ROOT=googletest-release-%GTEST_VERSION%/googletest
-DURIPARSER_BUILD_DOCS=OFF
-DURIPARSER_MSVC_RUNTIME=/MT
+ -DURIPARSER_WARNINGS_AS_ERRORS=ON
..
build:
diff --git a/doc/Mainpage.txt b/doc/Mainpage.txt
index bb5723c..19d8115 100644
--- a/doc/Mainpage.txt
+++ b/doc/Mainpage.txt
@@ -10,8 +10,8 @@
* - <a href="#shortening">Creating References</a>
* - <a href="#filenames">Filenames and URIs</a>
* - <a href="#normalization">Normalizing URIs</a>
- * - <a href="#querystrings">Working with query strings</a>
- * - <a href="#chartypes">Ansi and Unicode</a>
+ * - <a href="#querystrings">Working with Query Strings</a>
+ * - <a href="#chartypes">Narrow Strings and Wide Strings</a>
* - <a href="#autoconf">Autoconf Check</a>
*
*
@@ -226,7 +226,7 @@
* @endcode
*
*
- * @section querystrings Working with query strings
+ * @section querystrings Working with Query Strings
* <a href="http://tools.ietf.org/html/rfc3986" target="_blank">RFC 3986</a>
* itself does not understand the query part of a URI as a list of key/value pairs.
* But HTML 2.0 does and defines a media type <i>application/x-www-form-urlencoded</i>
@@ -281,37 +281,20 @@
* @endcode
*
*
- * @section chartypes Ansi and Unicode
+ * @section chartypes Narrow Strings and Wide Strings
* uriparser comes with two versions of every structure and function:
- * one handling Ansi text (char *) and one working with Unicode text (wchar_t *),
+ * one handling narrow strings (<code>char *</code>) and one working with wide strings (<code>wchar_t *</code>),
* for instance
- * - uriParseSingleUriA() for Ansi and
- * - uriParseSingleUriW() for Unicode.
+ * - uriParseSingleUriA() for <code>char *</code>
+ * - uriParseSingleUriW() for <code>wchar_t *</code>.
*
- * This tutorial only shows the usage of the Ansi editions but
- * their Unicode counterparts work in the very same way.
+ * This tutorial only shows the usage of the narrow string editions but
+ * their wide string counterparts work in the very same way.
*
*
* @section autoconf Autoconf Check
* You can use the code below to make <c>./configure</c> test for presence
- * of uriparser 0.6.4 or later.
- *
- *<div class="fragment"><pre class="fragment">URIPARSER_MISSING=<span class="stringliteral">"Please install uriparser 0.9.0 or later.
- * On a Debian-based system enter 'sudo apt-get install liburiparser-dev'."</span>
- *AC_CHECK_LIB(uriparser, uriParseSingleUriA,, AC_MSG_ERROR(${URIPARSER_MISSING}))
- *AC_CHECK_HEADER(uriparser/Uri.h,, AC_MSG_ERROR(${URIPARSER_MISSING}))
- *<b></b>
- *URIPARSER_TOO_OLD=<span class="stringliteral">"uriparser 0.9.0 or later is required, your copy is too old."</span>
- *AC_COMPILE_IFELSE([
- *<span class="preprocessor">\#include <uriparser/Uri.h>
- *\#if (defined(URI_VER_MAJOR) && defined(URI_VER_MINOR) && defined(URI_VER_RELEASE) \\<b></b>
- *&& ((URI_VER_MAJOR > 0) \\<b></b>
- *|| ((URI_VER_MAJOR == 0) && (URI_VER_MINOR > 9)) \\<b></b>
- *|| ((URI_VER_MAJOR == 0) && (URI_VER_MINOR == 9) && (URI_VER_RELEASE >= 0)) \\<b></b>
- *))</span>
- *<span class="comment"><b></b>/<b></b>* FINE *<b></b>/</span>
- *<span class="preprocessor">\#else
- *\# error uriparser not recent enough
- *\#endif</span>
- *],,AC_MSG_ERROR(${URIPARSER_TOO_OLD}))</pre></div>
+ * of uriparser 0.9.0 or later.
+ *
+ *<div class="fragment"><pre class="fragment">PKG_CHECK_MODULES([URIPARSER], [liburiparser >= 0.9.0], [], [])</pre></div>
*/
diff --git a/include/uriparser/Uri.h b/include/uriparser/Uri.h
index e822d33..44d8760 100644
--- a/include/uriparser/Uri.h
+++ b/include/uriparser/Uri.h
@@ -1,4 +1,4 @@
-/* 520782e6334595efe9dee874cfa720d7b49de30fa51caba8bce352e55f521ee1 (0.9.4+)
+/* 6db8b5726a796167bb96b3d83ff9ac6792a01474dbe3778deb3c2a25d60b3693 (0.9.5+)
*
* uriparser - RFC 3986 URI parsing library
*
diff --git a/include/uriparser/UriBase.h b/include/uriparser/UriBase.h
index 4147882..565abcf 100644
--- a/include/uriparser/UriBase.h
+++ b/include/uriparser/UriBase.h
@@ -55,7 +55,7 @@
/* Version */
#define URI_VER_MAJOR 0
#define URI_VER_MINOR 9
-#define URI_VER_RELEASE 4
+#define URI_VER_RELEASE 5
#define URI_VER_SUFFIX_ANSI ""
#define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI)
diff --git a/include/uriparser/UriDefsConfig.h b/include/uriparser/UriDefsConfig.h
index 392229a..51bc93e 100644
--- a/include/uriparser/UriDefsConfig.h
+++ b/include/uriparser/UriDefsConfig.h
@@ -59,15 +59,15 @@
/* No encoding at all */
# error URI_NO_ANSI and URI_NO_UNICODE cannot go together.
# else
-/* Unicode only */
+/* Wide strings only */
# define URI_ENABLE_UNICODE 1
# endif
#else
# ifdef URI_NO_UNICODE
-/* ANSI only */
+/* Narrow strings only */
# define URI_ENABLE_ANSI 1
# else
-/* Both ANSI and Unicode */
+/* Both narrow and wide strings */
# define URI_ENABLE_ANSI 1
# define URI_ENABLE_UNICODE 1
# endif
@@ -82,7 +82,7 @@
/* Intel C/C++ */
/* http://predef.sourceforge.net/precomp.html#sec20 */
/* http://www.intel.com/support/performancetools/c/windows/sb/CS-007751.htm#2 */
-# define URI_INLINE __force_inline
+# define URI_INLINE __forceinline
#elif defined(_MSC_VER)
/* Microsoft Visual C++ */
/* http://predef.sourceforge.net/precomp.html#sec32 */
diff --git a/include/uriparser/UriDefsUnicode.h b/include/uriparser/UriDefsUnicode.h
index 08e4728..01421f5 100644
--- a/include/uriparser/UriDefsUnicode.h
+++ b/include/uriparser/UriDefsUnicode.h
@@ -39,7 +39,7 @@
/**
* @file UriDefsUnicode.h
- * Holds definitions for the Unicode pass.
+ * Holds definitions for the wide string pass.
* NOTE: This header is included N times, not once.
*/
diff --git a/liburiparser.pc.in b/liburiparser.pc.in
index 22c7c95..9547860 100644
--- a/liburiparser.pc.in
+++ b/liburiparser.pc.in
@@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
-exec_prefix=@CMAKE_INSTALL_PREFIX@
-libdir=@CMAKE_INSTALL_FULL_LIBDIR@
-includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
+includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: liburiparser
Description: URI parsing and handling library
diff --git a/src/UriCommon.c b/src/UriCommon.c
index 60bd319..7ba92f2 100644
--- a/src/UriCommon.c
+++ b/src/UriCommon.c
@@ -119,17 +119,6 @@ int URI_FUNC(CompareRange)(
-/* Properly removes "." and ".." path segments */
-UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri,
- UriBool relative, UriMemoryManager * memory) {
- if (uri == NULL) {
- return URI_TRUE;
- }
- return URI_FUNC(RemoveDotSegmentsEx)(uri, relative, uri->owner, memory);
-}
-
-
-
UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
UriBool relative, UriBool pathOwned, UriMemoryManager * memory) {
URI_TYPE(PathSegment) * walker;
@@ -149,7 +138,13 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
URI_TYPE(PathSegment) * const prev = walker->reserved;
URI_TYPE(PathSegment) * const nextBackup = walker->next;
- /* Is this dot segment essential? */
+ /*
+ * Is this dot segment essential,
+ * i.e. is there a chance of changing semantics by dropping this dot segment?
+ *
+ * For example, changing "./http://foo" into "http://foo" would change semantics
+ * and hence the dot segment is essential to that case and cannot be removed.
+ */
removeSegment = URI_TRUE;
if (relative && (walker == uri->pathHead) && (walker->next != NULL)) {
const URI_CHAR * ch = walker->next->text.first;
@@ -162,16 +157,23 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
}
if (removeSegment) {
+ /* .. then let's go remove that segment. */
/* Last segment? */
if (walker->next != NULL) {
- /* Not last segment */
+ /* Not last segment, i.e. first or middle segment
+ * OLD: (prev|NULL) <- walker <- next
+ * NEW: (prev|NULL) <----------- next */
walker->next->reserved = prev;
if (prev == NULL) {
- /* First but not last segment */
+ /* First but not last segment
+ * OLD: head -> walker -> next
+ * NEW: head -----------> next */
uri->pathHead = walker->next;
} else {
- /* Middle segment */
+ /* Middle segment
+ * OLD: prev -> walker -> next
+ * NEW: prev -----------> next */
prev->next = walker->next;
}
@@ -220,11 +222,16 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
removeSegment = URI_TRUE;
if (relative) {
if (prev == NULL) {
+ /* We cannot remove traversal beyond because the
+ * URI is relative and may be resolved later.
+ * So we can simplify "a/../b/d" to "b/d" but
+ * we cannot simplify "../b/d" (outside of reference resolution). */
removeSegment = URI_FALSE;
} else if ((prev != NULL)
&& ((prev->text.afterLast - prev->text.first) == 2)
&& ((prev->text.first)[0] == _UT('.'))
&& ((prev->text.first)[1] == _UT('.'))) {
+ /* We need to protect against mis-simplifying "a/../../b" to "a/b". */
removeSegment = URI_FALSE;
}
}
@@ -234,9 +241,14 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
/* Not first segment */
prevPrev = prev->reserved;
if (prevPrev != NULL) {
- /* Not even prev is the first one */
+ /* Not even prev is the first one
+ * OLD: prevPrev -> prev -> walker -> (next|NULL)
+ * NEW: prevPrev -------------------> (next|NULL) */
prevPrev->next = walker->next;
if (walker->next != NULL) {
+ /* Update parent relationship as well
+ * OLD: prevPrev <- prev <- walker <- next
+ * NEW: prevPrev <------------------- next */
walker->next->reserved = prevPrev;
} else {
/* Last segment -> insert "" segment to represent trailing slash, update tail */
@@ -302,29 +314,58 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
}
} else {
URI_TYPE(PathSegment) * const anotherNextBackup = walker->next;
- /* First segment -> update head pointer */
- uri->pathHead = walker->next;
+ int freeWalker = URI_TRUE;
+
+ /* First segment */
if (walker->next != NULL) {
+ /* First segment of multiple -> update head
+ * OLD: head -> walker -> next
+ * NEW: head -----------> next */
+ uri->pathHead = walker->next;
+
+ /* Update parent link as well
+ * OLD: head <- walker <- next
+ * NEW: head <----------- next */
walker->next->reserved = NULL;
} else {
- /* Last segment -> update tail */
- uri->pathTail = NULL;
+ if (uri->absolutePath) {
+ /* First and only segment -> update head
+ * OLD: head -> walker -> NULL
+ * NEW: head -----------> NULL */
+ uri->pathHead = NULL;
+
+ /* Last segment -> update tail
+ * OLD: tail -> walker
+ * NEW: tail -> NULL */
+ uri->pathTail = NULL;
+ } else {
+ /* Re-use segment for "" path segment to represent trailing slash,
+ * then update head and tail */
+ if (pathOwned && (walker->text.first != walker->text.afterLast)) {
+ memory->free(memory, (URI_CHAR *)walker->text.first);
+ }
+ walker->text.first = URI_FUNC(SafeToPointTo);
+ walker->text.afterLast = URI_FUNC(SafeToPointTo);
+ freeWalker = URI_FALSE;
+ }
}
- if (pathOwned && (walker->text.first != walker->text.afterLast)) {
- memory->free(memory, (URI_CHAR *)walker->text.first);
+ if (freeWalker) {
+ if (pathOwned && (walker->text.first != walker->text.afterLast)) {
+ memory->free(memory, (URI_CHAR *)walker->text.first);
+ }
+ memory->free(memory, walker);
}
- memory->free(memory, walker);
walker = anotherNextBackup;
}
}
}
break;
-
- }
+ } /* end of switch */
if (!removeSegment) {
+ /* .. then let's move to the next element, and start again. */
if (walker->next != NULL) {
walker->next->reserved = walker;
} else {
@@ -344,7 +385,10 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri,
UriMemoryManager * memory) {
const UriBool ABSOLUTE = URI_FALSE;
- return URI_FUNC(RemoveDotSegments)(uri, ABSOLUTE, memory);
+ if (uri == NULL) {
+ return URI_TRUE;
+ }
+ return URI_FUNC(RemoveDotSegmentsEx)(uri, ABSOLUTE, uri->owner, memory);
}
diff --git a/src/UriCommon.h b/src/UriCommon.h
index 10bc250..42311dd 100644
--- a/src/UriCommon.h
+++ b/src/UriCommon.h
@@ -84,8 +84,6 @@ int URI_FUNC(CompareRange)(
UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri,
UriMemoryManager * memory);
-UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri, UriBool relative,
- UriMemoryManager * memory);
UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri,
UriBool relative, UriBool pathOwned, UriMemoryManager * memory);
diff --git a/test/MemoryManagerSuite.cpp b/test/MemoryManagerSuite.cpp
index 4cda664..a828d76 100644
--- a/test/MemoryManagerSuite.cpp
+++ b/test/MemoryManagerSuite.cpp
@@ -27,7 +27,11 @@
#include <gtest/gtest.h>
#include <uriparser/Uri.h>
+
+// For defaultMemoryManager
+extern "C" {
#include "../src/UriMemory.h"
+}
namespace {
diff --git a/test/test.cpp b/test/test.cpp
index 9a189f9..4b156a4 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -311,7 +311,7 @@ TEST(UriSuite, TestUri) {
ASSERT_TRUE(0 == uriParseUriA(&stateA, "//user:pass@localhost/one/two/three"));
uriFreeUriMembersA(&uriA);
- // ANSI and Unicode
+ // Both narrow and wide string version
ASSERT_TRUE(0 == uriParseUriA(&stateA, "http://www.example.com/"));
uriFreeUriMembersA(&uriA);
ASSERT_TRUE(0 == uriParseUriW(&stateW, L"http://www.example.com/"));
@@ -1098,6 +1098,19 @@ TEST(UriSuite, TestAddBase) {
// Bug related to absolutePath flag set despite presence of host
ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"/", L"http://a/"));
ASSERT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"/g/", L"http://a/g/"));
+
+ // GitHub issue #92
+ EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/../d;p?q", L"../..", L"http://a/"));
+ EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/../d;p?q", L"../../", L"http://a/"));
+
+ EXPECT_TRUE(testAddBaseHelper(L"http://a/b/../c/d;p?q", L"../..", L"http://a/"));
+ EXPECT_TRUE(testAddBaseHelper(L"http://a/b/../c/d;p?q", L"../../", L"http://a/"));
+
+ EXPECT_TRUE(testAddBaseHelper(L"http://a/../b/c/d;p?q", L"../..", L"http://a/"));
+ EXPECT_TRUE(testAddBaseHelper(L"http://a/../b/c/d;p?q", L"../../", L"http://a/"));
+
+ EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../..", L"http://a/"));
+ EXPECT_TRUE(testAddBaseHelper(L"http://a/b/c/d;p?q", L"../../../", L"http://a/"));
}
namespace {
@@ -1477,6 +1490,48 @@ TEST(UriSuite, TestNormalizeSyntaxComponents) {
URI_NORMALIZE_FRAGMENT));
}
+TEST(UriSuite, TestNormalizeSyntaxPath) {
+ // These are from GitHub issue #92
+ EXPECT_TRUE(testNormalizeSyntaxHelper(
+ L"http://a/b/c/../../..",
+ L"http://a/",
+ URI_NORMALIZE_PATH));
+ EXPECT_TRUE(testNormalizeSyntaxHelper(
+ L"http://a/b/../c/../..",
+ L"http://a/",
+ URI_NORMALIZE_PATH));
+ EXPECT_TRUE(testNormalizeSyntaxHelper(
+ L"http://a/b/c/../../..",
+ L"http://a/",
+ URI_NORMALIZE_PATH));
+
+ // .. and these are related
+ EXPECT_TRUE(testNormalizeSyntaxHelper(
+ L"http://a/..",
+ L"http://a/",
+ URI_NORMALIZE_PATH));
+ EXPECT_TRUE(testNormalizeSyntaxHelper(
+ L"/..",
+ L"/",
+ URI_NORMALIZE_PATH));
+ EXPECT_TRUE(testNormalizeSyntaxHelper(
+ L"http://a/..///",
+ L"http://a///",
+ URI_NORMALIZE_PATH));
+ EXPECT_TRUE(testNormalizeSyntaxHelper(
+ L"http://a/..///..",
+ L"http://a//",
+ URI_NORMALIZE_PATH));
+ EXPECT_TRUE(testNormalizeSyntaxHelper(
+ L"a/b/c/../../..",
+ L"",
+ URI_NORMALIZE_PATH));
+ EXPECT_TRUE(testNormalizeSyntaxHelper(
+ L"a/b/../../c/..",
+ L"",
+ URI_NORMALIZE_PATH));
+}
+
TEST(UriSuite, TestNormalizeCrashBug20080224) {
UriParserStateW stateW;
int res;