1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 2007-2009, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 7 #include "unicode/udbgutil.h" 8 #include <string.h> 9 10 /* 11 To add a new enum type 12 (For example: UShoeSize with values USHOE_WIDE=0, USHOE_REGULAR, USHOE_NARROW, USHOE_COUNT) 13 14 1. udbgutil.h: add UDBG_UShoeSize to the UDebugEnumType enum before UDBG_ENUM_COUNT 15 ( The subsequent steps involve this file, udbgutil.cpp ) 16 2. Find the marker "Add new enum types above this line" 17 3. Before that marker, add a #include of any header file you need. 18 4. Each enum type has three things in this section: a #define, a count_, and an array of Fields. 19 It may help to copy and paste a previous definition. 20 5. In the case of the USHOE_... strings above, "USHOE_" is common to all values- six characters 21 " #define LEN_USHOE 6 " 22 6 characters will strip off "USHOE_" leaving enum values of WIDE, REGULAR, and NARROW. 23 6. Define the 'count_' variable, with the number of enum values. If the enum has a _MAX or _COUNT value, 24 that can be helpful for automatically defining the count. Otherwise define it manually. 25 " static const int32_t count_UShoeSize = USHOE_COUNT; " 26 7. Define the field names, in order. 27 " static const Field names_UShoeSize[] = { 28 " FIELD_NAME_STR( LEN_USHOE, USHOE_WIDE ), 29 " FIELD_NAME_STR( LEN_USHOE, USHOE_REGULAR ), 30 " FIELD_NAME_STR( LEN_USHOE, USHOE_NARROW ), 31 " }; 32 ( The following command was usedfor converting ucol.h into partially correct entities ) 33 grep "^[ ]*UCOL" < unicode/ucol.h | 34 sed -e 's%^[ ]*\([A-Z]*\)_\([A-Z_]*\).*% FIELD_NAME_STR( LEN_\1, \1_\2 ),%g' 35 8. Now, a bit farther down, add the name of the enum itself to the end of names_UDebugEnumType 36 ( UDebugEnumType is an enum, too!) 37 names_UDebugEnumType[] { ... 38 " FIELD_NAME_STR( LEN_UDBG, UDBG_UShoeSize ), " 39 9. Find the function _udbg_enumCount and add the count macro: 40 " COUNT_CASE(UShoeSize) 41 10. Find the function _udbg_enumFields and add the field macro: 42 " FIELD_CASE(UShoeSize) 43 11. verify that your test code, and Java data generation, works properly. 44 */ 45 46 /** 47 * Structure representing an enum value 48 */ 49 struct Field { 50 int32_t prefix; /**< how many characters to remove in the prefix - i.e. UCHAR_ = 5 */ 51 const char *str; /**< The actual string value */ 52 int32_t num; /**< The numeric value */ 53 }; 54 55 /** 56 * Calculate the size of an array. 57 */ 58 #define DBG_ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0])) 59 60 /** 61 * Define another field name. Used in an array of Field s 62 * @param y the common prefix length (i.e. 6 for "USHOE_" ) 63 * @param x the actual enum value - it will be copied in both string and symbolic form. 64 * @see Field 65 */ 66 #define FIELD_NAME_STR(y,x) { y, #x, x } 67 68 69 // TODO: Currently, this whole functionality goes away with UCONFIG_NO_FORMATTING. Should be split up. 70 #if !UCONFIG_NO_FORMATTING 71 72 // Calendar 73 #include "unicode/ucal.h" 74 75 // 'UCAL_' = 5 76 #define LEN_UCAL 5 /* UCAL_ */ 77 static const int32_t count_UCalendarDateFields = UCAL_FIELD_COUNT; 78 static const Field names_UCalendarDateFields[] = 79 { 80 FIELD_NAME_STR( LEN_UCAL, UCAL_ERA ), 81 FIELD_NAME_STR( LEN_UCAL, UCAL_YEAR ), 82 FIELD_NAME_STR( LEN_UCAL, UCAL_MONTH ), 83 FIELD_NAME_STR( LEN_UCAL, UCAL_WEEK_OF_YEAR ), 84 FIELD_NAME_STR( LEN_UCAL, UCAL_WEEK_OF_MONTH ), 85 FIELD_NAME_STR( LEN_UCAL, UCAL_DATE ), 86 FIELD_NAME_STR( LEN_UCAL, UCAL_DAY_OF_YEAR ), 87 FIELD_NAME_STR( LEN_UCAL, UCAL_DAY_OF_WEEK ), 88 FIELD_NAME_STR( LEN_UCAL, UCAL_DAY_OF_WEEK_IN_MONTH ), 89 FIELD_NAME_STR( LEN_UCAL, UCAL_AM_PM ), 90 FIELD_NAME_STR( LEN_UCAL, UCAL_HOUR ), 91 FIELD_NAME_STR( LEN_UCAL, UCAL_HOUR_OF_DAY ), 92 FIELD_NAME_STR( LEN_UCAL, UCAL_MINUTE ), 93 FIELD_NAME_STR( LEN_UCAL, UCAL_SECOND ), 94 FIELD_NAME_STR( LEN_UCAL, UCAL_MILLISECOND ), 95 FIELD_NAME_STR( LEN_UCAL, UCAL_ZONE_OFFSET ), 96 FIELD_NAME_STR( LEN_UCAL, UCAL_DST_OFFSET ), 97 FIELD_NAME_STR( LEN_UCAL, UCAL_YEAR_WOY ), 98 FIELD_NAME_STR( LEN_UCAL, UCAL_DOW_LOCAL ), 99 FIELD_NAME_STR( LEN_UCAL, UCAL_EXTENDED_YEAR ), 100 FIELD_NAME_STR( LEN_UCAL, UCAL_JULIAN_DAY ), 101 FIELD_NAME_STR( LEN_UCAL, UCAL_MILLISECONDS_IN_DAY ), 102 FIELD_NAME_STR( LEN_UCAL, UCAL_IS_LEAP_MONTH ), 103 }; 104 105 106 static const int32_t count_UCalendarMonths = UCAL_UNDECIMBER+1; 107 static const Field names_UCalendarMonths[] = 108 { 109 FIELD_NAME_STR( LEN_UCAL, UCAL_JANUARY ), 110 FIELD_NAME_STR( LEN_UCAL, UCAL_FEBRUARY ), 111 FIELD_NAME_STR( LEN_UCAL, UCAL_MARCH ), 112 FIELD_NAME_STR( LEN_UCAL, UCAL_APRIL ), 113 FIELD_NAME_STR( LEN_UCAL, UCAL_MAY ), 114 FIELD_NAME_STR( LEN_UCAL, UCAL_JUNE ), 115 FIELD_NAME_STR( LEN_UCAL, UCAL_JULY ), 116 FIELD_NAME_STR( LEN_UCAL, UCAL_AUGUST ), 117 FIELD_NAME_STR( LEN_UCAL, UCAL_SEPTEMBER ), 118 FIELD_NAME_STR( LEN_UCAL, UCAL_OCTOBER ), 119 FIELD_NAME_STR( LEN_UCAL, UCAL_NOVEMBER ), 120 FIELD_NAME_STR( LEN_UCAL, UCAL_DECEMBER ), 121 FIELD_NAME_STR( LEN_UCAL, UCAL_UNDECIMBER) 122 }; 123 124 #include "unicode/udat.h" 125 126 #define LEN_UDAT 5 /* "UDAT_" */ 127 static const int32_t count_UDateFormatStyle = UDAT_SHORT+1; 128 static const Field names_UDateFormatStyle[] = 129 { 130 FIELD_NAME_STR( LEN_UDAT, UDAT_FULL ), 131 FIELD_NAME_STR( LEN_UDAT, UDAT_LONG ), 132 FIELD_NAME_STR( LEN_UDAT, UDAT_MEDIUM ), 133 FIELD_NAME_STR( LEN_UDAT, UDAT_SHORT ), 134 /* end regular */ 135 /* 136 * negative enums.. leave out for now. 137 FIELD_NAME_STR( LEN_UDAT, UDAT_NONE ), 138 FIELD_NAME_STR( LEN_UDAT, UDAT_IGNORE ), 139 */ 140 }; 141 142 #endif 143 144 #include "unicode/uloc.h" 145 146 #define LEN_UAR 12 /* "ULOC_ACCEPT_" */ 147 static const int32_t count_UAcceptResult = 3; 148 static const Field names_UAcceptResult[] = 149 { 150 FIELD_NAME_STR( LEN_UAR, ULOC_ACCEPT_FAILED ), 151 FIELD_NAME_STR( LEN_UAR, ULOC_ACCEPT_VALID ), 152 FIELD_NAME_STR( LEN_UAR, ULOC_ACCEPT_FALLBACK ), 153 }; 154 155 #if !UCONFIG_NO_COLLATION 156 #include "unicode/ucol.h" 157 #define LEN_UCOL 5 /* UCOL_ */ 158 static const int32_t count_UColAttributeValue = UCOL_ATTRIBUTE_VALUE_COUNT; 159 static const Field names_UColAttributeValue[] = { 160 FIELD_NAME_STR( LEN_UCOL, UCOL_PRIMARY ), 161 FIELD_NAME_STR( LEN_UCOL, UCOL_SECONDARY ), 162 FIELD_NAME_STR( LEN_UCOL, UCOL_TERTIARY ), 163 // FIELD_NAME_STR( LEN_UCOL, UCOL_CE_STRENGTH_LIMIT ), 164 FIELD_NAME_STR( LEN_UCOL, UCOL_QUATERNARY ), 165 // gap 166 FIELD_NAME_STR( LEN_UCOL, UCOL_IDENTICAL ), 167 // FIELD_NAME_STR( LEN_UCOL, UCOL_STRENGTH_LIMIT ), 168 FIELD_NAME_STR( LEN_UCOL, UCOL_OFF ), 169 FIELD_NAME_STR( LEN_UCOL, UCOL_ON ), 170 // gap 171 FIELD_NAME_STR( LEN_UCOL, UCOL_SHIFTED ), 172 FIELD_NAME_STR( LEN_UCOL, UCOL_NON_IGNORABLE ), 173 // gap 174 FIELD_NAME_STR( LEN_UCOL, UCOL_LOWER_FIRST ), 175 FIELD_NAME_STR( LEN_UCOL, UCOL_UPPER_FIRST ), 176 }; 177 178 #endif 179 180 #define LEN_UDBG 5 /* "UDBG_" */ 181 static const int32_t count_UDebugEnumType = UDBG_ENUM_COUNT; 182 static const Field names_UDebugEnumType[] = 183 { 184 FIELD_NAME_STR( LEN_UDBG, UDBG_UDebugEnumType ), 185 #if !UCONFIG_NO_FORMATTING 186 FIELD_NAME_STR( LEN_UDBG, UDBG_UCalendarDateFields ), 187 FIELD_NAME_STR( LEN_UDBG, UDBG_UCalendarMonths ), 188 FIELD_NAME_STR( LEN_UDBG, UDBG_UDateFormatStyle ), 189 #endif 190 FIELD_NAME_STR( LEN_UDBG, UDBG_UAcceptResult ), 191 #if !UCONFIG_NO_COLLATION 192 FIELD_NAME_STR( LEN_UDBG, UDBG_UColAttributeValue ), 193 #endif 194 }; 195 196 197 // --- Add new enum types above this line --- 198 199 #define COUNT_CASE(x) case UDBG_##x: return (actual?count_##x:DBG_ARRAY_COUNT(names_##x)); 200 #define COUNT_FAIL_CASE(x) case UDBG_##x: return -1; 201 202 #define FIELD_CASE(x) case UDBG_##x: return names_##x; 203 #define FIELD_FAIL_CASE(x) case UDBG_##x: return NULL; 204 205 // low level 206 207 /** 208 * @param type type of item 209 * @param actual TRUE: for the actual enum's type (UCAL_FIELD_COUNT, etc), or FALSE for the string count 210 */ 211 static int32_t _udbg_enumCount(UDebugEnumType type, UBool actual) { 212 switch(type) { 213 COUNT_CASE(UDebugEnumType) 214 #if !UCONFIG_NO_FORMATTING 215 COUNT_CASE(UCalendarDateFields) 216 COUNT_CASE(UCalendarMonths) 217 COUNT_CASE(UDateFormatStyle) 218 #endif 219 COUNT_CASE(UAcceptResult) 220 #if !UCONFIG_NO_COLLATION 221 COUNT_CASE(UColAttributeValue) 222 #endif 223 // COUNT_FAIL_CASE(UNonExistentEnum) 224 default: 225 return -1; 226 } 227 } 228 229 static const Field* _udbg_enumFields(UDebugEnumType type) { 230 switch(type) { 231 FIELD_CASE(UDebugEnumType) 232 #if !UCONFIG_NO_FORMATTING 233 FIELD_CASE(UCalendarDateFields) 234 FIELD_CASE(UCalendarMonths) 235 FIELD_CASE(UDateFormatStyle) 236 #endif 237 FIELD_CASE(UAcceptResult) 238 // FIELD_FAIL_CASE(UNonExistentEnum) 239 #if !UCONFIG_NO_COLLATION 240 FIELD_CASE(UColAttributeValue) 241 #endif 242 default: 243 return NULL; 244 } 245 } 246 247 // implementation 248 249 int32_t udbg_enumCount(UDebugEnumType type) { 250 return _udbg_enumCount(type, FALSE); 251 } 252 253 int32_t udbg_enumExpectedCount(UDebugEnumType type) { 254 return _udbg_enumCount(type, TRUE); 255 } 256 257 const char * udbg_enumName(UDebugEnumType type, int32_t field) { 258 if(field<0 || 259 field>=_udbg_enumCount(type,FALSE)) { // also will catch unsupported items 260 return NULL; 261 } else { 262 const Field *fields = _udbg_enumFields(type); 263 if(fields == NULL) { 264 return NULL; 265 } else { 266 return fields[field].str + fields[field].prefix; 267 } 268 } 269 } 270 271 int32_t udbg_enumArrayValue(UDebugEnumType type, int32_t field) { 272 if(field<0 || 273 field>=_udbg_enumCount(type,FALSE)) { // also will catch unsupported items 274 return -1; 275 } else { 276 const Field *fields = _udbg_enumFields(type); 277 if(fields == NULL) { 278 return -1; 279 } else { 280 return fields[field].num; 281 } 282 } 283 } 284 285 int32_t udbg_enumByName(UDebugEnumType type, const char *value) { 286 if(type<0||type>=_udbg_enumCount(UDBG_UDebugEnumType, TRUE)) { 287 return -1; // type out of range 288 } 289 const Field *fields = _udbg_enumFields(type); 290 for(int32_t field = 0;field<_udbg_enumCount(type, FALSE);field++) { 291 if(!strcmp(value, fields[field].str + fields[field].prefix)) { 292 return fields[field].num; 293 } 294 } 295 // try with the prefix 296 for(int32_t field = 0;field<_udbg_enumCount(type, FALSE);field++) { 297 if(!strcmp(value, fields[field].str)) { 298 return fields[field].num; 299 } 300 } 301 // fail 302 return -1; 303 } 304