/work/obj-fuzz/dist/include/js/SourceBufferHolder.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | /* |
7 | | * SourceBufferHolder groups buffer and length values and provides a way to |
8 | | * optionally pass ownership of the buffer to the JS engine without copying. |
9 | | * |
10 | | * Rules for use: |
11 | | * |
12 | | * 1) The data array must be allocated with js_malloc() or js_realloc() if |
13 | | * ownership is being granted to the SourceBufferHolder. |
14 | | * 2) If ownership is not given to the SourceBufferHolder, then the memory |
15 | | * must be kept alive until the JS compilation is complete. |
16 | | * 3) Any code calling SourceBufferHolder::take() must guarantee to keep the |
17 | | * memory alive until JS compilation completes. Normally only the JS |
18 | | * engine should be calling take(). |
19 | | * |
20 | | * Example use: |
21 | | * |
22 | | * size_t length = 512; |
23 | | * char16_t* chars = js_pod_malloc<char16_t>(length); |
24 | | * JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership); |
25 | | * JS::Compile(cx, options, srcBuf); |
26 | | */ |
27 | | |
28 | | #ifndef js_SourceBufferHolder_h |
29 | | #define js_SourceBufferHolder_h |
30 | | |
31 | | #include "mozilla/Assertions.h" // MOZ_ASSERT |
32 | | |
33 | | #include <stddef.h> // size_t |
34 | | |
35 | | #include "js/Utility.h" // JS::UniqueTwoByteChars |
36 | | |
37 | | namespace JS { |
38 | | |
39 | | class SourceBufferHolder final |
40 | | { |
41 | | private: |
42 | | const char16_t* data_; |
43 | | size_t length_; |
44 | | bool ownsChars_; |
45 | | |
46 | | private: |
47 | 8 | void fixEmptyBuffer() { |
48 | 8 | // Ensure that null buffers properly return an unowned, empty, |
49 | 8 | // null-terminated string. |
50 | 8 | static const char16_t NullChar_ = 0; |
51 | 8 | if (!data_) { |
52 | 0 | data_ = &NullChar_; |
53 | 0 | length_ = 0; |
54 | 0 | ownsChars_ = false; |
55 | 0 | } |
56 | 8 | } |
57 | | |
58 | | public: |
59 | | enum Ownership { |
60 | | NoOwnership, |
61 | | GiveOwnership |
62 | | }; |
63 | | |
64 | | SourceBufferHolder(const char16_t* data, size_t dataLength, Ownership ownership) |
65 | | : data_(data), |
66 | | length_(dataLength), |
67 | | ownsChars_(ownership == GiveOwnership) |
68 | 8 | { |
69 | 8 | fixEmptyBuffer(); |
70 | 8 | } |
71 | | |
72 | | SourceBufferHolder(UniqueTwoByteChars&& data, size_t dataLength) |
73 | | : data_(data.release()), |
74 | | length_(dataLength), |
75 | | ownsChars_(true) |
76 | 0 | { |
77 | 0 | fixEmptyBuffer(); |
78 | 0 | } |
79 | | |
80 | | SourceBufferHolder(SourceBufferHolder&& other) |
81 | | : data_(other.data_), |
82 | | length_(other.length_), |
83 | | ownsChars_(other.ownsChars_) |
84 | 0 | { |
85 | 0 | other.data_ = nullptr; |
86 | 0 | other.length_ = 0; |
87 | 0 | other.ownsChars_ = false; |
88 | 0 | } |
89 | | |
90 | 8 | ~SourceBufferHolder() { |
91 | 8 | if (ownsChars_) { |
92 | 8 | js_free(const_cast<char16_t*>(data_)); |
93 | 8 | } |
94 | 8 | } |
95 | | |
96 | | /** Access the underlying source buffer without affecting ownership. */ |
97 | 8 | const char16_t* get() const { |
98 | 8 | return data_; |
99 | 8 | } |
100 | | |
101 | | /** Length of the source buffer in char16_t code units (not bytes). */ |
102 | 32 | size_t length() const { |
103 | 32 | return length_; |
104 | 32 | } |
105 | | |
106 | | /** |
107 | | * Returns true if the SourceBufferHolder owns the buffer and will free it |
108 | | * upon destruction. If true, it is legal to call take(). |
109 | | */ |
110 | 0 | bool ownsChars() const { |
111 | 0 | return ownsChars_; |
112 | 0 | } |
113 | | |
114 | | /** |
115 | | * Retrieve and take ownership of the underlying data buffer. The caller |
116 | | * is now responsible for calling js_free() on the returned value, *but |
117 | | * only after JS script compilation has completed*. |
118 | | * |
119 | | * After the buffer has been taken the SourceBufferHolder functions as if |
120 | | * it had been constructed on an unowned buffer; get() and length() still |
121 | | * work. In order for this to be safe the taken buffer must be kept alive |
122 | | * until after JS script compilation completes as noted above. |
123 | | * |
124 | | * It's the caller's responsibility to check ownsChars() before taking the |
125 | | * buffer. Taking and then free'ing an unowned buffer will have dire |
126 | | * consequences. |
127 | | */ |
128 | 0 | char16_t* take() { |
129 | 0 | MOZ_ASSERT(ownsChars_); |
130 | 0 | ownsChars_ = false; |
131 | 0 | return const_cast<char16_t*>(data_); |
132 | 0 | } |
133 | | |
134 | | private: |
135 | | SourceBufferHolder(SourceBufferHolder&) = delete; |
136 | | SourceBufferHolder& operator=(SourceBufferHolder&) = delete; |
137 | | }; |
138 | | |
139 | | } // namespace JS |
140 | | |
141 | | #endif /* js_SourceBufferHolder_h */ |