Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/common/LETableReference.h
38825 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation. Oracle designates this6* particular file as subject to the "Classpath" exception as provided7* by Oracle in the LICENSE file that accompanied this code.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*/2324/*25* -*- c++ -*-26*27* (C) Copyright IBM Corp. and others 2013 - All Rights Reserved28*29* Range checking30*31*/3233#ifndef __LETABLEREFERENCE_H34#define __LETABLEREFERENCE_H3536#include "LETypes.h"37#include "LEFontInstance.h"3839/**40* \def LE_ENABLE_RAW41* If this is 1, enables old non-safe raw access42*/43#ifndef LE_ENABLE_RAW44#define LE_ENABLE_RAW 045#endif4647#define kQuestionmarkTableTag 0x3F3F3F3FUL /* ???? */48#define kStaticTableTag 0x30303030UL /* 0000 */49#define kTildeTableTag 0x7e7e7e7eUL /* ~~~~ */50#ifdef __cplusplus5152// internal - interface for range checking53U_NAMESPACE_BEGIN5455#if LE_ASSERT_BAD_FONT5657#ifndef LE_TRACE_TR58#define LE_TRACE_TR 059#endif6061class LETableReference; // fwd62/**63* defined in OpenTypeUtilities.cpp64* @internal65*/66U_CAPI void U_EXPORT2 _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len);6768#define LE_DEBUG_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);69#define LE_DEBUG_TR3(x,y,z) _debug_LETableReference(__FILE__, __LINE__, x, this, (const void*)y, (size_t)z);70#if LE_TRACE_TR71#define _TRTRACE(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);72#else73#define _TRTRACE(x)74#endif7576#else77#define LE_DEBUG_TR(x)78#define LE_DEBUG_TR3(x,y,z)79#define _TRTRACE(x)80#endif8182/**83* @internal84*/85class LETableReference {86public:8788/**89* Dummy enum asserting that a value is actually static data90* and does not need to be range checked91*/92enum EStaticData { kStaticData = 0 };9394/**95* @internal96* Construct from a specific tag97*/98LETableReference(const LEFontInstance* font, LETag tableTag, LEErrorCode &success) :99fFont(font), fTag(tableTag), fParent(NULL), fStart(NULL),fLength(LE_UINTPTR_MAX) {100loadTable(success);101_TRTRACE("INFO: new table load")102}103104LETableReference(const LETableReference &parent, LEErrorCode &success) : fFont(parent.fFont), fTag(parent.fTag), fParent(&parent), fStart(parent.fStart), fLength(parent.fLength) {105if(LE_FAILURE(success)) {106clear();107}108_TRTRACE("INFO: new clone")109}110111#if LE_ENABLE_RAW112/**113* Construct without a parent LETR.114*/115LETableReference(const le_uint8* data, size_t length = LE_UINTPTR_MAX) :116fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) {117_TRTRACE("INFO: new raw")118}119#endif120121/**122* Construct without a parent LETR.123*/124LETableReference(EStaticData /* NOTUSED */, const le_uint8* data, size_t length) :125fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) {126_TRTRACE("INFO: new EStaticData")127}128129LETableReference() :130fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(NULL), fLength(0) {131_TRTRACE("INFO: new empty")132}133134~LETableReference() {135fTag= (LETag)kTildeTableTag;136_TRTRACE("INFO: new dtor")137}138139/**140* @internal141* @param length if LE_UINTPTR_MAX means "whole table"142* subset143*/144LETableReference(const LETableReference &parent, size_t offset, size_t length,145LEErrorCode &err) :146fFont(parent.fFont), fTag(parent.fTag), fParent(&parent),147fStart((parent.fStart)+offset), fLength(length) {148if(LE_SUCCESS(err)) {149if(isEmpty()) {150//err = LE_MISSING_FONT_TABLE_ERROR;151clear(); // it's just empty. Not an error.152} else if(offset >= fParent->fLength || (offset & 0x01)) {153LE_DEBUG_TR3("offset out of range or odd alignment: (%p) +%d", NULL, offset);154err = LE_INDEX_OUT_OF_BOUNDS_ERROR;155clear();156} else {157if(fLength == LE_UINTPTR_MAX &&158fParent->fLength != LE_UINTPTR_MAX) {159fLength = (fParent->fLength) - offset; // decrement length as base address is incremented160}161if(fLength != LE_UINTPTR_MAX) { // if we have bounds:162if((offset+fLength < offset) || (offset+fLength > fParent->fLength)) {163LE_DEBUG_TR3("offset+fLength out of range: (%p) +%d", NULL, offset+fLength);164err = LE_INDEX_OUT_OF_BOUNDS_ERROR; // exceeded165clear();166}167}168}169} else {170clear();171}172_TRTRACE("INFO: new subset")173}174175const void* getAlias() const { return (const void*)fStart; }176#ifndef LE_ENABLE_RAW177const void* getAliasRAW() const { LE_DEBUG_TR("getAliasRAW()"); return (const void*)fStart; }178#endif179le_bool isEmpty() const { return fStart==NULL || fLength==0; }180le_bool isValid() const { return !isEmpty(); }181le_bool hasBounds() const { return fLength!=LE_UINTPTR_MAX; }182void clear() { fLength=0; fStart=NULL; }183size_t getLength() const { return fLength; }184const LEFontInstance* getFont() const { return fFont; }185LETag getTag() const { return fTag; }186const LETableReference* getParent() const { return fParent; }187188void addOffset(size_t offset, LEErrorCode &success) {189if(hasBounds()) {190if(offset >= fLength) {191LE_DEBUG_TR("addOffset off end");192success = LE_INDEX_OUT_OF_BOUNDS_ERROR;193return;194} else {195fLength -= offset;196}197}198fStart += offset;199}200201size_t ptrToOffset(const void *atPtr, LEErrorCode &success) const {202if(atPtr==NULL) return 0;203if(LE_FAILURE(success)) return LE_UINTPTR_MAX;204if((atPtr < fStart) ||205(hasBounds() && (atPtr >= fStart+fLength))) {206LE_DEBUG_TR3("ptrToOffset args out of range: %p", atPtr, 0);207success = LE_INDEX_OUT_OF_BOUNDS_ERROR;208return LE_UINTPTR_MAX;209}210return ((const le_uint8*)atPtr)-fStart;211}212213/**214* Clamp down the length, for range checking.215*/216size_t contractLength(size_t newLength) {217if(fLength!=LE_UINTPTR_MAX&&newLength>0&&newLength<=fLength) {218fLength = newLength;219}220return fLength;221}222223/**224* Throw an error if offset+length off end225*/226public:227size_t verifyLength(size_t offset, size_t length, LEErrorCode &success) {228if(isValid()&&229LE_SUCCESS(success) &&230fLength!=LE_UINTPTR_MAX && length!=LE_UINTPTR_MAX && offset!=LE_UINTPTR_MAX &&231(offset+length)>fLength) {232LE_DEBUG_TR3("verifyLength failed (%p) %d",NULL, offset+length);233success = LE_INDEX_OUT_OF_BOUNDS_ERROR;234#if LE_ASSERT_BAD_FONT235fprintf(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);236#endif237}238return fLength;239}240241/**242* Throw an error if size*count overflows243*/244size_t verifyLength(size_t offset, size_t size, le_uint32 count, LEErrorCode &success) {245if(count!=0 && size>LE_UINT32_MAX/count) {246LE_DEBUG_TR3("verifyLength failed size=%u, count=%u", size, count);247success = LE_INDEX_OUT_OF_BOUNDS_ERROR;248return 0;249}250return verifyLength(offset, size*count, success);251}252253/**254* Change parent link to another255*/256LETableReference &reparent(const LETableReference &base) {257fParent = &base;258return *this;259}260261/**262* remove parent link. Factory functions should do this.263*/264void orphan(void) {265fParent=NULL;266}267268protected:269const LEFontInstance* fFont;270LETag fTag;271const LETableReference *fParent;272const le_uint8 *fStart; // keep as 8 bit internally, for pointer math273size_t fLength;274275void loadTable(LEErrorCode &success) {276if(LE_SUCCESS(success)) {277fStart = (const le_uint8*)(fFont->getFontTable(fTag, fLength)); // note - a null table is not an error.278}279}280281void setRaw(const void *data, size_t length = LE_UINTPTR_MAX) {282fFont = NULL;283fTag = (LETag)kQuestionmarkTableTag;284fParent = NULL;285fStart = (const le_uint8*)data;286fLength = length;287}288289/**290* set this object pointing to static data291*/292void setTo(EStaticData /*notused*/, const void *data, size_t length) {293fFont = NULL;294fTag = (LETag)kStaticTableTag;295fParent = NULL;296fStart = (const le_uint8*)data;297fLength = length;298}299};300301302template<class T>303class LETableVarSizer {304public:305inline static size_t getSize();306};307308// base definition- could override for adjustments309template<class T> inline310size_t LETableVarSizer<T>::getSize() {311return sizeof(T);312}313314/**315* \def LE_VAR_ARRAY316* @param x Type (T)317* @param y some member that is of length ANY_NUMBER318* Call this after defining a class, for example:319* LE_VAR_ARRAY(FeatureListTable,featureRecordArray)320* this is roughly equivalent to:321* template<> inline size_t LETableVarSizer<FeatureListTable>::getSize() { return sizeof(FeatureListTable) - (sizeof(le_uint16)*ANY_NUMBER); }322* it's a specialization that informs the LETableReference subclasses to NOT include the variable array in the size.323* dereferencing NULL is valid here because we never actually dereference it, just inside sizeof.324*/325#define LE_VAR_ARRAY(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return sizeof(x) - (sizeof(((const x*)0)->y)); }326/**327* \def LE_CORRECT_SIZE328* @param x type (T)329* @param y fixed size for T330*/331#define LE_CORRECT_SIZE(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return y; }332333/**334* Open a new entry based on an existing table335*/336337template<class T>338class LEReferenceTo : public LETableReference {339public:340/**341* open a sub reference.342* @param parent parent reference343* @param success error status344* @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.345*/346inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr)347: LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) {348verifyLength(0, LETableVarSizer<T>::getSize(), success);349if(LE_FAILURE(success)) clear();350}351/**352* ptr plus offset353*/354inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr, size_t offset)355: LETableReference(parent, parent.ptrToOffset(atPtr, success)+offset, LE_UINTPTR_MAX, success) {356verifyLength(0, LETableVarSizer<T>::getSize(), success);357if(LE_FAILURE(success)) clear();358}359inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, size_t offset)360: LETableReference(parent, offset, LE_UINTPTR_MAX, success) {361verifyLength(0, LETableVarSizer<T>::getSize(), success);362if(LE_FAILURE(success)) clear();363}364inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success)365: LETableReference(parent, 0, LE_UINTPTR_MAX, success) {366verifyLength(0, LETableVarSizer<T>::getSize(), success);367if(LE_FAILURE(success)) clear();368}369inline LEReferenceTo(const LEFontInstance *font, LETag tableTag, LEErrorCode &success)370: LETableReference(font, tableTag, success) {371verifyLength(0, LETableVarSizer<T>::getSize(), success);372if(LE_FAILURE(success)) clear();373}374#if LE_ENABLE_RAW375inline LEReferenceTo(const le_uint8 *data, size_t length = LE_UINTPTR_MAX) : LETableReference(data, length) {}376inline LEReferenceTo(const T *data, size_t length = LE_UINTPTR_MAX) : LETableReference((const le_uint8*)data, length) {}377#endif378inline LEReferenceTo(EStaticData staticData, const le_uint8 *data, size_t length) : LETableReference(staticData, data, length) {}379inline LEReferenceTo(EStaticData staticData, const T *data, size_t length) : LETableReference(staticData, (const le_uint8*)data, length) {}380381inline LEReferenceTo() : LETableReference() {}382383#if LE_ENABLE_RAW384inline LEReferenceTo<T>& operator=(const T* other) {385setRaw(other);386return *this;387}388#endif389390LEReferenceTo<T>& setTo(LETableReference::EStaticData staticData, const T* other, size_t length) {391LETableReference::setTo(staticData, other, length);392return *this;393}394395LEReferenceTo<T> &reparent(const LETableReference &base) {396fParent = &base;397return *this;398}399400/**401* roll forward by one <T> size.402* same as addOffset(LETableVarSizer<T>::getSize(),success)403*/404void addObject(LEErrorCode &success) {405addOffset(LETableVarSizer<T>::getSize(), success);406}407void addObject(size_t count, LEErrorCode &success) {408addOffset(LETableVarSizer<T>::getSize()*count, success);409}410411const T *operator->() const { return getAlias(); }412const T *operator*() const { return getAlias(); }413const T *getAlias() const { return (const T*)fStart; }414#if LE_ENABLE_RAW415const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; }416#endif417418};419420421/**422* \def LE_UNBOUNDED_ARRAY423* define an array with no *known* bound. Will trim to available size.424* @internal425*/426#define LE_UNBOUNDED_ARRAY LE_UINT32_MAX427428template<class T>429class LEReferenceToArrayOf : public LETableReference {430public:431LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, size_t offset, le_uint32 count)432: LETableReference(parent, offset, LE_UINTPTR_MAX, success), fCount(count) {433_TRTRACE("INFO: new RTAO by offset")434if(LE_SUCCESS(success)) {435if(fCount == LE_UNBOUNDED_ARRAY) { // not a known length436fCount = getLength()/LETableVarSizer<T>::getSize(); // fit to max size437}438LETableReference::verifyLength(0, LETableVarSizer<T>::getSize(), fCount, success);439}440if(LE_FAILURE(success)) {441fCount=0;442clear();443}444}445446LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, le_uint32 count)447: LETableReference(parent, parent.ptrToOffset(array, success), LE_UINTPTR_MAX, success), fCount(count) {448_TRTRACE("INFO: new RTAO")449if(LE_SUCCESS(success)) {450if(fCount == LE_UNBOUNDED_ARRAY) { // not a known length451fCount = getLength()/LETableVarSizer<T>::getSize(); // fit to max size452}453LETableReference::verifyLength(0, LETableVarSizer<T>::getSize(), fCount, success);454}455if(LE_FAILURE(success)) clear();456}457LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, size_t offset, le_uint32 count)458: LETableReference(parent, parent.ptrToOffset(array, success)+offset, LE_UINTPTR_MAX, success), fCount(count) {459_TRTRACE("INFO: new RTAO")460if(LE_SUCCESS(success)) {461if(fCount == LE_UNBOUNDED_ARRAY) { // not a known length462fCount = getLength()/LETableVarSizer<T>::getSize(); // fit to max size463}464LETableReference::verifyLength(0, LETableVarSizer<T>::getSize(), fCount, success);465}466if(LE_FAILURE(success)) clear();467}468469LEReferenceToArrayOf() :LETableReference(), fCount(0) {}470471le_uint32 getCount() const { return fCount; }472473const T *getAlias() const { return (const T*)fStart; }474475const T *getAlias(le_uint32 i, LEErrorCode &success) const {476return ((const T*)(((const char*)getAlias())+getOffsetFor(i, success)));477}478479#ifndef LE_ENABLE_RAW480const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; }481#endif482483const T& getObject(le_uint32 i, LEErrorCode &success) const {484const T *ret = getAlias(i, success);485if (LE_FAILURE(success) || ret==NULL) {486return *(new T(0));487} else {488return *ret;489}490}491492/**493* by-value array accessor for integral types.494*/495const T operator[](le_uint32 i) const {496LEErrorCode success = LE_NO_ERROR;497const T *ret = getAlias(i, success);498if(LE_FAILURE(success) || ret==NULL) {499#if LE_ASSERT_BAD_FONT500LE_DEBUG_TR3("Range error, out of bounds? (%p) #%d", NULL, i);501#endif502return T(0); // will not work for all types.503}504return *ret;505}506507const LEReferenceTo<T> getReference(le_uint32 i, LEErrorCode &success) const {508if(LE_FAILURE(success)) return LEReferenceTo<T>();509return LEReferenceTo<T>(*this, success, getAlias(i,success));510}511512const T& operator()(le_uint32 i, LEErrorCode &success) const {513return *getAlias(i,success);514}515516size_t getOffsetFor(le_uint32 i, LEErrorCode &success) const {517if(LE_SUCCESS(success)&&i<getCount()) {518return LETableVarSizer<T>::getSize()*i;519} else {520LE_DEBUG_TR3("getOffsetFor failed (%p) index=%d",NULL, i);521success = LE_INDEX_OUT_OF_BOUNDS_ERROR;522}523return 0;524}525526LEReferenceToArrayOf<T> &reparent(const LETableReference &base) {527fParent = &base;528return *this;529}530531LEReferenceToArrayOf(const LETableReference& parent, LEErrorCode & success) : LETableReference(parent,0, LE_UINTPTR_MAX, success), fCount(0) {532_TRTRACE("INFO: null RTAO")533}534535private:536le_uint32 fCount;537};538539540541542#ifdef _TRTRACE543#undef _TRTRACE544#endif545546U_NAMESPACE_END547548#endif549550#endif551552553