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