12e5b6d6dSopenharmony_ci// © 2018 and later: Unicode, Inc. and others.
22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
32e5b6d6dSopenharmony_ci
42e5b6d6dSopenharmony_ci// layoutpropsbuilder.cpp
52e5b6d6dSopenharmony_ci// created: 2018aug30 Markus W. Scherer
62e5b6d6dSopenharmony_ci
72e5b6d6dSopenharmony_ci#include <stdio.h>
82e5b6d6dSopenharmony_ci#include <string.h>
92e5b6d6dSopenharmony_ci#include "unicode/utypes.h"
102e5b6d6dSopenharmony_ci#include "unicode/uchar.h"
112e5b6d6dSopenharmony_ci#include "unicode/ucptrie.h"
122e5b6d6dSopenharmony_ci#include "unicode/udata.h"
132e5b6d6dSopenharmony_ci#include "unicode/umutablecptrie.h"
142e5b6d6dSopenharmony_ci#include "unicode/uniset.h"
152e5b6d6dSopenharmony_ci#include "cmemory.h"
162e5b6d6dSopenharmony_ci#include "genprops.h"
172e5b6d6dSopenharmony_ci#include "ppucd.h"
182e5b6d6dSopenharmony_ci#include "uassert.h"
192e5b6d6dSopenharmony_ci#include "ulayout_props.h"
202e5b6d6dSopenharmony_ci#include "unewdata.h"
212e5b6d6dSopenharmony_ci
222e5b6d6dSopenharmony_ci/* Unicode layout properties file format ---------------------------------------
232e5b6d6dSopenharmony_ci
242e5b6d6dSopenharmony_ciThe file format prepared and written here contains several data
252e5b6d6dSopenharmony_cistructures that store indexes or data.
262e5b6d6dSopenharmony_ci
272e5b6d6dSopenharmony_ciBefore the data contents described below, there are the headers required by
282e5b6d6dSopenharmony_cithe udata API for loading ICU data. Especially, a UDataInfo structure
292e5b6d6dSopenharmony_ciprecedes the actual data. It contains platform properties values and the
302e5b6d6dSopenharmony_cifile format version.
312e5b6d6dSopenharmony_ci
322e5b6d6dSopenharmony_ciThe following is a description of format version 1.0 .
332e5b6d6dSopenharmony_ci
342e5b6d6dSopenharmony_ciThe file contains the following structures:
352e5b6d6dSopenharmony_ci
362e5b6d6dSopenharmony_ci    const int32_t indexes[i0] with values i0, i1, ...:
372e5b6d6dSopenharmony_ci    (see ULAYOUT_IX_... constants for names of indexes)
382e5b6d6dSopenharmony_ci
392e5b6d6dSopenharmony_ci    i0 indexesLength; -- length of indexes[] (ULAYOUT_IX_COUNT)
402e5b6d6dSopenharmony_ci    i1 inpcTop; -- limit byte offset of the InPC trie
412e5b6d6dSopenharmony_ci    i2 inscTop; -- limit byte offset of the InSC trie
422e5b6d6dSopenharmony_ci    i3 voTop; -- limit byte offset of the vo trie
432e5b6d6dSopenharmony_ci    i4..i7 -- reserved, same as the last limit byte offset
442e5b6d6dSopenharmony_ci    i8 -- reserved, 0
452e5b6d6dSopenharmony_ci
462e5b6d6dSopenharmony_ci    i9 maxValues; -- max values of the InPC, InSC, vo properties
472e5b6d6dSopenharmony_ci        (8 bits each; lowest 8 bits reserved, 0)
482e5b6d6dSopenharmony_ci    i10..i11 -- reserved, 0
492e5b6d6dSopenharmony_ci
502e5b6d6dSopenharmony_ci    After the indexes array follow consecutive, serialized,
512e5b6d6dSopenharmony_ci    single-property code point tries for the following properties,
522e5b6d6dSopenharmony_ci    each built "small" or "fast",
532e5b6d6dSopenharmony_ci    each padded to a multiple of 16 bytes:
542e5b6d6dSopenharmony_ci    - InPC
552e5b6d6dSopenharmony_ci    - InSC
562e5b6d6dSopenharmony_ci    - vo
572e5b6d6dSopenharmony_ci
582e5b6d6dSopenharmony_ci----------------------------------------------------------------------------- */
592e5b6d6dSopenharmony_ci
602e5b6d6dSopenharmony_ciU_NAMESPACE_USE
612e5b6d6dSopenharmony_ci
622e5b6d6dSopenharmony_ci// UDataInfo cf. udata.h
632e5b6d6dSopenharmony_cistatic UDataInfo dataInfo = {
642e5b6d6dSopenharmony_ci    sizeof(UDataInfo),
652e5b6d6dSopenharmony_ci    0,
662e5b6d6dSopenharmony_ci
672e5b6d6dSopenharmony_ci    U_IS_BIG_ENDIAN,
682e5b6d6dSopenharmony_ci    U_CHARSET_FAMILY,
692e5b6d6dSopenharmony_ci    U_SIZEOF_UCHAR,
702e5b6d6dSopenharmony_ci    0,
712e5b6d6dSopenharmony_ci
722e5b6d6dSopenharmony_ci    // dataFormat="Layo"
732e5b6d6dSopenharmony_ci    { ULAYOUT_FMT_0, ULAYOUT_FMT_1, ULAYOUT_FMT_2, ULAYOUT_FMT_3 },
742e5b6d6dSopenharmony_ci    { 1, 0, 0, 0 },  // formatVersion
752e5b6d6dSopenharmony_ci    { 12, 0, 0, 0 }  // dataVersion
762e5b6d6dSopenharmony_ci};
772e5b6d6dSopenharmony_ci
782e5b6d6dSopenharmony_ciclass LayoutPropsBuilder : public PropsBuilder {
792e5b6d6dSopenharmony_cipublic:
802e5b6d6dSopenharmony_ci    LayoutPropsBuilder(UErrorCode &errorCode);
812e5b6d6dSopenharmony_ci    virtual ~LayoutPropsBuilder() U_OVERRIDE;
822e5b6d6dSopenharmony_ci
832e5b6d6dSopenharmony_ci    virtual void setUnicodeVersion(const UVersionInfo version) U_OVERRIDE;
842e5b6d6dSopenharmony_ci    virtual void setProps(const UniProps &props, const UnicodeSet &newValues, UErrorCode &errorCode) U_OVERRIDE;
852e5b6d6dSopenharmony_ci    virtual void build(UErrorCode &errorCode) U_OVERRIDE;
862e5b6d6dSopenharmony_ci    virtual void writeBinaryData(const char *path, UBool withCopyright, UErrorCode &errorCode) U_OVERRIDE;
872e5b6d6dSopenharmony_ci
882e5b6d6dSopenharmony_ciprivate:
892e5b6d6dSopenharmony_ci    void setIntProp(const UniProps &, const UnicodeSet &newValues,
902e5b6d6dSopenharmony_ci                    UProperty prop, UMutableCPTrie *trie,
912e5b6d6dSopenharmony_ci                    UErrorCode &errorCode);
922e5b6d6dSopenharmony_ci    int32_t getMaxIntValue(UProperty prop) const {
932e5b6d6dSopenharmony_ci        return maxIntValues[prop - UCHAR_INT_START];
942e5b6d6dSopenharmony_ci    }
952e5b6d6dSopenharmony_ci    void checkMaxIntValue(UProperty prop, int32_t maxMax, UErrorCode &errorCode) const;
962e5b6d6dSopenharmony_ci
972e5b6d6dSopenharmony_ci    int32_t maxIntValues[UCHAR_INT_LIMIT - UCHAR_INT_START];
982e5b6d6dSopenharmony_ci    UMutableCPTrie *inpcMutableTrie;
992e5b6d6dSopenharmony_ci    UMutableCPTrie *inscMutableTrie;
1002e5b6d6dSopenharmony_ci    UMutableCPTrie *voMutableTrie;
1012e5b6d6dSopenharmony_ci
1022e5b6d6dSopenharmony_ci    UCPTrie *inpcTrie;
1032e5b6d6dSopenharmony_ci    UCPTrie *inscTrie;
1042e5b6d6dSopenharmony_ci    UCPTrie *voTrie;
1052e5b6d6dSopenharmony_ci};
1062e5b6d6dSopenharmony_ci
1072e5b6d6dSopenharmony_ciLayoutPropsBuilder::LayoutPropsBuilder(UErrorCode &errorCode) :
1082e5b6d6dSopenharmony_ci        inpcTrie(nullptr), inscTrie(nullptr), voTrie(nullptr) {
1092e5b6d6dSopenharmony_ci    memset(maxIntValues, 0, sizeof(maxIntValues));
1102e5b6d6dSopenharmony_ci    inpcMutableTrie = umutablecptrie_open(0, 0, &errorCode);
1112e5b6d6dSopenharmony_ci    inscMutableTrie = umutablecptrie_open(0, 0, &errorCode);
1122e5b6d6dSopenharmony_ci    voMutableTrie = umutablecptrie_open(0, 0, &errorCode);
1132e5b6d6dSopenharmony_ci    if (U_FAILURE(errorCode)) {
1142e5b6d6dSopenharmony_ci        fprintf(stderr, "genprops error: layoutpropsbuilder umutablecptrie_open() failed - %s\n",
1152e5b6d6dSopenharmony_ci                u_errorName(errorCode));
1162e5b6d6dSopenharmony_ci    }
1172e5b6d6dSopenharmony_ci}
1182e5b6d6dSopenharmony_ci
1192e5b6d6dSopenharmony_ciLayoutPropsBuilder::~LayoutPropsBuilder() {
1202e5b6d6dSopenharmony_ci    umutablecptrie_close(inpcMutableTrie);
1212e5b6d6dSopenharmony_ci    umutablecptrie_close(inscMutableTrie);
1222e5b6d6dSopenharmony_ci    umutablecptrie_close(voMutableTrie);
1232e5b6d6dSopenharmony_ci    ucptrie_close(inpcTrie);
1242e5b6d6dSopenharmony_ci    ucptrie_close(inscTrie);
1252e5b6d6dSopenharmony_ci    ucptrie_close(voTrie);
1262e5b6d6dSopenharmony_ci}
1272e5b6d6dSopenharmony_ci
1282e5b6d6dSopenharmony_civoid
1292e5b6d6dSopenharmony_ciLayoutPropsBuilder::setUnicodeVersion(const UVersionInfo version) {
1302e5b6d6dSopenharmony_ci    uprv_memcpy(dataInfo.dataVersion, version, 4);
1312e5b6d6dSopenharmony_ci}
1322e5b6d6dSopenharmony_ci
1332e5b6d6dSopenharmony_civoid
1342e5b6d6dSopenharmony_ciLayoutPropsBuilder::setProps(const UniProps &props, const UnicodeSet &newValues,
1352e5b6d6dSopenharmony_ci                             UErrorCode &errorCode) {
1362e5b6d6dSopenharmony_ci    setIntProp(props, newValues, UCHAR_INDIC_POSITIONAL_CATEGORY, inpcMutableTrie, errorCode);
1372e5b6d6dSopenharmony_ci    setIntProp(props, newValues, UCHAR_INDIC_SYLLABIC_CATEGORY, inscMutableTrie, errorCode);
1382e5b6d6dSopenharmony_ci    setIntProp(props, newValues, UCHAR_VERTICAL_ORIENTATION, voMutableTrie, errorCode);
1392e5b6d6dSopenharmony_ci}
1402e5b6d6dSopenharmony_ci
1412e5b6d6dSopenharmony_civoid LayoutPropsBuilder::setIntProp(const UniProps &props, const UnicodeSet &newValues,
1422e5b6d6dSopenharmony_ci                                    UProperty prop, UMutableCPTrie *trie,
1432e5b6d6dSopenharmony_ci                                    UErrorCode &errorCode) {
1442e5b6d6dSopenharmony_ci    if (U_SUCCESS(errorCode) && newValues.contains(prop)) {
1452e5b6d6dSopenharmony_ci        UChar32 start=props.start;
1462e5b6d6dSopenharmony_ci        UChar32 end=props.end;
1472e5b6d6dSopenharmony_ci        int32_t value = props.getIntProp(prop);
1482e5b6d6dSopenharmony_ci        if (value < 0) {
1492e5b6d6dSopenharmony_ci            fprintf(stderr, "error: unencodable negative value for property 0x%x %04lX..%04lX=%ld\n",
1502e5b6d6dSopenharmony_ci                    (int)prop, (long)start, (long)end, (long)value);
1512e5b6d6dSopenharmony_ci            errorCode = U_ILLEGAL_ARGUMENT_ERROR;
1522e5b6d6dSopenharmony_ci            return;
1532e5b6d6dSopenharmony_ci        }
1542e5b6d6dSopenharmony_ci        if (value > maxIntValues[prop - UCHAR_INT_START]) {
1552e5b6d6dSopenharmony_ci            maxIntValues[prop - UCHAR_INT_START] = value;
1562e5b6d6dSopenharmony_ci        }
1572e5b6d6dSopenharmony_ci        if (start == end) {
1582e5b6d6dSopenharmony_ci            umutablecptrie_set(trie, start, value, &errorCode);
1592e5b6d6dSopenharmony_ci        } else {
1602e5b6d6dSopenharmony_ci            umutablecptrie_setRange(trie, start, end, value, &errorCode);
1612e5b6d6dSopenharmony_ci        }
1622e5b6d6dSopenharmony_ci        if (U_FAILURE(errorCode)) {
1632e5b6d6dSopenharmony_ci            fprintf(stderr, "error: umutablecptrie_set(prop 0x%x trie %04lX..%04lX) failed - %s\n",
1642e5b6d6dSopenharmony_ci                    (int)prop, (long)start, (long)end, u_errorName(errorCode));
1652e5b6d6dSopenharmony_ci        }
1662e5b6d6dSopenharmony_ci    }
1672e5b6d6dSopenharmony_ci}
1682e5b6d6dSopenharmony_ci
1692e5b6d6dSopenharmony_cinamespace {
1702e5b6d6dSopenharmony_ci
1712e5b6d6dSopenharmony_ciUCPTrie *buildUCPTrie(const char *name, UMutableCPTrie *mutableTrie,
1722e5b6d6dSopenharmony_ci                      UCPTrieType type, UCPTrieValueWidth valueWidth, UErrorCode &errorCode) {
1732e5b6d6dSopenharmony_ci    UCPTrie *trie = umutablecptrie_buildImmutable(mutableTrie, type, valueWidth, &errorCode);
1742e5b6d6dSopenharmony_ci    if(U_FAILURE(errorCode)) {
1752e5b6d6dSopenharmony_ci        fprintf(stderr, "genprops error: %s trie buildImmutable() failed: %s\n",
1762e5b6d6dSopenharmony_ci                name, u_errorName(errorCode));
1772e5b6d6dSopenharmony_ci        return trie;
1782e5b6d6dSopenharmony_ci    }
1792e5b6d6dSopenharmony_ci    if (!beQuiet) {
1802e5b6d6dSopenharmony_ci        UErrorCode overflow = U_ZERO_ERROR;
1812e5b6d6dSopenharmony_ci        int32_t length = ucptrie_toBinary(trie, nullptr, 0, &overflow);
1822e5b6d6dSopenharmony_ci        printf("%11s trie size in bytes:        %5u\n", name, (int)length);
1832e5b6d6dSopenharmony_ci    }
1842e5b6d6dSopenharmony_ci    return trie;
1852e5b6d6dSopenharmony_ci}
1862e5b6d6dSopenharmony_ci
1872e5b6d6dSopenharmony_ciconstexpr int32_t TRIE_BLOCK_CAPACITY = 100000;
1882e5b6d6dSopenharmony_ci
1892e5b6d6dSopenharmony_ciuint8_t inpcBytes[TRIE_BLOCK_CAPACITY];
1902e5b6d6dSopenharmony_ciuint8_t inscBytes[TRIE_BLOCK_CAPACITY];
1912e5b6d6dSopenharmony_ciuint8_t voBytes[TRIE_BLOCK_CAPACITY];
1922e5b6d6dSopenharmony_ci
1932e5b6d6dSopenharmony_ciint32_t inpcLength = 0;
1942e5b6d6dSopenharmony_ciint32_t inscLength = 0;
1952e5b6d6dSopenharmony_ciint32_t voLength = 0;
1962e5b6d6dSopenharmony_ci
1972e5b6d6dSopenharmony_ciint32_t writeTrieBytes(const UCPTrie *trie, uint8_t block[], UErrorCode &errorCode) {
1982e5b6d6dSopenharmony_ci    int32_t length = ucptrie_toBinary(trie, block, TRIE_BLOCK_CAPACITY, &errorCode);
1992e5b6d6dSopenharmony_ci    while ((length & 0xf) != 0) {
2002e5b6d6dSopenharmony_ci        block[length++] = 0xaa;
2012e5b6d6dSopenharmony_ci    }
2022e5b6d6dSopenharmony_ci    return length;
2032e5b6d6dSopenharmony_ci}
2042e5b6d6dSopenharmony_ci
2052e5b6d6dSopenharmony_ci}  // namespace
2062e5b6d6dSopenharmony_ci
2072e5b6d6dSopenharmony_civoid
2082e5b6d6dSopenharmony_ciLayoutPropsBuilder::build(UErrorCode &errorCode) {
2092e5b6d6dSopenharmony_ci    if (U_FAILURE(errorCode)) { return; }
2102e5b6d6dSopenharmony_ci    if (!beQuiet) {
2112e5b6d6dSopenharmony_ci        puts("* text layout properties stats *");
2122e5b6d6dSopenharmony_ci    }
2132e5b6d6dSopenharmony_ci
2142e5b6d6dSopenharmony_ci    checkMaxIntValue(UCHAR_INDIC_POSITIONAL_CATEGORY, 0xff, errorCode);
2152e5b6d6dSopenharmony_ci    checkMaxIntValue(UCHAR_INDIC_SYLLABIC_CATEGORY, 0xff, errorCode);
2162e5b6d6dSopenharmony_ci    checkMaxIntValue(UCHAR_VERTICAL_ORIENTATION, 0xff, errorCode);
2172e5b6d6dSopenharmony_ci    inpcTrie = buildUCPTrie("inpc", inpcMutableTrie,
2182e5b6d6dSopenharmony_ci                            UCPTRIE_TYPE_SMALL, UCPTRIE_VALUE_BITS_8, errorCode);
2192e5b6d6dSopenharmony_ci    inscTrie = buildUCPTrie("insc", inscMutableTrie,
2202e5b6d6dSopenharmony_ci                            UCPTRIE_TYPE_SMALL, UCPTRIE_VALUE_BITS_8, errorCode);
2212e5b6d6dSopenharmony_ci    voTrie = buildUCPTrie("vo", voMutableTrie,
2222e5b6d6dSopenharmony_ci                          UCPTRIE_TYPE_SMALL, UCPTRIE_VALUE_BITS_8, errorCode);
2232e5b6d6dSopenharmony_ci
2242e5b6d6dSopenharmony_ci    inpcLength = writeTrieBytes(inpcTrie, inpcBytes, errorCode);
2252e5b6d6dSopenharmony_ci    inscLength = writeTrieBytes(inscTrie, inscBytes, errorCode);
2262e5b6d6dSopenharmony_ci    voLength = writeTrieBytes(voTrie, voBytes, errorCode);
2272e5b6d6dSopenharmony_ci
2282e5b6d6dSopenharmony_ci    if (!beQuiet) {
2292e5b6d6dSopenharmony_ci        int32_t size = ULAYOUT_IX_COUNT * 4 + inpcLength + inscLength + voLength;
2302e5b6d6dSopenharmony_ci        printf("data size:                             %5d\n", (int)size);
2312e5b6d6dSopenharmony_ci    }
2322e5b6d6dSopenharmony_ci}
2332e5b6d6dSopenharmony_ci
2342e5b6d6dSopenharmony_civoid LayoutPropsBuilder::checkMaxIntValue(UProperty prop, int32_t maxMax,
2352e5b6d6dSopenharmony_ci                                          UErrorCode &errorCode) const {
2362e5b6d6dSopenharmony_ci    int32_t max = getMaxIntValue(prop);
2372e5b6d6dSopenharmony_ci    if (max > maxMax) {
2382e5b6d6dSopenharmony_ci        fprintf(stderr, "genprops error: 0x%x max value = %d overflow\n", (int)prop, (int)max);
2392e5b6d6dSopenharmony_ci        errorCode = U_ILLEGAL_ARGUMENT_ERROR;
2402e5b6d6dSopenharmony_ci    }
2412e5b6d6dSopenharmony_ci}
2422e5b6d6dSopenharmony_ci
2432e5b6d6dSopenharmony_ci// In ICU 63, we had functions writeCSourceFile() and writeJavaSourceFile().
2442e5b6d6dSopenharmony_ci// For Java, each serialized trie was written as a String constant with
2452e5b6d6dSopenharmony_ci// one byte per char and an optimization for byte 0,
2462e5b6d6dSopenharmony_ci// to optimize for Java .class file size.
2472e5b6d6dSopenharmony_ci// (See ICU 63 if we need to resurrect some of that code.)
2482e5b6d6dSopenharmony_ci// Since ICU 64, we write a binary ulayout.icu file for use in both C++ & Java.
2492e5b6d6dSopenharmony_ci
2502e5b6d6dSopenharmony_civoid
2512e5b6d6dSopenharmony_ciLayoutPropsBuilder::writeBinaryData(const char *path, UBool withCopyright, UErrorCode &errorCode) {
2522e5b6d6dSopenharmony_ci    if (U_FAILURE(errorCode)) { return; }
2532e5b6d6dSopenharmony_ci
2542e5b6d6dSopenharmony_ci    UNewDataMemory *pData = udata_create(
2552e5b6d6dSopenharmony_ci        path, ULAYOUT_DATA_TYPE, ULAYOUT_DATA_NAME, &dataInfo,
2562e5b6d6dSopenharmony_ci        withCopyright ? U_COPYRIGHT_STRING : NULL, &errorCode);
2572e5b6d6dSopenharmony_ci    if (U_FAILURE(errorCode)) {
2582e5b6d6dSopenharmony_ci        fprintf(stderr, "genprops: udata_create(%s, ulayout.icu) failed - %s\n",
2592e5b6d6dSopenharmony_ci                path, u_errorName(errorCode));
2602e5b6d6dSopenharmony_ci        return;
2612e5b6d6dSopenharmony_ci    }
2622e5b6d6dSopenharmony_ci
2632e5b6d6dSopenharmony_ci    int32_t indexes[ULAYOUT_IX_COUNT] = { ULAYOUT_IX_COUNT };
2642e5b6d6dSopenharmony_ci    int32_t top = ULAYOUT_IX_COUNT * 4;
2652e5b6d6dSopenharmony_ci
2662e5b6d6dSopenharmony_ci    indexes[ULAYOUT_IX_INPC_TRIE_TOP] = (top += inpcLength);
2672e5b6d6dSopenharmony_ci    indexes[ULAYOUT_IX_INSC_TRIE_TOP] = (top += inscLength);
2682e5b6d6dSopenharmony_ci    indexes[ULAYOUT_IX_VO_TRIE_TOP] = (top += voLength);
2692e5b6d6dSopenharmony_ci
2702e5b6d6dSopenharmony_ci    // Set reserved trie-top values to the top of the last trie
2712e5b6d6dSopenharmony_ci    // so that they look empty until a later file format version
2722e5b6d6dSopenharmony_ci    // uses one or more of these slots.
2732e5b6d6dSopenharmony_ci    for (int32_t i = ULAYOUT_IX_RESERVED_TOP; i <= ULAYOUT_IX_TRIES_TOP; ++i) {
2742e5b6d6dSopenharmony_ci        indexes[i] = top;
2752e5b6d6dSopenharmony_ci    }
2762e5b6d6dSopenharmony_ci
2772e5b6d6dSopenharmony_ci    indexes[ULAYOUT_IX_MAX_VALUES] =
2782e5b6d6dSopenharmony_ci        ((getMaxIntValue(UCHAR_INDIC_POSITIONAL_CATEGORY)) << ULAYOUT_MAX_INPC_SHIFT) |
2792e5b6d6dSopenharmony_ci        ((getMaxIntValue(UCHAR_INDIC_SYLLABIC_CATEGORY)) << ULAYOUT_MAX_INSC_SHIFT) |
2802e5b6d6dSopenharmony_ci        ((getMaxIntValue(UCHAR_VERTICAL_ORIENTATION)) << ULAYOUT_MAX_VO_SHIFT);
2812e5b6d6dSopenharmony_ci
2822e5b6d6dSopenharmony_ci    udata_writeBlock(pData, indexes, sizeof(indexes));
2832e5b6d6dSopenharmony_ci    udata_writeBlock(pData, inpcBytes, inpcLength);
2842e5b6d6dSopenharmony_ci    udata_writeBlock(pData, inscBytes, inscLength);
2852e5b6d6dSopenharmony_ci    udata_writeBlock(pData, voBytes, voLength);
2862e5b6d6dSopenharmony_ci
2872e5b6d6dSopenharmony_ci    long dataLength = udata_finish(pData, &errorCode);
2882e5b6d6dSopenharmony_ci    if (U_FAILURE(errorCode)) {
2892e5b6d6dSopenharmony_ci        fprintf(stderr, "genprops: error %s writing the output file\n", u_errorName(errorCode));
2902e5b6d6dSopenharmony_ci        return;
2912e5b6d6dSopenharmony_ci    }
2922e5b6d6dSopenharmony_ci
2932e5b6d6dSopenharmony_ci    if (dataLength != (long)top) {
2942e5b6d6dSopenharmony_ci        fprintf(stderr,
2952e5b6d6dSopenharmony_ci                "udata_finish(ulayout.icu) reports %ld bytes written but should be %ld\n",
2962e5b6d6dSopenharmony_ci                dataLength, (long)top);
2972e5b6d6dSopenharmony_ci        errorCode = U_INTERNAL_PROGRAM_ERROR;
2982e5b6d6dSopenharmony_ci    }
2992e5b6d6dSopenharmony_ci}
3002e5b6d6dSopenharmony_ci
3012e5b6d6dSopenharmony_ciPropsBuilder *
3022e5b6d6dSopenharmony_cicreateLayoutPropsBuilder(UErrorCode &errorCode) {
3032e5b6d6dSopenharmony_ci    if(U_FAILURE(errorCode)) { return nullptr; }
3042e5b6d6dSopenharmony_ci    PropsBuilder *pb=new LayoutPropsBuilder(errorCode);
3052e5b6d6dSopenharmony_ci    if(pb==nullptr) {
3062e5b6d6dSopenharmony_ci        errorCode=U_MEMORY_ALLOCATION_ERROR;
3072e5b6d6dSopenharmony_ci    }
3082e5b6d6dSopenharmony_ci    return pb;
3092e5b6d6dSopenharmony_ci}
310