Added ICU library
This commit is contained in:
418
project/jni/icuuc/include/layout/LETableReference.h
Normal file
418
project/jni/icuuc/include/layout/LETableReference.h
Normal file
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* -*- c++ -*-
|
||||
*
|
||||
* (C) Copyright IBM Corp. and others 2013 - All Rights Reserved
|
||||
*
|
||||
* Range checking
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LETABLEREFERENCE_H
|
||||
#define __LETABLEREFERENCE_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LEFontInstance.h"
|
||||
|
||||
|
||||
#define kQuestionmarkTableTag 0x3F3F3F3FUL
|
||||
#define kTildeTableTag 0x7e7e7e7eUL
|
||||
#ifdef __cplusplus
|
||||
|
||||
// internal - interface for range checking
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
#if LE_ASSERT_BAD_FONT
|
||||
class LETableReference; // fwd
|
||||
/**
|
||||
* defined in OpenTypeUtilities.cpp
|
||||
* @internal
|
||||
*/
|
||||
extern void _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len);
|
||||
|
||||
#define LE_DEBUG_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
|
||||
#define LE_DEBUG_TR3(x,y,z) _debug_LETableReference(__FILE__, __LINE__, x, this, (const void*)y, (size_t)z);
|
||||
#if 0
|
||||
#define LE_TRACE_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
|
||||
#else
|
||||
#define LE_TRACE_TR(x)
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define LE_DEBUG_TR(x)
|
||||
#define LE_DEBUG_TR3(x,y,z)
|
||||
#define LE_TRACE_TR(x)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class LETableReference {
|
||||
public:
|
||||
/**
|
||||
* @internal
|
||||
* Construct from a specific tag
|
||||
*/
|
||||
LETableReference(const LEFontInstance* font, LETag tableTag, LEErrorCode &success) :
|
||||
fFont(font), fTag(tableTag), fParent(NULL), fStart(NULL),fLength(LE_UINTPTR_MAX) {
|
||||
loadTable(success);
|
||||
LE_TRACE_TR("INFO: new table load")
|
||||
}
|
||||
|
||||
LETableReference(const LETableReference &parent, LEErrorCode &success) : fFont(parent.fFont), fTag(parent.fTag), fParent(&parent), fStart(parent.fStart), fLength(parent.fLength) {
|
||||
if(LE_FAILURE(success)) {
|
||||
clear();
|
||||
}
|
||||
LE_TRACE_TR("INFO: new clone")
|
||||
}
|
||||
|
||||
LETableReference(const le_uint8* data, size_t length = LE_UINTPTR_MAX) :
|
||||
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) {
|
||||
LE_TRACE_TR("INFO: new raw")
|
||||
}
|
||||
LETableReference() :
|
||||
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(NULL), fLength(0) {
|
||||
LE_TRACE_TR("INFO: new empty")
|
||||
}
|
||||
|
||||
~LETableReference() {
|
||||
fTag=kTildeTableTag;
|
||||
LE_TRACE_TR("INFO: new dtor")
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param length if LE_UINTPTR_MAX means "whole table"
|
||||
* subset
|
||||
*/
|
||||
LETableReference(const LETableReference &parent, size_t offset, size_t length,
|
||||
LEErrorCode &err) :
|
||||
fFont(parent.fFont), fTag(parent.fTag), fParent(&parent),
|
||||
fStart((parent.fStart)+offset), fLength(length) {
|
||||
if(LE_SUCCESS(err)) {
|
||||
if(isEmpty()) {
|
||||
//err = LE_MISSING_FONT_TABLE_ERROR;
|
||||
clear(); // it's just empty. Not an error.
|
||||
} else if(offset >= fParent->fLength) {
|
||||
LE_DEBUG_TR3("offset out of range: (%p) +%d", NULL, offset);
|
||||
err = LE_INDEX_OUT_OF_BOUNDS_ERROR;
|
||||
clear();
|
||||
} else {
|
||||
if(fLength == LE_UINTPTR_MAX &&
|
||||
fParent->fLength != LE_UINTPTR_MAX) {
|
||||
fLength = (fParent->fLength) - offset; // decrement length as base address is incremented
|
||||
}
|
||||
if(fLength != LE_UINTPTR_MAX) { // if we have bounds:
|
||||
if(offset+fLength > fParent->fLength) {
|
||||
LE_DEBUG_TR3("offset+fLength out of range: (%p) +%d", NULL, offset+fLength);
|
||||
err = LE_INDEX_OUT_OF_BOUNDS_ERROR; // exceeded
|
||||
clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clear();
|
||||
}
|
||||
LE_TRACE_TR("INFO: new subset")
|
||||
}
|
||||
|
||||
const void* getAlias() const { return (const void*)fStart; }
|
||||
const void* getAliasRAW() const { LE_DEBUG_TR("getAliasRAW()"); return (const void*)fStart; }
|
||||
le_bool isEmpty() const { return fStart==NULL || fLength==0; }
|
||||
le_bool isValid() const { return !isEmpty(); }
|
||||
le_bool hasBounds() const { return fLength!=LE_UINTPTR_MAX; }
|
||||
void clear() { fLength=0; fStart=NULL; }
|
||||
size_t getLength() const { return fLength; }
|
||||
const LEFontInstance* getFont() const { return fFont; }
|
||||
LETag getTag() const { return fTag; }
|
||||
const LETableReference* getParent() const { return fParent; }
|
||||
|
||||
void addOffset(size_t offset, LEErrorCode &success) {
|
||||
if(hasBounds()) {
|
||||
if(offset > fLength) {
|
||||
LE_DEBUG_TR("addOffset off end");
|
||||
success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
|
||||
return;
|
||||
} else {
|
||||
fLength -= offset;
|
||||
}
|
||||
}
|
||||
fStart += offset;
|
||||
}
|
||||
|
||||
size_t ptrToOffset(const void *atPtr, LEErrorCode &success) const {
|
||||
if(atPtr==NULL) return 0;
|
||||
if(LE_FAILURE(success)) return LE_UINTPTR_MAX;
|
||||
if((atPtr < fStart) ||
|
||||
(hasBounds() && (atPtr > fStart+fLength))) {
|
||||
LE_DEBUG_TR3("ptrToOffset args out of range: %p", atPtr, 0);
|
||||
success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
|
||||
return LE_UINTPTR_MAX;
|
||||
}
|
||||
return ((const le_uint8*)atPtr)-fStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamp down the length, for range checking.
|
||||
*/
|
||||
size_t contractLength(size_t newLength) {
|
||||
if(fLength!=LE_UINTPTR_MAX&&newLength>0&&newLength<=fLength) {
|
||||
fLength = newLength;
|
||||
}
|
||||
return fLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an error if offset+length off end
|
||||
*/
|
||||
public:
|
||||
size_t verifyLength(size_t offset, size_t length, LEErrorCode &success) {
|
||||
if(isValid()&&
|
||||
LE_SUCCESS(success) &&
|
||||
fLength!=LE_UINTPTR_MAX && length!=LE_UINTPTR_MAX && offset!=LE_UINTPTR_MAX &&
|
||||
(offset+length)>fLength) {
|
||||
LE_DEBUG_TR3("verifyLength failed (%p) %d",NULL, offset+length);
|
||||
success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
|
||||
#if LE_ASSERT_BAD_FONT
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
return fLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change parent link to another
|
||||
*/
|
||||
LETableReference &reparent(const LETableReference &base) {
|
||||
fParent = &base;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove parent link. Factory functions should do this.
|
||||
*/
|
||||
void orphan(void) {
|
||||
fParent=NULL;
|
||||
}
|
||||
|
||||
protected:
|
||||
const LEFontInstance* fFont;
|
||||
LETag fTag;
|
||||
const LETableReference *fParent;
|
||||
const le_uint8 *fStart; // keep as 8 bit internally, for pointer math
|
||||
size_t fLength;
|
||||
|
||||
void loadTable(LEErrorCode &success) {
|
||||
if(LE_SUCCESS(success)) {
|
||||
fStart = (const le_uint8*)(fFont->getFontTable(fTag, fLength)); // note - a null table is not an error.
|
||||
}
|
||||
}
|
||||
|
||||
void setRaw(const void *data, size_t length = LE_UINTPTR_MAX) {
|
||||
fFont = NULL;
|
||||
fTag = kQuestionmarkTableTag;
|
||||
fParent = NULL;
|
||||
fStart = (const le_uint8*)data;
|
||||
fLength = length;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
class LETableVarSizer {
|
||||
public:
|
||||
inline static size_t getSize();
|
||||
};
|
||||
|
||||
// base definition- could override for adjustments
|
||||
template<class T> inline
|
||||
size_t LETableVarSizer<T>::getSize() {
|
||||
return sizeof(T);
|
||||
}
|
||||
|
||||
/**
|
||||
* \def LE_VAR_ARRAY
|
||||
* @param x Type (T)
|
||||
* @param y some member that is of length ANY_NUMBER
|
||||
* Call this after defining a class, for example:
|
||||
* LE_VAR_ARRAY(FeatureListTable,featureRecordArray)
|
||||
* this is roughly equivalent to:
|
||||
* template<> inline size_t LETableVarSizer<FeatureListTable>::getSize() { return sizeof(FeatureListTable) - (sizeof(le_uint16)*ANY_NUMBER); }
|
||||
* it's a specialization that informs the LETableReference subclasses to NOT include the variable array in the size.
|
||||
* dereferencing NULL is valid here because we never actually dereference it, just inside sizeof.
|
||||
*/
|
||||
#define LE_VAR_ARRAY(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return sizeof(x) - (sizeof(((const x*)0)->y)); }
|
||||
/**
|
||||
* \def LE_CORRECT_SIZE
|
||||
* @param x type (T)
|
||||
* @param y fixed size for T
|
||||
*/
|
||||
#define LE_CORRECT_SIZE(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return y; }
|
||||
|
||||
/**
|
||||
* Open a new entry based on an existing table
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def LE_UNBOUNDED_ARRAY
|
||||
* define an array with no *known* bound. Will trim to available size.
|
||||
* @internal
|
||||
*/
|
||||
#define LE_UNBOUNDED_ARRAY LE_UINT32_MAX
|
||||
|
||||
template<class T>
|
||||
class LEReferenceToArrayOf : public LETableReference {
|
||||
public:
|
||||
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, size_t offset, le_uint32 count)
|
||||
: LETableReference(parent, offset, LE_UINTPTR_MAX, success), fCount(count) {
|
||||
LE_TRACE_TR("INFO: new RTAO by offset")
|
||||
if(LE_SUCCESS(success)) {
|
||||
if(count == LE_UNBOUNDED_ARRAY) { // not a known length
|
||||
count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
|
||||
}
|
||||
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success);
|
||||
}
|
||||
if(LE_FAILURE(success)) {
|
||||
fCount=0;
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, le_uint32 count)
|
||||
: LETableReference(parent, parent.ptrToOffset(array, success), LE_UINTPTR_MAX, success), fCount(count) {
|
||||
LE_TRACE_TR("INFO: new RTAO")
|
||||
if(LE_SUCCESS(success)) {
|
||||
if(count == LE_UNBOUNDED_ARRAY) { // not a known length
|
||||
count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
|
||||
}
|
||||
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success);
|
||||
}
|
||||
if(LE_FAILURE(success)) clear();
|
||||
}
|
||||
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, size_t offset, le_uint32 count)
|
||||
: LETableReference(parent, parent.ptrToOffset(array, success)+offset, LE_UINTPTR_MAX, success), fCount(count) {
|
||||
LE_TRACE_TR("INFO: new RTAO")
|
||||
if(LE_SUCCESS(success)) {
|
||||
if(count == LE_UNBOUNDED_ARRAY) { // not a known length
|
||||
count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
|
||||
}
|
||||
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success);
|
||||
}
|
||||
if(LE_FAILURE(success)) clear();
|
||||
}
|
||||
|
||||
LEReferenceToArrayOf() :LETableReference(), fCount(0) {}
|
||||
|
||||
le_uint32 getCount() const { return fCount; }
|
||||
|
||||
using LETableReference::getAlias;
|
||||
|
||||
const T *getAlias(le_uint32 i, LEErrorCode &success) const {
|
||||
return ((const T*)(((const char*)getAlias())+getOffsetFor(i, success)));
|
||||
}
|
||||
|
||||
const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; }
|
||||
|
||||
const T& getObject(le_uint32 i, LEErrorCode &success) const {
|
||||
return *getAlias(i,success);
|
||||
}
|
||||
|
||||
const T& operator()(le_uint32 i, LEErrorCode &success) const {
|
||||
return *getAlias(i,success);
|
||||
}
|
||||
|
||||
size_t getOffsetFor(le_uint32 i, LEErrorCode &success) const {
|
||||
if(LE_SUCCESS(success)&&i<getCount()) {
|
||||
return LETableVarSizer<T>::getSize()*i;
|
||||
} else {
|
||||
success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LEReferenceToArrayOf<T> &reparent(const LETableReference &base) {
|
||||
fParent = &base;
|
||||
return *this;
|
||||
}
|
||||
|
||||
LEReferenceToArrayOf(const LETableReference& parent, LEErrorCode & success) : LETableReference(parent,0, LE_UINTPTR_MAX, success), fCount(0) {
|
||||
LE_TRACE_TR("INFO: null RTAO")
|
||||
}
|
||||
|
||||
private:
|
||||
le_uint32 fCount;
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
class LEReferenceTo : public LETableReference {
|
||||
public:
|
||||
/**
|
||||
* open a sub reference.
|
||||
* @param parent parent reference
|
||||
* @param success error status
|
||||
* @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.
|
||||
*/
|
||||
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr)
|
||||
: LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) {
|
||||
verifyLength(0, LETableVarSizer<T>::getSize(), success);
|
||||
if(LE_FAILURE(success)) clear();
|
||||
}
|
||||
/**
|
||||
* ptr plus offset
|
||||
*/
|
||||
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr, size_t offset)
|
||||
: LETableReference(parent, parent.ptrToOffset(atPtr, success)+offset, LE_UINTPTR_MAX, success) {
|
||||
verifyLength(0, LETableVarSizer<T>::getSize(), success);
|
||||
if(LE_FAILURE(success)) clear();
|
||||
}
|
||||
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, size_t offset)
|
||||
: LETableReference(parent, offset, LE_UINTPTR_MAX, success) {
|
||||
verifyLength(0, LETableVarSizer<T>::getSize(), success);
|
||||
if(LE_FAILURE(success)) clear();
|
||||
}
|
||||
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success)
|
||||
: LETableReference(parent, 0, LE_UINTPTR_MAX, success) {
|
||||
verifyLength(0, LETableVarSizer<T>::getSize(), success);
|
||||
if(LE_FAILURE(success)) clear();
|
||||
}
|
||||
inline LEReferenceTo(const LEFontInstance *font, LETag tableTag, LEErrorCode &success)
|
||||
: LETableReference(font, tableTag, success) {
|
||||
verifyLength(0, LETableVarSizer<T>::getSize(), success);
|
||||
if(LE_FAILURE(success)) clear();
|
||||
}
|
||||
inline LEReferenceTo(const le_uint8 *data, size_t length = LE_UINTPTR_MAX) : LETableReference(data, length) {}
|
||||
inline LEReferenceTo(const T *data, size_t length = LE_UINTPTR_MAX) : LETableReference((const le_uint8*)data, length) {}
|
||||
inline LEReferenceTo() : LETableReference(NULL) {}
|
||||
|
||||
inline LEReferenceTo<T>& operator=(const T* other) {
|
||||
setRaw(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LEReferenceTo<T> &reparent(const LETableReference &base) {
|
||||
fParent = &base;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* roll forward by one <T> size.
|
||||
* same as addOffset(LETableVarSizer<T>::getSize(),success)
|
||||
*/
|
||||
void addObject(LEErrorCode &success) {
|
||||
addOffset(LETableVarSizer<T>::getSize(), success);
|
||||
}
|
||||
void addObject(size_t count, LEErrorCode &success) {
|
||||
addOffset(LETableVarSizer<T>::getSize()*count, success);
|
||||
}
|
||||
|
||||
const T *operator->() const { return getAlias(); }
|
||||
const T *getAlias() const { return (const T*)fStart; }
|
||||
const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; }
|
||||
};
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user