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#include <string.h> 6 7#include <fbl/alloc_checker.h> 8#include <fbl/unique_ptr.h> 9#include <fuzz-utils/string-list.h> 10 11namespace fuzzing { 12 13StringList::StringList() { 14 iterator_ = elements_.end(); 15} 16 17StringList::StringList(const char* const* elements, size_t num_elements) { 18 for (size_t i = 0; i < num_elements; ++i) { 19 push_back(elements[i]); 20 } 21} 22 23StringList::~StringList() {} 24 25bool StringList::is_empty() const { 26 return elements_.is_empty(); 27} 28 29size_t StringList::length() const { 30 return elements_.size_slow(); 31} 32 33const char* StringList::first() { 34 iterator_ = elements_.begin(); 35 return next(); 36} 37 38const char* StringList::next() { 39 return iterator_ != elements_.end() ? (iterator_++)->str_.c_str() : nullptr; 40} 41 42void StringList::push_front(const char* str) { 43 push(str, true /* front */); 44} 45 46void StringList::push_back(const char* str) { 47 push(str, false /* !front */); 48} 49 50void StringList::push(const char* str, bool front) { 51 if (!str) { 52 return; 53 } 54 fbl::AllocChecker ac; 55 fbl::unique_ptr<StringElement> element(new (&ac) StringElement()); 56 ZX_ASSERT(ac.check()); 57 element->str_.Set(str, &ac); 58 ZX_ASSERT(ac.check()); 59 if (front) { 60 elements_.push_front(fbl::move(element)); 61 } else { 62 elements_.push_back(fbl::move(element)); 63 } 64 iterator_ = elements_.end(); 65} 66 67void StringList::keep_if(const char* substr) { 68 if (!substr) { 69 return; 70 } 71 while (elements_.erase_if([substr](const StringElement& element) -> bool { 72 return strstr(element.str_.c_str(), substr) == nullptr; 73 })) { 74 } 75 iterator_ = elements_.end(); 76} 77 78void StringList::keep_if_any(StringList* substrs) { 79 ZX_DEBUG_ASSERT(substrs); 80 while (elements_.erase_if([substrs](const StringElement& element) -> bool { 81 for (const char* substr = substrs->first(); substr; substr = substrs->next()) { 82 if (strstr(element.str_.c_str(), substr)) { 83 return false; 84 } 85 } 86 return true; 87 })) { 88 } 89 iterator_ = elements_.end(); 90} 91 92void StringList::keep_if_all(StringList* substrs) { 93 ZX_DEBUG_ASSERT(substrs); 94 while (elements_.erase_if([substrs](const StringElement& element) -> bool { 95 for (const char* substr = substrs->first(); substr; substr = substrs->next()) { 96 if (!strstr(element.str_.c_str(), substr)) { 97 return true; 98 } 99 } 100 return false; 101 })) { 102 } 103 iterator_ = elements_.end(); 104} 105 106void StringList::erase_if(const char* match) { 107 if (!match) { 108 return; 109 } 110 while (elements_.erase_if([match](const StringElement& element) -> bool { 111 return strcmp(element.str_.c_str(), match) == 0; 112 })) { 113 } 114 iterator_ = elements_.end(); 115} 116 117void StringList::clear() { 118 elements_.clear(); 119 iterator_ = elements_.begin(); 120} 121 122} // namespace fuzzing 123