1*0e209d39SAndroid Build Coastguard Worker // © 2016 and later: Unicode, Inc. and others. 2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html 3*0e209d39SAndroid Build Coastguard Worker /* 4*0e209d39SAndroid Build Coastguard Worker ******************************************************************************* 5*0e209d39SAndroid Build Coastguard Worker * Copyright (C) 2015-2016, International Business Machines 6*0e209d39SAndroid Build Coastguard Worker * Corporation and others. All Rights Reserved. 7*0e209d39SAndroid Build Coastguard Worker ******************************************************************************* 8*0e209d39SAndroid Build Coastguard Worker * resource.h 9*0e209d39SAndroid Build Coastguard Worker * 10*0e209d39SAndroid Build Coastguard Worker * created on: 2015nov04 11*0e209d39SAndroid Build Coastguard Worker * created by: Markus W. Scherer 12*0e209d39SAndroid Build Coastguard Worker */ 13*0e209d39SAndroid Build Coastguard Worker 14*0e209d39SAndroid Build Coastguard Worker #ifndef __URESOURCE_H__ 15*0e209d39SAndroid Build Coastguard Worker #define __URESOURCE_H__ 16*0e209d39SAndroid Build Coastguard Worker 17*0e209d39SAndroid Build Coastguard Worker /** 18*0e209d39SAndroid Build Coastguard Worker * \file 19*0e209d39SAndroid Build Coastguard Worker * \brief ICU resource bundle key and value types. 20*0e209d39SAndroid Build Coastguard Worker */ 21*0e209d39SAndroid Build Coastguard Worker 22*0e209d39SAndroid Build Coastguard Worker // Note: Ported from ICU4J class UResource and its nested classes, 23*0e209d39SAndroid Build Coastguard Worker // but the C++ classes are separate, not nested. 24*0e209d39SAndroid Build Coastguard Worker 25*0e209d39SAndroid Build Coastguard Worker // We use the Resource prefix for C++ classes, as usual. 26*0e209d39SAndroid Build Coastguard Worker // The UResource prefix would be used for C types. 27*0e209d39SAndroid Build Coastguard Worker 28*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h" 29*0e209d39SAndroid Build Coastguard Worker #include "unicode/unistr.h" 30*0e209d39SAndroid Build Coastguard Worker #include "unicode/ures.h" 31*0e209d39SAndroid Build Coastguard Worker #include "restrace.h" 32*0e209d39SAndroid Build Coastguard Worker 33*0e209d39SAndroid Build Coastguard Worker struct ResourceData; 34*0e209d39SAndroid Build Coastguard Worker 35*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN 36*0e209d39SAndroid Build Coastguard Worker 37*0e209d39SAndroid Build Coastguard Worker class ResourceValue; 38*0e209d39SAndroid Build Coastguard Worker 39*0e209d39SAndroid Build Coastguard Worker // Note: In C++, we use const char * pointers for keys, 40*0e209d39SAndroid Build Coastguard Worker // rather than an abstraction like Java UResource.Key. 41*0e209d39SAndroid Build Coastguard Worker 42*0e209d39SAndroid Build Coastguard Worker /** 43*0e209d39SAndroid Build Coastguard Worker * Interface for iterating over a resource bundle array resource. 44*0e209d39SAndroid Build Coastguard Worker */ 45*0e209d39SAndroid Build Coastguard Worker class U_COMMON_API ResourceArray { 46*0e209d39SAndroid Build Coastguard Worker public: 47*0e209d39SAndroid Build Coastguard Worker /** Constructs an empty array object. */ ResourceArray()48*0e209d39SAndroid Build Coastguard Worker ResourceArray() : items16(nullptr), items32(nullptr), length(0) {} 49*0e209d39SAndroid Build Coastguard Worker 50*0e209d39SAndroid Build Coastguard Worker /** Only for implementation use. @internal */ ResourceArray(const uint16_t * i16,const uint32_t * i32,int32_t len,const ResourceTracer & traceInfo)51*0e209d39SAndroid Build Coastguard Worker ResourceArray(const uint16_t *i16, const uint32_t *i32, int32_t len, 52*0e209d39SAndroid Build Coastguard Worker const ResourceTracer& traceInfo) : 53*0e209d39SAndroid Build Coastguard Worker items16(i16), items32(i32), length(len), 54*0e209d39SAndroid Build Coastguard Worker fTraceInfo(traceInfo) {} 55*0e209d39SAndroid Build Coastguard Worker 56*0e209d39SAndroid Build Coastguard Worker /** 57*0e209d39SAndroid Build Coastguard Worker * @return The number of items in the array resource. 58*0e209d39SAndroid Build Coastguard Worker */ getSize()59*0e209d39SAndroid Build Coastguard Worker int32_t getSize() const { return length; } 60*0e209d39SAndroid Build Coastguard Worker /** 61*0e209d39SAndroid Build Coastguard Worker * @param i Array item index. 62*0e209d39SAndroid Build Coastguard Worker * @param value Output-only, receives the value of the i'th item. 63*0e209d39SAndroid Build Coastguard Worker * @return true if i is non-negative and less than getSize(). 64*0e209d39SAndroid Build Coastguard Worker */ 65*0e209d39SAndroid Build Coastguard Worker UBool getValue(int32_t i, ResourceValue &value) const; 66*0e209d39SAndroid Build Coastguard Worker 67*0e209d39SAndroid Build Coastguard Worker /** Only for implementation use. @internal */ 68*0e209d39SAndroid Build Coastguard Worker uint32_t internalGetResource(const ResourceData *pResData, int32_t i) const; 69*0e209d39SAndroid Build Coastguard Worker 70*0e209d39SAndroid Build Coastguard Worker private: 71*0e209d39SAndroid Build Coastguard Worker const uint16_t *items16; 72*0e209d39SAndroid Build Coastguard Worker const uint32_t *items32; 73*0e209d39SAndroid Build Coastguard Worker int32_t length; 74*0e209d39SAndroid Build Coastguard Worker ResourceTracer fTraceInfo; 75*0e209d39SAndroid Build Coastguard Worker }; 76*0e209d39SAndroid Build Coastguard Worker 77*0e209d39SAndroid Build Coastguard Worker /** 78*0e209d39SAndroid Build Coastguard Worker * Interface for iterating over a resource bundle table resource. 79*0e209d39SAndroid Build Coastguard Worker */ 80*0e209d39SAndroid Build Coastguard Worker class U_COMMON_API ResourceTable { 81*0e209d39SAndroid Build Coastguard Worker public: 82*0e209d39SAndroid Build Coastguard Worker /** Constructs an empty table object. */ ResourceTable()83*0e209d39SAndroid Build Coastguard Worker ResourceTable() : keys16(nullptr), keys32(nullptr), items16(nullptr), items32(nullptr), length(0) {} 84*0e209d39SAndroid Build Coastguard Worker 85*0e209d39SAndroid Build Coastguard Worker /** Only for implementation use. @internal */ ResourceTable(const uint16_t * k16,const int32_t * k32,const uint16_t * i16,const uint32_t * i32,int32_t len,const ResourceTracer & traceInfo)86*0e209d39SAndroid Build Coastguard Worker ResourceTable(const uint16_t *k16, const int32_t *k32, 87*0e209d39SAndroid Build Coastguard Worker const uint16_t *i16, const uint32_t *i32, int32_t len, 88*0e209d39SAndroid Build Coastguard Worker const ResourceTracer& traceInfo) : 89*0e209d39SAndroid Build Coastguard Worker keys16(k16), keys32(k32), items16(i16), items32(i32), length(len), 90*0e209d39SAndroid Build Coastguard Worker fTraceInfo(traceInfo) {} 91*0e209d39SAndroid Build Coastguard Worker 92*0e209d39SAndroid Build Coastguard Worker /** 93*0e209d39SAndroid Build Coastguard Worker * @return The number of items in the array resource. 94*0e209d39SAndroid Build Coastguard Worker */ getSize()95*0e209d39SAndroid Build Coastguard Worker int32_t getSize() const { return length; } 96*0e209d39SAndroid Build Coastguard Worker /** 97*0e209d39SAndroid Build Coastguard Worker * @param i Table item index. 98*0e209d39SAndroid Build Coastguard Worker * @param key Output-only, receives the key of the i'th item. 99*0e209d39SAndroid Build Coastguard Worker * @param value Output-only, receives the value of the i'th item. 100*0e209d39SAndroid Build Coastguard Worker * @return true if i is non-negative and less than getSize(). 101*0e209d39SAndroid Build Coastguard Worker */ 102*0e209d39SAndroid Build Coastguard Worker UBool getKeyAndValue(int32_t i, const char *&key, ResourceValue &value) const; 103*0e209d39SAndroid Build Coastguard Worker 104*0e209d39SAndroid Build Coastguard Worker /** 105*0e209d39SAndroid Build Coastguard Worker * @param key Key string to find in the table. 106*0e209d39SAndroid Build Coastguard Worker * @param value Output-only, receives the value of the item with that key. 107*0e209d39SAndroid Build Coastguard Worker * @return true if the table contains the key. 108*0e209d39SAndroid Build Coastguard Worker */ 109*0e209d39SAndroid Build Coastguard Worker UBool findValue(const char *key, ResourceValue &value) const; 110*0e209d39SAndroid Build Coastguard Worker 111*0e209d39SAndroid Build Coastguard Worker private: 112*0e209d39SAndroid Build Coastguard Worker const uint16_t *keys16; 113*0e209d39SAndroid Build Coastguard Worker const int32_t *keys32; 114*0e209d39SAndroid Build Coastguard Worker const uint16_t *items16; 115*0e209d39SAndroid Build Coastguard Worker const uint32_t *items32; 116*0e209d39SAndroid Build Coastguard Worker int32_t length; 117*0e209d39SAndroid Build Coastguard Worker ResourceTracer fTraceInfo; 118*0e209d39SAndroid Build Coastguard Worker }; 119*0e209d39SAndroid Build Coastguard Worker 120*0e209d39SAndroid Build Coastguard Worker /** 121*0e209d39SAndroid Build Coastguard Worker * Represents a resource bundle item's value. 122*0e209d39SAndroid Build Coastguard Worker * Avoids object creations as much as possible. 123*0e209d39SAndroid Build Coastguard Worker * Mutable, not thread-safe. 124*0e209d39SAndroid Build Coastguard Worker */ 125*0e209d39SAndroid Build Coastguard Worker class U_COMMON_API ResourceValue : public UObject { 126*0e209d39SAndroid Build Coastguard Worker public: 127*0e209d39SAndroid Build Coastguard Worker virtual ~ResourceValue(); 128*0e209d39SAndroid Build Coastguard Worker 129*0e209d39SAndroid Build Coastguard Worker /** 130*0e209d39SAndroid Build Coastguard Worker * @return ICU resource type, for example, URES_STRING 131*0e209d39SAndroid Build Coastguard Worker */ 132*0e209d39SAndroid Build Coastguard Worker virtual UResType getType() const = 0; 133*0e209d39SAndroid Build Coastguard Worker 134*0e209d39SAndroid Build Coastguard Worker /** 135*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is not a string resource. 136*0e209d39SAndroid Build Coastguard Worker * 137*0e209d39SAndroid Build Coastguard Worker * @see ures_getString() 138*0e209d39SAndroid Build Coastguard Worker */ 139*0e209d39SAndroid Build Coastguard Worker virtual const char16_t *getString(int32_t &length, UErrorCode &errorCode) const = 0; 140*0e209d39SAndroid Build Coastguard Worker getUnicodeString(UErrorCode & errorCode)141*0e209d39SAndroid Build Coastguard Worker inline UnicodeString getUnicodeString(UErrorCode &errorCode) const { 142*0e209d39SAndroid Build Coastguard Worker int32_t len = 0; 143*0e209d39SAndroid Build Coastguard Worker const char16_t *r = getString(len, errorCode); 144*0e209d39SAndroid Build Coastguard Worker return UnicodeString(true, r, len); 145*0e209d39SAndroid Build Coastguard Worker } 146*0e209d39SAndroid Build Coastguard Worker 147*0e209d39SAndroid Build Coastguard Worker /** 148*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is not an alias resource. 149*0e209d39SAndroid Build Coastguard Worker */ 150*0e209d39SAndroid Build Coastguard Worker virtual const char16_t *getAliasString(int32_t &length, UErrorCode &errorCode) const = 0; 151*0e209d39SAndroid Build Coastguard Worker getAliasUnicodeString(UErrorCode & errorCode)152*0e209d39SAndroid Build Coastguard Worker inline UnicodeString getAliasUnicodeString(UErrorCode &errorCode) const { 153*0e209d39SAndroid Build Coastguard Worker int32_t len = 0; 154*0e209d39SAndroid Build Coastguard Worker const char16_t *r = getAliasString(len, errorCode); 155*0e209d39SAndroid Build Coastguard Worker return UnicodeString(true, r, len); 156*0e209d39SAndroid Build Coastguard Worker } 157*0e209d39SAndroid Build Coastguard Worker 158*0e209d39SAndroid Build Coastguard Worker /** 159*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is not an integer resource. 160*0e209d39SAndroid Build Coastguard Worker * 161*0e209d39SAndroid Build Coastguard Worker * @see ures_getInt() 162*0e209d39SAndroid Build Coastguard Worker */ 163*0e209d39SAndroid Build Coastguard Worker virtual int32_t getInt(UErrorCode &errorCode) const = 0; 164*0e209d39SAndroid Build Coastguard Worker 165*0e209d39SAndroid Build Coastguard Worker /** 166*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is not an integer resource. 167*0e209d39SAndroid Build Coastguard Worker * 168*0e209d39SAndroid Build Coastguard Worker * @see ures_getUInt() 169*0e209d39SAndroid Build Coastguard Worker */ 170*0e209d39SAndroid Build Coastguard Worker virtual uint32_t getUInt(UErrorCode &errorCode) const = 0; 171*0e209d39SAndroid Build Coastguard Worker 172*0e209d39SAndroid Build Coastguard Worker /** 173*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is not an intvector resource. 174*0e209d39SAndroid Build Coastguard Worker * 175*0e209d39SAndroid Build Coastguard Worker * @see ures_getIntVector() 176*0e209d39SAndroid Build Coastguard Worker */ 177*0e209d39SAndroid Build Coastguard Worker virtual const int32_t *getIntVector(int32_t &length, UErrorCode &errorCode) const = 0; 178*0e209d39SAndroid Build Coastguard Worker 179*0e209d39SAndroid Build Coastguard Worker /** 180*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is not a binary-blob resource. 181*0e209d39SAndroid Build Coastguard Worker * 182*0e209d39SAndroid Build Coastguard Worker * @see ures_getBinary() 183*0e209d39SAndroid Build Coastguard Worker */ 184*0e209d39SAndroid Build Coastguard Worker virtual const uint8_t *getBinary(int32_t &length, UErrorCode &errorCode) const = 0; 185*0e209d39SAndroid Build Coastguard Worker 186*0e209d39SAndroid Build Coastguard Worker /** 187*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is not an array resource 188*0e209d39SAndroid Build Coastguard Worker */ 189*0e209d39SAndroid Build Coastguard Worker virtual ResourceArray getArray(UErrorCode &errorCode) const = 0; 190*0e209d39SAndroid Build Coastguard Worker 191*0e209d39SAndroid Build Coastguard Worker /** 192*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is not a table resource 193*0e209d39SAndroid Build Coastguard Worker */ 194*0e209d39SAndroid Build Coastguard Worker virtual ResourceTable getTable(UErrorCode &errorCode) const = 0; 195*0e209d39SAndroid Build Coastguard Worker 196*0e209d39SAndroid Build Coastguard Worker /** 197*0e209d39SAndroid Build Coastguard Worker * Is this a no-fallback/no-inheritance marker string? 198*0e209d39SAndroid Build Coastguard Worker * Such a marker is used for 199*0e209d39SAndroid Build Coastguard Worker * CLDR no-fallback data values of (three empty-set symbols)=={2205, 2205, 2205} 200*0e209d39SAndroid Build Coastguard Worker * when enumerating tables with fallback from the specific resource bundle to root. 201*0e209d39SAndroid Build Coastguard Worker * 202*0e209d39SAndroid Build Coastguard Worker * @return true if this is a no-inheritance marker string 203*0e209d39SAndroid Build Coastguard Worker */ 204*0e209d39SAndroid Build Coastguard Worker virtual UBool isNoInheritanceMarker() const = 0; 205*0e209d39SAndroid Build Coastguard Worker 206*0e209d39SAndroid Build Coastguard Worker /** 207*0e209d39SAndroid Build Coastguard Worker * Sets the dest strings from the string values in this array resource. 208*0e209d39SAndroid Build Coastguard Worker * 209*0e209d39SAndroid Build Coastguard Worker * @return the number of strings in this array resource. 210*0e209d39SAndroid Build Coastguard Worker * If greater than capacity, then an overflow error is set. 211*0e209d39SAndroid Build Coastguard Worker * 212*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is not an array resource 213*0e209d39SAndroid Build Coastguard Worker * or if any of the array items is not a string 214*0e209d39SAndroid Build Coastguard Worker */ 215*0e209d39SAndroid Build Coastguard Worker virtual int32_t getStringArray(UnicodeString *dest, int32_t capacity, 216*0e209d39SAndroid Build Coastguard Worker UErrorCode &errorCode) const = 0; 217*0e209d39SAndroid Build Coastguard Worker 218*0e209d39SAndroid Build Coastguard Worker /** 219*0e209d39SAndroid Build Coastguard Worker * Same as 220*0e209d39SAndroid Build Coastguard Worker * <pre> 221*0e209d39SAndroid Build Coastguard Worker * if (getType() == URES_STRING) { 222*0e209d39SAndroid Build Coastguard Worker * return new String[] { getString(); } 223*0e209d39SAndroid Build Coastguard Worker * } else { 224*0e209d39SAndroid Build Coastguard Worker * return getStringArray(); 225*0e209d39SAndroid Build Coastguard Worker * } 226*0e209d39SAndroid Build Coastguard Worker * </pre> 227*0e209d39SAndroid Build Coastguard Worker * 228*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is 229*0e209d39SAndroid Build Coastguard Worker * neither a string resource nor an array resource containing strings 230*0e209d39SAndroid Build Coastguard Worker * @see getString() 231*0e209d39SAndroid Build Coastguard Worker * @see getStringArray() 232*0e209d39SAndroid Build Coastguard Worker */ 233*0e209d39SAndroid Build Coastguard Worker virtual int32_t getStringArrayOrStringAsArray(UnicodeString *dest, int32_t capacity, 234*0e209d39SAndroid Build Coastguard Worker UErrorCode &errorCode) const = 0; 235*0e209d39SAndroid Build Coastguard Worker 236*0e209d39SAndroid Build Coastguard Worker /** 237*0e209d39SAndroid Build Coastguard Worker * Same as 238*0e209d39SAndroid Build Coastguard Worker * <pre> 239*0e209d39SAndroid Build Coastguard Worker * if (getType() == URES_STRING) { 240*0e209d39SAndroid Build Coastguard Worker * return getString(); 241*0e209d39SAndroid Build Coastguard Worker * } else { 242*0e209d39SAndroid Build Coastguard Worker * return getStringArray()[0]; 243*0e209d39SAndroid Build Coastguard Worker * } 244*0e209d39SAndroid Build Coastguard Worker * </pre> 245*0e209d39SAndroid Build Coastguard Worker * 246*0e209d39SAndroid Build Coastguard Worker * Sets U_RESOURCE_TYPE_MISMATCH if this is 247*0e209d39SAndroid Build Coastguard Worker * neither a string resource nor an array resource containing strings 248*0e209d39SAndroid Build Coastguard Worker * @see getString() 249*0e209d39SAndroid Build Coastguard Worker * @see getStringArray() 250*0e209d39SAndroid Build Coastguard Worker */ 251*0e209d39SAndroid Build Coastguard Worker virtual UnicodeString getStringOrFirstOfArray(UErrorCode &errorCode) const = 0; 252*0e209d39SAndroid Build Coastguard Worker 253*0e209d39SAndroid Build Coastguard Worker protected: ResourceValue()254*0e209d39SAndroid Build Coastguard Worker ResourceValue() {} 255*0e209d39SAndroid Build Coastguard Worker 256*0e209d39SAndroid Build Coastguard Worker private: 257*0e209d39SAndroid Build Coastguard Worker ResourceValue(const ResourceValue &); // no copy constructor 258*0e209d39SAndroid Build Coastguard Worker ResourceValue &operator=(const ResourceValue &); // no assignment operator 259*0e209d39SAndroid Build Coastguard Worker }; 260*0e209d39SAndroid Build Coastguard Worker 261*0e209d39SAndroid Build Coastguard Worker /** 262*0e209d39SAndroid Build Coastguard Worker * Sink for ICU resource bundle contents. 263*0e209d39SAndroid Build Coastguard Worker */ 264*0e209d39SAndroid Build Coastguard Worker class U_COMMON_API ResourceSink : public UObject { 265*0e209d39SAndroid Build Coastguard Worker public: ResourceSink()266*0e209d39SAndroid Build Coastguard Worker ResourceSink() {} 267*0e209d39SAndroid Build Coastguard Worker virtual ~ResourceSink(); 268*0e209d39SAndroid Build Coastguard Worker 269*0e209d39SAndroid Build Coastguard Worker /** 270*0e209d39SAndroid Build Coastguard Worker * Called once for each bundle (child-parent-...-root). 271*0e209d39SAndroid Build Coastguard Worker * The value is normally an array or table resource, 272*0e209d39SAndroid Build Coastguard Worker * and implementations of this method normally iterate over the 273*0e209d39SAndroid Build Coastguard Worker * tree of resource items stored there. 274*0e209d39SAndroid Build Coastguard Worker * 275*0e209d39SAndroid Build Coastguard Worker * @param key The key string of the enumeration-start resource. 276*0e209d39SAndroid Build Coastguard Worker * Empty if the enumeration starts at the top level of the bundle. 277*0e209d39SAndroid Build Coastguard Worker * @param value Call getArray() or getTable() as appropriate. Then reuse for 278*0e209d39SAndroid Build Coastguard Worker * output values from Array and Table getters. Note: ResourceTable and 279*0e209d39SAndroid Build Coastguard Worker * ResourceArray instances must outlive the ResourceValue instance for 280*0e209d39SAndroid Build Coastguard Worker * ResourceTracer to be happy. 281*0e209d39SAndroid Build Coastguard Worker * @param noFallback true if the bundle has no parent; 282*0e209d39SAndroid Build Coastguard Worker * that is, its top-level table has the nofallback attribute, 283*0e209d39SAndroid Build Coastguard Worker * or it is the root bundle of a locale tree. 284*0e209d39SAndroid Build Coastguard Worker */ 285*0e209d39SAndroid Build Coastguard Worker virtual void put(const char *key, ResourceValue &value, UBool noFallback, 286*0e209d39SAndroid Build Coastguard Worker UErrorCode &errorCode) = 0; 287*0e209d39SAndroid Build Coastguard Worker 288*0e209d39SAndroid Build Coastguard Worker private: 289*0e209d39SAndroid Build Coastguard Worker ResourceSink(const ResourceSink &) = delete; // no copy constructor 290*0e209d39SAndroid Build Coastguard Worker ResourceSink &operator=(const ResourceSink &) = delete; // no assignment operator 291*0e209d39SAndroid Build Coastguard Worker }; 292*0e209d39SAndroid Build Coastguard Worker 293*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END 294*0e209d39SAndroid Build Coastguard Worker 295*0e209d39SAndroid Build Coastguard Worker #endif 296