16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 2011-2013, International Business Machines
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   file name:  ppucd.cpp
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   encoding:   US-ASCII
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   tab size:   8 (not used)
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   indentation:4
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created on: 2011dec11
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created by: Markus W. Scherer
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uchar.h"
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "charstr.h"
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cstring.h"
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ppucd.h"
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uparse.h"
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <stdio.h>
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <string.h>
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPropertyNames::~PropertyNames() {}
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPropertyNames::getPropertyEnum(const char *name) const {
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_getPropertyEnum(name);
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPropertyNames::getPropertyValueEnum(int32_t property, const char *name) const {
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_getPropertyValueEnum((UProperty)property, name);
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUniProps::UniProps()
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        : start(U_SENTINEL), end(U_SENTINEL),
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          bmg(U_SENTINEL), bpb(U_SENTINEL),
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          scf(U_SENTINEL), slc(U_SENTINEL), stc(U_SENTINEL), suc(U_SENTINEL),
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          digitValue(-1), numericValue(NULL),
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          name(NULL), nameAlias(NULL) {
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    memset(binProps, 0, sizeof(binProps));
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    memset(intProps, 0, sizeof(intProps));
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    memset(age, 0, 4);
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUniProps::~UniProps() {}
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst int32_t PreparsedUCD::kNumLineBuffers;
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::PreparsedUCD(const char *filename, UErrorCode &errorCode)
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        : icuPnames(new PropertyNames()), pnames(icuPnames),
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          file(NULL),
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          defaultLineIndex(-1), blockLineIndex(-1), lineIndex(0),
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          lineNumber(0),
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          lineType(NO_LINE),
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          fieldLimit(NULL), lineLimit(NULL) {
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) { return; }
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(filename==NULL || *filename==0 || (*filename=='-' && filename[1]==0)) {
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        filename=NULL;
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        file=stdin;
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        file=fopen(filename, "r");
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(file==NULL) {
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        perror("error opening preparsed UCD");
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr, "error opening preparsed UCD file %s\n", filename ? filename : "\"no file name given\"");
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_FILE_ACCESS_ERROR;
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    memset(ucdVersion, 0, 4);
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lines[0][0]=0;
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::~PreparsedUCD() {
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(file!=stdin) {
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fclose(file);
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    delete icuPnames;
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Same order as the LineType values.
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const char *lineTypeStrings[]={
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    NULL,
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    NULL,
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "ucd",
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "property",
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "binary",
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "value",
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "defaults",
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "block",
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "cp",
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "algnamesrange"
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::LineType
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::readLine(UErrorCode &errorCode) {
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) { return NO_LINE; }
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Select the next available line buffer.
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(!isLineBufferAvailable(lineIndex)) {
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++lineIndex;
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (lineIndex == kNumLineBuffers) {
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lineIndex = 0;
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *line=lines[lineIndex];
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *line=0;
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lineLimit=fieldLimit=line;
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lineType=NO_LINE;
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *result=fgets(line, sizeof(lines[0]), file);
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(result==NULL) {
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(ferror(file)) {
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            perror("error reading preparsed UCD");
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr, "error reading preparsed UCD before line %ld\n", (long)lineNumber);
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_FILE_ACCESS_ERROR;
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NO_LINE;
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ++lineNumber;
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(*line=='#') {
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fieldLimit=strchr(line, 0);
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return lineType=EMPTY_LINE;
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Remove trailing /r/n.
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char c;
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *limit=strchr(line, 0);
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(line<limit && ((c=*(limit-1))=='\n' || c=='\r')) { --limit; }
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Remove trailing white space.
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(line<limit && ((c=*(limit-1))==' ' || c=='\t')) { --limit; }
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *limit=0;
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lineLimit=limit;
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(line==limit) {
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fieldLimit=limit;
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return lineType=EMPTY_LINE;
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Split by ';'.
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *semi=line;
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while((semi=strchr(semi, ';'))!=NULL) { *semi++=0; }
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fieldLimit=strchr(line, 0);
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Determine the line type.
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t type;
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(type=EMPTY_LINE+1;; ++type) {
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(type==LINE_TYPE_COUNT) {
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: unknown line type (first field) '%s' on line %ld\n",
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    line, (long)lineNumber);
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return NO_LINE;
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(0==strcmp(line, lineTypeStrings[type])) {
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lineType=(LineType)type;
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(lineType==UNICODE_VERSION_LINE && fieldLimit<lineLimit) {
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        u_versionFromString(ucdVersion, fieldLimit+1);
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return lineType;
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char *
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::firstField() {
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *field=lines[lineIndex];
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fieldLimit=strchr(field, 0);
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return field;
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char *
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::nextField() {
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(fieldLimit==lineLimit) { return NULL; }
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *field=fieldLimit+1;
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fieldLimit=strchr(field, 0);
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return field;
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst UniProps *
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::getProps(UnicodeSet &newValues, UErrorCode &errorCode) {
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) { return NULL; }
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    newValues.clear();
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!lineHasPropertyValues()) {
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_ILLEGAL_ARGUMENT_ERROR;
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    firstField();
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *field=nextField();
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(field==NULL) {
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // No range field after the type.
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr,
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "error in preparsed UCD: missing default/block/cp range field "
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "(no second field) on line %ld\n",
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (long)lineNumber);
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_PARSE_ERROR;
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 start, end;
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!parseCodePointRange(field, start, end, errorCode)) { return NULL; }
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UniProps *props;
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(lineType) {
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case DEFAULTS_LINE:
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(defaultLineIndex>=0) {
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: second line with default properties on line %ld\n",
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    (long)lineNumber);
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return NULL;
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(start!=0 || end!=0x10ffff) {
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: default range must be 0..10FFFF, not '%s' on line %ld\n",
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    field, (long)lineNumber);
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return NULL;
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        props=&defaultProps;
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        defaultLineIndex=lineIndex;
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case BLOCK_LINE:
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        blockProps=defaultProps;  // Block inherits default properties.
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        props=&blockProps;
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        blockLineIndex=lineIndex;
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case CP_LINE:
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(blockProps.start<=start && end<=blockProps.end) {
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Code point range fully inside the last block inherits the block properties.
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cpProps=blockProps;
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(start>blockProps.end || end<blockProps.start) {
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Code point range fully outside the last block inherits the default properties.
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cpProps=defaultProps;
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Code point range partially overlapping with the last block is illegal.
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: cp range %s on line %ld only "
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "partially overlaps with block range %04lX..%04lX\n",
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    field, (long)lineNumber, (long)blockProps.start, (long)blockProps.end);
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return NULL;
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        props=&cpProps;
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Will not occur because of the range check above.
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_ILLEGAL_ARGUMENT_ERROR;
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    props->start=start;
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    props->end=end;
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while((field=nextField())!=NULL) {
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(!parseProperty(*props, field, newValues, errorCode)) { return NULL; }
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return props;
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const struct {
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *name;
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t prop;
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} ppucdProperties[]={
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "Name_Alias", PPUCD_NAME_ALIAS },
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "Conditional_Case_Mappings", PPUCD_CONDITIONAL_CASE_MAPPINGS },
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    { "Turkic_Case_Folding", PPUCD_TURKIC_CASE_FOLDING }
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Returns TRUE for "ok to continue parsing fields".
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::parseProperty(UniProps &props, const char *field, UnicodeSet &newValues,
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UErrorCode &errorCode) {
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    CharString pBuffer;
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *p=field;
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *v=strchr(p, '=');
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int binaryValue;
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(*p=='-') {
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(v!=NULL) {
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: mix of binary-property-no and "
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "enum-property syntax '%s' on line %ld\n",
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    field, (long)lineNumber);
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        binaryValue=0;
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++p;
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(v==NULL) {
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        binaryValue=1;
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        binaryValue=-1;
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Copy out the property name rather than modifying the field (writing a NUL).
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pBuffer.append(p, (int32_t)(v-p), errorCode);
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=pBuffer.data();
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++v;
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t prop=pnames->getPropertyEnum(p);
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(prop<0) {
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(int32_t i=0;; ++i) {
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(i==LENGTHOF(ppucdProperties)) {
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Ignore unknown property names.
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return TRUE;
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(0==uprv_stricmp(p, ppucdProperties[i].name)) {
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                prop=ppucdProperties[i].prop;
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                U_ASSERT(prop>=0);
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(prop<UCHAR_BINARY_LIMIT) {
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(binaryValue>=0) {
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.binProps[prop]=(UBool)binaryValue;
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // No binary value for a binary property.
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: enum-property syntax '%s' "
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "for binary property on line %ld\n",
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    field, (long)lineNumber);
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(binaryValue>=0) {
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Binary value for a non-binary property.
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr,
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "error in preparsed UCD: binary-property syntax '%s' "
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "for non-binary property on line %ld\n",
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                field, (long)lineNumber);
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_PARSE_ERROR;
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if (prop < UCHAR_INT_START) {
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr,
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "error in preparsed UCD: prop value is invalid: '%d' for line %ld\n",
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                prop, (long)lineNumber);
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_PARSE_ERROR;
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(prop<UCHAR_INT_LIMIT) {
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t value=pnames->getPropertyValueEnum(prop, v);
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(value==UCHAR_INVALID_CODE && prop==UCHAR_CANONICAL_COMBINING_CLASS) {
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // TODO: Make getPropertyValueEnum(UCHAR_CANONICAL_COMBINING_CLASS, v) work.
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            char *end;
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            unsigned long ccc=uprv_strtoul(v, &end, 10);
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(v<end && *end==0 && ccc<=254) {
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                value=(int32_t)ccc;
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(value==UCHAR_INVALID_CODE) {
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: '%s' is not a valid value on line %ld\n",
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    field, (long)lineNumber);
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.intProps[prop-UCHAR_INT_START]=value;
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(*v=='<') {
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Do not parse default values like <code point>, just set null values.
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        switch(prop) {
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_BIDI_MIRRORING_GLYPH:
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.bmg=U_SENTINEL;
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_BIDI_PAIRED_BRACKET:
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.bpb=U_SENTINEL;
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SIMPLE_CASE_FOLDING:
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.scf=U_SENTINEL;
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SIMPLE_LOWERCASE_MAPPING:
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.slc=U_SENTINEL;
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SIMPLE_TITLECASE_MAPPING:
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.stc=U_SENTINEL;
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SIMPLE_UPPERCASE_MAPPING:
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.suc=U_SENTINEL;
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_CASE_FOLDING:
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.cf.remove();
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_LOWERCASE_MAPPING:
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.lc.remove();
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_TITLECASE_MAPPING:
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.tc.remove();
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_UPPERCASE_MAPPING:
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.uc.remove();
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SCRIPT_EXTENSIONS:
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.scx.clear();
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        default:
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: '%s' is not a valid default value on line %ld\n",
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    field, (long)lineNumber);
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char c;
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        switch(prop) {
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_NUMERIC_VALUE:
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.numericValue=v;
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c=*v;
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if('0'<=c && c<='9' && v[1]==0) {
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                props.digitValue=c-'0';
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                props.digitValue=-1;
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_NAME:
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.name=v;
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_AGE:
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            u_versionFromString(props.age, v);  // Writes 0.0.0.0 if v is not numeric.
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_BIDI_MIRRORING_GLYPH:
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.bmg=parseCodePoint(v, errorCode);
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_BIDI_PAIRED_BRACKET:
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.bpb=parseCodePoint(v, errorCode);
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SIMPLE_CASE_FOLDING:
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.scf=parseCodePoint(v, errorCode);
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SIMPLE_LOWERCASE_MAPPING:
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.slc=parseCodePoint(v, errorCode);
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SIMPLE_TITLECASE_MAPPING:
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.stc=parseCodePoint(v, errorCode);
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SIMPLE_UPPERCASE_MAPPING:
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.suc=parseCodePoint(v, errorCode);
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_CASE_FOLDING:
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            parseString(v, props.cf, errorCode);
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_LOWERCASE_MAPPING:
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            parseString(v, props.lc, errorCode);
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_TITLECASE_MAPPING:
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            parseString(v, props.tc, errorCode);
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_UPPERCASE_MAPPING:
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            parseString(v, props.uc, errorCode);
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case PPUCD_NAME_ALIAS:
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            props.nameAlias=v;
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case PPUCD_CONDITIONAL_CASE_MAPPINGS:
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case PPUCD_TURKIC_CASE_FOLDING:
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // No need to parse their values: They are hardcoded in the runtime library.
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCHAR_SCRIPT_EXTENSIONS:
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            parseScriptExtensions(v, props.scx, errorCode);
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        default:
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Ignore unhandled properties.
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return TRUE;
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_SUCCESS(errorCode)) {
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        newValues.add((UChar32)prop);
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::getRangeForAlgNames(UChar32 &start, UChar32 &end, UErrorCode &errorCode) {
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) { return FALSE; }
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(lineType!=ALG_NAMES_RANGE_LINE) {
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_ILLEGAL_ARGUMENT_ERROR;
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    firstField();
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *field=nextField();
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(field==NULL) {
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // No range field after the type.
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr,
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "error in preparsed UCD: missing algnamesrange range field "
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "(no second field) on line %ld\n",
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (long)lineNumber);
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_PARSE_ERROR;
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return parseCodePointRange(field, start, end, errorCode);
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUChar32
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::parseCodePoint(const char *s, UErrorCode &errorCode) {
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char *end;
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t value=(uint32_t)uprv_strtoul(s, &end, 16);
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(end<=s || *end!=0 || value>=0x110000) {
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr,
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "error in preparsed UCD: '%s' is not a valid code point on line %ld\n",
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                s, (long)lineNumber);
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_PARSE_ERROR;
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return U_SENTINEL;
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (UChar32)value;
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::parseCodePointRange(const char *s, UChar32 &start, UChar32 &end, UErrorCode &errorCode) {
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t st, e;
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    u_parseCodePointRange(s, &st, &e, &errorCode);
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr,
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "error in preparsed UCD: '%s' is not a valid code point range on line %ld\n",
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                s, (long)lineNumber);
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    start=(UChar32)st;
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    end=(UChar32)e;
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::parseString(const char *s, UnicodeString &uni, UErrorCode &errorCode) {
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar *buffer=uni.getBuffer(-1);
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length=u_parseString(s, buffer, uni.getCapacity(), NULL, &errorCode);
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_ZERO_ERROR;
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uni.releaseBuffer(0);
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        buffer=uni.getBuffer(length);
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=u_parseString(s, buffer, uni.getCapacity(), NULL, &errorCode);
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uni.releaseBuffer(length);
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr,
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                "error in preparsed UCD: '%s' is not a valid Unicode string on line %ld\n",
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                s, (long)lineNumber);
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPreparsedUCD::parseScriptExtensions(const char *s, UnicodeSet &scx, UErrorCode &errorCode) {
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) { return; }
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    scx.clear();
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    CharString scString;
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *scs;
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const char *scLimit=strchr(s, ' ');
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(scLimit!=NULL) {
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            scs=scString.clear().append(s, (int32_t)(scLimit-s), errorCode).data();
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_FAILURE(errorCode)) { return; }
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            scs=s;
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t script=pnames->getPropertyValueEnum(UCHAR_SCRIPT, scs);
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(script==UCHAR_INVALID_CODE) {
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: '%s' is not a valid script code on line %ld\n",
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    scs, (long)lineNumber);
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(scx.contains(script)) {
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr,
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    "error in preparsed UCD: scx has duplicate '%s' codes on line %ld\n",
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    scs, (long)lineNumber);
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PARSE_ERROR;
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
5616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
5626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            scx.add(script);
5636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(scLimit!=NULL) {
5656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            s=scLimit+1;
5666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
5676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
5686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(scx.isEmpty()) {
5716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr, "error in preparsed UCD: empty scx= on line %ld\n", (long)lineNumber);
5726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_PARSE_ERROR;
5736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END
577