tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

formattedval_iterimpl.cpp (6245B)


      1 // © 2018 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 
      4 #include "unicode/utypes.h"
      5 
      6 #if !UCONFIG_NO_FORMATTING
      7 
      8 // This file contains one implementation of FormattedValue.
      9 // Other independent implementations should go into their own cpp file for
     10 // better dependency modularization.
     11 
     12 #include "formattedval_impl.h"
     13 #include "putilimp.h"
     14 
     15 U_NAMESPACE_BEGIN
     16 
     17 
     18 FormattedValueFieldPositionIteratorImpl::FormattedValueFieldPositionIteratorImpl(
     19        int32_t initialFieldCapacity,
     20        UErrorCode& status)
     21        : fFields(initialFieldCapacity * 4, status) {
     22 }
     23 
     24 FormattedValueFieldPositionIteratorImpl::~FormattedValueFieldPositionIteratorImpl() = default;
     25 
     26 UnicodeString FormattedValueFieldPositionIteratorImpl::toString(
     27        UErrorCode&) const {
     28    return fString;
     29 }
     30 
     31 UnicodeString FormattedValueFieldPositionIteratorImpl::toTempString(
     32        UErrorCode&) const {
     33    // The alias must point to memory owned by this object;
     34    // fastCopyFrom doesn't do this when using a stack buffer.
     35    return UnicodeString(true, fString.getBuffer(), fString.length());
     36 }
     37 
     38 Appendable& FormattedValueFieldPositionIteratorImpl::appendTo(
     39        Appendable& appendable,
     40        UErrorCode&) const {
     41    appendable.appendString(fString.getBuffer(), fString.length());
     42    return appendable;
     43 }
     44 
     45 UBool FormattedValueFieldPositionIteratorImpl::nextPosition(
     46        ConstrainedFieldPosition& cfpos,
     47        UErrorCode&) const {
     48    U_ASSERT(fFields.size() % 4 == 0);
     49    int32_t numFields = fFields.size() / 4;
     50    int32_t i = static_cast<int32_t>(cfpos.getInt64IterationContext());
     51    for (; i < numFields; i++) {
     52        UFieldCategory category = static_cast<UFieldCategory>(fFields.elementAti(i * 4));
     53        int32_t field = fFields.elementAti(i * 4 + 1);
     54        if (cfpos.matchesField(category, field)) {
     55            int32_t start = fFields.elementAti(i * 4 + 2);
     56            int32_t limit = fFields.elementAti(i * 4 + 3);
     57            cfpos.setState(category, field, start, limit);
     58            break;
     59        }
     60    }
     61    cfpos.setInt64IterationContext(i == numFields ? i : i + 1);
     62    return i < numFields;
     63 }
     64 
     65 
     66 FieldPositionIteratorHandler FormattedValueFieldPositionIteratorImpl::getHandler(
     67        UErrorCode& status) {
     68    return FieldPositionIteratorHandler(&fFields, status);
     69 }
     70 
     71 void FormattedValueFieldPositionIteratorImpl::appendString(
     72        UnicodeString string,
     73        UErrorCode& status) {
     74    if (U_FAILURE(status)) {
     75        return;
     76    }
     77    fString.append(string);
     78    // Make the string NUL-terminated
     79    if (fString.getTerminatedBuffer() == nullptr) {
     80        status = U_MEMORY_ALLOCATION_ERROR;
     81        return;
     82    }
     83 }
     84 
     85 
     86 void FormattedValueFieldPositionIteratorImpl::addOverlapSpans(
     87        UFieldCategory spanCategory,
     88        int8_t firstIndex,
     89        UErrorCode& status) {
     90    // In order to avoid fancy data structures, this is an O(N^2) algorithm,
     91    // which should be fine for all real-life applications of this function.
     92    int32_t s1a = INT32_MAX;
     93    int32_t s1b = 0;
     94    int32_t s2a = INT32_MAX;
     95    int32_t s2b = 0;
     96    int32_t numFields = fFields.size() / 4;
     97    for (int32_t i = 0; i<numFields; i++) {
     98        int32_t field1 = fFields.elementAti(i * 4 + 1);
     99        for (int32_t j = i + 1; j<numFields; j++) {
    100            int32_t field2 = fFields.elementAti(j * 4 + 1);
    101            if (field1 != field2) {
    102                continue;
    103            }
    104            // Found a duplicate
    105            s1a = uprv_min(s1a, fFields.elementAti(i * 4 + 2));
    106            s1b = uprv_max(s1b, fFields.elementAti(i * 4 + 3));
    107            s2a = uprv_min(s2a, fFields.elementAti(j * 4 + 2));
    108            s2b = uprv_max(s2b, fFields.elementAti(j * 4 + 3));
    109            break;
    110        }
    111    }
    112    if (s1a != INT32_MAX) {
    113        // Success: add the two span fields
    114        fFields.addElement(spanCategory, status);
    115        fFields.addElement(firstIndex, status);
    116        fFields.addElement(s1a, status);
    117        fFields.addElement(s1b, status);
    118        fFields.addElement(spanCategory, status);
    119        fFields.addElement(1 - firstIndex, status);
    120        fFields.addElement(s2a, status);
    121        fFields.addElement(s2b, status);
    122    }
    123 }
    124 
    125 
    126 void FormattedValueFieldPositionIteratorImpl::sort() {
    127    // Use bubble sort, O(N^2) but easy and no fancy data structures.
    128    int32_t numFields = fFields.size() / 4;
    129    while (true) {
    130        bool isSorted = true;
    131        for (int32_t i=0; i<numFields-1; i++) {
    132            int32_t categ1 = fFields.elementAti(i*4 + 0);
    133            int32_t field1 = fFields.elementAti(i*4 + 1);
    134            int32_t start1 = fFields.elementAti(i*4 + 2);
    135            int32_t limit1 = fFields.elementAti(i*4 + 3);
    136            int32_t categ2 = fFields.elementAti(i*4 + 4);
    137            int32_t field2 = fFields.elementAti(i*4 + 5);
    138            int32_t start2 = fFields.elementAti(i*4 + 6);
    139            int32_t limit2 = fFields.elementAti(i*4 + 7);
    140            int64_t comparison = 0;
    141            if (start1 != start2) {
    142                // Higher start index -> higher rank
    143                comparison = start2 - start1;
    144            } else if (limit1 != limit2) {
    145                // Higher length (end index) -> lower rank
    146                comparison = limit1 - limit2;
    147            } else if (categ1 != categ2) {
    148                // Higher field category -> lower rank
    149                comparison = categ1 - categ2;
    150            } else if (field1 != field2) {
    151                // Higher field -> higher rank
    152                comparison = field2 - field1;
    153            }
    154            if (comparison < 0) {
    155                // Perform a swap
    156                isSorted = false;
    157                fFields.setElementAt(categ2, i*4 + 0);
    158                fFields.setElementAt(field2, i*4 + 1);
    159                fFields.setElementAt(start2, i*4 + 2);
    160                fFields.setElementAt(limit2, i*4 + 3);
    161                fFields.setElementAt(categ1, i*4 + 4);
    162                fFields.setElementAt(field1, i*4 + 5);
    163                fFields.setElementAt(start1, i*4 + 6);
    164                fFields.setElementAt(limit1, i*4 + 7);
    165            }
    166        }
    167        if (isSorted) {
    168            break;
    169        }
    170    }
    171 }
    172 
    173 
    174 U_NAMESPACE_END
    175 
    176 #endif /* #if !UCONFIG_NO_FORMATTING */