11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
31cb0ef41Sopenharmony_ci/*
41cb0ef41Sopenharmony_ci******************************************************************************
51cb0ef41Sopenharmony_ci* Copyright (C) 1999-2015, International Business Machines Corporation and
61cb0ef41Sopenharmony_ci* others. All Rights Reserved.
71cb0ef41Sopenharmony_ci******************************************************************************
81cb0ef41Sopenharmony_ci*/
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "uvectr64.h"
111cb0ef41Sopenharmony_ci#include "cmemory.h"
121cb0ef41Sopenharmony_ci#include "putilimp.h"
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciU_NAMESPACE_BEGIN
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci#define DEFAULT_CAPACITY 8
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci/*
191cb0ef41Sopenharmony_ci * Constants for hinting whether a key is an integer
201cb0ef41Sopenharmony_ci * or a pointer.  If a hint bit is zero, then the associated
211cb0ef41Sopenharmony_ci * token is assumed to be an integer. This is needed for iSeries
221cb0ef41Sopenharmony_ci */
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciUOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector64)
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciUVector64::UVector64(UErrorCode &status) :
271cb0ef41Sopenharmony_ci    count(0),
281cb0ef41Sopenharmony_ci    capacity(0),
291cb0ef41Sopenharmony_ci    maxCapacity(0),
301cb0ef41Sopenharmony_ci    elements(nullptr)
311cb0ef41Sopenharmony_ci{
321cb0ef41Sopenharmony_ci    _init(DEFAULT_CAPACITY, status);
331cb0ef41Sopenharmony_ci}
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciUVector64::UVector64(int32_t initialCapacity, UErrorCode &status) :
361cb0ef41Sopenharmony_ci    count(0),
371cb0ef41Sopenharmony_ci    capacity(0),
381cb0ef41Sopenharmony_ci    maxCapacity(0),
391cb0ef41Sopenharmony_ci    elements(0)
401cb0ef41Sopenharmony_ci{
411cb0ef41Sopenharmony_ci    _init(initialCapacity, status);
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_civoid UVector64::_init(int32_t initialCapacity, UErrorCode &status) {
471cb0ef41Sopenharmony_ci    // Fix bogus initialCapacity values; avoid malloc(0)
481cb0ef41Sopenharmony_ci    if (initialCapacity < 1) {
491cb0ef41Sopenharmony_ci        initialCapacity = DEFAULT_CAPACITY;
501cb0ef41Sopenharmony_ci    }
511cb0ef41Sopenharmony_ci    if (maxCapacity>0 && maxCapacity<initialCapacity) {
521cb0ef41Sopenharmony_ci        initialCapacity = maxCapacity;
531cb0ef41Sopenharmony_ci    }
541cb0ef41Sopenharmony_ci    if (initialCapacity > (int32_t)(INT32_MAX / sizeof(int64_t))) {
551cb0ef41Sopenharmony_ci        initialCapacity = uprv_min(DEFAULT_CAPACITY, maxCapacity);
561cb0ef41Sopenharmony_ci    }
571cb0ef41Sopenharmony_ci    elements = (int64_t *)uprv_malloc(sizeof(int64_t)*initialCapacity);
581cb0ef41Sopenharmony_ci    if (elements == 0) {
591cb0ef41Sopenharmony_ci        status = U_MEMORY_ALLOCATION_ERROR;
601cb0ef41Sopenharmony_ci    } else {
611cb0ef41Sopenharmony_ci        capacity = initialCapacity;
621cb0ef41Sopenharmony_ci    }
631cb0ef41Sopenharmony_ci}
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ciUVector64::~UVector64() {
661cb0ef41Sopenharmony_ci    uprv_free(elements);
671cb0ef41Sopenharmony_ci    elements = 0;
681cb0ef41Sopenharmony_ci}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci/**
711cb0ef41Sopenharmony_ci * Assign this object to another (make this a copy of 'other').
721cb0ef41Sopenharmony_ci */
731cb0ef41Sopenharmony_civoid UVector64::assign(const UVector64& other, UErrorCode &ec) {
741cb0ef41Sopenharmony_ci    if (ensureCapacity(other.count, ec)) {
751cb0ef41Sopenharmony_ci        setSize(other.count);
761cb0ef41Sopenharmony_ci        for (int32_t i=0; i<other.count; ++i) {
771cb0ef41Sopenharmony_ci            elements[i] = other.elements[i];
781cb0ef41Sopenharmony_ci        }
791cb0ef41Sopenharmony_ci    }
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_cibool UVector64::operator==(const UVector64& other) {
841cb0ef41Sopenharmony_ci    int32_t i;
851cb0ef41Sopenharmony_ci    if (count != other.count) return false;
861cb0ef41Sopenharmony_ci    for (i=0; i<count; ++i) {
871cb0ef41Sopenharmony_ci        if (elements[i] != other.elements[i]) {
881cb0ef41Sopenharmony_ci            return false;
891cb0ef41Sopenharmony_ci        }
901cb0ef41Sopenharmony_ci    }
911cb0ef41Sopenharmony_ci    return true;
921cb0ef41Sopenharmony_ci}
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_civoid UVector64::setElementAt(int64_t elem, int32_t index) {
961cb0ef41Sopenharmony_ci    if (0 <= index && index < count) {
971cb0ef41Sopenharmony_ci        elements[index] = elem;
981cb0ef41Sopenharmony_ci    }
991cb0ef41Sopenharmony_ci    /* else index out of range */
1001cb0ef41Sopenharmony_ci}
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_civoid UVector64::insertElementAt(int64_t elem, int32_t index, UErrorCode &status) {
1031cb0ef41Sopenharmony_ci    // must have 0 <= index <= count
1041cb0ef41Sopenharmony_ci    if (0 <= index && index <= count && ensureCapacity(count + 1, status)) {
1051cb0ef41Sopenharmony_ci        for (int32_t i=count; i>index; --i) {
1061cb0ef41Sopenharmony_ci            elements[i] = elements[i-1];
1071cb0ef41Sopenharmony_ci        }
1081cb0ef41Sopenharmony_ci        elements[index] = elem;
1091cb0ef41Sopenharmony_ci        ++count;
1101cb0ef41Sopenharmony_ci    }
1111cb0ef41Sopenharmony_ci    /* else index out of range */
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_civoid UVector64::removeAllElements() {
1151cb0ef41Sopenharmony_ci    count = 0;
1161cb0ef41Sopenharmony_ci}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ciUBool UVector64::expandCapacity(int32_t minimumCapacity, UErrorCode &status) {
1191cb0ef41Sopenharmony_ci    if (U_FAILURE(status)) {
1201cb0ef41Sopenharmony_ci        return false;
1211cb0ef41Sopenharmony_ci    }
1221cb0ef41Sopenharmony_ci    if (minimumCapacity < 0) {
1231cb0ef41Sopenharmony_ci        status = U_ILLEGAL_ARGUMENT_ERROR;
1241cb0ef41Sopenharmony_ci        return false;
1251cb0ef41Sopenharmony_ci    }
1261cb0ef41Sopenharmony_ci    if (capacity >= minimumCapacity) {
1271cb0ef41Sopenharmony_ci        return true;
1281cb0ef41Sopenharmony_ci    }
1291cb0ef41Sopenharmony_ci    if (maxCapacity>0 && minimumCapacity>maxCapacity) {
1301cb0ef41Sopenharmony_ci        status = U_BUFFER_OVERFLOW_ERROR;
1311cb0ef41Sopenharmony_ci        return false;
1321cb0ef41Sopenharmony_ci    }
1331cb0ef41Sopenharmony_ci    if (capacity > (INT32_MAX - 1) / 2) {  // integer overflow check
1341cb0ef41Sopenharmony_ci        status = U_ILLEGAL_ARGUMENT_ERROR;
1351cb0ef41Sopenharmony_ci        return false;
1361cb0ef41Sopenharmony_ci    }
1371cb0ef41Sopenharmony_ci    int32_t newCap = capacity * 2;
1381cb0ef41Sopenharmony_ci    if (newCap < minimumCapacity) {
1391cb0ef41Sopenharmony_ci        newCap = minimumCapacity;
1401cb0ef41Sopenharmony_ci    }
1411cb0ef41Sopenharmony_ci    if (maxCapacity > 0 && newCap > maxCapacity) {
1421cb0ef41Sopenharmony_ci        newCap = maxCapacity;
1431cb0ef41Sopenharmony_ci    }
1441cb0ef41Sopenharmony_ci    if (newCap > (int32_t)(INT32_MAX / sizeof(int64_t))) {  // integer overflow check
1451cb0ef41Sopenharmony_ci        // We keep the original memory contents on bad minimumCapacity/maxCapacity.
1461cb0ef41Sopenharmony_ci        status = U_ILLEGAL_ARGUMENT_ERROR;
1471cb0ef41Sopenharmony_ci        return false;
1481cb0ef41Sopenharmony_ci    }
1491cb0ef41Sopenharmony_ci    int64_t* newElems = (int64_t *)uprv_realloc(elements, sizeof(int64_t)*newCap);
1501cb0ef41Sopenharmony_ci    if (newElems == nullptr) {
1511cb0ef41Sopenharmony_ci        // We keep the original contents on the memory failure on realloc.
1521cb0ef41Sopenharmony_ci        status = U_MEMORY_ALLOCATION_ERROR;
1531cb0ef41Sopenharmony_ci        return false;
1541cb0ef41Sopenharmony_ci    }
1551cb0ef41Sopenharmony_ci    elements = newElems;
1561cb0ef41Sopenharmony_ci    capacity = newCap;
1571cb0ef41Sopenharmony_ci    return true;
1581cb0ef41Sopenharmony_ci}
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_civoid UVector64::setMaxCapacity(int32_t limit) {
1611cb0ef41Sopenharmony_ci    U_ASSERT(limit >= 0);
1621cb0ef41Sopenharmony_ci    if (limit < 0) {
1631cb0ef41Sopenharmony_ci        limit = 0;
1641cb0ef41Sopenharmony_ci    }
1651cb0ef41Sopenharmony_ci    if (limit > (int32_t)(INT32_MAX / sizeof(int64_t))) {  // integer overflow check for realloc
1661cb0ef41Sopenharmony_ci        //  Something is very wrong, don't realloc, leave capacity and maxCapacity unchanged
1671cb0ef41Sopenharmony_ci        return;
1681cb0ef41Sopenharmony_ci    }
1691cb0ef41Sopenharmony_ci    maxCapacity = limit;
1701cb0ef41Sopenharmony_ci    if (capacity <= maxCapacity || maxCapacity == 0) {
1711cb0ef41Sopenharmony_ci        // Current capacity is within the new limit.
1721cb0ef41Sopenharmony_ci        return;
1731cb0ef41Sopenharmony_ci    }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci    // New maximum capacity is smaller than the current size.
1761cb0ef41Sopenharmony_ci    // Realloc the storage to the new, smaller size.
1771cb0ef41Sopenharmony_ci    int64_t* newElems = (int64_t *)uprv_realloc(elements, sizeof(int64_t)*maxCapacity);
1781cb0ef41Sopenharmony_ci    if (newElems == nullptr) {
1791cb0ef41Sopenharmony_ci        // Realloc to smaller failed.
1801cb0ef41Sopenharmony_ci        //   Just keep what we had.  No need to call it a failure.
1811cb0ef41Sopenharmony_ci        return;
1821cb0ef41Sopenharmony_ci    }
1831cb0ef41Sopenharmony_ci    elements = newElems;
1841cb0ef41Sopenharmony_ci    capacity = maxCapacity;
1851cb0ef41Sopenharmony_ci    if (count > capacity) {
1861cb0ef41Sopenharmony_ci        count = capacity;
1871cb0ef41Sopenharmony_ci    }
1881cb0ef41Sopenharmony_ci}
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci/**
1911cb0ef41Sopenharmony_ci * Change the size of this vector as follows: If newSize is smaller,
1921cb0ef41Sopenharmony_ci * then truncate the array, possibly deleting held elements for i >=
1931cb0ef41Sopenharmony_ci * newSize.  If newSize is larger, grow the array, filling in new
1941cb0ef41Sopenharmony_ci * slots with nullptr.
1951cb0ef41Sopenharmony_ci */
1961cb0ef41Sopenharmony_civoid UVector64::setSize(int32_t newSize) {
1971cb0ef41Sopenharmony_ci    int32_t i;
1981cb0ef41Sopenharmony_ci    if (newSize < 0) {
1991cb0ef41Sopenharmony_ci        return;
2001cb0ef41Sopenharmony_ci    }
2011cb0ef41Sopenharmony_ci    if (newSize > count) {
2021cb0ef41Sopenharmony_ci        UErrorCode ec = U_ZERO_ERROR;
2031cb0ef41Sopenharmony_ci        if (!ensureCapacity(newSize, ec)) {
2041cb0ef41Sopenharmony_ci            return;
2051cb0ef41Sopenharmony_ci        }
2061cb0ef41Sopenharmony_ci        for (i=count; i<newSize; ++i) {
2071cb0ef41Sopenharmony_ci            elements[i] = 0;
2081cb0ef41Sopenharmony_ci        }
2091cb0ef41Sopenharmony_ci    }
2101cb0ef41Sopenharmony_ci    count = newSize;
2111cb0ef41Sopenharmony_ci}
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ciU_NAMESPACE_END
2141cb0ef41Sopenharmony_ci
215