diff --git a/cef.gyp b/cef.gyp index f79ad89c..0ab7069e 100644 --- a/cef.gyp +++ b/cef.gyp @@ -689,6 +689,7 @@ 'libcef/cef_process_ui_thread.h', 'libcef/cef_string_list.cc', 'libcef/cef_string_map.cc', + 'libcef/cef_string_multimap.cc', 'libcef/cef_string_types.cc', 'libcef/cef_thread.cc', 'libcef/cef_thread.h', diff --git a/cef_paths.gypi b/cef_paths.gypi index a6c4371e..ea23744a 100644 --- a/cef_paths.gypi +++ b/cef_paths.gypi @@ -18,6 +18,7 @@ 'include/internal/cef_string.h', 'include/internal/cef_string_list.h', 'include/internal/cef_string_map.h', + 'include/internal/cef_string_multimap.h', 'include/internal/cef_string_types.h', 'include/internal/cef_string_wrappers.h', 'include/internal/cef_time.h', diff --git a/include/cef.h b/include/cef.h index 49d02773..b722ed3b 100644 --- a/include/cef.h +++ b/include/cef.h @@ -1773,7 +1773,7 @@ public: class CefRequest : public virtual CefBase { public: - typedef std::map HeaderMap; + typedef std::multimap HeaderMap; typedef cef_weburlrequest_flags_t RequestFlags; /// @@ -1984,7 +1984,7 @@ public: class CefResponse : public virtual CefBase { public: - typedef std::map HeaderMap; + typedef std::multimap HeaderMap; /// // Get the response status code. diff --git a/include/cef_capi.h b/include/cef_capi.h index d0116a93..bec1ae13 100644 --- a/include/cef_capi.h +++ b/include/cef_capi.h @@ -45,6 +45,7 @@ extern "C" { #include "internal/cef_string.h" #include "internal/cef_string_list.h" #include "internal/cef_string_map.h" +#include "internal/cef_string_multimap.h" #include "internal/cef_types.h" @@ -1593,20 +1594,20 @@ typedef struct _cef_request_t // Get the header values. /// void (CEF_CALLBACK *get_header_map)(struct _cef_request_t* self, - cef_string_map_t headerMap); + cef_string_multimap_t headerMap); /// // Set the header values. /// void (CEF_CALLBACK *set_header_map)(struct _cef_request_t* self, - cef_string_map_t headerMap); + cef_string_multimap_t headerMap); /// // Set all values at one time. /// void (CEF_CALLBACK *set)(struct _cef_request_t* self, const cef_string_t* url, const cef_string_t* method, struct _cef_post_data_t* postData, - cef_string_map_t headerMap); + cef_string_multimap_t headerMap); /// // Get the flags used in combination with cef_web_urlrequest_t. @@ -1808,13 +1809,13 @@ typedef struct _cef_response_t // Get all response header fields. /// void (CEF_CALLBACK *get_header_map)(struct _cef_response_t* self, - cef_string_map_t headerMap); + cef_string_multimap_t headerMap); /// // Set all response header fields. /// void (CEF_CALLBACK *set_header_map)(struct _cef_response_t* self, - cef_string_map_t headerMap); + cef_string_multimap_t headerMap); } cef_response_t; diff --git a/include/internal/cef_string_multimap.h b/include/internal/cef_string_multimap.h new file mode 100644 index 00000000..e99ae9a4 --- /dev/null +++ b/include/internal/cef_string_multimap.h @@ -0,0 +1,104 @@ +// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef _CEF_STRING_MULTIMAP_H +#define _CEF_STRING_MULTIMAP_H + +#include "cef_export.h" +#include "cef_string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// +// CEF string multimaps are a set of key/value string pairs. +// More than one value can be assigned to a single key. +/// +typedef void* cef_string_multimap_t; + +/// +// Allocate a new string multimap. +/// +CEF_EXPORT cef_string_multimap_t cef_string_multimap_alloc(); + +/// +// Return the number of elements in the string multimap. +/// +CEF_EXPORT int cef_string_multimap_size(cef_string_multimap_t map); + +/// +// Return the number of values with the specified key. +/// +CEF_EXPORT int cef_string_multimap_find_count(cef_string_multimap_t map, + const cef_string_t* key); + +/// +// Return the value_index-th value with the specified key. +/// +CEF_EXPORT int cef_string_multimap_enumerate(cef_string_multimap_t map, + const cef_string_t* key, + int value_index, + cef_string_t* value); + +/// +// Return the key at the specified zero-based string multimap index. +/// +CEF_EXPORT int cef_string_multimap_key(cef_string_multimap_t map, int index, + cef_string_t* key); + +/// +// Return the value at the specified zero-based string multimap index. +/// +CEF_EXPORT int cef_string_multimap_value(cef_string_multimap_t map, int index, + cef_string_t* value); + +/// +// Append a new key/value pair at the end of the string multimap. +/// +CEF_EXPORT int cef_string_multimap_append(cef_string_multimap_t map, + const cef_string_t* key, + const cef_string_t* value); + +/// +// Clear the string multimap. +/// +CEF_EXPORT void cef_string_multimap_clear(cef_string_multimap_t map); + +/// +// Free the string multimap. +/// +CEF_EXPORT void cef_string_multimap_free(cef_string_multimap_t map); + + +#ifdef __cplusplus +} +#endif + +#endif // _CEF_STRING_MULTIMAP_H diff --git a/libcef/browser_resource_loader_bridge.cc b/libcef/browser_resource_loader_bridge.cc index 594f00b2..029ef82a 100644 --- a/libcef/browser_resource_loader_bridge.cc +++ b/libcef/browser_resource_loader_bridge.cc @@ -225,7 +225,7 @@ class RequestProxy : public net::URLRequest::Delegate, while (info.headers->EnumerateHeaderLines(&header_index, &name, &value)) { if (!name.empty() && !value.empty()) - headerMap[name] = value; + headerMap.insert(std::make_pair(name, value)); } response->SetHeaderMap(headerMap); response->SetStatusText(info.headers->GetStatusText()); diff --git a/libcef/cef_string_multimap.cc b/libcef/cef_string_multimap.cc new file mode 100644 index 00000000..b83907e5 --- /dev/null +++ b/libcef/cef_string_multimap.cc @@ -0,0 +1,122 @@ +// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "include/internal/cef_string_multimap.h" +#include "base/logging.h" +#include + + +typedef std::multimap StringMultimap; +typedef StringMultimap::const_iterator StringMultimapIter; + +CEF_EXPORT cef_string_multimap_t cef_string_multimap_alloc() +{ + return new StringMultimap; +} + +CEF_EXPORT int cef_string_multimap_size(cef_string_multimap_t map) +{ + DCHECK(map); + StringMultimap* impl = (StringMultimap*)map; + return impl->size(); +} + +CEF_EXPORT int cef_string_multimap_find_count(cef_string_multimap_t map, + const cef_string_t* key) +{ + DCHECK(map); + DCHECK(key); + StringMultimap* impl = (StringMultimap*)map; + return impl->count(CefString(key)); +} + +CEF_EXPORT int cef_string_multimap_enumerate(cef_string_multimap_t map, + const cef_string_t* key, + int value_index, + cef_string_t* value) +{ + DCHECK(map); + DCHECK(key); + DCHECK(value); + + StringMultimap* impl = (StringMultimap*)map; + CefString key_str(key); + + DCHECK(value_index >= 0 && value_index < (int)impl->count(key_str)); + + if(value_index < 0 || value_index >= (int)impl->count(key_str)) + return NULL; + + std::pair range_it = + impl->equal_range(key_str); + + int count = value_index; + while (count-- && range_it.first != range_it.second) + range_it.first++; + + if (range_it.first == range_it.second) + return NULL; + + const CefString& val = range_it.first->second; + return cef_string_set(val.c_str(), val.length(), value, true); +} + +CEF_EXPORT int cef_string_multimap_key(cef_string_multimap_t map, int index, + cef_string_t* key) +{ + DCHECK(map); + DCHECK(key); + StringMultimap* impl = (StringMultimap*)map; + DCHECK(index >= 0 && index < (int)impl->size()); + if(index < 0 || index >= (int)impl->size()) + return NULL; + StringMultimap::const_iterator it = impl->begin(); + for(int ct = 0; it != impl->end(); ++it, ct++) { + if(ct == index) + return cef_string_set(it->first.c_str(), it->first.length(), key, true); + } + return 0; +} + +CEF_EXPORT int cef_string_multimap_value(cef_string_multimap_t map, int index, + cef_string_t* value) +{ + DCHECK(map); + DCHECK(value); + StringMultimap* impl = (StringMultimap*)map; + DCHECK(index >= 0 && index < (int)impl->size()); + if(index < 0 || index >= (int)impl->size()) + return NULL; + StringMultimap::const_iterator it = impl->begin(); + for(int ct = 0; it != impl->end(); ++it, ct++) { + if(ct == index) { + return cef_string_set(it->second.c_str(), it->second.length(), value, + true); + } + } + return 0; +} + +CEF_EXPORT int cef_string_multimap_append(cef_string_multimap_t map, + const cef_string_t* key, + const cef_string_t* value) +{ + DCHECK(map); + StringMultimap* impl = (StringMultimap*)map; + impl->insert(std::make_pair(CefString(key), CefString(value))); + return 1; +} + +CEF_EXPORT void cef_string_multimap_clear(cef_string_multimap_t map) +{ + DCHECK(map); + StringMultimap* impl = (StringMultimap*)map; + impl->clear(); +} + +CEF_EXPORT void cef_string_multimap_free(cef_string_multimap_t map) +{ + DCHECK(map); + delete (StringMultimap*)map; +} diff --git a/libcef/request_impl.cc b/libcef/request_impl.cc index 8f9d9503..0f7b9fb0 100644 --- a/libcef/request_impl.cc +++ b/libcef/request_impl.cc @@ -216,7 +216,7 @@ void CefRequestImpl::GetHeaderMap(const net::HttpRequestHeaders& headers, { net::HttpRequestHeaders::Iterator it(headers); do { - map[it.name()] = it.value(); + map.insert(std::make_pair(it.name(), it.value())); } while (it.GetNext()); } diff --git a/libcef_dll/cpptoc/request_cpptoc.cc b/libcef_dll/cpptoc/request_cpptoc.cc index 4011518c..b9922cbd 100644 --- a/libcef_dll/cpptoc/request_cpptoc.cc +++ b/libcef_dll/cpptoc/request_cpptoc.cc @@ -99,7 +99,7 @@ void CEF_CALLBACK request_set_post_data(struct _cef_request_t* self, } void CEF_CALLBACK request_get_header_map(struct _cef_request_t* self, - cef_string_map_t headerMap) + cef_string_multimap_t headerMap) { DCHECK(self); if(!self) @@ -107,11 +107,11 @@ void CEF_CALLBACK request_get_header_map(struct _cef_request_t* self, CefRequest::HeaderMap map; CefRequestCppToC::Get(self)->GetHeaderMap(map); - transfer_string_map_contents(map, headerMap); + transfer_string_multimap_contents(map, headerMap); } void CEF_CALLBACK request_set_header_map(struct _cef_request_t* self, - cef_string_map_t headerMap) + cef_string_multimap_t headerMap) { DCHECK(self); if(!self) @@ -119,14 +119,14 @@ void CEF_CALLBACK request_set_header_map(struct _cef_request_t* self, CefRequest::HeaderMap map; if(headerMap) - transfer_string_map_contents(headerMap, map); + transfer_string_multimap_contents(headerMap, map); CefRequestCppToC::Get(self)->SetHeaderMap(map); } void CEF_CALLBACK request_set(struct _cef_request_t* self, const cef_string_t* url, const cef_string_t* method, - struct _cef_post_data_t* postData, cef_string_map_t headerMap) + struct _cef_post_data_t* postData, cef_string_multimap_t headerMap) { DCHECK(self); if(!self) @@ -138,7 +138,7 @@ void CEF_CALLBACK request_set(struct _cef_request_t* self, if(postData) postDataPtr = CefPostDataCppToC::Unwrap(postData); if(headerMap) - transfer_string_map_contents(headerMap, map); + transfer_string_multimap_contents(headerMap, map); CefRequestCppToC::Get(self)->Set(CefString(url), CefString(method), postDataPtr, map); diff --git a/libcef_dll/cpptoc/response_cpptoc.cc b/libcef_dll/cpptoc/response_cpptoc.cc index 92ebec25..d723ddc1 100644 --- a/libcef_dll/cpptoc/response_cpptoc.cc +++ b/libcef_dll/cpptoc/response_cpptoc.cc @@ -88,7 +88,7 @@ cef_string_userfree_t CEF_CALLBACK response_get_header( } void CEF_CALLBACK response_get_header_map(struct _cef_response_t* self, - cef_string_map_t headerMap) + cef_string_multimap_t headerMap) { DCHECK(self); if(!self) @@ -96,11 +96,11 @@ void CEF_CALLBACK response_get_header_map(struct _cef_response_t* self, CefResponse::HeaderMap map; CefResponseCppToC::Get(self)->GetHeaderMap(map); - transfer_string_map_contents(map, headerMap); + transfer_string_multimap_contents(map, headerMap); } void CEF_CALLBACK response_set_header_map(struct _cef_response_t* self, - cef_string_map_t headerMap) + cef_string_multimap_t headerMap) { DCHECK(self); if(!self) @@ -108,7 +108,7 @@ void CEF_CALLBACK response_set_header_map(struct _cef_response_t* self, CefResponse::HeaderMap map; if(headerMap) - transfer_string_map_contents(headerMap, map); + transfer_string_multimap_contents(headerMap, map); CefResponseCppToC::Get(self)->SetHeaderMap(map); } diff --git a/libcef_dll/ctocpp/request_ctocpp.cc b/libcef_dll/ctocpp/request_ctocpp.cc index ca088677..c6a7317c 100644 --- a/libcef_dll/ctocpp/request_ctocpp.cc +++ b/libcef_dll/ctocpp/request_ctocpp.cc @@ -94,13 +94,13 @@ void CefRequestCToCpp::GetHeaderMap(HeaderMap& headerMap) if(CEF_MEMBER_MISSING(struct_, get_header_map)) return; - cef_string_map_t map = cef_string_map_alloc(); + cef_string_multimap_t map = cef_string_multimap_alloc(); if(!map) return; struct_->get_header_map(struct_, map); - transfer_string_map_contents(map, headerMap); - cef_string_map_free(map); + transfer_string_multimap_contents(map, headerMap); + cef_string_multimap_free(map); } void CefRequestCToCpp::SetHeaderMap(const HeaderMap& headerMap) @@ -108,18 +108,18 @@ void CefRequestCToCpp::SetHeaderMap(const HeaderMap& headerMap) if(CEF_MEMBER_MISSING(struct_, set_header_map)) return; - cef_string_map_t map = NULL; + cef_string_multimap_t map = NULL; if(!headerMap.empty()) { - map = cef_string_map_alloc(); + map = cef_string_multimap_alloc(); if(!map) return; - transfer_string_map_contents(headerMap, map); + transfer_string_multimap_contents(headerMap, map); } struct_->set_header_map(struct_, map); if(map) - cef_string_map_free(map); + cef_string_multimap_free(map); } void CefRequestCToCpp::Set(const CefString& url, const CefString& method, @@ -132,19 +132,19 @@ void CefRequestCToCpp::Set(const CefString& url, const CefString& method, if(postData.get()) postDataStruct = CefPostDataCToCpp::Unwrap(postData); - cef_string_map_t map = NULL; + cef_string_multimap_t map = NULL; if(!headerMap.empty()) { - map = cef_string_map_alloc(); + map = cef_string_multimap_alloc(); if(!map) return; - transfer_string_map_contents(headerMap, map); + transfer_string_multimap_contents(headerMap, map); } struct_->set(struct_, url.GetStruct(), method.GetStruct(), postDataStruct, map); if(map) - cef_string_map_free(map); + cef_string_multimap_free(map); } CefRequest::RequestFlags CefRequestCToCpp::GetFlags() diff --git a/libcef_dll/ctocpp/response_ctocpp.cc b/libcef_dll/ctocpp/response_ctocpp.cc index e59eb3a2..7ad6d194 100644 --- a/libcef_dll/ctocpp/response_ctocpp.cc +++ b/libcef_dll/ctocpp/response_ctocpp.cc @@ -86,13 +86,13 @@ void CefResponseCToCpp::GetHeaderMap(HeaderMap& headerMap) if(CEF_MEMBER_MISSING(struct_, get_header_map)) return; - cef_string_map_t map = cef_string_map_alloc(); + cef_string_multimap_t map = cef_string_multimap_alloc(); if(!map) return; struct_->get_header_map(struct_, map); - transfer_string_map_contents(map, headerMap); - cef_string_map_free(map); + transfer_string_multimap_contents(map, headerMap); + cef_string_multimap_free(map); } void CefResponseCToCpp::SetHeaderMap(const HeaderMap& headerMap) @@ -100,18 +100,18 @@ void CefResponseCToCpp::SetHeaderMap(const HeaderMap& headerMap) if(CEF_MEMBER_MISSING(struct_, set_header_map)) return; - cef_string_map_t map = NULL; + cef_string_multimap_t map = NULL; if(!headerMap.empty()) { - map = cef_string_map_alloc(); + map = cef_string_multimap_alloc(); if(!map) return; - transfer_string_map_contents(headerMap, map); + transfer_string_multimap_contents(headerMap, map); } struct_->set_header_map(struct_, map); if(map) - cef_string_map_free(map); + cef_string_multimap_free(map); } diff --git a/libcef_dll/transfer_util.cpp b/libcef_dll/transfer_util.cpp index e75ed9ee..e9d8d4e2 100644 --- a/libcef_dll/transfer_util.cpp +++ b/libcef_dll/transfer_util.cpp @@ -34,7 +34,7 @@ void transfer_string_map_contents(cef_string_map_t fromMap, cef_string_map_key(fromMap, i, key.GetWritableStruct()); cef_string_map_value(fromMap, i, value.GetWritableStruct()); - toMap.insert(std::pair(key, value)); + toMap.insert(std::make_pair(key, value)); } } @@ -45,3 +45,28 @@ void transfer_string_map_contents(const StringMap& fromMap, for(; it != fromMap.end(); ++it) cef_string_map_append(toMap, it->first.GetStruct(), it->second.GetStruct()); } + +void transfer_string_multimap_contents(cef_string_multimap_t fromMap, + StringMultimap& toMap) +{ + int size = cef_string_multimap_size(fromMap); + CefString key, value; + + for(int i = 0; i < size; ++i) { + cef_string_multimap_key(fromMap, i, key.GetWritableStruct()); + cef_string_multimap_value(fromMap, i, value.GetWritableStruct()); + + toMap.insert(std::make_pair(key, value)); + } +} + +void transfer_string_multimap_contents(const StringMultimap& fromMap, + cef_string_multimap_t toMap) +{ + StringMultimap::const_iterator it = fromMap.begin(); + for(; it != fromMap.end(); ++it) { + cef_string_multimap_append(toMap, + it->first.GetStruct(), + it->second.GetStruct()); + } +} diff --git a/libcef_dll/transfer_util.h b/libcef_dll/transfer_util.h index 577bdd53..7992dd39 100644 --- a/libcef_dll/transfer_util.h +++ b/libcef_dll/transfer_util.h @@ -7,6 +7,7 @@ #include "include/internal/cef_string_list.h" #include "include/internal/cef_string_map.h" +#include "include/internal/cef_string_multimap.h" #include #include @@ -24,4 +25,11 @@ void transfer_string_map_contents(cef_string_map_t fromMap, void transfer_string_map_contents(const StringMap& fromMap, cef_string_map_t toMap); +// Copy contents from one map type to another. +typedef std::multimap StringMultimap; +void transfer_string_multimap_contents(cef_string_multimap_t fromMap, + StringMultimap& toMap); +void transfer_string_multimap_contents(const StringMultimap& fromMap, + cef_string_multimap_t toMap); + #endif // _TRANSFER_UTIL_H diff --git a/tests/unittests/string_unittest.cc b/tests/unittests/string_unittest.cc index cd0d0ac1..1726dc89 100644 --- a/tests/unittests/string_unittest.cc +++ b/tests/unittests/string_unittest.cc @@ -5,6 +5,7 @@ #include "include/internal/cef_string.h" #include "include/internal/cef_string_list.h" #include "include/internal/cef_string_map.h" +#include "include/internal/cef_string_multimap.h" #include "testing/gtest/include/gtest/gtest.h" #include #include @@ -250,3 +251,96 @@ TEST(StringTest, Map) cef_string_map_free(mapPtr); } + +// Test string maps. +TEST(StringTest, Multimap) +{ + typedef std::multimap MapType; + MapType map; + map.insert(std::make_pair("Key 1", "String 1")); + map.insert(std::make_pair("Key 2", "String 2")); + map.insert(std::make_pair("Key 2", "String 2.1")); + map.insert(std::make_pair("Key 3", "String 3")); + + MapType::const_iterator it; + + it = map.find("Key 2"); + ASSERT_TRUE(it != map.end()); + ASSERT_EQ(it->first, "Key 2"); + ASSERT_EQ(it->second, "String 2"); + + std::pair + range_it = map.equal_range("Key 2"); + ASSERT_TRUE(range_it.first != range_it.second); + MapType::const_iterator same_key_it = range_it.first; + // Either of "String 2" or "String 2.1" is fine since + // std::multimap provides no guarantee wrt the order of + // values with the same key. + ASSERT_EQ(same_key_it->second.ToString().find("String 2"), (size_t)0); + ASSERT_EQ((++same_key_it)->second.ToString().find("String 2"), (size_t)0); + ASSERT_EQ(map.count("Key 2"), (size_t)2); + + ASSERT_EQ(map.find("Key 1")->second, "String 1"); + ASSERT_EQ(map.find("Key 3")->second, "String 3"); + + cef_string_multimap_t mapPtr = cef_string_multimap_alloc(); + + it = map.begin(); + for(; it != map.end(); ++it) { + cef_string_multimap_append(mapPtr, it->first.GetStruct(), + it->second.GetStruct()); + } + + CefString str; + int ret; + + ASSERT_EQ(cef_string_multimap_size(mapPtr), 4); + + ret = cef_string_multimap_key(mapPtr, 0, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str, "Key 1"); + ret = cef_string_multimap_value(mapPtr, 0, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str, "String 1"); + + ret = cef_string_multimap_key(mapPtr, 1, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str, "Key 2"); + ret = cef_string_multimap_value(mapPtr, 1, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str.ToString().find("String 2"), (size_t)0); + + ret = cef_string_multimap_key(mapPtr, 2, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str, "Key 2"); + ret = cef_string_multimap_value(mapPtr, 2, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str.ToString().find("String 2"), (size_t)0); + + ret = cef_string_multimap_key(mapPtr, 3, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str, "Key 3"); + ret = cef_string_multimap_value(mapPtr, 3, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str, "String 3"); + + CefString key; + key.FromASCII("Key 2"); + ret = cef_string_multimap_find_count(mapPtr, key.GetStruct()); + ASSERT_EQ(ret, 2); + + ret = cef_string_multimap_enumerate(mapPtr, + key.GetStruct(), 0, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str.ToString().find("String 2"), (size_t)0); + + ret = cef_string_multimap_enumerate(mapPtr, + key.GetStruct(), 1, str.GetWritableStruct()); + ASSERT_TRUE(ret); + ASSERT_EQ(str.ToString().find("String 2"), (size_t)0); + + cef_string_multimap_clear(mapPtr); + ASSERT_EQ(cef_string_multimap_size(mapPtr), 0); + + cef_string_multimap_free(mapPtr); +} diff --git a/tools/cef_parser.py b/tools/cef_parser.py index 78ec998b..78255cf2 100644 --- a/tools/cef_parser.py +++ b/tools/cef_parser.py @@ -1009,6 +1009,17 @@ class obj_analysis: self._get_basic(string.strip(vals[1])) ] return True + + # check for multimaps + if value.find('std::multimap') == 0: + self.result_type = 'multimap' + vals = string.split(value[14:-1], ',') + if len(vals) == 2: + self.result_value = [ + self._get_basic(string.strip(vals[0])), + self._get_basic(string.strip(vals[1])) + ] + return True # check for basic types basic = self._get_basic(value) @@ -1216,7 +1227,7 @@ class obj_analysis: def is_result_map(self): """ Returns true if this is a map type. """ - return (self.result_type == 'map') + return (self.result_type == 'map' or self.result_type == 'multimap') def get_result_map_type(self, defined_structs = []): """ Return the map type. """ @@ -1224,10 +1235,16 @@ class obj_analysis: raise Exception('Cannot use map as a return type') if self.result_value[0]['result_type'] == 'string' \ and self.result_value[1]['result_type'] == 'string': - return { - 'value' : 'cef_string_map_t', - 'format' : 'single' - } + if self.result_type == 'map': + return { + 'value' : 'cef_string_map_t', + 'format' : 'single' + } + elif self.result_type == 'multimap': + return { + 'value' : 'cef_string_multimap_t', + 'format' : 'multi' + } raise Exception('Only mappings of strings to strings are supported') def get_capi(self, defined_structs = []): @@ -1244,10 +1261,10 @@ class obj_analysis: result += self.get_result_string_type() elif self.is_result_map(): resdict = self.get_result_map_type(defined_structs) - if resdict['format'] == 'single': + if resdict['format'] == 'single' or resdict['format'] == 'multi': result += resdict['value'] else: - raise Exception('Only single-value map types are supported') + raise Exception('Unsupported map type') elif self.is_result_vector(): resdict = self.get_result_vector_type(defined_structs) if resdict['format'] != 'single': diff --git a/tools/make_capi_header.py b/tools/make_capi_header.py index 4bd645ca..6be8ce1f 100644 --- a/tools/make_capi_header.py +++ b/tools/make_capi_header.py @@ -92,6 +92,7 @@ extern "C" { #include "internal/cef_string.h" #include "internal/cef_string_list.h" #include "internal/cef_string_map.h" +#include "internal/cef_string_multimap.h" #include "internal/cef_types.h" """