1/* 2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <boot/PathBlocklist.h> 8 9#include <stdlib.h> 10 11#include <algorithm> 12 13 14// #pragma mark - BlockedPath 15 16 17BlockedPath::BlockedPath() 18 : 19 fPath(NULL), 20 fLength(0), 21 fCapacity(0) 22{ 23} 24 25 26BlockedPath::~BlockedPath() 27{ 28 free(fPath); 29} 30 31 32bool 33BlockedPath::SetTo(const char* path) 34{ 35 size_t length = strlen(path); 36 if (length > 0 && path[length - 1] == '/') 37 length--; 38 39 if (!_Resize(length, false)) 40 return false; 41 42 if (length > 0) { 43 memcpy(fPath, path, length); 44 fPath[length] = '\0'; 45 } 46 47 return true; 48} 49 50 51bool 52BlockedPath::Append(const char* component) 53{ 54 size_t componentLength = strlen(component); 55 if (componentLength > 0 && component[componentLength - 1] == '/') 56 componentLength--; 57 if (componentLength == 0) 58 return true; 59 60 size_t oldLength = fLength; 61 size_t length = (fLength > 0 ? fLength + 1 : 0) + componentLength; 62 if (!_Resize(length, true)) 63 return false; 64 65 if (oldLength > 0) 66 fPath[oldLength++] = '/'; 67 memcpy(fPath + oldLength, component, componentLength); 68 return true; 69} 70 71 72bool 73BlockedPath::_Resize(size_t length, bool keepData) 74{ 75 if (length == 0) { 76 free(fPath); 77 fPath = NULL; 78 fLength = 0; 79 fCapacity = 0; 80 return true; 81 } 82 83 if (length < fCapacity) { 84 fPath[length] = '\0'; 85 fLength = length; 86 return true; 87 } 88 89 size_t capacity = std::max(length + 1, 2 * fCapacity); 90 capacity = std::max(capacity, size_t(32)); 91 92 char* path; 93 if (fLength > 0 && keepData) { 94 path = (char*)realloc(fPath, capacity); 95 if (path == NULL) 96 return false; 97 } else { 98 path = (char*)malloc(capacity); 99 if (path == NULL) 100 return false; 101 free(fPath); 102 } 103 104 fPath = path; 105 fPath[length] = '\0'; 106 fLength = length; 107 fCapacity = capacity; 108 return true; 109} 110 111 112// #pragma mark - PathBlocklist 113 114 115PathBlocklist::PathBlocklist() 116{ 117} 118 119 120PathBlocklist::~PathBlocklist() 121{ 122 MakeEmpty(); 123} 124 125 126bool 127PathBlocklist::Add(const char* path) 128{ 129 BlockedPath* blockedPath = _FindPath(path); 130 if (blockedPath != NULL) 131 return true; 132 133 blockedPath = new(std::nothrow) BlockedPath; 134 if (blockedPath == NULL || !blockedPath->SetTo(path)) { 135 delete blockedPath; 136 return false; 137 } 138 139 fPaths.Add(blockedPath); 140 return true; 141} 142 143 144void 145PathBlocklist::Remove(const char* path) 146{ 147 BlockedPath* blockedPath = _FindPath(path); 148 if (blockedPath != NULL) { 149 fPaths.Remove(blockedPath); 150 delete blockedPath; 151 } 152} 153 154 155bool 156PathBlocklist::Contains(const char* path) const 157{ 158 return _FindPath(path) != NULL; 159} 160 161 162void 163PathBlocklist::MakeEmpty() 164{ 165 while (BlockedPath* blockedPath = fPaths.RemoveHead()) 166 delete blockedPath; 167} 168 169 170BlockedPath* 171PathBlocklist::_FindPath(const char* path) const 172{ 173 for (PathList::Iterator it = fPaths.GetIterator(); it.HasNext();) { 174 BlockedPath* blockedPath = it.Next(); 175 if (*blockedPath == path) 176 return blockedPath; 177 } 178 179 return NULL; 180} 181