array.c++ (3876B)
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 // Licensed under the MIT License: 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 #include "array.h" 23 #include "exception.h" 24 25 namespace kj { 26 27 void ExceptionSafeArrayUtil::construct(size_t count, void (*constructElement)(void*)) { 28 while (count > 0) { 29 constructElement(pos); 30 pos += elementSize; 31 ++constructedElementCount; 32 --count; 33 } 34 } 35 36 void ExceptionSafeArrayUtil::destroyAll() { 37 while (constructedElementCount > 0) { 38 pos -= elementSize; 39 --constructedElementCount; 40 destroyElement(pos); 41 } 42 } 43 44 const DestructorOnlyArrayDisposer DestructorOnlyArrayDisposer::instance = 45 DestructorOnlyArrayDisposer(); 46 47 void DestructorOnlyArrayDisposer::disposeImpl( 48 void* firstElement, size_t elementSize, size_t elementCount, 49 size_t capacity, void (*destroyElement)(void*)) const { 50 if (destroyElement != nullptr) { 51 ExceptionSafeArrayUtil guard(firstElement, elementSize, elementCount, destroyElement); 52 guard.destroyAll(); 53 } 54 } 55 56 const NullArrayDisposer NullArrayDisposer::instance = NullArrayDisposer(); 57 58 void NullArrayDisposer::disposeImpl( 59 void* firstElement, size_t elementSize, size_t elementCount, 60 size_t capacity, void (*destroyElement)(void*)) const {} 61 62 namespace _ { // private 63 64 struct AutoDeleter { 65 void* ptr; 66 inline void* release() { void* result = ptr; ptr = nullptr; return result; } 67 inline AutoDeleter(void* ptr): ptr(ptr) {} 68 inline ~AutoDeleter() { operator delete(ptr); } 69 }; 70 71 void* HeapArrayDisposer::allocateImpl(size_t elementSize, size_t elementCount, size_t capacity, 72 void (*constructElement)(void*), 73 void (*destroyElement)(void*)) { 74 AutoDeleter result(operator new(elementSize * capacity)); 75 76 if (constructElement == nullptr) { 77 // Nothing to do. 78 } else if (destroyElement == nullptr) { 79 byte* pos = reinterpret_cast<byte*>(result.ptr); 80 while (elementCount > 0) { 81 constructElement(pos); 82 pos += elementSize; 83 --elementCount; 84 } 85 } else { 86 ExceptionSafeArrayUtil guard(result.ptr, elementSize, 0, destroyElement); 87 guard.construct(elementCount, constructElement); 88 guard.release(); 89 } 90 91 return result.release(); 92 } 93 94 void HeapArrayDisposer::disposeImpl( 95 void* firstElement, size_t elementSize, size_t elementCount, size_t capacity, 96 void (*destroyElement)(void*)) const { 97 // Note that capacity is ignored since operator delete() doesn't care about it. 98 AutoDeleter deleter(firstElement); 99 100 if (destroyElement != nullptr) { 101 ExceptionSafeArrayUtil guard(firstElement, elementSize, elementCount, destroyElement); 102 guard.destroyAll(); 103 } 104 } 105 106 const HeapArrayDisposer HeapArrayDisposer::instance = HeapArrayDisposer(); 107 108 } // namespace _ (private) 109 } // namespace kj