diff --git a/Release/include/cpprest/http_compression.h b/Release/include/cpprest/http_compression.h index 1993e6244c..b6df43e026 100644 --- a/Release/include/cpprest/http_compression.h +++ b/Release/include/cpprest/http_compression.h @@ -51,7 +51,7 @@ class compress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done = nullptr) = 0; + bool& done) = 0; virtual pplx::task compress( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0; virtual void reset() = 0; @@ -71,7 +71,7 @@ class decompress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done = nullptr) = 0; + bool& done) = 0; virtual pplx::task decompress( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0; virtual void reset() = 0; diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index dfdeead4f3..1e88ddd2f0 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -714,7 +714,11 @@ namespace json private: std::string _message; public: - json_exception(const utility::char_t * const &message) : _message(utility::conversions::to_utf8string(message)) { } + json_exception(const char * const message) : _message(message) { } +#ifdef _UTF16_STRINGS + json_exception(const wchar_t * const message) : _message(utility::conversions::utf16_to_utf8(message)) { } +#endif // _UTF16_STRINGS + json_exception(std::string&& message) : _message(std::move(message)) { } // Must be narrow string because it derives from std::exception const char* what() const CPPREST_NOEXCEPT @@ -930,7 +934,7 @@ namespace json { if (index >= m_elements.size()) { - throw json_exception(_XPLATSTR("index out of bounds")); + throw json_exception("index out of bounds"); } m_elements.erase(m_elements.begin() + index); } @@ -943,7 +947,7 @@ namespace json json::value& at(size_type index) { if (index >= m_elements.size()) - throw json_exception(_XPLATSTR("index out of bounds")); + throw json_exception("index out of bounds"); return m_elements[index]; } @@ -956,7 +960,7 @@ namespace json const json::value& at(size_type index) const { if (index >= m_elements.size()) - throw json_exception(_XPLATSTR("index out of bounds")); + throw json_exception("index out of bounds"); return m_elements[index]; } @@ -1145,7 +1149,7 @@ namespace json auto iter = find_by_key(key); if (iter == m_elements.end()) { - throw web::json::json_exception(_XPLATSTR("Key not found")); + throw web::json::json_exception("Key not found"); } m_elements.erase(iter); @@ -1161,7 +1165,7 @@ namespace json auto iter = find_by_key(key); if (iter == m_elements.end()) { - throw web::json::json_exception(_XPLATSTR("Key not found")); + throw web::json::json_exception("Key not found"); } return iter->second; @@ -1177,7 +1181,7 @@ namespace json auto iter = find_by_key(key); if (iter == m_elements.end()) { - throw web::json::json_exception(_XPLATSTR("Key not found")); + throw web::json::json_exception("Key not found"); } return iter->second; @@ -1464,14 +1468,14 @@ namespace json virtual std::unique_ptr<_Value> _copy_value() = 0; virtual bool has_field(const utility::string_t &) const { return false; } - virtual value get_field(const utility::string_t &) const { throw json_exception(_XPLATSTR("not an object")); } - virtual value get_element(array::size_type) const { throw json_exception(_XPLATSTR("not an array")); } + virtual value get_field(const utility::string_t &) const { throw json_exception("not an object"); } + virtual value get_element(array::size_type) const { throw json_exception("not an array"); } - virtual value &index(const utility::string_t &) { throw json_exception(_XPLATSTR("not an object")); } - virtual value &index(array::size_type) { throw json_exception(_XPLATSTR("not an array")); } + virtual value &index(const utility::string_t &) { throw json_exception("not an object"); } + virtual value &index(array::size_type) { throw json_exception("not an array"); } - virtual const value &cnst_index(const utility::string_t &) const { throw json_exception(_XPLATSTR("not an object")); } - virtual const value &cnst_index(array::size_type) const { throw json_exception(_XPLATSTR("not an array")); } + virtual const value &cnst_index(const utility::string_t &) const { throw json_exception("not an object"); } + virtual const value &cnst_index(array::size_type) const { throw json_exception("not an array"); } // Common function used for serialization to strings and streams. virtual void serialize_impl(std::string& str) const @@ -1494,18 +1498,18 @@ namespace json virtual json::value::value_type type() const { return json::value::Null; } - virtual bool is_integer() const { throw json_exception(_XPLATSTR("not a number")); } - virtual bool is_double() const { throw json_exception(_XPLATSTR("not a number")); } - - virtual const json::number& as_number() { throw json_exception(_XPLATSTR("not a number")); } - virtual double as_double() const { throw json_exception(_XPLATSTR("not a number")); } - virtual int as_integer() const { throw json_exception(_XPLATSTR("not a number")); } - virtual bool as_bool() const { throw json_exception(_XPLATSTR("not a boolean")); } - virtual json::array& as_array() { throw json_exception(_XPLATSTR("not an array")); } - virtual const json::array& as_array() const { throw json_exception(_XPLATSTR("not an array")); } - virtual json::object& as_object() { throw json_exception(_XPLATSTR("not an object")); } - virtual const json::object& as_object() const { throw json_exception(_XPLATSTR("not an object")); } - virtual const utility::string_t& as_string() const { throw json_exception(_XPLATSTR("not a string")); } + virtual bool is_integer() const { throw json_exception("not a number"); } + virtual bool is_double() const { throw json_exception("not a number"); } + + virtual const json::number& as_number() { throw json_exception("not a number"); } + virtual double as_double() const { throw json_exception("not a number"); } + virtual int as_integer() const { throw json_exception("not a number"); } + virtual bool as_bool() const { throw json_exception("not a boolean"); } + virtual json::array& as_array() { throw json_exception("not an array"); } + virtual const json::array& as_array() const { throw json_exception("not an array"); } + virtual json::object& as_object() { throw json_exception("not an object"); } + virtual const json::object& as_object() const { throw json_exception("not an object"); } + virtual const utility::string_t& as_string() const { throw json_exception("not a string"); } virtual size_t size() const { return 0; } diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 72e13f046c..7ee22133fe 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1530,7 +1530,7 @@ class asio_context final : public request_context, public std::enable_shared_fro size_t got; size_t inbytes = 0; size_t outbytes = 0; - bool done = false; + bool done; try { @@ -1547,7 +1547,7 @@ class asio_context final : public request_context, public std::enable_shared_fro output.size() - outbytes, web::http::compression::operation_hint::has_more, processed, - &done); + done); inbytes += processed; outbytes += got; } while (got && !done); diff --git a/Release/src/http/client/http_client_msg.cpp b/Release/src/http/client/http_client_msg.cpp index 9cab7c8da9..dd7f3dc5c5 100644 --- a/Release/src/http/client/http_client_msg.cpp +++ b/Release/src/http/client/http_client_msg.cpp @@ -12,6 +12,7 @@ ****/ #include "stdafx.h" #include "../common/internal_http_helpers.h" +#include "cpprest/asyncrt_utils.h" namespace web { namespace http { @@ -61,29 +62,41 @@ void details::_http_request::set_request_uri(const uri& relative) utility::string_t details::_http_request::to_string() const { - utility::ostringstream_t buffer; - buffer.imbue(std::locale::classic()); - buffer << m_method << _XPLATSTR(" ") << (this->m_uri.is_empty() ? _XPLATSTR("/") : this->m_uri.to_string()) << _XPLATSTR(" HTTP/1.1\r\n"); - buffer << http_msg_base::to_string(); - return buffer.str(); + utility::string_t result(m_method); + result += _XPLATSTR(' '); + if (this->m_uri.is_empty()) + { + result += _XPLATSTR('/'); + } + else + { + result += this->m_uri.to_string(); + } + + result += _XPLATSTR(" HTTP/1.1\r\n"); + result += http_msg_base::to_string(); + return result; } utility::string_t details::_http_response::to_string() const { + utility::string_t result(_XPLATSTR("HTTP/1.1 ")); + result += utility::conversions::details::to_string_t(m_status_code); + result += ' '; // If the user didn't explicitly set a reason phrase then we should have it default // if they used one of the standard known status codes. - auto reason_phrase = m_reason_phrase; - if(reason_phrase.empty()) + if (m_reason_phrase.empty()) { - reason_phrase = get_default_reason_phrase(status_code()); + result += get_default_reason_phrase(status_code()); + } + else + { + result += m_reason_phrase; } - utility::ostringstream_t buffer; - buffer.imbue(std::locale::classic()); - buffer << _XPLATSTR("HTTP/1.1 ") << m_status_code << _XPLATSTR(" ") << reason_phrase << _XPLATSTR("\r\n"); - - buffer << http_msg_base::to_string(); - return buffer.str(); + result += _XPLATSTR("\r\n"); + result += http_msg_base::to_string(); + return result; } }} // namespace web::http diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index 5a0697b489..79f682ec50 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -160,7 +160,8 @@ class HttpRequestCallback final : std::wstring msg(L"IXMLHttpRequest2Callback::OnError: "); msg.append(std::to_wstring(hrError)); msg.append(L": "); - msg.append(utility::conversions::to_string_t(utility::details::windows_category().message(hrError))); + msg.append(utility::conversions::to_string_t( + utility::details::windows_category().message(hrError))); m_request->report_error(hrError, msg); } else diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp index 194f1efc97..9d409906c5 100644 --- a/Release/src/http/common/http_compression.cpp +++ b/Release/src/http/common/http_compression.cpp @@ -75,23 +75,19 @@ class zlib_compressor_base : public compress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { if (m_state == Z_STREAM_END || (hint != operation_hint::is_last && !input_size)) { input_bytes_processed = 0; - if (done) - { - *done = (m_state == Z_STREAM_END); - } + done = (m_state == Z_STREAM_END); return 0; } if (m_state != Z_OK && m_state != Z_BUF_ERROR && m_state != Z_STREAM_ERROR) { - std::stringstream ss; - ss << "Prior unrecoverable compression stream error " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Prior unrecoverable compression stream error " + + std::to_string(m_state)); } if (input_size > std::numeric_limits::max() || output_size > std::numeric_limits::max()) @@ -108,16 +104,11 @@ class zlib_compressor_base : public compress_provider if (m_state != Z_OK && m_state != Z_STREAM_ERROR && !(hint == operation_hint::is_last && (m_state == Z_STREAM_END || m_state == Z_BUF_ERROR))) { - std::stringstream ss; - ss << "Unrecoverable compression stream error " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Unrecoverable compression stream error " + std::to_string(m_state)); } input_bytes_processed = input_size - m_stream.avail_in; - if (done) - { - *done = (m_state == Z_STREAM_END); - } + done = (m_state == Z_STREAM_END); return output_size - m_stream.avail_out; } @@ -129,7 +120,7 @@ class zlib_compressor_base : public compress_provider try { r.output_bytes_produced = - compress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + compress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { @@ -146,9 +137,7 @@ class zlib_compressor_base : public compress_provider m_state = deflateReset(&m_stream); if (m_state != Z_OK) { - std::stringstream ss; - ss << "Failed to reset zlib compressor " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Failed to reset zlib compressor " + std::to_string(m_state)); } } @@ -181,23 +170,18 @@ class zlib_decompressor_base : public decompress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { if (m_state == Z_STREAM_END || !input_size) { input_bytes_processed = 0; - if (done) - { - *done = (m_state == Z_STREAM_END); - } + done = (m_state == Z_STREAM_END); return 0; } if (m_state != Z_OK && m_state != Z_BUF_ERROR && m_state != Z_STREAM_ERROR) { - std::stringstream ss; - ss << "Prior unrecoverable decompression stream error " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Prior unrecoverable decompression stream error " + std::to_string(m_state)); } if (input_size > std::numeric_limits::max() || output_size > std::numeric_limits::max()) @@ -215,16 +199,11 @@ class zlib_decompressor_base : public decompress_provider { // Z_BUF_ERROR is a success code for Z_FINISH, and the caller can continue as if operation_hint::is_last was // not given - std::stringstream ss; - ss << "Unrecoverable decompression stream error " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Unrecoverable decompression stream error " + std::to_string(m_state)); } input_bytes_processed = input_size - m_stream.avail_in; - if (done) - { - *done = (m_state == Z_STREAM_END); - } + done = (m_state == Z_STREAM_END); return output_size - m_stream.avail_out; } @@ -236,7 +215,7 @@ class zlib_decompressor_base : public decompress_provider try { r.output_bytes_produced = - decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { @@ -253,9 +232,7 @@ class zlib_decompressor_base : public decompress_provider m_state = inflateReset(&m_stream); if (m_state != Z_OK) { - std::stringstream ss; - ss << "Failed to reset zlib decompressor " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Failed to reset zlib decompressor " + std::to_string(m_state)); } } @@ -331,15 +308,12 @@ class brotli_compressor : public compress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { if (m_done || (hint != operation_hint::is_last && !input_size)) { input_bytes_processed = 0; - if (done) - { - *done = m_done; - } + done = m_done; return 0; } @@ -397,10 +371,7 @@ class brotli_compressor : public compress_provider } input_bytes_processed = input_size - avail_in; - if (done) - { - *done = m_done; - } + done = m_done; return output_size - avail_out; } @@ -495,15 +466,12 @@ class brotli_decompressor : public decompress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { if (m_state == BROTLI_DECODER_RESULT_SUCCESS /* || !input_size*/) { input_bytes_processed = 0; - if (done) - { - *done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); - } + done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); return 0; } @@ -529,10 +497,7 @@ class brotli_decompressor : public decompress_provider } input_bytes_processed = input_size - avail_in; - if (done) - { - *done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); - } + done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); return output_size - avail_out; } @@ -761,7 +726,7 @@ std::unique_ptr make_gzip_compressor(int compressionLevel, in return std::unique_ptr(); #endif // CPPREST_HTTP_COMPRESSION } - + std::unique_ptr make_deflate_compressor(int compressionLevel, int method, int strategy, int memLevel) { #if defined(CPPREST_HTTP_COMPRESSION) @@ -1088,14 +1053,13 @@ utility::string_t build_supported_header(header_types type, { const std::vector>& f = factories.empty() ? web::http::compression::builtin::g_decompress_factories : factories; - utility::ostringstream_t os; + utility::string_t result; bool start; _ASSERTE(type == header_types::te || type == header_types::accept_encoding); // Add all specified algorithms and their weights to the header start = true; - os.imbue(std::locale::classic()); for (auto& factory : f) { if (factory) @@ -1104,12 +1068,15 @@ utility::string_t build_supported_header(header_types type, if (!start) { - os << _XPLATSTR(", "); + result += _XPLATSTR(", "); } - os << factory->algorithm(); + result += factory->algorithm(); if (weight <= 1000) { - os << _XPLATSTR(";q=") << weight / 1000 << _XPLATSTR(".") << weight % 1000; + result += _XPLATSTR(";q="); + result += utility::conversions::details::to_string_t(weight / 1000); + result += _XPLATSTR('.'); + result += utility::conversions::details::to_string_t(weight % 1000); } start = false; } @@ -1118,10 +1085,10 @@ utility::string_t build_supported_header(header_types type, if (start && type == header_types::accept_encoding) { // Request that no encoding be applied - os << _XPLATSTR("identity;q=1, *;q=0"); + result += _XPLATSTR("identity;q=1, *;q=0"); } - return os.str(); + return result; } } // namespace details } // namespace compression diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 7a80017828..44870f5420 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -253,7 +253,7 @@ void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers http_version __cdecl http_version::from_string(const std::string& http_version_string) { - std::stringstream str(http_version_string); + std::istringstream str(http_version_string); str.imbue(std::locale::classic()); std::string http; std::getline(str, http, '/'); @@ -1009,22 +1009,24 @@ static utility::string_t convert_body_to_string_t(const utility::string_t &conte // static utility::string_t http_headers_body_to_string(const http_headers &headers, concurrency::streams::istream instream) { - utility::ostringstream_t buffer; - buffer.imbue(std::locale::classic()); - + utility::string_t result; for (const auto &header : headers) { - buffer << header.first << _XPLATSTR(": ") << header.second << CRLF; + result += header.first; + result += _XPLATSTR(": "); + result += header.second; + result += CRLF; } - buffer << CRLF; + + result += CRLF; utility::string_t content_type; if(headers.match(http::header_names::content_type, content_type)) { - buffer << convert_body_to_string_t(content_type, instream); + result += convert_body_to_string_t(content_type, instream); } - return buffer.str(); + return result; } utility::string_t details::http_msg_base::to_string() const diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 13b813b858..5ab3086954 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -693,7 +693,8 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys // Get the path - remove the version portion and prefix space try { - m_request.set_request_uri(utility::conversions::to_string_t(http_path_and_version.substr(1, http_path_and_version.size() - VersionPortionSize - 1))); + m_request.set_request_uri(utility::conversions::to_string_t( + http_path_and_version.substr(1, http_path_and_version.size() - VersionPortionSize - 1))); } catch (const std::exception& e) // may be std::range_error indicating invalid Unicode, or web::uri_exception { @@ -722,7 +723,8 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys auto endpoint = m_socket->remote_endpoint(socket_ec); if (!socket_ec) { - m_request._get_impl()->_set_remote_address(utility::conversions::to_string_t(endpoint.address().to_string())); + m_request._get_impl()->_set_remote_address(utility::conversions::to_string_t( + endpoint.address().to_string())); } return handle_headers(); @@ -743,7 +745,8 @@ will_deref_and_erase_t asio_server_connection::handle_headers() if (colon != std::string::npos && colon != 0) { auto name = utility::conversions::to_string_t(header.substr(0, colon)); - auto value = utility::conversions::to_string_t(header.substr(colon + 1, header.length() - (colon + 1))); // also exclude '\r' + auto value = utility::conversions::to_string_t( + header.substr(colon + 1, header.length() - (colon + 1))); // also exclude '\r' web::http::details::trim_whitespace(name); web::http::details::trim_whitespace(value); diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 3adb4fb882..242dae4800 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -243,7 +243,7 @@ pplx::task http_windows_server::register_listener(_In_ web::http::experime utility::string_t host_uri = http::uri::decode(u.to_string()); if(host_uri.back() != U('/') && u.query().empty() && u.fragment().empty()) { - host_uri.append(U("/")); + host_uri.push_back(U('/')); } // inside here we check for a few specific error types that know about @@ -252,19 +252,16 @@ pplx::task http_windows_server::register_listener(_In_ web::http::experime if(errorCode) { HttpCloseUrlGroup(urlGroupId); - utility::stringstream_t os; - os.imbue(std::locale::classic()); - if(errorCode == ERROR_ALREADY_EXISTS || errorCode == ERROR_SHARING_VIOLATION) { - os << _XPLATSTR("Address '") << pListener->uri().to_string() << _XPLATSTR("' is already in use"); - return pplx::task_from_exception(http_exception(errorCode, os.str())); + return pplx::task_from_exception(http_exception(errorCode, + _XPLATSTR("Address '") + pListener->uri().to_string() + _XPLATSTR("' is already in use"))); } else if (errorCode == ERROR_ACCESS_DENIED) { - os << _XPLATSTR("Access denied: attempting to add Address '") << pListener->uri().to_string() << _XPLATSTR("'. "); - os << _XPLATSTR("Run as administrator to listen on an hostname other than localhost, or to listen on port 80."); - return pplx::task_from_exception(http_exception(errorCode, os.str())); + return pplx::task_from_exception(http_exception(errorCode, + _XPLATSTR("Access denied: attempting to add Address '") + pListener->uri().to_string() + _XPLATSTR("'. ") + _XPLATSTR("Run as administrator to listen on an hostname other than localhost, or to listen on port 80."))); } else { @@ -738,7 +735,8 @@ void windows_request_context::read_body_io_completion(DWORD error_code, DWORD by auto body = request_body_buf.alloc(CHUNK_SIZE); try { - got = m_decompressor->decompress(m_compress_buffer.data()+total_used, bytes_read-total_used, body, CHUNK_SIZE, http::compression::operation_hint::has_more, used, NULL); + bool done_unused; + got = m_decompressor->decompress(m_compress_buffer.data()+total_used, bytes_read-total_used, body, CHUNK_SIZE, http::compression::operation_hint::has_more, used, done_unused); } catch (...) { diff --git a/Release/src/http/oauth/oauth1.cpp b/Release/src/http/oauth/oauth1.cpp index 37c71deb22..22029593b8 100644 --- a/Release/src/http/oauth/oauth1.cpp +++ b/Release/src/http/oauth/oauth1.cpp @@ -12,6 +12,7 @@ ****/ #include "stdafx.h" +#include "cpprest/asyncrt_utils.h" #if !defined(CPPREST_TARGET_XP) @@ -153,15 +154,17 @@ std::vector oauth1_config::_hmac_sha1(const utility::string_t& ke // - If URI port is unspecified. utility::string_t oauth1_config::_build_base_string_uri(const uri& u) { - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << u.scheme() << "://" << u.host(); + utility::string_t result(u.scheme()); + result += _XPLATSTR("://"); + result += u.host(); if (!u.is_port_default() && u.port() != 80 && u.port() != 443) { - os << ":" << u.port(); + result += _XPLATSTR(':'); + result += utility::conversions::details::to_string_t(u.port()); } - os << u.path(); - return uri::encode_data_string(os.str()); + + result += u.path(); + return uri::encode_data_string(std::move(result)); } utility::string_t oauth1_config::_build_normalized_parameters(web::http::uri u, const oauth1_state& state) const @@ -172,18 +175,12 @@ utility::string_t oauth1_config::_build_normalized_parameters(web::http::uri u, std::vector queries; for (const auto& query : queries_map) { - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << query.first << "=" << query.second; - queries.push_back(os.str()); + queries.push_back(query.first + _XPLATSTR('=') + query.second); } for (const auto& query : parameters()) { - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << query.first << "=" << query.second; - queries.push_back(os.str()); + queries.push_back(query.first + _XPLATSTR('=') + query.second); } // Push oauth1 parameters. @@ -202,15 +199,21 @@ utility::string_t oauth1_config::_build_normalized_parameters(web::http::uri u, } // Sort parameters and build the string. - sort(queries.begin(), queries.end()); - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - for (auto i = queries.begin(); i != queries.end() - 1; ++i) + utility::string_t result; + if (!queries.empty()) { - os << *i << U("&"); + auto i = queries.begin(); + auto e = queries.end(); + sort(i, e); + result = *i; + while (++i != e) + { + result += _XPLATSTR('&'); + result += *i; + } } - os << queries.back(); - return uri::encode_data_string(os.str()); + + return uri::encode_data_string(result); } static bool is_application_x_www_form_urlencoded (http_request &request) @@ -222,10 +225,9 @@ static bool is_application_x_www_form_urlencoded (http_request &request) utility::string_t oauth1_config::_build_signature_base_string(http_request request, oauth1_state state) const { uri u(request.absolute_uri()); - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << request.method(); - os << "&" << _build_base_string_uri(u); + utility::string_t result(request.method()); + result += _XPLATSTR('&'); + result += _build_base_string_uri(u); // http://oauth.net/core/1.0a/#signing_process // 9.1.1. Normalize Request Parameters @@ -233,19 +235,21 @@ utility::string_t oauth1_config::_build_signature_base_string(http_request reque // - Parameters in the OAuth HTTP Authorization header excluding the realm parameter. // - Parameters in the HTTP POST request body (with a content-type of application/x-www-form-urlencoded). // - HTTP GET parameters added to the URLs in the query part (as defined by [RFC3986] section 3). + result += _XPLATSTR('&'); if (is_application_x_www_form_urlencoded(request)) { // Note: this should be improved to not block and handle any potential exceptions. utility::string_t str = request.extract_string(true).get(); request.set_body(str, web::http::details::mime_types::application_x_www_form_urlencoded); uri v = http::uri_builder(request.absolute_uri()).append_query(std::move(str), false).to_uri(); - os << "&" << _build_normalized_parameters(std::move(v), std::move(state)); + result += _build_normalized_parameters(std::move(v), std::move(state)); } else { - os << "&" << _build_normalized_parameters(std::move(u), std::move(state)); + result += _build_normalized_parameters(std::move(u), std::move(state)); } - return os.str(); + + return result; } utility::string_t oauth1_config::_build_signature(http_request request, oauth1_state state) const @@ -323,31 +327,57 @@ pplx::task oauth1_config::_request_token(oauth1_state state, bool is_temp_ void oauth1_config::_authenticate_request(http_request &request, oauth1_state state) { - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << "OAuth "; + utility::string_t authHeader(_XPLATSTR("OAuth ")); if (!realm().empty()) { - os << oauth1_strings::realm << "=\"" << web::uri::encode_data_string (realm()) << "\", "; + authHeader += oauth1_strings::realm; + authHeader += _XPLATSTR("=\""); + authHeader += web::uri::encode_data_string(realm()); + authHeader += _XPLATSTR("\", "); } - os << oauth1_strings::version << "=\"1.0"; - os << "\", " << oauth1_strings::consumer_key << "=\"" << web::uri::encode_data_string (consumer_key()); + + authHeader += oauth1_strings::version; + authHeader += _XPLATSTR("=\"1.0\", "); + authHeader += oauth1_strings::consumer_key; + authHeader += _XPLATSTR("=\""); + authHeader += web::uri::encode_data_string (consumer_key()); + if (!m_token.access_token().empty()) { - os << "\", " << oauth1_strings::token << "=\"" << web::uri::encode_data_string(m_token.access_token()); + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::token; + authHeader += _XPLATSTR("=\""); + authHeader += web::uri::encode_data_string(m_token.access_token()); } - os << "\", " << oauth1_strings::signature_method << "=\"" << method(); - os << "\", " << oauth1_strings::timestamp << "=\"" << state.timestamp(); - os << "\", " << oauth1_strings::nonce << "=\"" << state.nonce(); - os << "\", " << oauth1_strings::signature << "=\"" << uri::encode_data_string(_build_signature(request, state)); - os << "\""; + + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::signature_method; + authHeader += _XPLATSTR("=\""); + authHeader += method(); + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::timestamp; + authHeader += _XPLATSTR("=\""); + authHeader += state.timestamp(); + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::nonce; + authHeader += _XPLATSTR("=\""); + authHeader += state.nonce(); + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::signature; + authHeader += _XPLATSTR("=\""); + authHeader += uri::encode_data_string(_build_signature(request, state)); + authHeader += _XPLATSTR("\""); if (!state.extra_key().empty()) { - os << ", " << state.extra_key() << "=\"" << web::uri::encode_data_string(state.extra_value()) << "\""; + authHeader += _XPLATSTR(", "); + authHeader += state.extra_key(); + authHeader += _XPLATSTR("=\""); + authHeader += web::uri::encode_data_string(state.extra_value()); + authHeader += _XPLATSTR("\""); } - request.headers().add(header_names::authorization, os.str()); + request.headers().add(header_names::authorization, std::move(authHeader)); } pplx::task oauth1_config::build_authorization_uri() @@ -373,11 +403,10 @@ pplx::task oauth1_config::token_from_redirected_uri(const web::http::uri& } if (m_token.access_token() != token_param->second) { - utility::ostringstream_t err; - err.imbue(std::locale::classic()); - err << U("redirected URI parameter 'oauth_token'='") << token_param->second - << U("' does not match temporary token='") << m_token.access_token() << U("'."); - return pplx::task_from_exception(oauth1_exception(err.str().c_str())); + return pplx::task_from_exception(oauth1_exception( + _XPLATSTR("redirected URI parameter 'oauth_token'='") + token_param->second + + _XPLATSTR("' does not match temporary token='") + m_token.access_token() + _XPLATSTR("'.") + )); } auto verifier_param = query.find(oauth1_strings::verifier); diff --git a/Release/src/http/oauth/oauth2.cpp b/Release/src/http/oauth/oauth2.cpp index 247241933f..c85cf44c2f 100644 --- a/Release/src/http/oauth/oauth2.cpp +++ b/Release/src/http/oauth/oauth2.cpp @@ -71,11 +71,12 @@ pplx::task oauth2_config::token_from_redirected_uri(const web::http::uri& } if (state() != state_param->second) { - utility::ostringstream_t err; - err.imbue(std::locale::classic()); - err << U("redirected URI parameter 'state'='") << state_param->second - << U("' does not match state='") << state() << U("'."); - return pplx::task_from_exception(oauth2_exception(err.str())); + utility::string_t err(_XPLATSTR("redirected URI parameter 'state'='")); + err += state_param->second; + err += _XPLATSTR("' does not match state='"); + err += state(); + err += _XPLATSTR("'."); + return pplx::task_from_exception(oauth2_exception(std::move(err))); } auto code_param = query.find(oauth2_strings::code); diff --git a/Release/src/json/json_parsing.cpp b/Release/src/json/json_parsing.cpp index 295bd6e16a..a73a84b3ad 100644 --- a/Release/src/json/json_parsing.cpp +++ b/Release/src/json/json_parsing.cpp @@ -49,10 +49,13 @@ template #endif void CreateException(const Token &tk, const utility::string_t &message) { - utility::ostringstream_t os; - os << _XPLATSTR("* Line ") << tk.start.m_line << _XPLATSTR(", Column ") << tk.start.m_column << _XPLATSTR(" Syntax error: ") << message; - utility::string_t osStr = os.str(); - throw web::json::json_exception(osStr.c_str()); + std::string str("* Line "); + str += std::to_string(tk.start.m_line); + str += ", Column "; + str += std::to_string(tk.start.m_column); + str += " Syntax error: "; + str += utility::conversions::to_utf8string(message); + throw web::json::json_exception(std::move(str)); } template diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index e971c3c544..3903ce9ca7 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -275,11 +275,10 @@ std::string windows_category_impl::message(int errorCode) const CPPREST_NOEXCEPT &buffer[0], buffer_size, NULL); + if (result == 0) { - std::ostringstream os; - os << "Unable to get an error message for error code: " << errorCode << "."; - return os.str(); + return "Unable to get an error message for error code: " + std::to_string(errorCode) + "."; } return utility::conversions::to_utf8string(buffer); @@ -688,80 +687,92 @@ utility::string_t datetime::to_string(date_format format) const throw utility::details::create_system_error(GetLastError()); } - std::wostringstream outStream; - outStream.imbue(std::locale::classic()); - + std::wstring result; if (format == RFC_1123) { + { + wchar_t dateStr[18] = {0}; #if _WIN32_WINNT < _WIN32_WINNT_VISTA - TCHAR dateStr[18] = {0}; - status = GetDateFormat(LOCALE_INVARIANT, 0, &systemTime, __TEXT("ddd',' dd MMM yyyy"), dateStr, sizeof(dateStr) / sizeof(TCHAR)); + status = GetDateFormatW(LOCALE_INVARIANT, 0, &systemTime, L"ddd',' dd MMM yyyy", dateStr, sizeof(dateStr) / sizeof(wchar_t)); #else - wchar_t dateStr[18] = {0}; - status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"ddd',' dd MMM yyyy", dateStr, sizeof(dateStr) / sizeof(wchar_t), NULL); + status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"ddd',' dd MMM yyyy", dateStr, sizeof(dateStr) / sizeof(wchar_t), NULL); #endif // _WIN32_WINNT < _WIN32_WINNT_VISTA - if (status == 0) - { - throw utility::details::create_system_error(GetLastError()); + if (status == 0) + { + throw utility::details::create_system_error(GetLastError()); + } + + result += dateStr; + result += L' '; } + { + wchar_t timeStr[10] = {0}; #if _WIN32_WINNT < _WIN32_WINNT_VISTA - TCHAR timeStr[10] = {0}; - status = GetTimeFormat(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, __TEXT("HH':'mm':'ss"), timeStr, sizeof(timeStr) / sizeof(TCHAR)); + status = GetTimeFormatW(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t)); #else - wchar_t timeStr[10] = {0}; - status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t)); + status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t)); #endif // _WIN32_WINNT < _WIN32_WINNT_VISTA - if (status == 0) - { - throw utility::details::create_system_error(GetLastError()); + if (status == 0) + { + throw utility::details::create_system_error(GetLastError()); + } + + result += timeStr; + result += L" GMT"; } - outStream << dateStr << " " << timeStr << " " << "GMT"; } else if (format == ISO_8601) { const size_t buffSize = 64; + { + wchar_t dateStr[buffSize] = {0}; #if _WIN32_WINNT < _WIN32_WINNT_VISTA - TCHAR dateStr[buffSize] = {0}; - status = GetDateFormat(LOCALE_INVARIANT, 0, &systemTime, __TEXT("yyyy-MM-dd"), dateStr, buffSize); + status = GetDateFormatW(LOCALE_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize); #else - wchar_t dateStr[buffSize] = {0}; - status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize, NULL); + status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize, NULL); #endif // _WIN32_WINNT < _WIN32_WINNT_VISTA - if (status == 0) - { - throw utility::details::create_system_error(GetLastError()); + if (status == 0) + { + throw utility::details::create_system_error(GetLastError()); + } + + result += dateStr; + result += L'T'; } + { + wchar_t timeStr[buffSize] = {0}; #if _WIN32_WINNT < _WIN32_WINNT_VISTA - TCHAR timeStr[buffSize] = {0}; - status = GetTimeFormat(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, __TEXT("HH':'mm':'ss"), timeStr, buffSize); + status = GetTimeFormatW(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, buffSize); #else - wchar_t timeStr[buffSize] = {0}; - status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, buffSize); + status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, buffSize); #endif // _WIN32_WINNT < _WIN32_WINNT_VISTA - if (status == 0) - { - throw utility::details::create_system_error(GetLastError()); + if (status == 0) + { + throw utility::details::create_system_error(GetLastError()); + } + + result += timeStr; } - outStream << dateStr << "T" << timeStr; + uint64_t frac_sec = largeInt.QuadPart % _secondTicks; if (frac_sec > 0) { // Append fractional second, which is a 7-digit value with no trailing zeros // This way, '1200' becomes '00012' - char buf[9] = { 0 }; - sprintf_s(buf, sizeof(buf), ".%07ld", (long int)frac_sec); - // trim trailing zeros - for (int i = 7; buf[i] == '0'; i--) buf[i] = '\0'; - outStream << buf; + wchar_t buf[9] = { 0 }; + size_t appended = swprintf_s(buf, 9, L".%07ld", static_cast(frac_sec)); + while (buf[appended - 1] == L'0') --appended; // trim trailing zeros + result.append(buf, appended); } - outStream << "Z"; + + result += L'Z'; } - return outStream.str(); + return result; #else //LINUX uint64_t input = m_interval; uint64_t frac_sec = input % _secondTicks; @@ -1103,33 +1114,44 @@ utility::string_t __cdecl timespan::seconds_to_xml_duration(utility::seconds dur // The format is: // PdaysDThoursHminutesMsecondsS - utility::ostringstream_t oss; - oss.imbue(std::locale::classic()); - - oss << _XPLATSTR("P"); + utility::string_t result; + // (approximate mins/hours/secs as 2 digits each + 1 prefix character) + 1 for P prefix + 1 for T + size_t baseReserveSize = ((numHours > 0) + (numMins > 0) + (numSecs > 0)) * 3 + 1; if (numDays > 0) { - oss << numDays << _XPLATSTR("D"); + utility::string_t daysStr = utility::conversions::details::to_string_t(numDays); + result.reserve(baseReserveSize + daysStr.size() + 1); + result += _XPLATSTR('P'); + result += daysStr; + result += _XPLATSTR('D'); + } + else + { + result.reserve(baseReserveSize); + result += _XPLATSTR('P'); } - oss << _XPLATSTR("T"); + result += _XPLATSTR('T'); if (numHours > 0) { - oss << numHours << _XPLATSTR("H"); + result += utility::conversions::details::to_string_t(numHours); + result += _XPLATSTR('H'); } if (numMins > 0) { - oss << numMins << _XPLATSTR("M"); + result += utility::conversions::details::to_string_t(numMins); + result += _XPLATSTR('M'); } if (numSecs > 0) { - oss << numSecs << _XPLATSTR("S"); + result += utility::conversions::details::to_string_t(numSecs); + result += _XPLATSTR('S'); } - return oss.str(); + return result; } utility::seconds __cdecl timespan::xml_duration_to_seconds(const utility::string_t ×panString) diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 39b7121d57..c4c46941ba 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -97,12 +97,12 @@ namespace details // Utility function to build up error string based on error code and location. static std::string build_error_msg(const std::error_code &ec, const std::string &location) { - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << location - << ": " << ec.value() - << ": " << ec.message(); - return ss.str(); + std::string result = location; + result += ": "; + result += std::to_string(ec.value()); + result += ": "; + result += ec.message(); + return result; } static utility::string_t g_subProtocolHeader(_XPLATSTR("Sec-WebSocket-Protocol")); diff --git a/Release/src/websockets/client/ws_msg.cpp b/Release/src/websockets/client/ws_msg.cpp index 1d24409c67..ee27cde01f 100644 --- a/Release/src/websockets/client/ws_msg.cpp +++ b/Release/src/websockets/client/ws_msg.cpp @@ -45,7 +45,7 @@ std::vector<::utility::string_t> websocket_client_config::subprotocols() const auto subprotocolHeader = m_headers.find(g_subProtocolHeader); if (subprotocolHeader != m_headers.end()) { - utility::stringstream_t header(subprotocolHeader->second); + utility::istringstream_t header(subprotocolHeader->second); utility::string_t token; while (std::getline(header, token, U(','))) { diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index 10e37186fa..fd9142931a 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -55,17 +55,14 @@ SUITE(compression_tests) size_t output_size, web::http::compression::operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { size_t bytes; if (_done) { input_bytes_processed = 0; - if (done) - { - *done = true; - } + done = true; return 0; } if (_size == static_cast(-1) || input_size > _size - _so_far) @@ -82,10 +79,7 @@ SUITE(compression_tests) } _so_far += bytes; _done = (_so_far == _size); - if (done) - { - *done = _done; - } + done = _done; input_bytes_processed = bytes; return input_bytes_processed; } @@ -102,7 +96,7 @@ SUITE(compression_tests) try { r.output_bytes_produced = - decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { @@ -120,17 +114,14 @@ SUITE(compression_tests) size_t output_size, web::http::compression::operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { size_t bytes; if (_done) { input_bytes_processed = 0; - if (done) - { - *done = true; - } + done = true; return 0; } if (_size == static_cast(-1) || input_size > _size - _so_far) @@ -147,10 +138,7 @@ SUITE(compression_tests) } _so_far += bytes; _done = (hint == web::http::compression::operation_hint::is_last && _so_far == _size); - if (done) - { - *done = _done; - } + done = _done; input_bytes_processed = bytes; return input_bytes_processed; } @@ -167,7 +155,7 @@ SUITE(compression_tests) try { r.output_bytes_produced = - compress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + compress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { @@ -224,14 +212,17 @@ SUITE(compression_tests) input_buffer.reserve(buffer_size); for (size_t i = 0; i < buffer_size; ++i) { + uint8_t element; if (compressible) { - input_buffer.push_back(static_cast('a' + i % 26)); + element = static_cast('a' + i % 26); } else { - input_buffer.push_back(static_cast(std::rand())); + element = static_cast(std::rand()); } + + input_buffer.push_back(element); } // compress in chunks @@ -869,7 +860,7 @@ SUITE(compression_tests) pre.size(), web::http::compression::operation_hint::is_last, used, - &done); + done); VERIFY_IS_TRUE(used == v.size()); VERIFY_IS_TRUE(done); @@ -1019,7 +1010,7 @@ SUITE(compression_tests) pre.size(), web::http::compression::operation_hint::is_last, used, - &done); + done); VERIFY_ARE_EQUAL(used, v.size()); VERIFY_IS_TRUE(done); @@ -1110,7 +1101,7 @@ SUITE(compression_tests) vv.size(), web::http::compression::operation_hint::is_last, used, - &done); + done); VERIFY_ARE_EQUAL(used, p_request->m_body.size()); VERIFY_IS_TRUE(done); } @@ -1219,7 +1210,7 @@ SUITE(compression_tests) cmp.size() - extra, web::http::compression::operation_hint::is_last, used, - &done); + done); VERIFY_ARE_EQUAL(used, v.size()); VERIFY_IS_TRUE(done); }