1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) Electronic Arts Inc. All rights reserved.
3 ///////////////////////////////////////////////////////////////////////////////
4 
5 #ifndef EASTL_STRING_MAP_H
6 #define EASTL_STRING_MAP_H
7 
8 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
9 	#pragma once
10 #endif
11 
12 #include <EASTL/map.h>
13 #include <EASTL/string.h>
14 
15 namespace eastl
16 {
17 
18 
19 template<typename T, typename Predicate = str_less<const char*>, typename Allocator = EASTLAllocatorType>
20 class string_map : public eastl::map<const char*, T, Predicate, Allocator>
21 {
22 public:
23 	typedef eastl::map<const char*, T, Predicate, Allocator> base;
24 	typedef string_map<T, Predicate, Allocator>              this_type;
25 	typedef typename base::base_type::allocator_type         allocator_type;
26 	typedef typename base::base_type::insert_return_type     insert_return_type;
27 	typedef typename base::base_type::iterator               iterator;
28 	typedef typename base::base_type::reverse_iterator       reverse_iterator;
29 	typedef typename base::base_type::const_iterator         const_iterator;
30 	typedef typename base::base_type::size_type              size_type;
31 	typedef typename base::base_type::key_type               key_type;
32 	typedef typename base::base_type::value_type             value_type;
33 	typedef typename base::mapped_type                       mapped_type;
34 
base(allocator)35 		                string_map(const allocator_type& allocator = allocator_type()) : base(allocator) {}
36 						string_map(const string_map& src, const allocator_type& allocator = allocator_type());
37 						~string_map();
38 	void				clear();
39 
40 	this_type&			operator=(const this_type& x);
41 
42 	insert_return_type	insert(const char* key, const T& value);
43 	insert_return_type	insert(const char* key);
44 	iterator			erase(iterator position);
45 	size_type			erase(const char* key);
46 	mapped_type&		operator[](const char* key);
47 
48 private:
49 	char*				strduplicate(const char* str);
50 
51 	// Not implemented right now
52 	// insert_return_type	insert(const value_type& value);
53 	// iterator			    insert(iterator position, const value_type& value);
54     // reverse_iterator	    erase(reverse_iterator position);
55     // reverse_iterator	    erase(reverse_iterator first, reverse_iterator last);
56     // void				    erase(const key_type* first, const key_type* last);
57 };
58 
59 
60 
61 template<typename T, typename Predicate, typename Allocator>
string_map(const string_map & src,const allocator_type & allocator)62 string_map<T, Predicate, Allocator>::string_map(const string_map& src, const allocator_type& allocator) : base(allocator)
63 {
64 	for (const_iterator i=src.begin(), e=src.end(); i!=e; ++i)
65 		base::base_type::insert(eastl::make_pair(strduplicate(i->first), i->second));
66 }
67 
68 template<typename T, typename Predicate, typename Allocator>
~string_map()69 string_map<T, Predicate, Allocator>::~string_map()
70 {
71 	clear();
72 }
73 
74 template<typename T, typename Predicate, typename Allocator>
75 void
clear()76 string_map<T, Predicate, Allocator>::clear()
77 {
78 	allocator_type& allocator = base::base_type::get_allocator();
79 	for (const_iterator i=base::base_type::begin(), e=base::base_type::end(); i!=e; ++i)
80 		allocator.deallocate((void*)i->first, 0);
81 	base::base_type::clear();
82 }
83 
84 template<typename T, typename Predicate, typename Allocator>
85 typename string_map<T, Predicate, Allocator>::this_type&
86 string_map<T, Predicate, Allocator>::operator=(const this_type& x)
87 {
88 	allocator_type allocator = base::base_type::get_allocator();
89 	this->~this_type();
90 	new (this) this_type(x, allocator);
91 	return *this;
92 }
93 
94 template<typename T, typename Predicate, typename Allocator>
95 typename string_map<T, Predicate, Allocator>::insert_return_type
insert(const char * key)96 string_map<T, Predicate, Allocator>::insert(const char* key)
97 {
98 	return insert(key, mapped_type());
99 }
100 
101 template<typename T, typename Predicate, typename Allocator>
102 typename string_map<T, Predicate, Allocator>::insert_return_type
insert(const char * key,const T & value)103 string_map<T, Predicate, Allocator>::insert(const char* key, const T& value)
104 {
105 	EASTL_ASSERT(key);
106 	iterator i = base::base_type::find(key);
107 	if (i != base::base_type::end())
108 	{
109 		insert_return_type ret;
110 		ret.first = i;
111 		ret.second = false;
112 		return ret;
113 	}
114 	return base::base_type::insert(eastl::make_pair(strduplicate(key), value));
115 }
116 
117 template<typename T, typename Predicate, typename Allocator>
118 typename string_map<T, Predicate, Allocator>::iterator
erase(iterator position)119 string_map<T, Predicate, Allocator>::erase(iterator position)
120 {
121 	const char* key = position->first;
122 	iterator result = base::base_type::erase(position);
123 	base::base_type::get_allocator().deallocate((void*)key, 0);
124 	return result;
125 }
126 
127 template<typename T, typename Predicate, typename Allocator>
128 typename string_map<T, Predicate, Allocator>::size_type
erase(const char * key)129 string_map<T, Predicate, Allocator>::erase(const char* key)
130 {
131 	const iterator it(base::base_type::find(key));
132 
133     if(it != base::base_type::end())
134     {
135         erase(it);
136         return 1;
137     }
138     return 0;
139 }
140 
141 template<typename T, typename Predicate, typename Allocator>
142 typename string_map<T, Predicate, Allocator>::mapped_type&
143 string_map<T, Predicate, Allocator>::operator[](const char* key)
144 {
145 	using base_value_type = typename base::base_type::value_type;
146 
147 	EASTL_ASSERT(key);
148 	iterator i = base::base_type::find(key);
149 	if (i != base::base_type::end())
150 		return i->second;
151 	return base::base_type::insert(base_value_type(pair_first_construct, strduplicate(key))).first->second;
152 }
153 
154 template<typename T, typename Predicate, typename Allocator>
155 char*
strduplicate(const char * str)156 string_map<T, Predicate, Allocator>::strduplicate(const char* str)
157 {
158 	size_t len = strlen(str);
159 	char* result = (char*)base::base_type::get_allocator().allocate(len + 1);
160 	memcpy(result, str, len+1);
161 	return result;
162 }
163 
164 
165 }
166 
167 #endif
168