author | vadim |
Fri, 06 Mar 2015 13:15:16 +0300 | |
changeset 31691 | 1a80984cc48f |
parent 29908 | 83e2c403fefd |
child 31707 | 1820e72671e8 |
permissions | -rw-r--r-- |
16891 | 1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
3 |
* |
|
4 |
* This code is free software; you can redistribute it and/or modify it |
|
5 |
* under the terms of the GNU General Public License version 2 only, as |
|
6 |
* published by the Free Software Foundation. Oracle designates this |
|
7 |
* particular file as subject to the "Classpath" exception as provided |
|
8 |
* by Oracle in the LICENSE file that accompanied this code. |
|
9 |
* |
|
10 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
11 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
12 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
13 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
14 |
* accompanied this code). |
|
15 |
* |
|
16 |
* You should have received a copy of the GNU General Public License version |
|
17 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
18 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
19 |
* |
|
20 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
21 |
* or visit www.oracle.com if you need additional information or have any |
|
22 |
* questions. |
|
23 |
*/ |
|
24 |
||
25 |
/* |
|
26 |
* -*- c++ -*- |
|
27 |
* |
|
28 |
* (C) Copyright IBM Corp. and others 2013 - All Rights Reserved |
|
29 |
* |
|
30 |
* Range checking |
|
31 |
* |
|
32 |
*/ |
|
33 |
||
34 |
#ifndef __LETABLEREFERENCE_H |
|
35 |
#define __LETABLEREFERENCE_H |
|
36 |
||
37 |
#include "LETypes.h" |
|
38 |
#include "LEFontInstance.h" |
|
39 |
||
22330 | 40 |
/** |
41 |
* \def LE_ENABLE_RAW |
|
42 |
* If this is 1, enables old non-safe raw access |
|
43 |
*/ |
|
44 |
#ifndef LE_ENABLE_RAW |
|
45 |
#define LE_ENABLE_RAW 0 |
|
46 |
#endif |
|
16891 | 47 |
|
22330 | 48 |
#define kQuestionmarkTableTag 0x3F3F3F3FUL /* ???? */ |
49 |
#define kStaticTableTag 0x30303030UL /* 0000 */ |
|
50 |
#define kTildeTableTag 0x7e7e7e7eUL /* ~~~~ */ |
|
16891 | 51 |
#ifdef __cplusplus |
52 |
||
53 |
// internal - interface for range checking |
|
54 |
U_NAMESPACE_BEGIN |
|
55 |
||
56 |
#if LE_ASSERT_BAD_FONT |
|
22330 | 57 |
|
58 |
#ifndef LE_TRACE_TR |
|
59 |
#define LE_TRACE_TR 0 |
|
60 |
#endif |
|
61 |
||
16891 | 62 |
class LETableReference; // fwd |
63 |
/** |
|
64 |
* defined in OpenTypeUtilities.cpp |
|
65 |
* @internal |
|
66 |
*/ |
|
22330 | 67 |
U_CAPI void U_EXPORT2 _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len); |
16891 | 68 |
|
69 |
#define LE_DEBUG_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0); |
|
70 |
#define LE_DEBUG_TR3(x,y,z) _debug_LETableReference(__FILE__, __LINE__, x, this, (const void*)y, (size_t)z); |
|
22330 | 71 |
#if LE_TRACE_TR |
72 |
#define _TRTRACE(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0); |
|
16891 | 73 |
#else |
22330 | 74 |
#define _TRTRACE(x) |
16891 | 75 |
#endif |
76 |
||
77 |
#else |
|
78 |
#define LE_DEBUG_TR(x) |
|
79 |
#define LE_DEBUG_TR3(x,y,z) |
|
22330 | 80 |
#define _TRTRACE(x) |
16891 | 81 |
#endif |
82 |
||
83 |
/** |
|
84 |
* @internal |
|
85 |
*/ |
|
86 |
class LETableReference { |
|
87 |
public: |
|
22330 | 88 |
|
89 |
/** |
|
90 |
* Dummy enum asserting that a value is actually static data |
|
91 |
* and does not need to be range checked |
|
92 |
*/ |
|
93 |
enum EStaticData { kStaticData = 0 }; |
|
94 |
||
16891 | 95 |
/** |
96 |
* @internal |
|
97 |
* Construct from a specific tag |
|
98 |
*/ |
|
99 |
LETableReference(const LEFontInstance* font, LETag tableTag, LEErrorCode &success) : |
|
100 |
fFont(font), fTag(tableTag), fParent(NULL), fStart(NULL),fLength(LE_UINTPTR_MAX) { |
|
101 |
loadTable(success); |
|
22330 | 102 |
_TRTRACE("INFO: new table load") |
16891 | 103 |
} |
104 |
||
105 |
LETableReference(const LETableReference &parent, LEErrorCode &success) : fFont(parent.fFont), fTag(parent.fTag), fParent(&parent), fStart(parent.fStart), fLength(parent.fLength) { |
|
106 |
if(LE_FAILURE(success)) { |
|
107 |
clear(); |
|
108 |
} |
|
22330 | 109 |
_TRTRACE("INFO: new clone") |
16891 | 110 |
} |
111 |
||
22330 | 112 |
#if LE_ENABLE_RAW |
113 |
/** |
|
114 |
* Construct without a parent LETR. |
|
115 |
*/ |
|
16891 | 116 |
LETableReference(const le_uint8* data, size_t length = LE_UINTPTR_MAX) : |
117 |
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) { |
|
22330 | 118 |
_TRTRACE("INFO: new raw") |
16891 | 119 |
} |
22330 | 120 |
#endif |
121 |
||
122 |
/** |
|
123 |
* Construct without a parent LETR. |
|
124 |
*/ |
|
125 |
LETableReference(EStaticData /* NOTUSED */, const le_uint8* data, size_t length) : |
|
126 |
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) { |
|
127 |
_TRTRACE("INFO: new EStaticData") |
|
128 |
} |
|
129 |
||
16891 | 130 |
LETableReference() : |
131 |
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(NULL), fLength(0) { |
|
22330 | 132 |
_TRTRACE("INFO: new empty") |
16891 | 133 |
} |
134 |
||
135 |
~LETableReference() { |
|
22330 | 136 |
fTag= (LETag)kTildeTableTag; |
137 |
_TRTRACE("INFO: new dtor") |
|
16891 | 138 |
} |
139 |
||
140 |
/** |
|
141 |
* @internal |
|
142 |
* @param length if LE_UINTPTR_MAX means "whole table" |
|
143 |
* subset |
|
144 |
*/ |
|
145 |
LETableReference(const LETableReference &parent, size_t offset, size_t length, |
|
146 |
LEErrorCode &err) : |
|
147 |
fFont(parent.fFont), fTag(parent.fTag), fParent(&parent), |
|
148 |
fStart((parent.fStart)+offset), fLength(length) { |
|
149 |
if(LE_SUCCESS(err)) { |
|
150 |
if(isEmpty()) { |
|
151 |
//err = LE_MISSING_FONT_TABLE_ERROR; |
|
152 |
clear(); // it's just empty. Not an error. |
|
29908 | 153 |
} else if(offset >= fParent->fLength || (offset & 0x01)) { |
154 |
LE_DEBUG_TR3("offset out of range or odd alignment: (%p) +%d", NULL, offset); |
|
16891 | 155 |
err = LE_INDEX_OUT_OF_BOUNDS_ERROR; |
156 |
clear(); |
|
157 |
} else { |
|
158 |
if(fLength == LE_UINTPTR_MAX && |
|
159 |
fParent->fLength != LE_UINTPTR_MAX) { |
|
160 |
fLength = (fParent->fLength) - offset; // decrement length as base address is incremented |
|
161 |
} |
|
162 |
if(fLength != LE_UINTPTR_MAX) { // if we have bounds: |
|
22330 | 163 |
if((offset+fLength < offset) || (offset+fLength > fParent->fLength)) { |
16891 | 164 |
LE_DEBUG_TR3("offset+fLength out of range: (%p) +%d", NULL, offset+fLength); |
165 |
err = LE_INDEX_OUT_OF_BOUNDS_ERROR; // exceeded |
|
166 |
clear(); |
|
167 |
} |
|
168 |
} |
|
169 |
} |
|
170 |
} else { |
|
171 |
clear(); |
|
172 |
} |
|
22330 | 173 |
_TRTRACE("INFO: new subset") |
16891 | 174 |
} |
175 |
||
176 |
const void* getAlias() const { return (const void*)fStart; } |
|
22330 | 177 |
#ifndef LE_ENABLE_RAW |
178 |
const void* getAliasRAW() const { LE_DEBUG_TR("getAliasRAW()"); return (const void*)fStart; } |
|
179 |
#endif |
|
16891 | 180 |
le_bool isEmpty() const { return fStart==NULL || fLength==0; } |
181 |
le_bool isValid() const { return !isEmpty(); } |
|
182 |
le_bool hasBounds() const { return fLength!=LE_UINTPTR_MAX; } |
|
183 |
void clear() { fLength=0; fStart=NULL; } |
|
184 |
size_t getLength() const { return fLength; } |
|
185 |
const LEFontInstance* getFont() const { return fFont; } |
|
186 |
LETag getTag() const { return fTag; } |
|
187 |
const LETableReference* getParent() const { return fParent; } |
|
188 |
||
189 |
void addOffset(size_t offset, LEErrorCode &success) { |
|
190 |
if(hasBounds()) { |
|
31691 | 191 |
if(offset >= fLength) { |
16891 | 192 |
LE_DEBUG_TR("addOffset off end"); |
193 |
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; |
|
194 |
return; |
|
195 |
} else { |
|
196 |
fLength -= offset; |
|
197 |
} |
|
198 |
} |
|
199 |
fStart += offset; |
|
200 |
} |
|
201 |
||
202 |
size_t ptrToOffset(const void *atPtr, LEErrorCode &success) const { |
|
203 |
if(atPtr==NULL) return 0; |
|
204 |
if(LE_FAILURE(success)) return LE_UINTPTR_MAX; |
|
205 |
if((atPtr < fStart) || |
|
31691 | 206 |
(hasBounds() && (atPtr >= fStart+fLength))) { |
16891 | 207 |
LE_DEBUG_TR3("ptrToOffset args out of range: %p", atPtr, 0); |
208 |
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; |
|
209 |
return LE_UINTPTR_MAX; |
|
210 |
} |
|
211 |
return ((const le_uint8*)atPtr)-fStart; |
|
212 |
} |
|
213 |
||
214 |
/** |
|
215 |
* Clamp down the length, for range checking. |
|
216 |
*/ |
|
217 |
size_t contractLength(size_t newLength) { |
|
218 |
if(fLength!=LE_UINTPTR_MAX&&newLength>0&&newLength<=fLength) { |
|
219 |
fLength = newLength; |
|
220 |
} |
|
221 |
return fLength; |
|
222 |
} |
|
223 |
||
224 |
/** |
|
225 |
* Throw an error if offset+length off end |
|
226 |
*/ |
|
227 |
public: |
|
228 |
size_t verifyLength(size_t offset, size_t length, LEErrorCode &success) { |
|
229 |
if(isValid()&& |
|
230 |
LE_SUCCESS(success) && |
|
231 |
fLength!=LE_UINTPTR_MAX && length!=LE_UINTPTR_MAX && offset!=LE_UINTPTR_MAX && |
|
232 |
(offset+length)>fLength) { |
|
233 |
LE_DEBUG_TR3("verifyLength failed (%p) %d",NULL, offset+length); |
|
234 |
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; |
|
235 |
#if LE_ASSERT_BAD_FONT |
|
236 |
fprintf(stderr, "offset=%lu, len=%lu, would be at %p, (%lu) off end. End at %p\n", offset,length, fStart+offset+length, (offset+length-fLength), (offset+length-fLength)+fStart); |
|
237 |
#endif |
|
238 |
} |
|
239 |
return fLength; |
|
240 |
} |
|
241 |
||
242 |
/** |
|
243 |
* Change parent link to another |
|
244 |
*/ |
|
245 |
LETableReference &reparent(const LETableReference &base) { |
|
246 |
fParent = &base; |
|
247 |
return *this; |
|
248 |
} |
|
249 |
||
250 |
/** |
|
251 |
* remove parent link. Factory functions should do this. |
|
252 |
*/ |
|
253 |
void orphan(void) { |
|
254 |
fParent=NULL; |
|
255 |
} |
|
256 |
||
257 |
protected: |
|
258 |
const LEFontInstance* fFont; |
|
259 |
LETag fTag; |
|
260 |
const LETableReference *fParent; |
|
261 |
const le_uint8 *fStart; // keep as 8 bit internally, for pointer math |
|
262 |
size_t fLength; |
|
263 |
||
264 |
void loadTable(LEErrorCode &success) { |
|
265 |
if(LE_SUCCESS(success)) { |
|
266 |
fStart = (const le_uint8*)(fFont->getFontTable(fTag, fLength)); // note - a null table is not an error. |
|
267 |
} |
|
268 |
} |
|
269 |
||
270 |
void setRaw(const void *data, size_t length = LE_UINTPTR_MAX) { |
|
271 |
fFont = NULL; |
|
22330 | 272 |
fTag = (LETag)kQuestionmarkTableTag; |
273 |
fParent = NULL; |
|
274 |
fStart = (const le_uint8*)data; |
|
275 |
fLength = length; |
|
276 |
} |
|
277 |
||
278 |
/** |
|
279 |
* set this object pointing to static data |
|
280 |
*/ |
|
281 |
void setTo(EStaticData /*notused*/, const void *data, size_t length) { |
|
282 |
fFont = NULL; |
|
283 |
fTag = (LETag)kStaticTableTag; |
|
16891 | 284 |
fParent = NULL; |
285 |
fStart = (const le_uint8*)data; |
|
286 |
fLength = length; |
|
287 |
} |
|
288 |
}; |
|
289 |
||
290 |
||
291 |
template<class T> |
|
292 |
class LETableVarSizer { |
|
293 |
public: |
|
294 |
inline static size_t getSize(); |
|
295 |
}; |
|
296 |
||
297 |
// base definition- could override for adjustments |
|
298 |
template<class T> inline |
|
299 |
size_t LETableVarSizer<T>::getSize() { |
|
300 |
return sizeof(T); |
|
301 |
} |
|
302 |
||
303 |
/** |
|
304 |
* \def LE_VAR_ARRAY |
|
305 |
* @param x Type (T) |
|
306 |
* @param y some member that is of length ANY_NUMBER |
|
307 |
* Call this after defining a class, for example: |
|
308 |
* LE_VAR_ARRAY(FeatureListTable,featureRecordArray) |
|
309 |
* this is roughly equivalent to: |
|
310 |
* template<> inline size_t LETableVarSizer<FeatureListTable>::getSize() { return sizeof(FeatureListTable) - (sizeof(le_uint16)*ANY_NUMBER); } |
|
311 |
* it's a specialization that informs the LETableReference subclasses to NOT include the variable array in the size. |
|
312 |
* dereferencing NULL is valid here because we never actually dereference it, just inside sizeof. |
|
313 |
*/ |
|
314 |
#define LE_VAR_ARRAY(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return sizeof(x) - (sizeof(((const x*)0)->y)); } |
|
315 |
/** |
|
316 |
* \def LE_CORRECT_SIZE |
|
317 |
* @param x type (T) |
|
318 |
* @param y fixed size for T |
|
319 |
*/ |
|
320 |
#define LE_CORRECT_SIZE(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return y; } |
|
321 |
||
322 |
/** |
|
323 |
* Open a new entry based on an existing table |
|
324 |
*/ |
|
325 |
||
326 |
template<class T> |
|
327 |
class LEReferenceTo : public LETableReference { |
|
328 |
public: |
|
329 |
/** |
|
330 |
* open a sub reference. |
|
331 |
* @param parent parent reference |
|
332 |
* @param success error status |
|
333 |
* @param atPtr location of reference - if NULL, will be at offset zero (i.e. downcast of parent). Otherwise must be a pointer within parent's bounds. |
|
334 |
*/ |
|
18518
153791a0895c
8015144: Performance regression in ICU OpenType Layout library
prr
parents:
16891
diff
changeset
|
335 |
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr) |
16891 | 336 |
: LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) { |
337 |
verifyLength(0, LETableVarSizer<T>::getSize(), success); |
|
338 |
if(LE_FAILURE(success)) clear(); |
|
339 |
} |
|
340 |
/** |
|
341 |
* ptr plus offset |
|
342 |
*/ |
|
18518
153791a0895c
8015144: Performance regression in ICU OpenType Layout library
prr
parents:
16891
diff
changeset
|
343 |
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr, size_t offset) |
16891 | 344 |
: LETableReference(parent, parent.ptrToOffset(atPtr, success)+offset, LE_UINTPTR_MAX, success) { |
345 |
verifyLength(0, LETableVarSizer<T>::getSize(), success); |
|
346 |
if(LE_FAILURE(success)) clear(); |
|
347 |
} |
|
18518
153791a0895c
8015144: Performance regression in ICU OpenType Layout library
prr
parents:
16891
diff
changeset
|
348 |
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, size_t offset) |
16891 | 349 |
: LETableReference(parent, offset, LE_UINTPTR_MAX, success) { |
350 |
verifyLength(0, LETableVarSizer<T>::getSize(), success); |
|
351 |
if(LE_FAILURE(success)) clear(); |
|
352 |
} |
|
18518
153791a0895c
8015144: Performance regression in ICU OpenType Layout library
prr
parents:
16891
diff
changeset
|
353 |
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success) |
16891 | 354 |
: LETableReference(parent, 0, LE_UINTPTR_MAX, success) { |
355 |
verifyLength(0, LETableVarSizer<T>::getSize(), success); |
|
356 |
if(LE_FAILURE(success)) clear(); |
|
357 |
} |
|
18518
153791a0895c
8015144: Performance regression in ICU OpenType Layout library
prr
parents:
16891
diff
changeset
|
358 |
inline LEReferenceTo(const LEFontInstance *font, LETag tableTag, LEErrorCode &success) |
16891 | 359 |
: LETableReference(font, tableTag, success) { |
360 |
verifyLength(0, LETableVarSizer<T>::getSize(), success); |
|
361 |
if(LE_FAILURE(success)) clear(); |
|
362 |
} |
|
22330 | 363 |
#if LE_ENABLE_RAW |
18518
153791a0895c
8015144: Performance regression in ICU OpenType Layout library
prr
parents:
16891
diff
changeset
|
364 |
inline LEReferenceTo(const le_uint8 *data, size_t length = LE_UINTPTR_MAX) : LETableReference(data, length) {} |
153791a0895c
8015144: Performance regression in ICU OpenType Layout library
prr
parents:
16891
diff
changeset
|
365 |
inline LEReferenceTo(const T *data, size_t length = LE_UINTPTR_MAX) : LETableReference((const le_uint8*)data, length) {} |
22330 | 366 |
#endif |
367 |
inline LEReferenceTo(EStaticData staticData, const le_uint8 *data, size_t length) : LETableReference(staticData, data, length) {} |
|
368 |
inline LEReferenceTo(EStaticData staticData, const T *data, size_t length) : LETableReference(staticData, (const le_uint8*)data, length) {} |
|
16891 | 369 |
|
22330 | 370 |
inline LEReferenceTo() : LETableReference() {} |
371 |
||
372 |
#if LE_ENABLE_RAW |
|
18518
153791a0895c
8015144: Performance regression in ICU OpenType Layout library
prr
parents:
16891
diff
changeset
|
373 |
inline LEReferenceTo<T>& operator=(const T* other) { |
16891 | 374 |
setRaw(other); |
375 |
return *this; |
|
376 |
} |
|
22330 | 377 |
#endif |
378 |
||
379 |
LEReferenceTo<T>& setTo(LETableReference::EStaticData staticData, const T* other, size_t length) { |
|
380 |
LETableReference::setTo(staticData, other, length); |
|
381 |
return *this; |
|
382 |
} |
|
16891 | 383 |
|
384 |
LEReferenceTo<T> &reparent(const LETableReference &base) { |
|
385 |
fParent = &base; |
|
386 |
return *this; |
|
387 |
} |
|
388 |
||
389 |
/** |
|
390 |
* roll forward by one <T> size. |
|
391 |
* same as addOffset(LETableVarSizer<T>::getSize(),success) |
|
392 |
*/ |
|
393 |
void addObject(LEErrorCode &success) { |
|
394 |
addOffset(LETableVarSizer<T>::getSize(), success); |
|
395 |
} |
|
396 |
void addObject(size_t count, LEErrorCode &success) { |
|
397 |
addOffset(LETableVarSizer<T>::getSize()*count, success); |
|
398 |
} |
|
399 |
||
400 |
const T *operator->() const { return getAlias(); } |
|
22330 | 401 |
const T *operator*() const { return getAlias(); } |
16891 | 402 |
const T *getAlias() const { return (const T*)fStart; } |
22330 | 403 |
#if LE_ENABLE_RAW |
404 |
const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; } |
|
405 |
#endif |
|
406 |
||
16891 | 407 |
}; |
408 |
||
409 |
||
22330 | 410 |
/** |
411 |
* \def LE_UNBOUNDED_ARRAY |
|
412 |
* define an array with no *known* bound. Will trim to available size. |
|
413 |
* @internal |
|
414 |
*/ |
|
415 |
#define LE_UNBOUNDED_ARRAY LE_UINT32_MAX |
|
416 |
||
417 |
template<class T> |
|
418 |
class LEReferenceToArrayOf : public LETableReference { |
|
419 |
public: |
|
420 |
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, size_t offset, le_uint32 count) |
|
421 |
: LETableReference(parent, offset, LE_UINTPTR_MAX, success), fCount(count) { |
|
422 |
_TRTRACE("INFO: new RTAO by offset") |
|
423 |
if(LE_SUCCESS(success)) { |
|
424 |
if(fCount == LE_UNBOUNDED_ARRAY) { // not a known length |
|
425 |
fCount = getLength()/LETableVarSizer<T>::getSize(); // fit to max size |
|
426 |
} |
|
427 |
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*fCount, success); |
|
428 |
} |
|
429 |
if(LE_FAILURE(success)) { |
|
430 |
fCount=0; |
|
431 |
clear(); |
|
432 |
} |
|
433 |
} |
|
434 |
||
435 |
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, le_uint32 count) |
|
436 |
: LETableReference(parent, parent.ptrToOffset(array, success), LE_UINTPTR_MAX, success), fCount(count) { |
|
437 |
_TRTRACE("INFO: new RTAO") |
|
438 |
if(LE_SUCCESS(success)) { |
|
439 |
if(fCount == LE_UNBOUNDED_ARRAY) { // not a known length |
|
440 |
fCount = getLength()/LETableVarSizer<T>::getSize(); // fit to max size |
|
441 |
} |
|
442 |
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*fCount, success); |
|
443 |
} |
|
444 |
if(LE_FAILURE(success)) clear(); |
|
445 |
} |
|
446 |
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, size_t offset, le_uint32 count) |
|
447 |
: LETableReference(parent, parent.ptrToOffset(array, success)+offset, LE_UINTPTR_MAX, success), fCount(count) { |
|
448 |
_TRTRACE("INFO: new RTAO") |
|
449 |
if(LE_SUCCESS(success)) { |
|
450 |
if(fCount == LE_UNBOUNDED_ARRAY) { // not a known length |
|
451 |
fCount = getLength()/LETableVarSizer<T>::getSize(); // fit to max size |
|
452 |
} |
|
453 |
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*fCount, success); |
|
454 |
} |
|
455 |
if(LE_FAILURE(success)) clear(); |
|
456 |
} |
|
457 |
||
458 |
LEReferenceToArrayOf() :LETableReference(), fCount(0) {} |
|
459 |
||
460 |
le_uint32 getCount() const { return fCount; } |
|
461 |
||
462 |
const T *getAlias() const { return (const T*)fStart; } |
|
463 |
||
464 |
const T *getAlias(le_uint32 i, LEErrorCode &success) const { |
|
465 |
return ((const T*)(((const char*)getAlias())+getOffsetFor(i, success))); |
|
466 |
} |
|
467 |
||
468 |
#ifndef LE_ENABLE_RAW |
|
469 |
const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; } |
|
470 |
#endif |
|
471 |
||
472 |
const T& getObject(le_uint32 i, LEErrorCode &success) const { |
|
28547 | 473 |
const T *ret = getAlias(i, success); |
474 |
if (LE_FAILURE(success) || ret==NULL) { |
|
475 |
return *(new T(0)); |
|
476 |
} else { |
|
477 |
return *ret; |
|
478 |
} |
|
22330 | 479 |
} |
480 |
||
481 |
/** |
|
482 |
* by-value array accessor for integral types. |
|
483 |
*/ |
|
484 |
const T operator[](le_uint32 i) const { |
|
485 |
LEErrorCode success = LE_NO_ERROR; |
|
486 |
const T *ret = getAlias(i, success); |
|
487 |
if(LE_FAILURE(success) || ret==NULL) { |
|
488 |
#if LE_ASSERT_BAD_FONT |
|
489 |
LE_DEBUG_TR3("Range error, out of bounds? (%p) #%d", NULL, i); |
|
490 |
#endif |
|
491 |
return T(0); // will not work for all types. |
|
492 |
} |
|
493 |
return *ret; |
|
494 |
} |
|
495 |
||
496 |
const LEReferenceTo<T> getReference(le_uint32 i, LEErrorCode &success) const { |
|
497 |
if(LE_FAILURE(success)) return LEReferenceTo<T>(); |
|
498 |
return LEReferenceTo<T>(*this, success, getAlias(i,success)); |
|
499 |
} |
|
500 |
||
501 |
const T& operator()(le_uint32 i, LEErrorCode &success) const { |
|
502 |
return *getAlias(i,success); |
|
503 |
} |
|
504 |
||
505 |
size_t getOffsetFor(le_uint32 i, LEErrorCode &success) const { |
|
506 |
if(LE_SUCCESS(success)&&i<getCount()) { |
|
507 |
return LETableVarSizer<T>::getSize()*i; |
|
508 |
} else { |
|
509 |
LE_DEBUG_TR3("getOffsetFor failed (%p) index=%d",NULL, i); |
|
510 |
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; |
|
511 |
} |
|
512 |
return 0; |
|
513 |
} |
|
514 |
||
515 |
LEReferenceToArrayOf<T> &reparent(const LETableReference &base) { |
|
516 |
fParent = &base; |
|
517 |
return *this; |
|
518 |
} |
|
519 |
||
520 |
LEReferenceToArrayOf(const LETableReference& parent, LEErrorCode & success) : LETableReference(parent,0, LE_UINTPTR_MAX, success), fCount(0) { |
|
521 |
_TRTRACE("INFO: null RTAO") |
|
522 |
} |
|
523 |
||
524 |
private: |
|
525 |
le_uint32 fCount; |
|
526 |
}; |
|
527 |
||
528 |
||
529 |
||
530 |
||
531 |
#ifdef _TRTRACE |
|
532 |
#undef _TRTRACE |
|
533 |
#endif |
|
534 |
||
16891 | 535 |
U_NAMESPACE_END |
536 |
||
537 |
#endif |
|
538 |
||
539 |
#endif |