
927 changed files with 3905 additions and 173664 deletions
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
ADD_SUBDIRECTORY(cpprestsdk) |
@ -1,204 +0,0 @@
@@ -1,204 +0,0 @@
|
||||
set(CMAKE_LEGACY_CYGWIN_WIN32 0) |
||||
cmake_minimum_required(VERSION 2.6) |
||||
|
||||
enable_testing() |
||||
|
||||
set(WARNINGS) |
||||
set(ANDROID_STL_FLAGS) |
||||
|
||||
# Platform (not compiler) specific settings |
||||
if(IOS) |
||||
set(IOS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Build_iOS") |
||||
set(Boost_FRAMEWORK "-F ${IOS_SOURCE_DIR} -framework boost") |
||||
set(Boost_INCLUDE_DIR "${IOS_SOURCE_DIR}/boost.framework/Headers") |
||||
|
||||
set(OPENSSL_FOUND 1) |
||||
set(OPENSSL_INCLUDE_DIR "${IOS_SOURCE_DIR}/openssl/include") |
||||
set(OPENSSL_LIBRARIES |
||||
"${IOS_SOURCE_DIR}/openssl/lib/libcrypto.a" |
||||
"${IOS_SOURCE_DIR}/openssl/lib/libssl.a" |
||||
) |
||||
|
||||
# The cxx_flags must be reset here, because the ios-cmake toolchain file unfortunately sets "-headerpad_max_install_names" which is not a valid clang flag. |
||||
set(CMAKE_CXX_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden") |
||||
|
||||
set(BUILD_SHARED_LIBS OFF) |
||||
set(BUILD_SAMPLES OFF) |
||||
option(BUILD_TESTS "Build tests." ON) |
||||
elseif(ANDROID) |
||||
set(Boost_COMPILER "-clang") |
||||
set(Boost_USE_STATIC_LIBS ON) |
||||
if(ARM) |
||||
set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android/build") |
||||
set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android/build/lib") |
||||
else() |
||||
set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build") |
||||
set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build/lib") |
||||
endif() |
||||
find_host_package(Boost 1.55 EXACT REQUIRED COMPONENTS random system thread filesystem chrono atomic) |
||||
|
||||
set(OPENSSL_FOUND 1) |
||||
if(ARM) |
||||
set(OPENSSL_INCLUDE_DIR "${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/include") |
||||
set(OPENSSL_LIBRARIES |
||||
"${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/lib/libssl.a" |
||||
"${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/lib/libcrypto.a" |
||||
) |
||||
else() |
||||
set(OPENSSL_INCLUDE_DIR "${CMAKE_BINARY_DIR}/../openssl/x86/include") |
||||
set(OPENSSL_LIBRARIES |
||||
"${CMAKE_BINARY_DIR}/../openssl/x86/lib/libssl.a" |
||||
"${CMAKE_BINARY_DIR}/../openssl/x86/lib/libcrypto.a" |
||||
) |
||||
endif() |
||||
|
||||
if(ARM) |
||||
set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/thumb/libgnustl_static.a") |
||||
else() |
||||
set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/libgnustl_static.a") |
||||
endif() |
||||
# These are used in the shared library case |
||||
set(ANDROID_STL_FLAGS |
||||
${LIBCXX_STL} |
||||
atomic |
||||
dl |
||||
gcc |
||||
c |
||||
m |
||||
-nodefaultlibs |
||||
) |
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared Libraries." OFF) |
||||
set(BUILD_SAMPLES OFF) |
||||
option(BUILD_TESTS "Build tests." ON) |
||||
elseif(UNIX) # This includes OSX |
||||
find_package(Boost REQUIRED COMPONENTS random chrono system thread regex filesystem) |
||||
find_package(Threads REQUIRED) |
||||
if(APPLE AND NOT OPENSSL_ROOT_DIR) |
||||
# Prefer a homebrew version of OpenSSL over the one in /usr/lib |
||||
file(GLOB OPENSSL_ROOT_DIR /usr/local/Cellar/openssl/*) |
||||
# Prefer the latest (make the latest one first) |
||||
list(REVERSE OPENSSL_ROOT_DIR) |
||||
endif() |
||||
# This should prevent linking against the system provided 0.9.8y |
||||
set(_OPENSSL_VERSION "") |
||||
find_package(OpenSSL 1.0.0 REQUIRED) |
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared Libraries." ON) |
||||
option(BUILD_TESTS "Build tests." OFF) |
||||
option(BUILD_SAMPLES "Build samples." OFF) |
||||
option(CASA_INSTALL_HEADERS "Install header files." ON) |
||||
if(CASA_INSTALL_HEADERS) |
||||
file(GLOB CASA_HEADERS_CPPREST include/cpprest/*.hpp include/cpprest/*.h include/cpprest/*.dat) |
||||
install(FILES ${CASA_HEADERS_CPPREST} DESTINATION include/cpprest) |
||||
file(GLOB CASA_HEADERS_PPLX include/pplx/*.hpp include/pplx/*.h) |
||||
install(FILES ${CASA_HEADERS_PPLX} DESTINATION include/pplx) |
||||
file(GLOB CASA_HEADERS_DETAILS include/cpprest/details/*.hpp include/cpprest/details/*.h include/cpprest/details/*.dat) |
||||
install(FILES ${CASA_HEADERS_DETAILS} DESTINATION include/cpprest/details) |
||||
endif() |
||||
elseif(WIN32) |
||||
option(BUILD_SHARED_LIBS "Build shared Libraries." ON) |
||||
option(BUILD_TESTS "Build tests." ON) |
||||
option(BUILD_SAMPLES "Build samples." ON) |
||||
option(Boost_USE_STATIC_LIBS ON) |
||||
|
||||
add_definitions(-DUNICODE -D_UNICODE) |
||||
|
||||
if(NOT BUILD_SHARED_LIBS) |
||||
# This causes cmake to not link the test libraries separately, but instead hold onto their object files. |
||||
set(TEST_LIBRARY_TARGET_TYPE OBJECT) |
||||
set(Casablanca_DEFINITIONS -D_NO_ASYNCRTIMP -D_NO_PPLXIMP CACHE INTERNAL "Definitions for consume casablanca library") |
||||
else() |
||||
set(Casablanca_DEFINITIONS "" CACHE INTERNAL "Definitions for consume casablanca library") |
||||
endif() |
||||
add_definitions(${Casablanca_DEFINITIONS} -D_WINSOCK_DEPRECATED_NO_WARNINGS -DWIN32) |
||||
|
||||
find_package(Boost 1.55 REQUIRED COMPONENTS random system thread filesystem chrono atomic) |
||||
find_package(OpenSSL 1.0 REQUIRED) |
||||
else() |
||||
message(FATAL_ERROR "-- Unsupported Build Platform.") |
||||
endif() |
||||
|
||||
# Compiler (not platform) specific settings |
||||
if(ANDROID) |
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") |
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic") |
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -Wno-pointer-arith") |
||||
include_directories( |
||||
"${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include" |
||||
"${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include" |
||||
"${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include/backward" |
||||
) |
||||
elseif((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR IOS) |
||||
message("-- Setting clang options") |
||||
|
||||
set(WARNINGS "-Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls") |
||||
set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder") |
||||
set(WARNINGS "${WARNINGS} ${OSX_SUPPRESSIONS}") |
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") |
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") |
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11") |
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") |
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") |
||||
message("-- Setting gcc options") |
||||
|
||||
set(WARNINGS "-Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code") |
||||
|
||||
set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") |
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") |
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") |
||||
message("-- Setting msvc options") |
||||
set(WARNINGS) |
||||
else() |
||||
message("-- Unknown compiler, success is doubtful.") |
||||
message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}") |
||||
endif() |
||||
|
||||
# Reconfigure final output directory |
||||
# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) |
||||
# set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) |
||||
# set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) |
||||
|
||||
# These settings can be used by the test targets |
||||
set(Casablanca_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) |
||||
set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include ${Boost_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libs/websocketpp) |
||||
|
||||
set(Casablanca_LIBRARY ${LIB}cpprest) |
||||
set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} ${Boost_LIBRARIES} ${Boost_FRAMEWORK}) |
||||
|
||||
# Everything in the project needs access to the casablanca include directories |
||||
include_directories(${Casablanca_INCLUDE_DIRS}) |
||||
|
||||
# Finally, the tests all use the same style declaration to build themselves, so we use a function |
||||
function(add_casablanca_test NAME SOURCES_VAR) |
||||
add_library(${NAME} ${TEST_LIBRARY_TARGET_TYPE} ${${SOURCES_VAR}}) |
||||
message("-- Added test library ${NAME}") |
||||
if (NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") |
||||
target_link_libraries(${NAME} |
||||
${LIB}httptest_utilities |
||||
${LIB}common_utilities |
||||
${LIB}unittestpp |
||||
${Casablanca_LIBRARIES} |
||||
${ANDROID_STL_FLAGS} |
||||
) |
||||
if (BUILD_SHARED_LIBS) |
||||
add_test(NAME ${NAME} |
||||
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} |
||||
COMMAND test_runner lib${NAME}${CMAKE_SHARED_LIBRARY_SUFFIX} |
||||
) |
||||
endif() |
||||
endif() |
||||
endfunction() |
||||
|
||||
add_subdirectory(src) |
||||
|
||||
if(BUILD_TESTS) |
||||
add_subdirectory(tests) |
||||
endif() |
||||
|
||||
if(BUILD_SAMPLES) |
||||
add_subdirectory(samples) |
||||
endif() |
@ -1,16 +0,0 @@
@@ -1,16 +0,0 @@
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.root))\Build\Common.Build.settings" /> |
||||
|
||||
<ItemGroup> |
||||
<ProjectFile Include="src\dirs.proj"/> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup Condition="'$(BuildTests)'!=''"> |
||||
<ProjectFile Include="tests\dirs.proj" Condition="'$(Platform)'!='ARM' or '$(WindowsSDKDesktopARMSupport)' == 'true'"/> |
||||
<ProjectFile Include="samples\dirs.proj" Condition="'$(Platform)'!='ARM' or '$(WindowsSDKDesktopARMSupport)' == 'true'"/> |
||||
</ItemGroup> |
||||
|
||||
<Import Project="$(TargetsPath)\Common.Build.Traversal.targets" /> |
||||
|
||||
</Project> |
File diff suppressed because it is too large
Load Diff
@ -1,593 +0,0 @@
@@ -1,593 +0,0 @@
|
||||
/***
|
||||
* ==++== |
||||
* |
||||
* Copyright (c) Microsoft Corporation. All rights reserved. |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
* ==--== |
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
||||
* |
||||
* Various common utilities. |
||||
* |
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
* |
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
||||
****/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <string> |
||||
#include <vector> |
||||
#include <cstdint> |
||||
#include <system_error> |
||||
#include <random> |
||||
#include <locale.h> |
||||
|
||||
#include "pplx/pplxtasks.h" |
||||
#include "cpprest/details/basic_types.h" |
||||
|
||||
#if !defined(_WIN32) || (_MSC_VER >= 1700) |
||||
#include <chrono> |
||||
#endif |
||||
|
||||
#ifndef _WIN32 |
||||
#include <boost/algorithm/string.hpp> |
||||
#if !defined(ANDROID) && !defined(__ANDROID__) // CodePlex 269
|
||||
#include <xlocale.h> |
||||
#endif |
||||
#endif |
||||
|
||||
/// Various utilities for string conversions and date and time manipulation.
|
||||
namespace utility |
||||
{ |
||||
|
||||
// Left over from VS2010 support, remains to avoid breaking.
|
||||
typedef std::chrono::seconds seconds; |
||||
|
||||
/// Functions for converting to/from std::chrono::seconds to xml string.
|
||||
namespace timespan |
||||
{ |
||||
/// <summary>
|
||||
/// Converts a timespan/interval in seconds to xml duration string as specified by
|
||||
/// http://www.w3.org/TR/xmlschema-2/#duration
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t __cdecl seconds_to_xml_duration(utility::seconds numSecs); |
||||
|
||||
/// <summary>
|
||||
/// Converts an xml duration to timespan/interval in seconds
|
||||
/// http://www.w3.org/TR/xmlschema-2/#duration
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::seconds __cdecl xml_duration_to_seconds(const utility::string_t ×panString); |
||||
} |
||||
|
||||
/// Functions for Unicode string conversions.
|
||||
namespace conversions |
||||
{ |
||||
/// <summary>
|
||||
/// Converts a UTF-16 string to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="w">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP std::string __cdecl utf16_to_utf8(const utf16string &w); |
||||
|
||||
/// <summary>
|
||||
/// Converts a UTF-8 string to a UTF-16
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl utf8_to_utf16(const std::string &s); |
||||
|
||||
/// <summary>
|
||||
/// Converts a ASCII (us-ascii) string to a UTF-16 string.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character us-ascii string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl usascii_to_utf16(const std::string &s); |
||||
|
||||
/// <summary>
|
||||
/// Converts a Latin1 (iso-8859-1) string to a UTF-16 string.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl latin1_to_utf16(const std::string &s); |
||||
|
||||
/// <summary>
|
||||
/// Converts a Latin1 (iso-8859-1) string to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP utf8string __cdecl latin1_to_utf8(const std::string &s); |
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(std::string &&s); |
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(utf16string &&s); |
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const std::string &s); |
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const utf16string &s); |
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-16 from string.
|
||||
/// </summary>
|
||||
/// <param name="value">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl to_utf16string(const std::string &value); |
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-16 from string.
|
||||
/// </summary>
|
||||
/// <param name="value">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl to_utf16string(utf16string value); |
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="value">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP std::string __cdecl to_utf8string(std::string value); |
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="value">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP std::string __cdecl to_utf8string(const utf16string &value); |
||||
|
||||
/// <summary>
|
||||
/// Encode the given byte array into a base64 string
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_base64(const std::vector<unsigned char>& data); |
||||
|
||||
/// <summary>
|
||||
/// Encode the given 8-byte integer into a base64 string
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_base64(uint64_t data); |
||||
|
||||
/// <summary>
|
||||
/// Decode the given base64 string to a byte array
|
||||
/// </summary>
|
||||
_ASYNCRTIMP std::vector<unsigned char> __cdecl from_base64(const utility::string_t& str); |
||||
|
||||
template <typename Source> |
||||
utility::string_t print_string(const Source &val, const std::locale &loc) |
||||
{ |
||||
utility::ostringstream_t oss; |
||||
oss.imbue(loc); |
||||
oss << val; |
||||
if (oss.bad()) |
||||
{ |
||||
throw std::bad_cast(); |
||||
} |
||||
return oss.str(); |
||||
} |
||||
|
||||
template <typename Source> |
||||
utility::string_t print_string(const Source &val) |
||||
{ |
||||
return print_string(val, std::locale()); |
||||
} |
||||
|
||||
template <typename Target> |
||||
Target scan_string(const utility::string_t &str, const std::locale &loc) |
||||
{ |
||||
Target t; |
||||
utility::istringstream_t iss(str); |
||||
iss.imbue(loc); |
||||
iss >> t; |
||||
if (iss.bad()) |
||||
{ |
||||
throw std::bad_cast(); |
||||
} |
||||
return t; |
||||
} |
||||
|
||||
template <typename Target> |
||||
Target scan_string(const utility::string_t &str) |
||||
{ |
||||
return scan_string<Target>(str, std::locale()); |
||||
} |
||||
} |
||||
|
||||
namespace details |
||||
{ |
||||
/// <summary>
|
||||
/// Cross platform RAII container for setting thread local locale.
|
||||
/// </summary>
|
||||
class scoped_c_thread_locale |
||||
{ |
||||
public: |
||||
_ASYNCRTIMP scoped_c_thread_locale(); |
||||
_ASYNCRTIMP ~scoped_c_thread_locale(); |
||||
|
||||
#if !defined(ANDROID) && !defined(__ANDROID__) // CodePlex 269
|
||||
#ifdef _WIN32 |
||||
typedef _locale_t xplat_locale; |
||||
#else |
||||
typedef locale_t xplat_locale; |
||||
#endif |
||||
|
||||
static _ASYNCRTIMP xplat_locale __cdecl c_locale(); |
||||
#endif |
||||
private: |
||||
#ifdef _WIN32 |
||||
std::string m_prevLocale; |
||||
int m_prevThreadSetting; |
||||
#elif !(defined(ANDROID) || defined(__ANDROID__)) |
||||
locale_t m_prevLocale; |
||||
#endif |
||||
scoped_c_thread_locale(const scoped_c_thread_locale &); |
||||
scoped_c_thread_locale & operator=(const scoped_c_thread_locale &); |
||||
}; |
||||
|
||||
/// <summary>
|
||||
/// Our own implementation of alpha numeric instead of std::isalnum to avoid
|
||||
/// taking global lock for performance reasons.
|
||||
/// </summary>
|
||||
inline bool __cdecl is_alnum(char ch) |
||||
{ |
||||
return (ch >= '0' && ch <= '9') |
||||
|| (ch >= 'A' && ch <= 'Z') |
||||
|| (ch >= 'a' && ch <= 'z'); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Simplistic implementation of make_unique. A better implementation would be based on variadic templates
|
||||
/// and therefore not be compatible with Dev10.
|
||||
/// </summary>
|
||||
template <typename _Type> |
||||
std::unique_ptr<_Type> make_unique() { |
||||
return std::unique_ptr<_Type>(new _Type()); |
||||
} |
||||
|
||||
template <typename _Type, typename _Arg1> |
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1) { |
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1))); |
||||
} |
||||
|
||||
template <typename _Type, typename _Arg1, typename _Arg2> |
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2) { |
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2))); |
||||
} |
||||
|
||||
template <typename _Type, typename _Arg1, typename _Arg2, typename _Arg3> |
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3) { |
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3))); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string comparision.
|
||||
/// </summary>
|
||||
/// <param name="left">First string to compare.</param>
|
||||
/// <param name="right">Second strong to compare.</param>
|
||||
/// <returns>true if the strings are equivalent, false otherwise</returns>
|
||||
inline bool str_icmp(const utility::string_t &left, const utility::string_t &right) |
||||
{ |
||||
#ifdef _WIN32 |
||||
return _wcsicmp(left.c_str(), right.c_str()) == 0; |
||||
#else |
||||
return boost::iequals(left, right); |
||||
#endif |
||||
} |
||||
|
||||
#ifdef _WIN32 |
||||
|
||||
/// <summary>
|
||||
/// Category error type for Windows OS errors.
|
||||
/// </summary>
|
||||
class windows_category_impl : public std::error_category |
||||
{ |
||||
public: |
||||
virtual const char *name() const CPPREST_NOEXCEPT { return "windows"; } |
||||
|
||||
_ASYNCRTIMP virtual std::string message(int errorCode) const CPPREST_NOEXCEPT; |
||||
|
||||
_ASYNCRTIMP virtual std::error_condition default_error_condition(int errorCode) const CPPREST_NOEXCEPT; |
||||
}; |
||||
|
||||
/// <summary>
|
||||
/// Gets the one global instance of the windows error category.
|
||||
/// </summary>
|
||||
/// </returns>An error category instance.</returns>
|
||||
_ASYNCRTIMP const std::error_category & __cdecl windows_category(); |
||||
|
||||
#else |
||||
|
||||
/// <summary>
|
||||
/// Gets the one global instance of the linux error category.
|
||||
/// </summary>
|
||||
/// </returns>An error category instance.</returns>
|
||||
_ASYNCRTIMP const std::error_category & __cdecl linux_category(); |
||||
|
||||
#endif |
||||
|
||||
/// <summary>
|
||||
/// Gets the one global instance of the current platform's error category.
|
||||
/// <summary>
|
||||
_ASYNCRTIMP const std::error_category & __cdecl platform_category(); |
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of std::system_error from a OS error code.
|
||||
/// </summary>
|
||||
inline std::system_error __cdecl create_system_error(unsigned long errorCode) |
||||
{ |
||||
std::error_code code((int)errorCode, platform_category()); |
||||
return std::system_error(code, code.message()); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates a std::error_code from a OS error code.
|
||||
/// </summary>
|
||||
inline std::error_code __cdecl create_error_code(unsigned long errorCode) |
||||
{ |
||||
return std::error_code((int)errorCode, platform_category()); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates the corresponding error message from a OS error code.
|
||||
/// </summary>
|
||||
inline utility::string_t __cdecl create_error_message(unsigned long errorCode) |
||||
{ |
||||
return utility::conversions::to_string_t(create_error_code(errorCode).message()); |
||||
} |
||||
|
||||
} |
||||
|
||||
class datetime |
||||
{ |
||||
public: |
||||
typedef uint64_t interval_type; |
||||
|
||||
/// <summary>
|
||||
/// Defines the supported date and time string formats.
|
||||
/// </summary>
|
||||
enum date_format { RFC_1123, ISO_8601 }; |
||||
|
||||
/// <summary>
|
||||
/// Returns the current UTC time.
|
||||
/// </summary>
|
||||
static _ASYNCRTIMP datetime __cdecl utc_now(); |
||||
|
||||
/// <summary>
|
||||
/// An invalid UTC timestamp value.
|
||||
/// </summary>
|
||||
enum:interval_type { utc_timestamp_invalid = static_cast<interval_type>(-1) }; |
||||
|
||||
/// <summary>
|
||||
/// Returns seconds since Unix/POSIX time epoch at 01-01-1970 00:00:00.
|
||||
/// If time is before epoch, utc_timestamp_invalid is returned.
|
||||
/// </summary>
|
||||
static interval_type utc_timestamp() |
||||
{ |
||||
const auto seconds = utc_now().to_interval() / _secondTicks; |
||||
if (seconds >= 11644473600LL) |
||||
{ |
||||
return seconds - 11644473600LL; |
||||
} |
||||
else |
||||
{ |
||||
return utc_timestamp_invalid; |
||||
} |
||||
} |
||||
|
||||
datetime() : m_interval(0) |
||||
{ |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 format.
|
||||
/// </summary>
|
||||
/// <returns>Returns a <c>datetime</c> of zero if not successful.</returns>
|
||||
static _ASYNCRTIMP datetime __cdecl from_string(const utility::string_t& timestring, date_format format = RFC_1123); |
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of the <c>datetime</c>.
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t to_string(date_format format = RFC_1123) const; |
||||
|
||||
/// <summary>
|
||||
/// Returns the integral time value.
|
||||
/// </summary>
|
||||
interval_type to_interval() const |
||||
{ |
||||
return m_interval; |
||||
} |
||||
|
||||
datetime operator- (interval_type value) const |
||||
{ |
||||
return datetime(m_interval - value); |
||||
} |
||||
|
||||
datetime operator+ (interval_type value) const |
||||
{ |
||||
return datetime(m_interval + value); |
||||
} |
||||
|
||||
bool operator== (datetime dt) const |
||||
{ |
||||
return m_interval == dt.m_interval; |
||||
} |
||||
|
||||
bool operator!= (const datetime& dt) const |
||||
{ |
||||
return !(*this == dt); |
||||
} |
||||
|
||||
static interval_type from_milliseconds(unsigned int milliseconds) |
||||
{ |
||||
return milliseconds*_msTicks; |
||||
} |
||||
|
||||
static interval_type from_seconds(unsigned int seconds) |
||||
{ |
||||
return seconds*_secondTicks; |
||||
} |
||||
|
||||
static interval_type from_minutes(unsigned int minutes) |
||||
{ |
||||
return minutes*_minuteTicks; |
||||
} |
||||
|
||||
static interval_type from_hours(unsigned int hours) |
||||
{ |
||||
return hours*_hourTicks; |
||||
} |
||||
|
||||
static interval_type from_days(unsigned int days) |
||||
{ |
||||
return days*_dayTicks; |
||||
} |
||||
|
||||
bool is_initialized() const |
||||
{ |
||||
return m_interval != 0; |
||||
} |
||||
|
||||
private: |
||||
|
||||
friend int operator- (datetime t1, datetime t2); |
||||
|
||||
static const interval_type _msTicks = static_cast<interval_type>(10000); |
||||
static const interval_type _secondTicks = 1000*_msTicks; |
||||
static const interval_type _minuteTicks = 60*_secondTicks; |
||||
static const interval_type _hourTicks = 60*60*_secondTicks; |
||||
static const interval_type _dayTicks = 24*60*60*_secondTicks; |
||||
|
||||
|
||||
#ifdef _WIN32 |
||||
// void* to avoid pulling in windows.h
|
||||
static _ASYNCRTIMP bool __cdecl datetime::system_type_to_datetime(/*SYSTEMTIME*/ void* psysTime, uint64_t seconds, datetime * pdt); |
||||
#else |
||||
static datetime timeval_to_datetime(const timeval &time); |
||||
#endif |
||||
|
||||
// Private constructor. Use static methods to create an instance.
|
||||
datetime(interval_type interval) : m_interval(interval) |
||||
{ |
||||
} |
||||
|
||||
// Storing as hundreds of nanoseconds 10e-7, i.e. 1 here equals 100ns.
|
||||
interval_type m_interval; |
||||
}; |
||||
|
||||
#ifndef _WIN32 |
||||
|
||||
// temporary workaround for the fact that
|
||||
// utf16char is not fully supported in GCC
|
||||
class cmp |
||||
{ |
||||
public: |
||||
|
||||
static int icmp(std::string left, std::string right) |
||||
{ |
||||
size_t i; |
||||
for (i = 0; i < left.size(); ++i) |
||||
{ |
||||
if (i == right.size()) return 1; |
||||
|
||||
auto l = cmp::tolower(left[i]); |
||||
auto r = cmp::tolower(right[i]); |
||||
if (l > r) return 1; |
||||
if (l < r) return -1; |
||||
} |
||||
if (i < right.size()) return -1; |
||||
return 0; |
||||
} |
||||
|
||||
private: |
||||
static char tolower(char c) |
||||
{ |
||||
if (c >= 'A' && c <= 'Z') |
||||
return static_cast<char>(c - 'A' + 'a'); |
||||
return c; |
||||
} |
||||
}; |
||||
|
||||
#endif |
||||
|
||||
inline int operator- (datetime t1, datetime t2) |
||||
{ |
||||
auto diff = (t1.m_interval - t2.m_interval); |
||||
|
||||
// Round it down to seconds
|
||||
diff /= 10 * 1000 * 1000; |
||||
|
||||
return static_cast<int>(diff); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Nonce string generator class.
|
||||
/// </summary>
|
||||
class nonce_generator |
||||
{ |
||||
public: |
||||
|
||||
/// <summary>
|
||||
/// Define default nonce length.
|
||||
/// </summary>
|
||||
enum { default_length = 32 }; |
||||
|
||||
/// <summary>
|
||||
/// Nonce generator constructor.
|
||||
/// </summary>
|
||||
/// <param name="length">Length of the generated nonce string.</param>
|
||||
nonce_generator(int length=default_length) : |
||||
m_random(static_cast<unsigned int>(utility::datetime::utc_timestamp())), |
||||
m_length(length) |
||||
{} |
||||
|
||||
/// <summary>
|
||||
/// Generate a nonce string containing random alphanumeric characters (A-Za-z0-9).
|
||||
/// Length of the generated string is set by length().
|
||||
/// </summary>
|
||||
/// <returns>The generated nonce string.</returns>
|
||||
_ASYNCRTIMP utility::string_t generate(); |
||||
|
||||
/// <summary>
|
||||
/// Get length of generated nonce string.
|
||||
/// </summary>
|
||||
/// <returns>Nonce string length.</returns>
|
||||
int length() const { return m_length; } |
||||
|
||||
/// <summary>
|
||||
/// Set length of the generated nonce string.
|
||||
/// </summary>
|
||||
/// <param name="length">Lenght of nonce string.</param>
|
||||
void set_length(int length) { m_length = length; } |
||||
|
||||
private: |
||||
static const utility::string_t c_allowed_chars; |
||||
std::mt19937 m_random; |
||||
int m_length; |
||||
}; |
||||
|
||||
} // namespace utility;
|
@ -1,450 +0,0 @@
@@ -1,450 +0,0 @@
|
||||
/***
|
||||
* ==++== |
||||
* |
||||
* Copyright (c) Microsoft Corporation. All rights reserved. |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
* ==--== |
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
||||
* |
||||
* Protocol independent support for URIs. |
||||
* |
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
* |
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
||||
****/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <map> |
||||
#include <memory> |
||||
#include <string> |
||||
#include <vector> |
||||
#include <functional> |
||||
|
||||
#include "cpprest/asyncrt_utils.h" |
||||
#include "cpprest/details/basic_types.h" |
||||
|
||||
namespace web { |
||||
namespace details |
||||
{ |
||||
struct uri_components |
||||
{ |
||||
uri_components() : m_path(_XPLATSTR("/")), m_port(-1) |
||||
{} |
||||
|
||||
uri_components(const uri_components &other) : |
||||
m_scheme(other.m_scheme), |
||||
m_host(other.m_host), |
||||
m_user_info(other.m_user_info), |
||||
m_path(other.m_path), |
||||
m_query(other.m_query), |
||||
m_fragment(other.m_fragment), |
||||
m_port(other.m_port) |
||||
{} |
||||
|
||||
uri_components & operator=(const uri_components &other) |
||||
{ |
||||
if (this != &other) |
||||
{ |
||||
m_scheme = other.m_scheme; |
||||
m_host = other.m_host; |
||||
m_user_info = other.m_user_info; |
||||
m_path = other.m_path; |
||||
m_query = other.m_query; |
||||
m_fragment = other.m_fragment; |
||||
m_port = other.m_port; |
||||
} |
||||
return *this; |
||||
} |
||||
|
||||
uri_components(uri_components &&other) CPPREST_NOEXCEPT : |
||||
m_scheme(std::move(other.m_scheme)), |
||||
m_host(std::move(other.m_host)), |
||||
m_user_info(std::move(other.m_user_info)), |
||||
m_path(std::move(other.m_path)), |
||||
m_query(std::move(other.m_query)), |
||||
m_fragment(std::move(other.m_fragment)), |
||||
m_port(other.m_port) |
||||
{} |
||||
|
||||
uri_components & operator=(uri_components &&other) CPPREST_NOEXCEPT |
||||
{ |
||||
if (this != &other) |
||||
{ |
||||
m_scheme = std::move(other.m_scheme); |
||||
m_host = std::move(other.m_host); |
||||
m_user_info = std::move(other.m_user_info); |
||||
m_path = std::move(other.m_path); |
||||
m_query = std::move(other.m_query); |
||||
m_fragment = std::move(other.m_fragment); |
||||
m_port = other.m_port; |
||||
} |
||||
return *this; |
||||
} |
||||
|
||||
_ASYNCRTIMP utility::string_t join(); |
||||
|
||||
utility::string_t m_scheme; |
||||
utility::string_t m_host; |
||||
utility::string_t m_user_info; |
||||
utility::string_t m_path; |
||||
utility::string_t m_query; |
||||
utility::string_t m_fragment; |
||||
int m_port; |
||||
}; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// A single exception type to represent errors in parsing, encoding, and decoding URIs.
|
||||
/// </summary>
|
||||
class uri_exception : public std::exception |
||||
{ |
||||
public: |
||||
|
||||
uri_exception(std::string msg) : m_msg(std::move(msg)) {} |
||||
|
||||
~uri_exception() CPPREST_NOEXCEPT {} |
||||
|
||||
const char* what() const CPPREST_NOEXCEPT |
||||
{ |
||||
return m_msg.c_str(); |
||||
} |
||||
|
||||
private: |
||||
std::string m_msg; |
||||
}; |
||||
|
||||
/// <summary>
|
||||
/// A flexible, protocol independent URI implementation.
|
||||
///
|
||||
/// URI instances are immutable. Querying the various fields on an emtpy URI will return empty strings. Querying
|
||||
/// various diagnostic members on an empty URI will return false.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation accepts both URIs ('http://msn.com/path') and URI relative-references
|
||||
/// ('/path?query#frag').
|
||||
///
|
||||
/// This implementation does not provide any scheme-specific handling -- an example of this
|
||||
/// would be the following: 'http://path1/path'. This is a valid URI, but it's not a valid
|
||||
/// http-uri -- that is, it's syntactically correct but does not conform to the requirements
|
||||
/// of the http scheme (http requires a host).
|
||||
/// We could provide this by allowing a pluggable 'scheme' policy-class, which would provide
|
||||
/// extra capability for validating and canonicalizing a URI according to scheme, and would
|
||||
/// introduce a layer of type-safety for URIs of differing schemes, and thus differing semantics.
|
||||
///
|
||||
/// One issue with implementing a scheme-independent URI facility is that of comparing for equality.
|
||||
/// For instance, these URIs are considered equal 'http://msn.com', 'http://msn.com:80'. That is --
|
||||
/// the 'default' port can be either omitted or explicit. Since we don't have a way to map a scheme
|
||||
/// to it's default port, we don't have a way to know these are equal. This is just one of a class of
|
||||
/// issues with regard to scheme-specific behavior.
|
||||
/// </remarks>
|
||||
class uri |
||||
{ |
||||
public: |
||||
|
||||
/// <summary>
|
||||
/// The various components of a URI. This enum is used to indicate which
|
||||
/// URI component is being encoded to the encode_uri_component. This allows
|
||||
/// specific encoding to be performed.
|
||||
///
|
||||
/// Scheme and port don't allow '%' so they don't need to be encoded.
|
||||
/// </summary>
|
||||
class components |
||||
{ |
||||
public: |
||||
enum component |
||||
{ |
||||
user_info, |
||||
host, |
||||
path, |
||||
query, |
||||
fragment, |
||||
full_uri |
||||
}; |
||||
}; |
||||
|
||||
/// <summary>
|
||||
/// Encodes a URI component according to RFC 3986.
|
||||
/// Note if a full URI is specified instead of an individual URI component all
|
||||
/// characters not in the unreserved set are escaped.
|
||||
/// </summary>
|
||||
/// <param name="raw">The URI as a string.</param>
|
||||
/// <returns>The encoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl encode_uri(const utility::string_t &raw, uri::components::component = components::full_uri); |
||||
|
||||
/// <summary>
|
||||
/// Encodes a string by converting all characters except for RFC 3986 unreserved characters to their
|
||||
/// hexadecimal representation.
|
||||
/// </summary>
|
||||
/// <param name="utf8data">The UTF-8 string data.</param>
|
||||
/// <returns>The encoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl encode_data_string(const utility::string_t &utf8data); |
||||
|
||||
/// <summary>
|
||||
/// Decodes an encoded string.
|
||||
/// </summary>
|
||||
/// <param name="encoded">The URI as a string.</param>
|
||||
/// <returns>The decoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl decode(const utility::string_t &encoded); |
||||
|
||||
/// <summary>
|
||||
/// Splits a path into its hierarchical components.
|
||||
/// </summary>
|
||||
/// <param name="path">The path as a string</param>
|
||||
/// <returns>A <c>std::vector<utility::string_t></c> containing the segments in the path.</returns>
|
||||
_ASYNCRTIMP static std::vector<utility::string_t> __cdecl split_path(const utility::string_t &path); |
||||
|
||||
/// <summary>
|
||||
/// Splits a query into its key-value components.
|
||||
/// </summary>
|
||||
/// <param name="query">The query string</param>
|
||||
/// <returns>A <c>std::map<utility::string_t, utility::string_t></c> containing the key-value components of the query.</returns>
|
||||
_ASYNCRTIMP static std::map<utility::string_t, utility::string_t> __cdecl split_query(const utility::string_t &query); |
||||
|
||||
/// <summary>
|
||||
/// Validates a string as a URI.
|
||||
/// </summary>
|
||||
/// <param name="uri_string">The URI string to be validated.</param>
|
||||
/// <returns><c>true</c> if the given string represents a valid URI, <c>false</c> otherwise.</returns>
|
||||
_ASYNCRTIMP static bool __cdecl validate(const utility::string_t &uri_string); |
||||
|
||||
/// <summary>
|
||||
/// Creates an empty uri
|
||||
/// </summary>
|
||||
uri() { m_uri = _XPLATSTR("/");}; |
||||
|
||||
/// <summary>
|
||||
/// Creates a URI from the given encoded string. This will throw an exception if the string
|
||||
/// does not contain a valid URI. Use uri::validate if processing user-input.
|
||||
/// </summary>
|
||||
/// <param name="uri_string">A pointer to an encoded string to create the URI instance.</param>
|
||||
_ASYNCRTIMP uri(const utility::char_t *uri_string); |
||||
|
||||
/// <summary>
|
||||
/// Creates a URI from the given encoded string. This will throw an exception if the string
|
||||
/// does not contain a valid URI. Use uri::validate if processing user-input.
|
||||
/// </summary>
|
||||
/// <param name="uri_string">An encoded URI string to create the URI instance.</param>
|
||||
_ASYNCRTIMP uri(const utility::string_t &uri_string); |
||||
|
||||
/// <summary>
|
||||
/// Copy constructor.
|
||||
/// </summary>
|
||||
uri(const uri &other) : |
||||
m_uri(other.m_uri), |
||||
m_components(other.m_components) |
||||
{} |
||||
|
||||
/// <summary>
|
||||
/// Copy assignment operator.
|
||||
/// </summary>
|
||||
uri & operator=(const uri &other) |
||||
{ |
||||
if (this != &other) |
||||
{ |
||||
m_uri = other.m_uri; |
||||
m_components = other.m_components; |
||||
} |
||||
return *this; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// </summary>
|
||||
uri(uri &&other) CPPREST_NOEXCEPT : |
||||
m_uri(std::move(other.m_uri)), |
||||
m_components(std::move(other.m_components)) |
||||
{} |
||||
|
||||
/// <summary>
|
||||
/// Move assignment operator
|
||||
/// </summary>
|
||||
uri & operator=(uri &&other) CPPREST_NOEXCEPT |
||||
{ |
||||
if (this != &other) |
||||
{ |
||||
m_uri = std::move(other.m_uri); |
||||
m_components = std::move(other.m_components); |
||||
} |
||||
return *this; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Get the scheme component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI scheme as a string.</returns>
|
||||
const utility::string_t &scheme() const { return m_components.m_scheme; } |
||||
|
||||
/// <summary>
|
||||
/// Get the user information component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI user information as a string.</returns>
|
||||
const utility::string_t &user_info() const { return m_components.m_user_info; } |
||||
|
||||
/// <summary>
|
||||
/// Get the host component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI host as a string.</returns>
|
||||
const utility::string_t &host() const { return m_components.m_host; } |
||||
|
||||
/// <summary>
|
||||
/// Get the port component of the URI. Returns -1 if no port is specified.
|
||||
/// </summary>
|
||||
/// <returns>The URI port as an integer.</returns>
|
||||
int port() const { return m_components.m_port; } |
||||
|
||||
/// <summary>
|
||||
/// Get the path component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI path as a string.</returns>
|
||||
const utility::string_t &path() const { return m_components.m_path; } |
||||
|
||||
/// <summary>
|
||||
/// Get the query component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI query as a string.</returns>
|
||||
const utility::string_t &query() const { return m_components.m_query; } |
||||
|
||||
/// <summary>
|
||||
/// Get the fragment component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI fragment as a string.</returns>
|
||||
const utility::string_t &fragment() const { return m_components.m_fragment; } |
||||
|
||||
/// <summary>
|
||||
/// Creates a new uri object with the same authority portion as this one, omitting the resource and query portions.
|
||||
/// </summary>
|
||||
/// <returns>The new uri object with the same authority.</returns>
|
||||
_ASYNCRTIMP uri authority() const; |
||||
|
||||
/// <summary>
|
||||
/// Gets the path, query, and fragment portion of this uri, which may be empty.
|
||||
/// </summary>
|
||||
/// <returns>The new URI object with the path, query and fragment portion of this URI.</returns>
|
||||
_ASYNCRTIMP uri resource() const; |
||||
|
||||
/// <summary>
|
||||
/// An empty URI specifies no components, and serves as a default value
|
||||
/// </summary>
|
||||
bool is_empty() const |
||||
{ |
||||
return this->m_uri.empty() || this->m_uri == _XPLATSTR("/"); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// A loopback URI is one which refers to a hostname or ip address with meaning only on the local machine.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Examples include "locahost", or ip addresses in the loopback range (127.0.0.0/24).
|
||||
/// </remarks>
|
||||
/// <returns><c>true</c> if this URI references the local host, <c>false</c> otherwise.</returns>
|
||||
bool is_host_loopback() const |
||||
{ |
||||
return !is_empty() && ((host() == _XPLATSTR("localhost")) || (host().size() > 4 && host().substr(0,4) == _XPLATSTR("127."))); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// A wildcard URI is one which refers to all hostnames that resolve to the local machine (using the * or +)
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// http://*:80
|
||||
/// </example>
|
||||
bool is_host_wildcard() const |
||||
{ |
||||
return !is_empty() && (this->host() == _XPLATSTR("*") || this->host() == _XPLATSTR("+")); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// A portable URI is one with a hostname that can be resolved globally (used from another machine).
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this URI can be resolved globally (used from another machine), <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// The hostname "localhost" is a reserved name that is guaranteed to resolve to the local machine,
|
||||
/// and cannot be used for inter-machine communication. Likewise the hostnames "*" and "+" on Windows
|
||||
/// represent wildcards, and do not map to a resolvable address.
|
||||
/// </remarks>
|
||||
bool is_host_portable() const |
||||
{ |
||||
return !(is_empty() || is_host_loopback() || is_host_wildcard()); |
||||
} |
||||
|
||||
// <summary>
|
||||
/// A default port is one where the port is unspecified, and will be determined by the operating system.
|
||||
/// The choice of default port may be dictated by the scheme (http -> 80) or not.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this URI instance has a default port, <c>false</c> otherwise.</returns>
|
||||
bool is_port_default() const |
||||
{ |
||||
return !is_empty() && this->port() == 0; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// An "authority" URI is one with only a scheme, optional userinfo, hostname, and (optional) port.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this is an "authority" URI, <c>false</c> otherwise.</returns>
|
||||
bool is_authority() const |
||||
{ |
||||
return !is_empty() && is_path_empty() && query().empty() && fragment().empty(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns whether the other URI has the same authority as this one
|
||||
/// </summary>
|
||||
/// <param name="other">The URI to compare the authority with.</param>
|
||||
/// <returns><c>true</c> if both the URI's have the same authority, <c>false</c> otherwise.</returns>
|
||||
bool has_same_authority(const uri &other) const |
||||
{ |
||||
return !is_empty() && this->authority() == other.authority(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns whether the path portion of this URI is empty
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if the path portion of this URI is empty, <c>false</c> otherwise.</returns>
|
||||
bool is_path_empty() const |
||||
{ |
||||
return path().empty() || path() == _XPLATSTR("/"); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns the full (encoded) URI as a string.
|
||||
/// </summary>
|
||||
/// <returns>The full encoded URI string.</returns>
|
||||
utility::string_t to_string() const |
||||
{ |
||||
return m_uri; |
||||
} |
||||
|
||||
_ASYNCRTIMP bool operator == (const uri &other) const; |
||||
|
||||
bool operator < (const uri &other) const |
||||
{ |
||||
return m_uri < other.m_uri; |
||||
} |
||||
|
||||
bool operator != (const uri &other) const |
||||
{ |
||||
return !(this->operator == (other)); |
||||
} |
||||
|
||||
private: |
||||
friend class uri_builder; |
||||
|
||||
// Encodes all characters not in given set determined by given function.
|
||||
static utility::string_t encode_impl(const utility::string_t &raw, const std::function<bool(int)>& should_encode); |
||||
|
||||
utility::string_t m_uri; |
||||
details::uri_components m_components; |
||||
}; |
||||
|
||||
} // namespace web
|
@ -1,632 +0,0 @@
@@ -1,632 +0,0 @@
|
||||
/***
|
||||
* ==++== |
||||
* |
||||
* Copyright (c) Microsoft Corporation. All rights reserved. |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
* ==--== |
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
||||
* |
||||
* This file defines a basic STL-container-based stream buffer. Reading from the buffer will not remove any data |
||||
* from it and seeking is thus supported. |
||||
* |
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
* |
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
||||
****/ |
||||
#pragma once |
||||
|
||||
#include <vector> |
||||
#include <queue> |
||||
#include <algorithm> |
||||
#include <iterator> |
||||
|
||||
#include "pplx/pplxtasks.h" |
||||
#include "cpprest/astreambuf.h" |
||||
#include "cpprest/streams.h" |
||||
|
||||
namespace Concurrency { namespace streams { |
||||
|
||||
// Forward declarations
|
||||
|
||||
template<typename _CollectionType> class container_buffer; |
||||
|
||||
namespace details { |
||||
|
||||
/// <summary>
|
||||
/// The basic_container_buffer class serves as a memory-based steam buffer that supports writing or reading
|
||||
/// sequences of characters.
|
||||
/// The class itself should not be used in application code, it is used by the stream definitions farther down in the header file.
|
||||
/// </summary>
|
||||
/// <remarks> When closed, neither writing nor reading is supported any longer. <c>basic_container_buffer</c> does not support simultaneous use of the buffer
|
||||
/// for reading and writing.</remarks>
|
||||
template<typename _CollectionType> |
||||
class basic_container_buffer : public streams::details::streambuf_state_manager<typename _CollectionType::value_type> |
||||
{ |
||||
public: |
||||
typedef typename _CollectionType::value_type _CharType; |
||||
typedef typename basic_streambuf<_CharType>::traits traits; |
||||
typedef typename basic_streambuf<_CharType>::int_type int_type; |
||||
typedef typename basic_streambuf<_CharType>::pos_type pos_type; |
||||
typedef typename basic_streambuf<_CharType>::off_type off_type; |
||||
|
||||
/// <summary>
|
||||
/// Returns the underlying data container
|
||||
/// </summary>
|
||||
_CollectionType& collection() |
||||
{ |
||||
return m_data; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~basic_container_buffer() |
||||
{ |
||||
// Invoke the synchronous versions since we need to
|
||||
// purge the request queue before deleting the buffer
|
||||
this->_close_read(); |
||||
this->_close_write(); |
||||
} |
||||
|
||||
|
||||
protected: |
||||
/// <summary>
|
||||
/// can_seek is used to determine whether a stream buffer supports seeking.
|
||||
/// </summary>
|
||||
virtual bool can_seek() const { return this->is_open(); } |
||||
|
||||
/// <summary>
|
||||
/// <c>has_size<c/> is used to determine whether a stream buffer supports size().
|
||||
/// </summary>
|
||||
virtual bool has_size() const { return this->is_open(); } |
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the stream, if known. Calls to <c>has_size</c> will determine whether
|
||||
/// the result of <c>size</c> can be relied on.
|
||||
/// </summary>
|
||||
virtual utility::size64_t size() const |
||||
{ |
||||
return utility::size64_t(m_data.size()); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Get the stream buffer size, if one has been set.
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will always return '0'.</remarks>
|
||||
virtual size_t buffer_size(std::ios_base::openmode = std::ios_base::in) const |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sets the stream buffer implementation to buffer or not buffer.
|
||||