#ifndef CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_
#define CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_
#pragma once
#include <map>
#include "include/base/cef_logging.h"
template <typename ObjectType>
struct DefaultCefBrowserInfoMapTraits {
static void Destruct(ObjectType info) { delete info; }
};
template <typename IdType,
typename ObjectType,
typename Traits = DefaultCefBrowserInfoMapTraits<ObjectType>>
class CefBrowserInfoMap {
public:
class Visitor {
public:
using InfoIdType = IdType;
using InfoObjectType = ObjectType;
virtual bool OnNextInfo(int browser_id,
InfoIdType info_id,
InfoObjectType info,
bool* remove) = 0;
protected:
virtual ~Visitor() {}
};
CefBrowserInfoMap() = default;
CefBrowserInfoMap(const CefBrowserInfoMap&) = delete;
CefBrowserInfoMap& operator=(const CefBrowserInfoMap&) = delete;
~CefBrowserInfoMap() { clear(); }
void Add(int browser_id, IdType info_id, ObjectType info) {
InfoMap* info_map = nullptr;
typename BrowserInfoMap::const_iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser == browser_info_map_.end()) {
info_map = new InfoMap;
browser_info_map_.insert(std::make_pair(browser_id, info_map));
} else {
info_map = it_browser->second;
DCHECK(info_map->find(info_id) == info_map->end());
}
info_map->insert(std::make_pair(info_id, info));
}
ObjectType Find(int browser_id, IdType info_id, Visitor* vistor) {
if (browser_info_map_.empty())
return ObjectType();
typename BrowserInfoMap::iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser == browser_info_map_.end())
return ObjectType();
InfoMap* info_map = it_browser->second;
typename InfoMap::iterator it_info = info_map->find(info_id);
if (it_info == info_map->end())
return ObjectType();
ObjectType info = it_info->second;
bool remove = false;
if (vistor)
vistor->OnNextInfo(browser_id, it_info->first, info, &remove);
if (remove) {
info_map->erase(it_info);
if (info_map->empty()) {
browser_info_map_.erase(it_browser);
delete info_map;
}
}
return info;
}
void FindAll(Visitor* visitor) {
DCHECK(visitor);
if (browser_info_map_.empty())
return;
bool remove, keepgoing = true;
typename BrowserInfoMap::iterator it_browser = browser_info_map_.begin();
while (it_browser != browser_info_map_.end()) {
InfoMap* info_map = it_browser->second;
typename InfoMap::iterator it_info = info_map->begin();
while (it_info != info_map->end()) {
remove = false;
keepgoing = visitor->OnNextInfo(it_browser->first, it_info->first,
it_info->second, &remove);
if (remove)
info_map->erase(it_info++);
else
++it_info;
if (!keepgoing)
break;
}
if (info_map->empty()) {
browser_info_map_.erase(it_browser++);
delete info_map;
} else {
++it_browser;
}
if (!keepgoing)
break;
}
}
void FindAll(int browser_id, Visitor* visitor) {
DCHECK(visitor);
if (browser_info_map_.empty())
return;
typename BrowserInfoMap::iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser == browser_info_map_.end())
return;
InfoMap* info_map = it_browser->second;
bool remove, keepgoing;
typename InfoMap::iterator it_info = info_map->begin();
while (it_info != info_map->end()) {
remove = false;
keepgoing = visitor->OnNextInfo(browser_id, it_info->first,
it_info->second, &remove);
if (remove)
info_map->erase(it_info++);
else
++it_info;
if (!keepgoing)
break;
}
if (info_map->empty()) {
browser_info_map_.erase(it_browser);
delete info_map;
}
}
bool empty() const { return browser_info_map_.empty(); }
size_t size() const {
if (browser_info_map_.empty())
return 0;
size_t size = 0;
typename BrowserInfoMap::const_iterator it_browser =
browser_info_map_.begin();
for (; it_browser != browser_info_map_.end(); ++it_browser)
size += it_browser->second->size();
return size;
}
size_t size(int browser_id) const {
if (browser_info_map_.empty())
return 0;
typename BrowserInfoMap::const_iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser != browser_info_map_.end())
return it_browser->second->size();
return 0;
}
void clear() {
if (browser_info_map_.empty())
return;
typename BrowserInfoMap::const_iterator it_browser =
browser_info_map_.begin();
for (; it_browser != browser_info_map_.end(); ++it_browser) {
InfoMap* info_map = it_browser->second;
typename InfoMap::const_iterator it_info = info_map->begin();
for (; it_info != info_map->end(); ++it_info)
Traits::Destruct(it_info->second);
delete info_map;
}
browser_info_map_.clear();
}
void clear(int browser_id) {
if (browser_info_map_.empty())
return;
typename BrowserInfoMap::iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser == browser_info_map_.end())
return;
InfoMap* info_map = it_browser->second;
typename InfoMap::const_iterator it_info = info_map->begin();
for (; it_info != info_map->end(); ++it_info)
Traits::Destruct(it_info->second);
browser_info_map_.erase(it_browser);
delete info_map;
}
private:
using InfoMap = std::map<IdType, ObjectType>;
using BrowserInfoMap = std::map<int, InfoMap*>;
BrowserInfoMap browser_info_map_;
};
#endif