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 |
110 | |