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/alloc_checker.h> 8 #include <fbl/intrusive_double_list.h> 9 #include <fbl/string.h> 10 #include <fbl/unique_ptr.h> 11 12 namespace fuzzing { 13 14 // |fuzzing::StringList| is a small wrapper class used to make C-style strings easy to store and 15 // manipulate in a |fbl::DoublyLinkedList|. 16 class StringList final { 17 public: 18 StringList(); 19 StringList(const char* const* elements, size_t num_elements); 20 ~StringList(); 21 22 // Identical to |fbl::DoublyLinkedList<fbl::unique_ptr<StringElement>>::is_empty|. 23 bool is_empty() const; 24 25 // Identical to |fbl::DoublyLinkedList<fbl::unique_ptr<StringElement>>::size_slow|. 26 size_t length() const; 27 28 // These methods are similar to |fbl::DoublyLinkedList|'s, except that take raw C strings and 29 // abstract away the process of wrapping them in the |StringElement| structure defined below. 30 void push_front(const char* str); 31 void push_back(const char* str); push_front(const fbl::String & str)32 void push_front(const fbl::String& str) { return push_front(str.c_str()); } push_back(const fbl::String & str)33 void push_back(const fbl::String& str) { return push_back(str.c_str()); } 34 35 // These methods are similar to |fbl::DoublyLinkedList|'s, except that they apply a simple 36 // substring pattern match instead of taking a functor. Empty strings match everything, while 37 // null inputs leave the list unchanged. 38 39 // Keeps elements if they **CONTAIN** |substr|. Null strings leave the list unchanged. 40 void keep_if(const char* substr); keep_if(const fbl::String & substr)41 void keep_if(const fbl::String& substr) { return keep_if(substr.c_str()); } 42 43 // Keeps elements if they contain at least one element of |substrs|. 44 void keep_if_any(StringList* substrs); 45 46 // Keeps elements if they contain every element of |substrs|. 47 void keep_if_all(StringList* substrs); 48 49 // Removes elements if they exactly **MATCH** |match|. Null strings leave the list unchanged. 50 void erase_if(const char* match); erase_if(const fbl::String & match)51 void erase_if(const fbl::String& match) { return erase_if(match.c_str()); } 52 53 // In place of iterators, this class provides |first| and |next| methods. The former resets the 54 // internal iterator to the beginning of the list, while the latter returns successive elements 55 // with each successive call until it reaches the end of the list and returns null. The list 56 // can be simply iterated by: 57 // for(const char *s = list.first(); s; s = list.next()) { ... } 58 const char* first(); 59 const char* next(); 60 61 // Like|fbl::DoublyLinkedList<fbl::unique_ptr<StringElement>>::clear|, but also resets the 62 // internal iterator. 63 void clear(); 64 65 private: 66 DISALLOW_COPY_ASSIGN_AND_MOVE(StringList); 67 68 // |fuzzing::StringList::StringElement| is an internal intrusive container used to back the 69 // strings in the list. 70 struct StringElement final : public fbl::DoublyLinkedListable<fbl::unique_ptr<StringElement>> { 71 fbl::String str_; 72 }; 73 74 // Implements |push_front| and |push_back| above, depending on the value of |front|. 75 void push(const char* str, bool front); 76 77 // The actual list elements, and an iterator to return the |next| one. 78 using List = fbl::DoublyLinkedList<fbl::unique_ptr<StringElement>>; 79 List elements_; 80 List::iterator iterator_; 81 }; 82 83 } // namespace fuzzing 84