bool is_matching_content_type(const utility::string_t& actual, const utility::string_t& expected) { // Check if the response's actual content type matches the expected content type. // It is OK if the actual content type has additional parameters (e.g. application/json;odata=minimalmetadata;streaming=true;charset=utf-8). return (actual.size() == expected.size() || (actual.size() > expected.size() && actual.at(expected.size()) == U(';'))) && std::equal(expected.cbegin(), expected.cend(), actual.cbegin()); }
void split_string(::utility::string_t& source, const ::utility::string_t& delim, std::list<::utility::string_t>& ret) { ret.clear(); if (delim.empty() || source.empty()) { ret.push_back(source); return ; } size_t last = 0; size_t index = source.find(delim, last); while (index!=std::string::npos) { ret.push_back(source.substr(last, index - last)); last = index + delim.size(); index = source.find(delim, last); } if(index - last > 0) { ret.push_back(source.substr(last, index - last)); } }
utility::string_t get_object_name(const utility::string_t& object_type_name) { utility::string_t object_name; object_name.reserve(37U + object_type_name.size()); object_name.append(object_name_prefix); object_name.append(object_type_name); object_name.append(get_random_string()); return object_name; }
void extract_fractional_second(const utility::string_t& dateString, utility::string_t& resultString, uint64_t& ufrac_second) { resultString = dateString; // First, the string must be strictly longer than 2 characters, and the trailing character must be 'Z' if (resultString.size() > 2 && resultString[resultString.size() - 1] == U('Z')) { // Second, find the last non-digit by scanning the string backwards auto last_non_digit = std::find_if_not(resultString.rbegin() + 1, resultString.rend(), is_digit); if (last_non_digit < resultString.rend() - 1) { // Finally, make sure the last non-digit is a dot: auto last_dot = last_non_digit.base() - 1; if (*last_dot == U('.')) { // Got it! Now extract the fractional second auto last_before_Z = std::end(resultString) - 1; ufrac_second = timeticks_from_second(last_dot, last_before_Z); // And erase it from the string resultString.erase(last_dot, last_before_Z); } } } }
/// <summary> /// Parses the given Content-Type header value to get out actual content type and charset. /// If the charset isn't specified the default charset for the content type will be set. /// </summary> static void parse_content_type_and_charset(const utility::string_t& content_type, utility::string_t& content, utility::string_t& charset) { const size_t semi_colon_index = content_type.find_first_of(_XPLATSTR(";")); // No charset specified. if (semi_colon_index == utility::string_t::npos) { content = content_type; trim_whitespace(content); charset = get_default_charset(content); return; } // Split into content type and second part which could be charset. content = content_type.substr(0, semi_colon_index); trim_whitespace(content); utility::string_t possible_charset = content_type.substr(semi_colon_index + 1); trim_whitespace(possible_charset); const size_t equals_index = possible_charset.find_first_of(_XPLATSTR("=")); // No charset specified. if (equals_index == utility::string_t::npos) { charset = get_default_charset(content); return; } // Split and make sure 'charset' utility::string_t charset_key = possible_charset.substr(0, equals_index); trim_whitespace(charset_key); if (!utility::details::str_iequal(charset_key, _XPLATSTR("charset"))) { charset = get_default_charset(content); return; } charset = possible_charset.substr(equals_index + 1); // Remove the redundant ';' at the end of charset. while (charset.back() == ';') { charset.pop_back(); } trim_whitespace(charset); if (charset.front() == _XPLATSTR('"') && charset.back() == _XPLATSTR('"')) { charset = charset.substr(1, charset.size() - 2); trim_whitespace(charset); } }
/// <summary> /// Determines whether or not the given content type is 'textual' according the feature specifications. /// </summary> static bool is_content_type_textual(const utility::string_t& content_type) { #if !defined(_WIN32) || _MSC_VER >= 1900 static const utility::string_t textual_types[] = {mime_types::message_http, mime_types::application_json, mime_types::application_xml, mime_types::application_atom_xml, mime_types::application_http, mime_types::application_x_www_form_urlencoded}; #endif if (content_type.size() >= 4 && utility::details::str_iequal(content_type.substr(0, 4), _XPLATSTR("text"))) { return true; } return (is_content_type_one_of(std::begin(textual_types), std::end(textual_types), content_type)); }
::utility::string_t strip_string(const ::utility::string_t& escaped) { ::utility::string_t::size_type first = 0; ::utility::string_t::size_type size = escaped.size(); if (escaped.empty()) { return escaped; } if (escaped[0] == U('"')) { first += 1; } if (escaped[size - 1] == U('"')) { size -= 1; } return escaped.substr(first, size - first); }
std::map<utility::string_t, utility::string_t> uri::split_query(const utility::string_t &query) { std::map<utility::string_t, utility::string_t> results; // Split into key value pairs separated by '&'. size_t prev_amp_index = 0; while(prev_amp_index != utility::string_t::npos) { size_t amp_index = query.find_first_of(_XPLATSTR('&'), prev_amp_index); if (amp_index == utility::string_t::npos) amp_index = query.find_first_of(_XPLATSTR(';'), prev_amp_index); utility::string_t key_value_pair = query.substr( prev_amp_index, amp_index == utility::string_t::npos ? query.size() - prev_amp_index : amp_index - prev_amp_index); prev_amp_index = amp_index == utility::string_t::npos ? utility::string_t::npos : amp_index + 1; size_t equals_index = key_value_pair.find_first_of(_XPLATSTR('=')); if(equals_index == utility::string_t::npos) { continue; } else if (equals_index == 0) { utility::string_t value(key_value_pair.begin() + equals_index + 1, key_value_pair.end()); results[_XPLATSTR("")] = value; } else { utility::string_t key(key_value_pair.begin(), key_value_pair.begin() + equals_index); utility::string_t value(key_value_pair.begin() + equals_index + 1, key_value_pair.end()); results[key] = value; } } return results; }
std::vector<unsigned char> _from_base64(const utility::string_t& input) { std::vector<unsigned char> result; if ( input.empty() ) return result; size_t padding = 0; // Validation { auto size = input.size(); if ( (size % 4) != 0 ) { throw std::runtime_error("length of base64 string is not an even multiple of 4"); } for (auto iter = input.begin(); iter != input.end(); ++iter,--size) { auto ch = *iter; if ( ch < 0 || _base64_dectbl[ch] == 255 ) { throw std::runtime_error("invalid character found in base64 string"); } if ( _base64_dectbl[ch] == 254 ) { padding++; // padding only at the end if ( size > 2 || (size == 2 && _base64_dectbl[*(iter+1)] != 254) ) { throw std::runtime_error("invalid padding character found in base64 string"); } } } } auto size = input.size(); const char_t* ptr = &input[0]; auto outsz = (size / 4)*3; outsz -= padding; result.resize(outsz); size_t idx = 0; for (; size > 4; ++idx ) { unsigned char target[3]; memset(target, 0, sizeof(target)); _triple_byte* record = reinterpret_cast<_triple_byte*>(target); unsigned char val0 = _base64_dectbl[ptr[0]]; unsigned char val1 = _base64_dectbl[ptr[1]]; unsigned char val2 = _base64_dectbl[ptr[2]]; unsigned char val3 = _base64_dectbl[ptr[3]]; record->_0 = val0; record->_1_1 = val1 >> 4; result[idx] = target[0]; record->_1_2 = val1 & 0xF; record->_2_1 = val2 >> 2; result[++idx] = target[1]; record->_2_2 = val2 & 0x3; record->_3 = val3 & 0x3F; result[++idx] = target[2]; ptr += 4; size -= 4; } // Handle the last four bytes separately, to avoid having the conditional statements // in all the iterations (a performance issue). { unsigned char target[3]; memset(target, 0, sizeof(target)); _triple_byte* record = reinterpret_cast<_triple_byte*>(target); unsigned char val0 = _base64_dectbl[ptr[0]]; unsigned char val1 = _base64_dectbl[ptr[1]]; unsigned char val2 = _base64_dectbl[ptr[2]]; unsigned char val3 = _base64_dectbl[ptr[3]]; record->_0 = val0; record->_1_1 = val1 >> 4; result[idx] = target[0]; record->_1_2 = val1 & 0xF; if ( val2 != 254 ) { record->_2_1 = val2 >> 2; result[++idx] = target[1]; } else { // There shouldn't be any information (ones) in the unused bits, if ( record->_1_2 != 0 )