1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkUnicodeStringArray.cxx
5 Language: C++
6
7 Copyright 2004 Sandia Corporation.
8 Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
9 license for use of this work by or on behalf of the
10 U.S. Government. Redistribution and use in source and binary forms, with
11 or without modification, are permitted provided that this Notice and any
12 statement of authorship are reproduced on all copies.
13
14 =========================================================================*/
15
16 #include "vtkUnicodeString.h"
17
18 #include "vtkArrayIteratorTemplate.h"
19 #include "vtkIdList.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkUnicodeStringArray.h"
22
23 #include <vector>
24 #include <algorithm>
25
26 class vtkUnicodeStringArray::Implementation
27 {
28 public:
29 typedef std::vector<vtkUnicodeString> StorageT;
30 StorageT Storage;
31 };
32
33 vtkStandardNewMacro(vtkUnicodeStringArray);
34
vtkUnicodeStringArray()35 vtkUnicodeStringArray::vtkUnicodeStringArray()
36 {
37 this->Internal = new Implementation;
38 }
39
~vtkUnicodeStringArray()40 vtkUnicodeStringArray::~vtkUnicodeStringArray()
41 {
42 delete this->Internal;
43 }
44
PrintSelf(ostream & os,vtkIndent indent)45 void vtkUnicodeStringArray::PrintSelf(ostream& os, vtkIndent indent)
46 {
47 this->Superclass::PrintSelf(os,indent);
48 }
49
Allocate(vtkIdType sz,vtkIdType)50 vtkTypeBool vtkUnicodeStringArray::Allocate(vtkIdType sz, vtkIdType)
51 {
52 this->Internal->Storage.reserve(sz);
53 this->DataChanged();
54 return 1;
55 }
56
Initialize()57 void vtkUnicodeStringArray::Initialize()
58 {
59 this->Internal->Storage.clear();
60 this->DataChanged();
61 }
62
GetDataType()63 int vtkUnicodeStringArray::GetDataType()
64 {
65 return VTK_UNICODE_STRING;
66 }
67
GetDataTypeSize()68 int vtkUnicodeStringArray::GetDataTypeSize()
69 {
70 return 0;
71 }
72
GetElementComponentSize()73 int vtkUnicodeStringArray::GetElementComponentSize()
74 {
75 return sizeof(vtkUnicodeString::value_type);
76 }
77
SetNumberOfTuples(vtkIdType number)78 void vtkUnicodeStringArray::SetNumberOfTuples(vtkIdType number)
79 {
80 this->Internal->Storage.resize(number);
81 this->DataChanged();
82 }
83
SetTuple(vtkIdType i,vtkIdType j,vtkAbstractArray * source)84 void vtkUnicodeStringArray::SetTuple(vtkIdType i, vtkIdType j, vtkAbstractArray* source)
85 {
86 vtkUnicodeStringArray* const array = vtkArrayDownCast<vtkUnicodeStringArray>(source);
87 if(!array)
88 {
89 vtkWarningMacro("Input and output array data types do not match.");
90 return;
91 }
92
93 this->Internal->Storage[i] = array->Internal->Storage[j];
94 this->DataChanged();
95 }
96
InsertTuple(vtkIdType i,vtkIdType j,vtkAbstractArray * source)97 void vtkUnicodeStringArray::InsertTuple(vtkIdType i, vtkIdType j, vtkAbstractArray* source)
98 {
99 vtkUnicodeStringArray* const array = vtkArrayDownCast<vtkUnicodeStringArray>(source);
100 if(!array)
101 {
102 vtkWarningMacro("Input and output array data types do not match.");
103 return;
104 }
105
106 if(static_cast<vtkIdType>(this->Internal->Storage.size()) <= i)
107 this->Internal->Storage.resize(i + 1);
108
109 this->Internal->Storage[i] = array->Internal->Storage[j];
110 this->DataChanged();
111 }
112
InsertTuples(vtkIdList * dstIds,vtkIdList * srcIds,vtkAbstractArray * source)113 void vtkUnicodeStringArray::InsertTuples(vtkIdList *dstIds, vtkIdList *srcIds,
114 vtkAbstractArray *source)
115 {
116 vtkUnicodeStringArray* const array =
117 vtkArrayDownCast<vtkUnicodeStringArray>(source);
118 if(!array)
119 {
120 vtkWarningMacro("Input and output array data types do not match.");
121 return;
122 }
123
124 vtkIdType numIds = dstIds->GetNumberOfIds();
125 if (srcIds->GetNumberOfIds() != numIds)
126 {
127 vtkWarningMacro("Input and output id array sizes do not match.");
128 return;
129 }
130
131 // Find maximum destination id and resize if needed
132 vtkIdType maxDstId = 0;
133 for (vtkIdType idIndex = 0; idIndex < numIds; ++idIndex)
134 {
135 maxDstId = std::max(maxDstId, dstIds->GetId(idIndex));
136 }
137
138 if (static_cast<vtkIdType>(this->Internal->Storage.size()) <= maxDstId)
139 {
140 this->Internal->Storage.resize(maxDstId + 1);
141 }
142
143 // Copy data
144 for (vtkIdType idIndex = 0; idIndex < numIds; ++idIndex)
145 {
146 this->Internal->Storage[dstIds->GetId(idIndex)] =
147 array->Internal->Storage[srcIds->GetId(idIndex)];
148 }
149
150 this->DataChanged();
151 }
152
153 //------------------------------------------------------------------------------
InsertTuples(vtkIdType dstStart,vtkIdType n,vtkIdType srcStart,vtkAbstractArray * source)154 void vtkUnicodeStringArray::InsertTuples(vtkIdType dstStart, vtkIdType n,
155 vtkIdType srcStart,
156 vtkAbstractArray *source)
157 {
158 vtkUnicodeStringArray* sa = vtkArrayDownCast<vtkUnicodeStringArray>(source);
159 if (!sa)
160 {
161 vtkWarningMacro("Input and outputs array data types do not match.");
162 return ;
163 }
164
165 if (this->NumberOfComponents != source->GetNumberOfComponents())
166 {
167 vtkWarningMacro("Input and output component sizes do not match.");
168 return;
169 }
170
171 vtkIdType srcEnd = srcStart + n;
172 if (srcEnd > source->GetNumberOfTuples())
173 {
174 vtkWarningMacro("Source range exceeds array size (srcStart=" << srcStart
175 << ", n=" << n << ", numTuples="
176 << source->GetNumberOfTuples() << ").");
177 return;
178 }
179
180 for (vtkIdType i = 0; i < n; ++i)
181 {
182 vtkIdType numComp = this->NumberOfComponents;
183 vtkIdType srcLoc = (srcStart + i) * this->NumberOfComponents;
184 vtkIdType dstLoc = (dstStart + i) * this->NumberOfComponents;
185 while (numComp-- > 0)
186 {
187 this->InsertValue(dstLoc++, sa->GetValue(srcLoc++));
188 }
189 }
190
191 this->DataChanged();
192 }
193
InsertNextTuple(vtkIdType j,vtkAbstractArray * source)194 vtkIdType vtkUnicodeStringArray::InsertNextTuple(vtkIdType j, vtkAbstractArray* source)
195 {
196 vtkUnicodeStringArray* const array = vtkArrayDownCast<vtkUnicodeStringArray>(source);
197 if(!array)
198 {
199 vtkWarningMacro("Input and output array data types do not match.");
200 return 0;
201 }
202
203 this->Internal->Storage.push_back(array->Internal->Storage[j]);
204 this->DataChanged();
205 return static_cast<vtkIdType>(this->Internal->Storage.size()) - 1;
206 }
207
GetVoidPointer(vtkIdType id)208 void* vtkUnicodeStringArray::GetVoidPointer(vtkIdType id)
209 {
210 // Err.. not totally sure what to do here
211 if (this->Internal->Storage.empty())
212 return nullptr;
213 else
214 return &this->Internal->Storage[id];
215 }
216
DeepCopy(vtkAbstractArray * da)217 void vtkUnicodeStringArray::DeepCopy(vtkAbstractArray* da)
218 {
219 if(!da)
220 return;
221
222 if(this == da)
223 return;
224
225 vtkUnicodeStringArray* const array = vtkArrayDownCast<vtkUnicodeStringArray>(da);
226 if(!array)
227 {
228 vtkWarningMacro("Input and output array data types do not match.");
229 return;
230 }
231
232 this->Internal->Storage = array->Internal->Storage;
233 this->DataChanged();
234 }
235
InterpolateTuple(vtkIdType i,vtkIdList * ptIndices,vtkAbstractArray * source,double * weights)236 void vtkUnicodeStringArray::InterpolateTuple(vtkIdType i, vtkIdList *ptIndices,
237 vtkAbstractArray* source, double* weights)
238 {
239 if(this->GetDataType() != source->GetDataType())
240 {
241 vtkErrorMacro("Cannot CopyValue from array of type "
242 << source->GetDataTypeAsString());
243 return;
244 }
245
246 if (ptIndices->GetNumberOfIds() == 0)
247 {
248 // nothing to do.
249 return;
250 }
251
252 // We use nearest neighbour for interpolating strings.
253 // First determine which is the nearest neighbour using the weights-
254 // it's the index with maximum weight.
255 vtkIdType nearest = ptIndices->GetId(0);
256 double max_weight = weights[0];
257 for (int k=1; k < ptIndices->GetNumberOfIds(); k++)
258 {
259 if (weights[k] > max_weight)
260 {
261 nearest = ptIndices->GetId(k);
262 max_weight = weights[k];
263 }
264 }
265
266 this->InsertTuple(i, nearest, source);
267 }
268
InterpolateTuple(vtkIdType i,vtkIdType id1,vtkAbstractArray * source1,vtkIdType id2,vtkAbstractArray * source2,double t)269 void vtkUnicodeStringArray::InterpolateTuple(vtkIdType i,
270 vtkIdType id1, vtkAbstractArray* source1,
271 vtkIdType id2, vtkAbstractArray* source2, double t)
272 {
273 if (source1->GetDataType() != this->GetDataType() ||
274 source2->GetDataType() != this->GetDataType())
275 {
276 vtkErrorMacro("All arrays to InterpolateValue() must be of same type.");
277 return;
278 }
279
280 if (t >= 0.5)
281 {
282 // Use p2
283 this->InsertTuple(i, id2, source2);
284 }
285 else
286 {
287 // Use p1.
288 this->InsertTuple(i, id1, source1);
289 }
290 }
291
Squeeze()292 void vtkUnicodeStringArray::Squeeze()
293 {
294 this->Internal->Storage.shrink_to_fit();
295 this->DataChanged();
296 }
297
Resize(vtkIdType numTuples)298 vtkTypeBool vtkUnicodeStringArray::Resize(vtkIdType numTuples)
299 {
300 this->Internal->Storage.resize(numTuples);
301 this->DataChanged();
302 return 1;
303 }
304
SetVoidArray(void *,vtkIdType,int)305 void vtkUnicodeStringArray::SetVoidArray(void*, vtkIdType, int)
306 {
307 vtkErrorMacro("Not implemented.");
308 }
309
SetVoidArray(void *,vtkIdType,int,int)310 void vtkUnicodeStringArray::SetVoidArray(void*, vtkIdType, int, int)
311 {
312 vtkErrorMacro("Not implemented.");
313 }
314
SetArrayFreeFunction(void (*)(void *))315 void vtkUnicodeStringArray::SetArrayFreeFunction(void (*)(void *))
316 {
317 vtkErrorMacro("Not implemented.");
318 }
319
GetActualMemorySize()320 unsigned long vtkUnicodeStringArray::GetActualMemorySize()
321 {
322 unsigned long count = 0;
323 for(Implementation::StorageT::size_type i = 0; i != this->Internal->Storage.size(); ++i)
324 {
325 count += static_cast<unsigned long>(this->Internal->Storage[i].byte_count());
326 count += static_cast<unsigned long>(sizeof(vtkUnicodeString));
327 }
328 return count;
329 }
330
IsNumeric()331 int vtkUnicodeStringArray::IsNumeric()
332 {
333 return 0;
334 }
335
NewIterator()336 vtkArrayIterator* vtkUnicodeStringArray::NewIterator()
337 {
338 vtkErrorMacro("Not implemented.");
339 return nullptr;
340 }
341
GetVariantValue(vtkIdType idx)342 vtkVariant vtkUnicodeStringArray::GetVariantValue(vtkIdType idx)
343 {
344 return this->GetValue(idx);
345 }
346
LookupValue(vtkVariant value)347 vtkIdType vtkUnicodeStringArray::LookupValue(vtkVariant value)
348 {
349 const vtkUnicodeString search_value = value.ToUnicodeString();
350
351 for(Implementation::StorageT::size_type i = 0; i != this->Internal->Storage.size(); ++i)
352 {
353 if(this->Internal->Storage[i] == search_value)
354 return static_cast<vtkIdType>(i);
355 }
356
357 return -1;
358 }
359
LookupValue(vtkVariant value,vtkIdList * ids)360 void vtkUnicodeStringArray::LookupValue(vtkVariant value, vtkIdList* ids)
361 {
362 const vtkUnicodeString search_value = value.ToUnicodeString();
363
364 ids->Reset();
365 for(Implementation::StorageT::size_type i = 0; i != this->Internal->Storage.size(); ++i)
366 {
367 if(this->Internal->Storage[i] == search_value)
368 ids->InsertNextId(static_cast<vtkIdType>(i));
369 }
370 }
371
SetVariantValue(vtkIdType id,vtkVariant value)372 void vtkUnicodeStringArray::SetVariantValue(vtkIdType id, vtkVariant value)
373 {
374 this->SetValue( id, value.ToUnicodeString() );
375 }
376
InsertVariantValue(vtkIdType id,vtkVariant value)377 void vtkUnicodeStringArray::InsertVariantValue(vtkIdType id, vtkVariant value)
378 {
379 this->InsertValue( id, value.ToUnicodeString() );
380 }
381
DataChanged()382 void vtkUnicodeStringArray::DataChanged()
383 {
384 this->MaxId = static_cast<vtkIdType>(this->Internal->Storage.size()) - 1;
385 }
386
ClearLookup()387 void vtkUnicodeStringArray::ClearLookup()
388 {
389 }
390
InsertNextValue(const vtkUnicodeString & value)391 vtkIdType vtkUnicodeStringArray::InsertNextValue(const vtkUnicodeString& value)
392 {
393 this->Internal->Storage.push_back(value);
394 this->DataChanged();
395 return static_cast<vtkIdType>(this->Internal->Storage.size()) - 1;
396 }
397
InsertValue(vtkIdType i,const vtkUnicodeString & value)398 void vtkUnicodeStringArray::InsertValue(vtkIdType i, const vtkUnicodeString& value)
399 {
400 // Range check
401 if(static_cast<vtkIdType>(this->Internal->Storage.size()) <= i)
402 this->Internal->Storage.resize(i + 1);
403
404 this->SetValue(i, value);
405 }
406
SetValue(vtkIdType i,const vtkUnicodeString & value)407 void vtkUnicodeStringArray::SetValue(vtkIdType i, const vtkUnicodeString& value)
408 {
409 this->Internal->Storage[i] = value;
410 this->DataChanged();
411 }
412
GetValue(vtkIdType i)413 vtkUnicodeString& vtkUnicodeStringArray::GetValue(vtkIdType i)
414 {
415 return this->Internal->Storage[i];
416 }
417
InsertNextUTF8Value(const char * value)418 void vtkUnicodeStringArray::InsertNextUTF8Value(const char* value)
419 {
420 this->InsertNextValue(vtkUnicodeString::from_utf8(value));
421 }
422
SetUTF8Value(vtkIdType i,const char * value)423 void vtkUnicodeStringArray::SetUTF8Value(vtkIdType i, const char* value)
424 {
425 this->SetValue(i, vtkUnicodeString::from_utf8(value));
426 }
427
GetUTF8Value(vtkIdType i)428 const char* vtkUnicodeStringArray::GetUTF8Value(vtkIdType i)
429 {
430 return this->Internal->Storage[i].utf8_str();
431 }
432