Line data Source code
1 : // © 2016 and later: Unicode, Inc. and others.
2 : // License & terms of use: http://www.unicode.org/copyright.html
3 : /*
4 : ******************************************************************************
5 : * Copyright (C) 1999-2015, International Business Machines Corporation and
6 : * others. All Rights Reserved.
7 : ******************************************************************************
8 : */
9 :
10 : #include "uvectr64.h"
11 : #include "cmemory.h"
12 : #include "putilimp.h"
13 :
14 : U_NAMESPACE_BEGIN
15 :
16 : #define DEFAULT_CAPACITY 8
17 :
18 : /*
19 : * Constants for hinting whether a key is an integer
20 : * or a pointer. If a hint bit is zero, then the associated
21 : * token is assumed to be an integer. This is needed for iSeries
22 : */
23 :
24 0 : UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector64)
25 :
26 0 : UVector64::UVector64(UErrorCode &status) :
27 : count(0),
28 : capacity(0),
29 : maxCapacity(0),
30 0 : elements(NULL)
31 : {
32 0 : _init(DEFAULT_CAPACITY, status);
33 0 : }
34 :
35 0 : UVector64::UVector64(int32_t initialCapacity, UErrorCode &status) :
36 : count(0),
37 : capacity(0),
38 : maxCapacity(0),
39 0 : elements(0)
40 : {
41 0 : _init(initialCapacity, status);
42 0 : }
43 :
44 :
45 :
46 0 : void UVector64::_init(int32_t initialCapacity, UErrorCode &status) {
47 : // Fix bogus initialCapacity values; avoid malloc(0)
48 0 : if (initialCapacity < 1) {
49 0 : initialCapacity = DEFAULT_CAPACITY;
50 : }
51 0 : if (maxCapacity>0 && maxCapacity<initialCapacity) {
52 0 : initialCapacity = maxCapacity;
53 : }
54 0 : if (initialCapacity > (int32_t)(INT32_MAX / sizeof(int64_t))) {
55 0 : initialCapacity = uprv_min(DEFAULT_CAPACITY, maxCapacity);
56 : }
57 0 : elements = (int64_t *)uprv_malloc(sizeof(int64_t)*initialCapacity);
58 0 : if (elements == 0) {
59 0 : status = U_MEMORY_ALLOCATION_ERROR;
60 : } else {
61 0 : capacity = initialCapacity;
62 : }
63 0 : }
64 :
65 0 : UVector64::~UVector64() {
66 0 : uprv_free(elements);
67 0 : elements = 0;
68 0 : }
69 :
70 : /**
71 : * Assign this object to another (make this a copy of 'other').
72 : */
73 0 : void UVector64::assign(const UVector64& other, UErrorCode &ec) {
74 0 : if (ensureCapacity(other.count, ec)) {
75 0 : setSize(other.count);
76 0 : for (int32_t i=0; i<other.count; ++i) {
77 0 : elements[i] = other.elements[i];
78 : }
79 : }
80 0 : }
81 :
82 :
83 0 : UBool UVector64::operator==(const UVector64& other) {
84 : int32_t i;
85 0 : if (count != other.count) return FALSE;
86 0 : for (i=0; i<count; ++i) {
87 0 : if (elements[i] != other.elements[i]) {
88 0 : return FALSE;
89 : }
90 : }
91 0 : return TRUE;
92 : }
93 :
94 :
95 0 : void UVector64::setElementAt(int64_t elem, int32_t index) {
96 0 : if (0 <= index && index < count) {
97 0 : elements[index] = elem;
98 : }
99 : /* else index out of range */
100 0 : }
101 :
102 0 : void UVector64::insertElementAt(int64_t elem, int32_t index, UErrorCode &status) {
103 : // must have 0 <= index <= count
104 0 : if (0 <= index && index <= count && ensureCapacity(count + 1, status)) {
105 0 : for (int32_t i=count; i>index; --i) {
106 0 : elements[i] = elements[i-1];
107 : }
108 0 : elements[index] = elem;
109 0 : ++count;
110 : }
111 : /* else index out of range */
112 0 : }
113 :
114 0 : void UVector64::removeAllElements(void) {
115 0 : count = 0;
116 0 : }
117 :
118 0 : UBool UVector64::expandCapacity(int32_t minimumCapacity, UErrorCode &status) {
119 0 : if (U_FAILURE(status)) {
120 0 : return FALSE;
121 : }
122 0 : if (minimumCapacity < 0) {
123 0 : status = U_ILLEGAL_ARGUMENT_ERROR;
124 0 : return FALSE;
125 : }
126 0 : if (capacity >= minimumCapacity) {
127 0 : return TRUE;
128 : }
129 0 : if (maxCapacity>0 && minimumCapacity>maxCapacity) {
130 0 : status = U_BUFFER_OVERFLOW_ERROR;
131 0 : return FALSE;
132 : }
133 0 : if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check
134 0 : status = U_ILLEGAL_ARGUMENT_ERROR;
135 0 : return FALSE;
136 : }
137 0 : int32_t newCap = capacity * 2;
138 0 : if (newCap < minimumCapacity) {
139 0 : newCap = minimumCapacity;
140 : }
141 0 : if (maxCapacity > 0 && newCap > maxCapacity) {
142 0 : newCap = maxCapacity;
143 : }
144 0 : if (newCap > (int32_t)(INT32_MAX / sizeof(int64_t))) { // integer overflow check
145 : // We keep the original memory contents on bad minimumCapacity/maxCapacity.
146 0 : status = U_ILLEGAL_ARGUMENT_ERROR;
147 0 : return FALSE;
148 : }
149 0 : int64_t* newElems = (int64_t *)uprv_realloc(elements, sizeof(int64_t)*newCap);
150 0 : if (newElems == NULL) {
151 : // We keep the original contents on the memory failure on realloc.
152 0 : status = U_MEMORY_ALLOCATION_ERROR;
153 0 : return FALSE;
154 : }
155 0 : elements = newElems;
156 0 : capacity = newCap;
157 0 : return TRUE;
158 : }
159 :
160 0 : void UVector64::setMaxCapacity(int32_t limit) {
161 0 : U_ASSERT(limit >= 0);
162 0 : if (limit < 0) {
163 0 : limit = 0;
164 : }
165 0 : if (limit > (int32_t)(INT32_MAX / sizeof(int64_t))) { // integer overflow check for realloc
166 : // Something is very wrong, don't realloc, leave capacity and maxCapacity unchanged
167 0 : return;
168 : }
169 0 : maxCapacity = limit;
170 0 : if (capacity <= maxCapacity || maxCapacity == 0) {
171 : // Current capacity is within the new limit.
172 0 : return;
173 : }
174 :
175 : // New maximum capacity is smaller than the current size.
176 : // Realloc the storage to the new, smaller size.
177 0 : int64_t* newElems = (int64_t *)uprv_realloc(elements, sizeof(int64_t)*maxCapacity);
178 0 : if (newElems == NULL) {
179 : // Realloc to smaller failed.
180 : // Just keep what we had. No need to call it a failure.
181 0 : return;
182 : }
183 0 : elements = newElems;
184 0 : capacity = maxCapacity;
185 0 : if (count > capacity) {
186 0 : count = capacity;
187 : }
188 : }
189 :
190 : /**
191 : * Change the size of this vector as follows: If newSize is smaller,
192 : * then truncate the array, possibly deleting held elements for i >=
193 : * newSize. If newSize is larger, grow the array, filling in new
194 : * slots with NULL.
195 : */
196 0 : void UVector64::setSize(int32_t newSize) {
197 : int32_t i;
198 0 : if (newSize < 0) {
199 0 : return;
200 : }
201 0 : if (newSize > count) {
202 0 : UErrorCode ec = U_ZERO_ERROR;
203 0 : if (!ensureCapacity(newSize, ec)) {
204 0 : return;
205 : }
206 0 : for (i=count; i<newSize; ++i) {
207 0 : elements[i] = 0;
208 : }
209 : }
210 0 : count = newSize;
211 : }
212 :
213 : U_NAMESPACE_END
214 :
|