1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <fbl/intrusive_wavl_tree.h>
8 #include <fbl/string.h>
9 #include <fbl/unique_ptr.h>
10 
11 namespace fuzzing {
12 
13 // |fuzzing::StringMap| is a small wrapper class used to make C-style strings easy to store and
14 // manipulate in a |fbl::WAVLTree|.
15 class StringMap final {
16 public:
17     StringMap();
18     ~StringMap();
19 
20     // Identical to |fbl::WAVLTree<fbl::unique_ptr<StringElement>>::is_empty|.
21     bool is_empty() const;
22 
23     // Identical to |fbl::WAVLTree<fbl::unique_ptr<StringElement>>::size|.
24     size_t size() const;
25 
26     // In place of iterators, this class provides |first| and |next| methods.  The former resets the
27     // internal iterator to the beginning of the map, while the latter returns successive key-value
28     // pairs via |out_key| and |out_value| with each successive call until it reaches the end of the
29     // map and returns null.  The map can be simply iterated by:
30     //   const char *key;
31     //   const char *value;
32     //   map.begin();
33     //   while(map.next(&key, &value)) { ... }
34     void begin();
35     bool next(const char** out_key, const char** out_val);
36     bool next(fbl::String* out_key, fbl::String* out_val);
37 
38     // Returns the value for the given |key|, or null if the key isn't found.
39     const char* get(const char* key) const;
get(const fbl::String & key)40     const char* get(const fbl::String& key) const { return get(key.c_str()); }
41 
42     // Associates the given |value| with the given |key|.  |key| and |value| must not be null.
43     void set(const char* key, const char* val);
set(const fbl::String & key,const fbl::String & val)44     void set(const fbl::String& key, const fbl::String& val) { set(key.c_str(), val.c_str()); }
45 
46     // Removes any value associated with the given |key| and removes it from the map.
47     void erase(const char* key);
erase(const fbl::String & key)48     void erase(const fbl::String& key) { erase(key.c_str()); };
49 
50     // Erases all keys.
51     void clear();
52 
53 private:
54     DISALLOW_COPY_ASSIGN_AND_MOVE(StringMap);
55 
56     // |fuzzing::StringMap::StringElement| is an internal intrusive container used to back the
57     // strings in the list.
58     struct StringElement final : public fbl::WAVLTreeContainable<fbl::unique_ptr<StringElement>> {
59         fbl::String key;
60         fbl::String val;
61     };
62 
63     // |fuzzing::StringMap::KeyTraits| is used to sort keys lexicographically.
64     struct KeyTraits {
GetKeyKeyTraits65         static const char* GetKey(const StringElement& element) { return element.key.c_str(); }
LessThanKeyTraits66         static bool LessThan(const char* key1, const char* key2) { return strcmp(key1, key2) < 0; }
EqualToKeyTraits67         static bool EqualTo(const char* key1, const char* key2) { return strcmp(key1, key2) == 0; }
68     };
69 
70     // The actual map pairs, and an iterator to return the |next| one.
71     using Map = fbl::WAVLTree<const char*, fbl::unique_ptr<StringElement>, KeyTraits>;
72     Map elements_;
73     Map::iterator iterator_;
74 };
75 
76 } // namespace fuzzing
77