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