| Index: source/tools/genrb/parse.cpp
|
| diff --git a/source/tools/genrb/parse.cpp b/source/tools/genrb/parse.cpp
|
| index b1cab3a64689231f1bf209a0564542c7a99bb70e..34b94aec281816bdc62ba297c1adf1a9aa932b09 100644
|
| --- a/source/tools/genrb/parse.cpp
|
| +++ b/source/tools/genrb/parse.cpp
|
| @@ -1,7 +1,7 @@
|
| /*
|
| *******************************************************************************
|
| *
|
| -* Copyright (C) 1998-2014, International Business Machines
|
| +* Copyright (C) 1998-2015, International Business Machines
|
| * Corporation and others. All Rights Reserved.
|
| *
|
| *******************************************************************************
|
| @@ -28,6 +28,7 @@
|
| # define UNISTR_FROM_STRING_EXPLICIT explicit
|
| #endif
|
|
|
| +#include <assert.h>
|
| #include "parse.h"
|
| #include "errmsg.h"
|
| #include "uhash.h"
|
| @@ -39,10 +40,13 @@
|
| #include "reslist.h"
|
| #include "rbt_pars.h"
|
| #include "genrb.h"
|
| +#include "unicode/stringpiece.h"
|
| +#include "unicode/unistr.h"
|
| #include "unicode/ustring.h"
|
| #include "unicode/uscript.h"
|
| #include "unicode/utf16.h"
|
| #include "unicode/putil.h"
|
| +#include "charstr.h"
|
| #include "collationbuilder.h"
|
| #include "collationdata.h"
|
| #include "collationdatareader.h"
|
| @@ -70,7 +74,11 @@
|
| #define OPENSQBRACKET 0x005B
|
| #define CLOSESQBRACKET 0x005D
|
|
|
| +using icu::CharString;
|
| +using icu::LocalMemory;
|
| using icu::LocalPointer;
|
| +using icu::LocalUCHARBUFPointer;
|
| +using icu::StringPiece;
|
| using icu::UnicodeString;
|
|
|
| struct Lookahead
|
| @@ -516,7 +524,7 @@ parseTransliterator(ParseState* state, char *tag, uint32_t startline, const stru
|
|
|
| return result;
|
| }
|
| -static struct SResource* dependencyArray = NULL;
|
| +static ArrayResource* dependencyArray = NULL;
|
|
|
| static struct SResource *
|
| parseDependency(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
|
| @@ -571,7 +579,7 @@ parseDependency(ParseState* state, char *tag, uint32_t startline, const struct U
|
| }
|
| elem = string_open(state->bundle, NULL, tokenValue->fChars, tokenValue->fLength, comment, status);
|
|
|
| - array_add(dependencyArray, elem, status);
|
| + dependencyArray->add(elem);
|
|
|
| if (U_FAILURE(*status))
|
| {
|
| @@ -651,15 +659,12 @@ parseAlias(ParseState* state, char *tag, uint32_t startline, const struct UStrin
|
| namespace {
|
|
|
| static struct SResource* resLookup(struct SResource* res, const char* key){
|
| - struct SResource *current = NULL;
|
| - struct SResTable *list;
|
| - if (res == res_none()) {
|
| + if (res == res_none() || !res->isTable()) {
|
| return NULL;
|
| }
|
|
|
| - list = &(res->u.fTable);
|
| -
|
| - current = list->fFirst;
|
| + TableResource *list = static_cast<TableResource *>(res);
|
| + SResource *current = list->fFirst;
|
| while (current != NULL) {
|
| if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), key) == 0) {
|
| return current;
|
| @@ -690,47 +695,20 @@ GenrbImporter::getRules(
|
| const char *localeID, const char *collationType,
|
| UnicodeString &rules,
|
| const char *& /*errorReason*/, UErrorCode &errorCode) {
|
| - struct SRBRoot *data = NULL;
|
| - UCHARBUF *ucbuf = NULL;
|
| - int localeLength = strlen(localeID);
|
| - char* filename = (char*)uprv_malloc(localeLength+5);
|
| - char *inputDirBuf = NULL;
|
| - char *openFileName = NULL;
|
| - const char* cp = "";
|
| - int32_t i = 0;
|
| - int32_t dirlen = 0;
|
| - int32_t filelen = 0;
|
| - struct SResource* root;
|
| - struct SResource* collations;
|
| - struct SResource* collation;
|
| - struct SResource* sequence;
|
| -
|
| - memcpy(filename, localeID, localeLength);
|
| - for(i = 0; i < localeLength; i++){
|
| + CharString filename(localeID, errorCode);
|
| + for(int32_t i = 0; i < filename.length(); i++){
|
| if(filename[i] == '-'){
|
| - filename[i] = '_';
|
| + filename.data()[i] = '_';
|
| }
|
| }
|
| - filename[localeLength] = '.';
|
| - filename[localeLength+1] = 't';
|
| - filename[localeLength+2] = 'x';
|
| - filename[localeLength+3] = 't';
|
| - filename[localeLength+4] = 0;
|
| -
|
| -
|
| + filename.append(".txt", errorCode);
|
| if (U_FAILURE(errorCode)) {
|
| return;
|
| }
|
| - if(filename==NULL){
|
| - errorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
| - return;
|
| - }else{
|
| - filelen = (int32_t)uprv_strlen(filename);
|
| - }
|
| + CharString inputDirBuf;
|
| + CharString openFileName;
|
| if(inputDir == NULL) {
|
| - const char *filenameBegin = uprv_strrchr(filename, U_FILE_SEP_CHAR);
|
| - openFileName = (char *) uprv_malloc(dirlen + filelen + 2);
|
| - openFileName[0] = '\0';
|
| + const char *filenameBegin = uprv_strrchr(filename.data(), U_FILE_SEP_CHAR);
|
| if (filenameBegin != NULL) {
|
| /*
|
| * When a filename ../../../data/root.txt is specified,
|
| @@ -738,36 +716,19 @@ GenrbImporter::getRules(
|
| * This is very important when the resource file includes
|
| * another file, like UCARules.txt or thaidict.brk.
|
| */
|
| - int32_t filenameSize = (int32_t)(filenameBegin - filename + 1);
|
| - inputDirBuf = (char *)uprv_malloc(filenameSize);
|
| -
|
| - /* test for NULL */
|
| - if(inputDirBuf == NULL) {
|
| - errorCode = U_MEMORY_ALLOCATION_ERROR;
|
| - goto finish;
|
| - }
|
| -
|
| - uprv_strncpy(inputDirBuf, filename, filenameSize);
|
| - inputDirBuf[filenameSize - 1] = 0;
|
| - inputDir = inputDirBuf;
|
| - dirlen = (int32_t)uprv_strlen(inputDir);
|
| + StringPiece dir = filename.toStringPiece();
|
| + const char *filenameLimit = filename.data() + filename.length();
|
| + dir.remove_suffix((int32_t)(filenameLimit - filenameBegin));
|
| + inputDirBuf.append(dir, errorCode);
|
| + inputDir = inputDirBuf.data();
|
| }
|
| }else{
|
| - dirlen = (int32_t)uprv_strlen(inputDir);
|
| -
|
| - if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) {
|
| - openFileName = (char *) uprv_malloc(dirlen + filelen + 2);
|
| -
|
| - /* test for NULL */
|
| - if(openFileName == NULL) {
|
| - errorCode = U_MEMORY_ALLOCATION_ERROR;
|
| - goto finish;
|
| - }
|
| + int32_t dirlen = (int32_t)uprv_strlen(inputDir);
|
|
|
| - openFileName[0] = '\0';
|
| + if((filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')) {
|
| /*
|
| * append the input dir to openFileName if the first char in
|
| - * filename is not file seperation char and the last char input directory is not '.'.
|
| + * filename is not file separator char and the last char input directory is not '.'.
|
| * This is to support :
|
| * genrb -s. /home/icu/data
|
| * genrb -s. icu/data
|
| @@ -776,70 +737,49 @@ GenrbImporter::getRules(
|
| * user should use
|
| * genrb -s. icu/data --- start from CWD and look in icu/data dir
|
| */
|
| - if( (filename[0] != U_FILE_SEP_CHAR) && (inputDir[dirlen-1] !='.')){
|
| - uprv_strcpy(openFileName, inputDir);
|
| - openFileName[dirlen] = U_FILE_SEP_CHAR;
|
| + openFileName.append(inputDir, dirlen, errorCode);
|
| + if(inputDir[dirlen-1] != U_FILE_SEP_CHAR) {
|
| + openFileName.append(U_FILE_SEP_CHAR, errorCode);
|
| }
|
| - openFileName[dirlen + 1] = '\0';
|
| - } else {
|
| - openFileName = (char *) uprv_malloc(dirlen + filelen + 1);
|
| -
|
| - /* test for NULL */
|
| - if(openFileName == NULL) {
|
| - errorCode = U_MEMORY_ALLOCATION_ERROR;
|
| - goto finish;
|
| - }
|
| -
|
| - uprv_strcpy(openFileName, inputDir);
|
| -
|
| }
|
| }
|
| - uprv_strcat(openFileName, filename);
|
| - /* printf("%s\n", openFileName); */
|
| - errorCode = U_ZERO_ERROR;
|
| - ucbuf = ucbuf_open(openFileName, &cp,getShowWarning(),TRUE, &errorCode);
|
| -
|
| + openFileName.append(filename, errorCode);
|
| + if(U_FAILURE(errorCode)) {
|
| + return;
|
| + }
|
| + // printf("GenrbImporter::getRules(%s, %s) reads %s\n", localeID, collationType, openFileName.data());
|
| + const char* cp = "";
|
| + LocalUCHARBUFPointer ucbuf(
|
| + ucbuf_open(openFileName.data(), &cp, getShowWarning(), TRUE, &errorCode));
|
| if(errorCode == U_FILE_ACCESS_ERROR) {
|
| -
|
| - fprintf(stderr, "couldn't open file %s\n", openFileName == NULL ? filename : openFileName);
|
| - goto finish;
|
| + fprintf(stderr, "couldn't open file %s\n", openFileName.data());
|
| + return;
|
| }
|
| - if (ucbuf == NULL || U_FAILURE(errorCode)) {
|
| - fprintf(stderr, "An error occured processing file %s. Error: %s\n", openFileName == NULL ? filename : openFileName,u_errorName(errorCode));
|
| - goto finish;
|
| + if (ucbuf.isNull() || U_FAILURE(errorCode)) {
|
| + fprintf(stderr, "An error occured processing file %s. Error: %s\n", openFileName.data(), u_errorName(errorCode));
|
| + return;
|
| }
|
|
|
| /* Parse the data into an SRBRoot */
|
| - data = parse(ucbuf, inputDir, outputDir, filename, FALSE, FALSE, &errorCode);
|
| + struct SRBRoot *data =
|
| + parse(ucbuf.getAlias(), inputDir, outputDir, filename.data(), FALSE, FALSE, &errorCode);
|
| if (U_FAILURE(errorCode)) {
|
| - goto finish;
|
| + return;
|
| }
|
|
|
| - root = data->fRoot;
|
| - collations = resLookup(root, "collations");
|
| + struct SResource *root = data->fRoot;
|
| + struct SResource *collations = resLookup(root, "collations");
|
| if (collations != NULL) {
|
| - collation = resLookup(collations, collationType);
|
| + struct SResource *collation = resLookup(collations, collationType);
|
| if (collation != NULL) {
|
| - sequence = resLookup(collation, "Sequence");
|
| - if (sequence != NULL) {
|
| + struct SResource *sequence = resLookup(collation, "Sequence");
|
| + if (sequence != NULL && sequence->isString()) {
|
| // No string pointer aliasing so that we need not hold onto the resource bundle.
|
| - rules.setTo(sequence->u.fString.fChars, sequence->u.fString.fLength);
|
| + StringResource *sr = static_cast<StringResource *>(sequence);
|
| + rules = sr->fString;
|
| }
|
| }
|
| }
|
| -
|
| -finish:
|
| - if (inputDirBuf != NULL) {
|
| - uprv_free(inputDirBuf);
|
| - }
|
| -
|
| - if (openFileName != NULL) {
|
| - uprv_free(openFileName);
|
| - }
|
| -
|
| - if(ucbuf) {
|
| - ucbuf_close(ucbuf);
|
| - }
|
| }
|
|
|
| // Quick-and-dirty escaping function.
|
| @@ -867,8 +807,8 @@ escape(const UChar *s, char *buffer) {
|
|
|
| #endif // !UCONFIG_NO_COLLATION
|
|
|
| -static struct SResource *
|
| -addCollation(ParseState* state, struct SResource *result, const char *collationType,
|
| +static TableResource *
|
| +addCollation(ParseState* state, TableResource *result, const char *collationType,
|
| uint32_t startline, UErrorCode *status)
|
| {
|
| // TODO: Use LocalPointer for result, or make caller close it when there is a failure.
|
| @@ -931,42 +871,44 @@ addCollation(ParseState* state, struct SResource *result, const char *collation
|
| {
|
| // Ignore the parsed resources, continue parsing.
|
| }
|
| - else if (uprv_strcmp(subtag, "Version") == 0)
|
| + else if (uprv_strcmp(subtag, "Version") == 0 && member->isString())
|
| {
|
| + StringResource *sr = static_cast<StringResource *>(member);
|
| char ver[40];
|
| - int32_t length = member->u.fString.fLength;
|
| + int32_t length = sr->length();
|
|
|
| - if (length >= (int32_t) sizeof(ver))
|
| + if (length >= UPRV_LENGTHOF(ver))
|
| {
|
| - length = (int32_t) sizeof(ver) - 1;
|
| + length = UPRV_LENGTHOF(ver) - 1;
|
| }
|
|
|
| - u_UCharsToChars(member->u.fString.fChars, ver, length + 1); /* +1 for copying NULL */
|
| + sr->fString.extract(0, length, ver, UPRV_LENGTHOF(ver), US_INV);
|
| u_versionFromString(version, ver);
|
|
|
| - table_add(result, member, line, status);
|
| + result->add(member, line, *status);
|
| member = NULL;
|
| }
|
| else if(uprv_strcmp(subtag, "%%CollationBin")==0)
|
| {
|
| /* discard duplicate %%CollationBin if any*/
|
| }
|
| - else if (uprv_strcmp(subtag, "Sequence") == 0)
|
| + else if (uprv_strcmp(subtag, "Sequence") == 0 && member->isString())
|
| {
|
| - rules.setTo(member->u.fString.fChars, member->u.fString.fLength);
|
| + StringResource *sr = static_cast<StringResource *>(member);
|
| + rules = sr->fString;
|
| haveRules = TRUE;
|
| // Defer building the collator until we have seen
|
| // all sub-elements of the collation table, including the Version.
|
| /* in order to achieve smaller data files, we can direct genrb */
|
| /* to omit collation rules */
|
| if(!state->omitCollationRules) {
|
| - table_add(result, member, line, status);
|
| + result->add(member, line, *status);
|
| member = NULL;
|
| }
|
| }
|
| else // Just copy non-special items.
|
| {
|
| - table_add(result, member, line, status);
|
| + result->add(member, line, *status);
|
| member = NULL;
|
| }
|
| res_close(member); // TODO: use LocalPointer
|
| @@ -1027,7 +969,7 @@ addCollation(ParseState* state, struct SResource *result, const char *collation
|
| escape(parseError.postContext, postBuffer);
|
| error(line, " error context: \"...%s\" ! \"%s...\"", preBuffer, postBuffer);
|
| }
|
| - if(isStrict()) {
|
| + if(isStrict() || t.isNull()) {
|
| *status = intStatus;
|
| res_close(result);
|
| return NULL;
|
| @@ -1069,9 +1011,14 @@ addCollation(ParseState* state, struct SResource *result, const char *collation
|
| if(isVerbose()) {
|
| printf("%s~%s collation tailoring part sizes:\n", state->filename, collationType);
|
| icu::CollationInfo::printSizes(totalSize, indexes);
|
| + if(t->settings->hasReordering()) {
|
| + printf("%s~%s collation reordering ranges:\n", state->filename, collationType);
|
| + icu::CollationInfo::printReorderRanges(
|
| + *t->data, t->settings->reorderCodes, t->settings->reorderCodesLength);
|
| + }
|
| }
|
| struct SResource *collationBin = bin_open(state->bundle, "%%CollationBin", totalSize, dest, NULL, NULL, status);
|
| - table_add(result, collationBin, line, status);
|
| + result->add(collationBin, line, *status);
|
| if (U_FAILURE(*status)) {
|
| res_close(result);
|
| return NULL;
|
| @@ -1088,9 +1035,8 @@ keepCollationType(const char * /*type*/) {
|
| static struct SResource *
|
| parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool newCollation, UErrorCode *status)
|
| {
|
| - struct SResource *result = NULL;
|
| + TableResource *result = NULL;
|
| struct SResource *member = NULL;
|
| - struct SResource *collationRes = NULL;
|
| struct UString *tokenValue;
|
| struct UString comment;
|
| enum ETokenType token;
|
| @@ -1154,7 +1100,7 @@ parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n
|
| return NULL;
|
| }
|
|
|
| - table_add(result, member, line, status);
|
| + result->add(member, line, *status);
|
| }
|
| else
|
| {
|
| @@ -1164,6 +1110,7 @@ parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n
|
| /* then, we cannot handle aliases */
|
| if(token == TOK_OPEN_BRACE) {
|
| token = getToken(state, &tokenValue, &comment, &line, status);
|
| + TableResource *collationRes;
|
| if (keepCollationType(subtag)) {
|
| collationRes = table_open(state->bundle, subtag, NULL, status);
|
| } else {
|
| @@ -1172,7 +1119,7 @@ parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n
|
| // need to parse the collation data regardless
|
| collationRes = addCollation(state, collationRes, subtag, startline, status);
|
| if (collationRes != NULL) {
|
| - table_add(result, collationRes, startline, status);
|
| + result->add(collationRes, startline, *status);
|
| }
|
| } else if(token == TOK_COLON) { /* right now, we'll just try to see if we have aliases */
|
| /* we could have a table too */
|
| @@ -1186,7 +1133,7 @@ parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n
|
| return NULL;
|
| }
|
|
|
| - table_add(result, member, line, status);
|
| + result->add(member, line, *status);
|
| } else {
|
| res_close(result);
|
| *status = U_INVALID_FORMAT_ERROR;
|
| @@ -1215,7 +1162,7 @@ parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n
|
| /* Necessary, because CollationElements requires the bundle->fRoot member to be present which,
|
| if this weren't special-cased, wouldn't be set until the entire file had been processed. */
|
| static struct SResource *
|
| -realParseTable(ParseState* state, struct SResource *table, char *tag, uint32_t startline, UErrorCode *status)
|
| +realParseTable(ParseState* state, TableResource *table, char *tag, uint32_t startline, UErrorCode *status)
|
| {
|
| struct SResource *member = NULL;
|
| struct UString *tokenValue=NULL;
|
| @@ -1281,7 +1228,7 @@ realParseTable(ParseState* state, struct SResource *table, char *tag, uint32_t s
|
| return NULL;
|
| }
|
|
|
| - table_add(table, member, line, status);
|
| + table->add(member, line, *status);
|
|
|
| if (U_FAILURE(*status))
|
| {
|
| @@ -1301,8 +1248,6 @@ realParseTable(ParseState* state, struct SResource *table, char *tag, uint32_t s
|
| static struct SResource *
|
| parseTable(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
|
| {
|
| - struct SResource *result;
|
| -
|
| if (tag != NULL && uprv_strcmp(tag, "CollationElements") == 0)
|
| {
|
| return parseCollationElements(state, tag, startline, FALSE, status);
|
| @@ -1315,7 +1260,7 @@ parseTable(ParseState* state, char *tag, uint32_t startline, const struct UStrin
|
| printf(" table %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)startline);
|
| }
|
|
|
| - result = table_open(state->bundle, tag, comment, status);
|
| + TableResource *result = table_open(state->bundle, tag, comment, status);
|
|
|
| if (result == NULL || U_FAILURE(*status))
|
| {
|
| @@ -1327,14 +1272,13 @@ parseTable(ParseState* state, char *tag, uint32_t startline, const struct UStrin
|
| static struct SResource *
|
| parseArray(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
|
| {
|
| - struct SResource *result = NULL;
|
| struct SResource *member = NULL;
|
| struct UString *tokenValue;
|
| struct UString memberComments;
|
| enum ETokenType token;
|
| UBool readToken = FALSE;
|
|
|
| - result = array_open(state->bundle, tag, comment, status);
|
| + ArrayResource *result = array_open(state->bundle, tag, comment, status);
|
|
|
| if (result == NULL || U_FAILURE(*status))
|
| {
|
| @@ -1390,13 +1334,7 @@ parseArray(ParseState* state, char *tag, uint32_t startline, const struct UStrin
|
| return NULL;
|
| }
|
|
|
| - array_add(result, member, status);
|
| -
|
| - if (U_FAILURE(*status))
|
| - {
|
| - res_close(result);
|
| - return NULL;
|
| - }
|
| + result->add(member);
|
|
|
| /* eat optional comma if present */
|
| token = peekToken(state, 0, NULL, NULL, NULL, status);
|
| @@ -1421,7 +1359,6 @@ parseArray(ParseState* state, char *tag, uint32_t startline, const struct UStrin
|
| static struct SResource *
|
| parseIntVector(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
|
| {
|
| - struct SResource *result = NULL;
|
| enum ETokenType token;
|
| char *string;
|
| int32_t value;
|
| @@ -1430,7 +1367,7 @@ parseIntVector(ParseState* state, char *tag, uint32_t startline, const struct US
|
| uint32_t len;
|
| struct UString memberComments;
|
|
|
| - result = intvector_open(state->bundle, tag, comment, status);
|
| + IntVectorResource *result = intvector_open(state->bundle, tag, comment, status);
|
|
|
| if (result == NULL || U_FAILURE(*status))
|
| {
|
| @@ -1474,7 +1411,7 @@ parseIntVector(ParseState* state, char *tag, uint32_t startline, const struct US
|
|
|
| if(len==uprv_strlen(string))
|
| {
|
| - intvector_add(result, value, status);
|
| + result->add(value, *status);
|
| uprv_free(string);
|
| token = peekToken(state, 0, NULL, NULL, NULL, status);
|
| }
|
| @@ -1509,28 +1446,16 @@ parseIntVector(ParseState* state, char *tag, uint32_t startline, const struct US
|
| static struct SResource *
|
| parseBinary(ParseState* state, char *tag, uint32_t startline, const struct UString *comment, UErrorCode *status)
|
| {
|
| - struct SResource *result = NULL;
|
| - uint8_t *value;
|
| - char *string;
|
| - char toConv[3] = {'\0', '\0', '\0'};
|
| - uint32_t count;
|
| - uint32_t i;
|
| - uint32_t line;
|
| - char *stopstring;
|
| - uint32_t len;
|
| -
|
| - string = getInvariantString(state, &line, NULL, status);
|
| -
|
| - if (string == NULL || U_FAILURE(*status))
|
| + uint32_t line;
|
| + LocalMemory<char> string(getInvariantString(state, &line, NULL, status));
|
| + if (string.isNull() || U_FAILURE(*status))
|
| {
|
| return NULL;
|
| }
|
|
|
| expect(state, TOK_CLOSE_BRACE, NULL, NULL, NULL, status);
|
| -
|
| if (U_FAILURE(*status))
|
| {
|
| - uprv_free(string);
|
| return NULL;
|
| }
|
|
|
| @@ -1538,54 +1463,47 @@ parseBinary(ParseState* state, char *tag, uint32_t startline, const struct UStri
|
| printf(" binary %s at line %i \n", (tag == NULL) ? "(null)" : tag, (int)startline);
|
| }
|
|
|
| - count = (uint32_t)uprv_strlen(string);
|
| + uint32_t count = (uint32_t)uprv_strlen(string.getAlias());
|
| if (count > 0){
|
| if((count % 2)==0){
|
| - value = static_cast<uint8_t *>(uprv_malloc(sizeof(uint8_t) * count));
|
| -
|
| - if (value == NULL)
|
| + LocalMemory<uint8_t> value;
|
| + if (value.allocateInsteadAndCopy(count) == NULL)
|
| {
|
| - uprv_free(string);
|
| *status = U_MEMORY_ALLOCATION_ERROR;
|
| return NULL;
|
| }
|
|
|
| - for (i = 0; i < count; i += 2)
|
| + char toConv[3] = {'\0', '\0', '\0'};
|
| + for (uint32_t i = 0; i < count; i += 2)
|
| {
|
| toConv[0] = string[i];
|
| toConv[1] = string[i + 1];
|
|
|
| + char *stopstring;
|
| value[i >> 1] = (uint8_t) uprv_strtoul(toConv, &stopstring, 16);
|
| - len=(uint32_t)(stopstring-toConv);
|
| + uint32_t len=(uint32_t)(stopstring-toConv);
|
|
|
| - if(len!=uprv_strlen(toConv))
|
| + if(len!=2)
|
| {
|
| - uprv_free(string);
|
| *status=U_INVALID_CHAR_FOUND;
|
| return NULL;
|
| }
|
| }
|
|
|
| - result = bin_open(state->bundle, tag, (i >> 1), value,NULL, comment, status);
|
| -
|
| - uprv_free(value);
|
| + return bin_open(state->bundle, tag, count >> 1, value.getAlias(), NULL, comment, status);
|
| }
|
| else
|
| {
|
| *status = U_INVALID_CHAR_FOUND;
|
| - uprv_free(string);
|
| - error(line, "Encountered invalid binary string");
|
| + error(line, "Encountered invalid binary value (length is odd)");
|
| return NULL;
|
| }
|
| }
|
| else
|
| {
|
| - result = bin_open(state->bundle, tag, 0, NULL, "",comment,status);
|
| - warning(startline, "Encountered empty binary tag");
|
| + warning(startline, "Encountered empty binary value");
|
| + return bin_open(state->bundle, tag, 0, NULL, "", comment, status);
|
| }
|
| - uprv_free(string);
|
| -
|
| - return result;
|
| }
|
|
|
| static struct SResource *
|
| @@ -1641,15 +1559,8 @@ parseInteger(ParseState* state, char *tag, uint32_t startline, const struct UStr
|
| static struct SResource *
|
| parseImport(ParseState* state, char *tag, uint32_t startline, const struct UString* comment, UErrorCode *status)
|
| {
|
| - struct SResource *result;
|
| - FileStream *file;
|
| - int32_t len;
|
| - uint8_t *data;
|
| - char *filename;
|
| uint32_t line;
|
| - char *fullname = NULL;
|
| - filename = getInvariantString(state, &line, NULL, status);
|
| -
|
| + LocalMemory<char> filename(getInvariantString(state, &line, NULL, status));
|
| if (U_FAILURE(*status))
|
| {
|
| return NULL;
|
| @@ -1659,7 +1570,6 @@ parseImport(ParseState* state, char *tag, uint32_t startline, const struct UStri
|
|
|
| if (U_FAILURE(*status))
|
| {
|
| - uprv_free(filename);
|
| return NULL;
|
| }
|
|
|
| @@ -1668,90 +1578,36 @@ parseImport(ParseState* state, char *tag, uint32_t startline, const struct UStri
|
| }
|
|
|
| /* Open the input file for reading */
|
| - if (state->inputdir == NULL)
|
| - {
|
| -#if 1
|
| - /*
|
| - * Always save file file name, even if there's
|
| - * no input directory specified. MIGHT BREAK SOMETHING
|
| - */
|
| - int32_t filenameLength = uprv_strlen(filename);
|
| -
|
| - fullname = (char *) uprv_malloc(filenameLength + 1);
|
| - uprv_strcpy(fullname, filename);
|
| -#endif
|
| -
|
| - file = T_FileStream_open(filename, "rb");
|
| + CharString fullname;
|
| + if (state->inputdir != NULL) {
|
| + fullname.append(state->inputdir, *status);
|
| }
|
| - else
|
| - {
|
| -
|
| - int32_t count = (int32_t)uprv_strlen(filename);
|
| -
|
| - if (state->inputdir[state->inputdirLength - 1] != U_FILE_SEP_CHAR)
|
| - {
|
| - fullname = (char *) uprv_malloc(state->inputdirLength + count + 2);
|
| -
|
| - /* test for NULL */
|
| - if(fullname == NULL)
|
| - {
|
| - *status = U_MEMORY_ALLOCATION_ERROR;
|
| - return NULL;
|
| - }
|
| -
|
| - uprv_strcpy(fullname, state->inputdir);
|
| -
|
| - fullname[state->inputdirLength] = U_FILE_SEP_CHAR;
|
| - fullname[state->inputdirLength + 1] = '\0';
|
| -
|
| - uprv_strcat(fullname, filename);
|
| - }
|
| - else
|
| - {
|
| - fullname = (char *) uprv_malloc(state->inputdirLength + count + 1);
|
| -
|
| - /* test for NULL */
|
| - if(fullname == NULL)
|
| - {
|
| - *status = U_MEMORY_ALLOCATION_ERROR;
|
| - return NULL;
|
| - }
|
| -
|
| - uprv_strcpy(fullname, state->inputdir);
|
| - uprv_strcat(fullname, filename);
|
| - }
|
| -
|
| - file = T_FileStream_open(fullname, "rb");
|
| -
|
| + fullname.appendPathPart(filename.getAlias(), *status);
|
| + if (U_FAILURE(*status)) {
|
| + return NULL;
|
| }
|
|
|
| + FileStream *file = T_FileStream_open(fullname.data(), "rb");
|
| if (file == NULL)
|
| {
|
| - error(line, "couldn't open input file %s", filename);
|
| + error(line, "couldn't open input file %s", filename.getAlias());
|
| *status = U_FILE_ACCESS_ERROR;
|
| return NULL;
|
| }
|
|
|
| - len = T_FileStream_size(file);
|
| - data = (uint8_t*)uprv_malloc(len * sizeof(uint8_t));
|
| - /* test for NULL */
|
| - if(data == NULL)
|
| + int32_t len = T_FileStream_size(file);
|
| + LocalMemory<uint8_t> data;
|
| + if(data.allocateInsteadAndCopy(len) == NULL)
|
| {
|
| *status = U_MEMORY_ALLOCATION_ERROR;
|
| T_FileStream_close (file);
|
| return NULL;
|
| }
|
|
|
| - /* int32_t numRead = */ T_FileStream_read (file, data, len);
|
| + /* int32_t numRead = */ T_FileStream_read(file, data.getAlias(), len);
|
| T_FileStream_close (file);
|
|
|
| - result = bin_open(state->bundle, tag, len, data, fullname, comment, status);
|
| -
|
| - uprv_free(data);
|
| - uprv_free(filename);
|
| - uprv_free(fullname);
|
| -
|
| - return result;
|
| + return bin_open(state->bundle, tag, len, data.getAlias(), fullname.data(), comment, status);
|
| }
|
|
|
| static struct SResource *
|
| @@ -2133,7 +1989,7 @@ parse(UCHARBUF *buf, const char *inputDir, const char *outputDir, const char *fi
|
| ustr_init(&comment);
|
| expect(&state, TOK_STRING, &tokenValue, &comment, NULL, status);
|
|
|
| - state.bundle = bundle_open(&comment, FALSE, status);
|
| + state.bundle = new SRBRoot(&comment, FALSE, *status);
|
|
|
| if (state.bundle == NULL || U_FAILURE(*status))
|
| {
|
| @@ -2141,7 +1997,7 @@ parse(UCHARBUF *buf, const char *inputDir, const char *outputDir, const char *fi
|
| }
|
|
|
|
|
| - bundle_setlocale(state.bundle, tokenValue->fChars, status);
|
| + state.bundle->setLocale(tokenValue->fChars, *status);
|
|
|
| /* The following code is to make Empty bundle work no matter with :table specifer or not */
|
| token = getToken(&state, NULL, NULL, &line, status);
|
| @@ -2178,7 +2034,7 @@ parse(UCHARBUF *buf, const char *inputDir, const char *outputDir, const char *fi
|
|
|
| if (U_FAILURE(*status))
|
| {
|
| - bundle_close(state.bundle, status);
|
| + delete state.bundle;
|
| return NULL;
|
| }
|
|
|
| @@ -2188,17 +2044,20 @@ parse(UCHARBUF *buf, const char *inputDir, const char *outputDir, const char *fi
|
| * This is the same as a regular table, but also sets the
|
| * URES_ATT_NO_FALLBACK flag in indexes[URES_INDEX_ATTRIBUTES] .
|
| */
|
| - state.bundle->noFallback=TRUE;
|
| + state.bundle->fNoFallback=TRUE;
|
| }
|
| /* top-level tables need not handle special table names like "collations" */
|
| - realParseTable(&state, state.bundle->fRoot, NULL, line, status);
|
| + assert(!state.bundle->fIsPoolBundle);
|
| + assert(state.bundle->fRoot->fType == URES_TABLE);
|
| + TableResource *rootTable = static_cast<TableResource *>(state.bundle->fRoot);
|
| + realParseTable(&state, rootTable, NULL, line, status);
|
| if(dependencyArray!=NULL){
|
| - table_add(state.bundle->fRoot, dependencyArray, 0, status);
|
| + rootTable->add(dependencyArray, 0, *status);
|
| dependencyArray = NULL;
|
| }
|
| if (U_FAILURE(*status))
|
| {
|
| - bundle_close(state.bundle, status);
|
| + delete state.bundle;
|
| res_close(dependencyArray);
|
| return NULL;
|
| }
|
|
|