1 // Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and
2 // other Axom Project Developers. See the top-level LICENSE file for details.
3 //
4 // SPDX-License-Identifier: (BSD-3-Clause)
5 
6 // Associated header file
7 #include "View.hpp"
8 
9 // Sidre component headers
10 #include "Buffer.hpp"
11 #include "Group.hpp"
12 #include "DataStore.hpp"
13 #include "Attribute.hpp"
14 
15 #include "axom/core/Macros.hpp"
16 
17 namespace axom
18 {
19 namespace sidre
20 {
21 /*
22  *************************************************************************
23  *
24  * Return path of View's owning Group object.
25  * Needs to be in the .cpp file because Group methods aren't
26  * accessible in .hpp file.
27  *
28  *************************************************************************
29  */
getPath() const30 std::string View::getPath() const { return getOwningGroup()->getPathName(); }
31 
32 /*
33  *************************************************************************
34  *
35  * Return full path of View object, including its name.
36  * Needs to be in the .cpp file because Group methods aren't
37  * accessible in .hpp file.
38  *
39  *************************************************************************
40  */
getPathName() const41 std::string View::getPathName() const
42 {
43   const auto path = getPath();
44 
45   if(path.length() < 1)
46   {
47     return getName();
48   }
49 
50   return path + getOwningGroup()->getPathDelimiter() + getName();
51 }
52 
53 /*
54  *************************************************************************
55  *
56  * Allocate data for view, previously described.
57  * The state may transition from EMPTY to BUFFER;
58  * otherwise, the state must already be BUFFER.
59  *
60  *************************************************************************
61  */
allocate(int allocID)62 View* View::allocate(int allocID)
63 {
64   allocID = getValidAllocatorID(allocID);
65 
66   if(isAllocateValid())
67   {
68     if(m_state == EMPTY)
69     {
70       SLIC_ASSERT_MSG(m_data_buffer == nullptr,
71                       SIDRE_VIEW_LOG_PREPEND
72                         << "State was EMPTY, but data buffer was not null.");
73       m_data_buffer = m_owning_group->getDataStore()->createBuffer();
74       m_data_buffer->attachToView(this);
75       m_state = BUFFER;
76     }
77 
78     TypeID type = static_cast<TypeID>(m_schema.dtype().id());
79     IndexType num_elems = m_schema.dtype().number_of_elements();
80     m_data_buffer->allocate(type, num_elems, allocID);
81     apply();
82   }
83 
84   return this;
85 }
86 
87 /*
88  *************************************************************************
89  *
90  * Allocate data for view with type and number of elements.
91  *
92  *************************************************************************
93  */
allocate(TypeID type,IndexType num_elems,int allocID)94 View* View::allocate(TypeID type, IndexType num_elems, int allocID)
95 {
96   allocID = getValidAllocatorID(allocID);
97 
98   if(type == NO_TYPE_ID || num_elems < 0)
99   {
100     SLIC_CHECK_MSG(type != NO_TYPE_ID,
101                    SIDRE_VIEW_LOG_PREPEND
102                      << "Could not allocate: Data type was 'NO_TYPE_ID'.");
103     SLIC_CHECK_MSG(
104       num_elems >= 0,
105       SIDRE_VIEW_LOG_PREPEND
106         << "Could not allocate: num_elems cannot be less than zero.");
107 
108     return this;
109   }
110 
111   describe(type, num_elems);
112   allocate(allocID);
113 
114   return this;
115 }
116 
117 /*
118  *************************************************************************
119  *
120  * Allocate data for view described by a Conduit data type object.
121  *
122  *************************************************************************
123  */
allocate(const DataType & dtype,int allocID)124 View* View::allocate(const DataType& dtype, int allocID)
125 {
126   allocID = getValidAllocatorID(allocID);
127 
128   if(dtype.is_empty())
129   {
130     SLIC_CHECK_MSG(!dtype.is_empty(),
131                    SIDRE_VIEW_LOG_PREPEND
132                      << "Unable to allocate View with empty data type.");
133     return this;
134   }
135 
136   describe(dtype);
137   allocate(allocID);
138 
139   return this;
140 }
141 
142 /*
143  *************************************************************************
144  *
145  * Reallocate data for view to given number of elements.
146  * This function requires that the view is already described.
147  * The state may transition from EMPTY to BUFFER;
148  * otherwise, the state must already be BUFFER.
149  *
150  *************************************************************************
151  */
reallocate(IndexType num_elems)152 View* View::reallocate(IndexType num_elems)
153 {
154   TypeID vtype = static_cast<TypeID>(m_schema.dtype().id());
155 
156   if(num_elems < 0)
157   {
158     SLIC_CHECK_MSG(
159       false,
160       SIDRE_VIEW_LOG_PREPEND << "Unable to reallocate, num_elems must be >= 0");
161   }
162   else if(isAllocateValid())
163   {
164     if(m_state == EMPTY)
165     {
166       allocate(vtype, num_elems);
167     }
168     else if(m_data_buffer->isAllocated())  //  XXX if ( isAllocated() )
169     {
170       describe(vtype, num_elems);
171       m_data_buffer->reallocate(num_elems);
172       apply();
173     }
174     else
175     {
176       allocate(vtype, num_elems);
177     }
178   }
179 
180   return this;
181 }
182 
183 /*
184  *************************************************************************
185  *
186  * Deallocate data for view.
187  *
188  *************************************************************************
189  */
deallocate()190 View* View::deallocate()
191 {
192   if(!isAllocateValid())
193   {
194     SLIC_CHECK_MSG(isAllocateValid(),
195                    SIDRE_VIEW_LOG_PREPEND
196                      << "View's state " << getStateStringName(m_state)
197                      << " does not allow data deallocation");
198     return this;
199   }
200 
201   if(hasBuffer())
202   {
203     m_data_buffer->deallocate();
204   }
205 
206   return this;
207 }
208 
209 /*
210  *************************************************************************
211  *
212  * Reallocate data for view using a Conduit data type object.
213  *
214  *************************************************************************
215  */
reallocate(const DataType & dtype)216 View* View::reallocate(const DataType& dtype)
217 {
218   // If we don't have an allocated buffer, we can just call allocate.
219   if(!isAllocated())
220   {
221     return allocate(dtype);
222   }
223 
224   TypeID type = static_cast<TypeID>(dtype.id());
225   TypeID view_type = static_cast<TypeID>(m_schema.dtype().id());
226 
227   if(dtype.is_empty() || !isAllocateValid() || type != view_type)
228   {
229     SLIC_CHECK_MSG(!dtype.is_empty(),
230                    SIDRE_VIEW_LOG_PREPEND
231                      << "Unable to re-allocate View with empty data type.");
232     SLIC_CHECK_MSG(isAllocateValid(),
233                    SIDRE_VIEW_LOG_PREPEND
234                      << "View's state " << getStateStringName(m_state)
235                      << " does not allow data re-allocation");
236     SLIC_CHECK_MSG(type == view_type,
237                    SIDRE_VIEW_LOG_PREPEND
238                      << "Attempting to re-allocate view with different type.");
239     return this;
240   }
241 
242   describe(dtype);
243   IndexType num_elems = dtype.number_of_elements();
244   m_data_buffer->reallocate(num_elems);
245   apply();
246 
247   return this;
248 }
249 
250 /*
251  *************************************************************************
252  *
253  * Attach/detach buffer to view.
254  *
255  *************************************************************************
256  */
attachBuffer(Buffer * buff)257 View* View::attachBuffer(Buffer* buff)
258 {
259   if(m_state == BUFFER && buff == nullptr)
260   {
261     Buffer* old_buffer = detachBuffer();
262     if(old_buffer->getNumViews() == 0)
263     {
264       getOwningGroup()->getDataStore()->destroyBuffer(old_buffer);
265     }
266     unapply();
267   }
268   else if(m_state == EMPTY && buff != nullptr)
269   {
270     m_data_buffer = buff;
271     buff->attachToView(this);
272     m_state = BUFFER;
273     SLIC_ASSERT(m_is_applied == false);
274 
275     // If view is described and the buffer is allocated, then call apply.
276     if(isDescribed() && m_data_buffer->isAllocated())
277     {
278       apply();
279     }
280   }
281 
282   return this;
283 }
284 
285 /*
286  *************************************************************************
287  *
288  * Detach buffer from view.
289  *
290  *************************************************************************
291  */
detachBuffer()292 Buffer* View::detachBuffer()
293 {
294   Buffer* buff = nullptr;
295 
296   if(m_state == BUFFER)
297   {
298     buff = m_data_buffer;
299     m_data_buffer->detachFromView(this);
300   }
301 
302   return buff;
303 }
304 
305 /*
306  *************************************************************************
307  *
308  * Clear data and metadata from a View.
309  *
310  *************************************************************************
311  */
clear()312 void View::clear()
313 {
314   switch(m_state)
315   {
316   case EMPTY:
317     undescribe();
318     break;
319   case BUFFER:
320     attachBuffer(nullptr);
321     undescribe();
322     break;
323   case EXTERNAL:
324     setExternalDataPtr(nullptr);
325     undescribe();
326     break;
327   case STRING:
328   case SCALAR:
329     unapply();
330     undescribe();
331     break;
332   default:
333     SLIC_ASSERT_MSG(false,
334                     SIDRE_VIEW_LOG_PREPEND << "View is in unexpected state: "
335                                            << getStateStringName(m_state));
336   }
337 
338   m_attr_values.clear();
339   m_state = EMPTY;
340 }
341 
342 /*
343  *************************************************************************
344  *
345  * Apply data description to data.
346  *
347  *************************************************************************
348  */
apply()349 View* View::apply()
350 {
351   if(!isApplyValid())
352   {
353     SLIC_CHECK_MSG(isApplyValid(),
354                    SIDRE_VIEW_LOG_PREPEND
355                      << "View's state, '" << getStateStringName(m_state)
356                      << "', does not allow apply operation");
357     return this;
358   }
359 
360   void* data_pointer = nullptr;
361 
362   if(hasBuffer())
363   {
364     data_pointer = m_data_buffer->getVoidPtr();
365   }
366   else
367   {
368     SLIC_ASSERT(m_state == EXTERNAL);
369     data_pointer = m_external_ptr;
370   }
371 
372   m_node.set_external(m_schema, data_pointer);
373   m_is_applied = true;
374 
375   return this;
376 }
377 
378 /*
379  *************************************************************************
380  *
381  * Apply given # elems, offset, stride description to data view.
382  *
383  *************************************************************************
384  */
apply(IndexType num_elems,IndexType offset,IndexType stride)385 View* View::apply(IndexType num_elems, IndexType offset, IndexType stride)
386 {
387   if(num_elems < 0)
388   {
389     SLIC_CHECK_MSG(num_elems >= 0,
390                    SIDRE_VIEW_LOG_PREPEND
391                      << "Could not apply -- num_elems was less than zero.");
392     return this;
393   }
394 
395   DataType dtype(m_schema.dtype());
396   if(dtype.is_empty())
397   {
398     dtype = conduit::DataType::default_dtype(m_data_buffer->getTypeID());
399   }
400 
401   const size_t bytes_per_elem = dtype.element_bytes();
402 
403   dtype.set_number_of_elements(num_elems);
404   dtype.set_offset(offset * bytes_per_elem);
405   dtype.set_stride(stride * bytes_per_elem);
406 
407   describe(dtype);
408 
409   apply();
410 
411   return this;
412 }
413 
414 /*
415  *************************************************************************
416  *
417  * Apply given type, # elems, offset, stride description to data view.
418  *
419  *************************************************************************
420  */
apply(TypeID type,IndexType num_elems,IndexType offset,IndexType stride)421 View* View::apply(TypeID type, IndexType num_elems, IndexType offset, IndexType stride)
422 {
423   if(type == NO_TYPE_ID || num_elems < 0)
424   {
425     SLIC_CHECK_MSG(
426       type != NO_TYPE_ID,
427       SIDRE_VIEW_LOG_PREPEND << "Could not apply -- invalid type.");
428 
429     SLIC_CHECK_MSG(num_elems >= 0,
430                    SIDRE_VIEW_LOG_PREPEND
431                      << "Could not apply -- num_elems was less than zero.");
432 
433     return this;
434   }
435 
436   DataType dtype = conduit::DataType::default_dtype(type);
437 
438   const size_t bytes_per_elem = dtype.element_bytes();
439 
440   dtype.set_number_of_elements(num_elems);
441   dtype.set_offset(offset * bytes_per_elem);
442   dtype.set_stride(stride * bytes_per_elem);
443 
444   describe(dtype);
445   apply();
446 
447   return this;
448 }
449 
450 /*
451  *************************************************************************
452  *
453  * Apply given type, number of dimensions and shape to data view.
454  * If ndims is 1 then do not save in m_shape.
455  *
456  *************************************************************************
457  */
apply(TypeID type,int ndims,const IndexType * shape)458 View* View::apply(TypeID type, int ndims, const IndexType* shape)
459 {
460   if(type == NO_TYPE_ID || ndims < 1 || shape == nullptr)
461   {
462     SLIC_CHECK_MSG(
463       type != NO_TYPE_ID,
464       SIDRE_VIEW_LOG_PREPEND << "Could not apply -- invalid type.");
465     SLIC_CHECK_MSG(
466       ndims >= 1,
467       SIDRE_VIEW_LOG_PREPEND << "Could not apply -- ndims was less than one.");
468     SLIC_CHECK_MSG(
469       shape != nullptr,
470       SIDRE_VIEW_LOG_PREPEND << "Could not apply -- shape was null.");
471 
472     return this;
473   }
474 
475   describe(type, ndims, shape);
476   apply();
477 
478   return this;
479 }
480 
481 /*
482  *************************************************************************
483  *
484  * Apply a data type description to data view.
485  *
486  *************************************************************************
487  */
apply(const DataType & dtype)488 View* View::apply(const DataType& dtype)
489 {
490   if(dtype.is_empty())
491   {
492     SLIC_CHECK_MSG(!dtype.is_empty(),
493                    SIDRE_VIEW_LOG_PREPEND
494                      << "Unable to apply description, data type is empty.");
495     return this;
496   }
497 
498   describe(dtype);
499   apply();
500 
501   return this;
502 }
503 
504 /*
505  *************************************************************************
506  *
507  * Get void pointer to any data held by the view.
508  *
509  *************************************************************************
510  */
getVoidPtr() const511 void* View::getVoidPtr() const
512 {
513   void* rv = nullptr;
514 
515   switch(m_state)
516   {
517   case EMPTY:
518     break;
519   case EXTERNAL:
520     if(isApplied())
521     {
522       rv = const_cast<void*>(m_node.data_ptr());
523     }
524     else
525     {
526       rv = m_external_ptr;  // Opaque
527     }
528     break;
529   case BUFFER:
530     if(isApplied())
531     {
532       rv = const_cast<void*>(m_node.data_ptr());
533     }
534     else
535     {
536       SLIC_CHECK_MSG(false,
537                      SIDRE_VIEW_LOG_PREPEND << "View has no applied data.");
538     }
539     break;
540   case STRING:
541   case SCALAR:
542     rv = const_cast<void*>(m_node.data_ptr());
543     break;
544   default:
545     SLIC_ASSERT_MSG(false,
546                     SIDRE_VIEW_LOG_PREPEND << "View is in unexpected state: "
547                                            << getStateStringName(m_state));
548   }
549 
550   return rv;
551 }
552 
553 /*
554  *************************************************************************
555  *
556  * Set data view to hold external data.
557  *
558  *************************************************************************
559  */
setExternalDataPtr(void * external_ptr)560 View* View::setExternalDataPtr(void* external_ptr)
561 {
562   if(m_state == EMPTY || m_state == EXTERNAL)
563   {
564     if(external_ptr == nullptr)
565     {
566       unapply();
567       m_external_ptr = nullptr;
568       m_state = EMPTY;
569     }
570     else
571     {
572       m_external_ptr = external_ptr;
573       m_state = EXTERNAL;
574 
575       if(isDescribed())
576       {
577         apply();
578       }
579     }
580   }
581   else
582   {
583     SLIC_CHECK_MSG(m_state == EMPTY || m_state == EXTERNAL,
584                    SIDRE_VIEW_LOG_PREPEND
585                      << "Calling setExternalDataPtr on View with "
586                      << getStateStringName(m_state) << " data is not allowed.");
587   }
588 
589   return this;
590 }
591 
592 /*
593  *************************************************************************
594  *
595  * Update the data in this View with the data from other
596  *
597  *************************************************************************
598  */
updateFrom(const View * other)599 View* View::updateFrom(const View* other)
600 {
601   if(!isUpdateableFrom(other))
602   {
603     SLIC_WARNING(SIDRE_VIEW_LOG_PREPEND
604                  << "View '" << getPathName() << "' is not updateable "
605                  << "from View '" << other->getPathName() << "'");
606     return this;
607   }
608 
609   SLIC_WARNING_IF(getTypeID() != other->getTypeID(),
610                   SIDRE_VIEW_LOG_PREPEND
611                     << "Updating View " << getPathName() << " with type "
612                     << getTypeID() << " from View " << other->getPathName()
613                     << " with type " << other->getTypeID());
614 
615   char* dst = static_cast<char*>(getVoidPtr());
616   dst += getOffset() * getBytesPerElement();
617 
618   char* src = static_cast<char*>(other->getVoidPtr());
619   src += other->getOffset() * other->getBytesPerElement();
620 
621   copy(dst, src, getTotalBytes());
622 
623   return this;
624 }
625 
626 /*
627  *************************************************************************
628  *
629  * Return true if view contains allocated data. This could mean a buffer
630  * with allocated data, or a scalar value, or a string.
631  *
632  * Note: Most of our isXXX functions are implemented in the header.
633  * This one is in not, because we are only forward declaring the buffer
634  * class in the view header.
635  *************************************************************************
636  */
isAllocated() const637 bool View::isAllocated() const
638 {
639   bool rv = false;
640 
641   switch(m_state)
642   {
643   case EMPTY:
644     break;
645   case BUFFER:
646     // false if buffer is not allocated or view is not described
647     rv = isDescribed() && m_data_buffer->isAllocated();
648     break;
649   case EXTERNAL:
650   case STRING:
651   case SCALAR:
652     rv = true;
653     break;
654   default:
655     SLIC_ASSERT_MSG(false,
656                     SIDRE_VIEW_LOG_PREPEND << "View is in unexpected state: "
657                                            << getStateStringName(m_state));
658   }
659 
660   return rv;
661 }
662 
663 /*
664  *************************************************************************
665  *
666  * Return number of dimensions and fill in shape information.
667  *
668  *************************************************************************
669  */
getShape(int ndims,IndexType * shape) const670 int View::getShape(int ndims, IndexType* shape) const
671 {
672   if(static_cast<unsigned>(ndims) < m_shape.size())
673   {
674     return -1;
675   }
676 
677   const int shapeSize = getNumDimensions();
678   for(int i = 0; i < shapeSize; ++i)
679   {
680     shape[i] = m_shape[i];
681   }
682 
683   // Fill the rest of the array with zeros (when ndims > shapeSize)
684   if(ndims > shapeSize)
685   {
686     for(int i = shapeSize; i < ndims; ++i)
687     {
688       shape[i] = 0;
689     }
690   }
691 
692   return m_shape.size();
693 }
694 
695 /*
696  *************************************************************************
697  *
698  * Return offset from description in terms of number of elements (0 if not
699  * described)
700  *
701  *************************************************************************
702  */
getOffset() const703 IndexType View::getOffset() const
704 {
705   int offset = 0;
706 
707   if(isDescribed())
708   {
709     offset = m_schema.dtype().offset();
710 
711     const int bytes_per_elem = getBytesPerElement();
712     if(bytes_per_elem != 0)
713     {
714       SLIC_ERROR_IF(
715         offset % bytes_per_elem != 0,
716         SIDRE_VIEW_LOG_PREPEND
717           << "Error calculating offset. "
718           << "Sidre assumes that offsets are given as integral number "
719           << "of elements into the array.  In this View, the offset was "
720           << offset << " bytes and each element is " << bytes_per_elem
721           << " bytes. If you have a need for "
722           << "non-integral offsets, please contact the Sidre team");
723 
724       offset /= bytes_per_elem;
725     }
726   }
727 
728   return static_cast<IndexType>(offset);
729 }
730 
731 /*
732  *************************************************************************
733  *
734  * Return stride from description in terms of number of elements (1 if not
735  * described)
736  *
737  *************************************************************************
738  */
getStride() const739 IndexType View::getStride() const
740 {
741   int stride = 1;
742 
743   if(isDescribed())
744   {
745     stride = m_schema.dtype().stride();
746 
747     const int bytes_per_elem = getBytesPerElement();
748     if(bytes_per_elem != 0)
749     {
750       SLIC_ERROR_IF(
751         stride % bytes_per_elem != 0,
752         SIDRE_VIEW_LOG_PREPEND
753           << "Error caclulating stride. "
754           << "Sidre assumes that strides are given as integral number "
755           << "of elements into the array. In this View, the stride was "
756           << stride << " bytes and each element is " << bytes_per_elem
757           << " bytes. If you have a need for "
758           << "non-integral strides, please contact the Sidre team");
759 
760       stride /= bytes_per_elem;
761     }
762   }
763 
764   return static_cast<IndexType>(stride);
765 }
766 
767 /*
768  *************************************************************************
769  *
770  * Test equivalence of two Views
771  *
772  *************************************************************************
773  */
isEquivalentTo(const View * other) const774 bool View::isEquivalentTo(const View* other) const
775 {
776   //add isAllocated() if it can be declared const
777   return (getName() == other->getName()) && (getTypeID() == other->getTypeID()) &&
778     (isApplied() == other->isApplied()) && (hasBuffer() == other->hasBuffer()) &&
779     (getTotalBytes() == other->getTotalBytes());
780 }
781 
782 /*
783  *************************************************************************
784  *
785  * Test whether the two Views can update each other
786  *
787  *************************************************************************
788  */
isUpdateableFrom(const View * other) const789 bool View::isUpdateableFrom(const View* other) const
790 {
791   const bool valid_state = (m_state == BUFFER) || (m_state == EXTERNAL);
792   const bool other_valid_state =
793     (other->m_state == BUFFER) || (other->m_state == EXTERNAL);
794   const bool same_length = (getTotalBytes() == other->getTotalBytes());
795   const bool unit_stride = (getStride() == 1) && (other->getStride() == 1);
796 
797   return valid_state && other_valid_state && same_length && unit_stride;
798 }
799 
800 /*
801  *************************************************************************
802  *
803  * Print JSON description of data view to stdout.
804  *
805  *************************************************************************
806  */
print() const807 void View::print() const { print(std::cout); }
808 
809 /*
810  *************************************************************************
811  *
812  * Print JSON description of data view to an ostream.
813  *
814  *************************************************************************
815  */
print(std::ostream & os) const816 void View::print(std::ostream& os) const
817 {
818   Node n;
819   copyToConduitNode(n);
820   n.to_json_stream(os);
821 }
822 
823 /*
824  *************************************************************************
825  *
826  * Copy data view description to given Conduit node.
827  *
828  *************************************************************************
829  */
copyToConduitNode(Node & n) const830 void View::copyToConduitNode(Node& n) const
831 {
832   n["name"] = m_name;
833   n["schema"] = m_schema.to_json();
834   n["value"] = m_node.to_json();
835   n["state"] = getStateStringName(m_state);
836   n["is_applied"] = m_is_applied;
837 }
838 
839 /*
840  *************************************************************************
841  *
842  * Copy data view native layout to given Conduit node.
843  *
844  *************************************************************************
845  */
createNativeLayout(Node & n) const846 void View::createNativeLayout(Node& n) const
847 {
848   // see ATK-726 - Handle undescribed and unallocated views in Sidre's
849   // createNativeLayout()
850   // TODO: Need to handle cases where the view is not described
851   // TODO: Need to handle cases where the view is not allocated
852   // TODO: Need to handle cases where the view is not applied
853 
854   // Note: We are using conduit's pointer rather than the View pointer
855   //    since the conduit pointer handles offsetting
856   // Note: const_cast the pointer to satisfy conduit's interface
857   void* data_ptr = const_cast<void*>(m_node.data_ptr());
858   n.set_external(m_node.schema(), data_ptr);
859 }
860 
861 /*
862  *************************************************************************
863  *
864  * PRIVATE ctor for View not associated with any data.
865  *
866  *************************************************************************
867  */
View(const std::string & name)868 View::View(const std::string& name)
869   : m_name(name)
870   , m_index(InvalidIndex)
871   , m_owning_group(nullptr)
872   , m_data_buffer(nullptr)
873   , m_schema()
874   , m_node()
875   , m_shape()
876   , m_external_ptr(nullptr)
877   , m_state(EMPTY)
878   , m_is_applied(false)
879 { }
880 
881 /*
882  *************************************************************************
883  *
884  * PRIVATE dtor.
885  *
886  *************************************************************************
887  */
~View()888 View::~View()
889 {
890   if(m_data_buffer != nullptr)
891   {
892     m_data_buffer->detachFromView(this);
893   }
894 }
895 
896 /*
897  *************************************************************************
898  *
899  * PRIVATE method to describe data view with type and number of elements.
900  *         Caller has already checked arguments.
901  *
902  *************************************************************************
903  */
describe(TypeID type,IndexType num_elems)904 void View::describe(TypeID type, IndexType num_elems)
905 {
906   DataType dtype = conduit::DataType::default_dtype(type);
907   dtype.set_number_of_elements(num_elems);
908   m_schema.set(dtype);
909   describeShape();
910   m_is_applied = false;
911 }
912 
913 /*
914  *************************************************************************
915  *
916  * PRIVATE method to describe data view with type, number of dimensions,
917  *         and number of elements per dimension.
918  *         Caller has already checked arguments.
919  *
920  *************************************************************************
921  */
describe(TypeID type,int ndims,const IndexType * shape)922 void View::describe(TypeID type, int ndims, const IndexType* shape)
923 {
924   IndexType num_elems = 0;
925   if(ndims > 0)
926   {
927     num_elems = shape[0];
928     for(int i = 1; i < ndims; i++)
929     {
930       num_elems *= shape[i];
931     }
932   }
933 
934   describe(type, num_elems);
935   describeShape(ndims, shape);
936 }
937 
938 /*
939  *************************************************************************
940  *
941  * PRIVATE method to describe data view with a Conduit data type object.
942  *         Caller has already checked arguments.
943  *
944  *************************************************************************
945  */
describe(const DataType & dtype)946 void View::describe(const DataType& dtype)
947 {
948   m_schema.set(dtype);
949   describeShape();
950   m_is_applied = false;
951 }
952 
953 /*
954  *************************************************************************
955  *
956  * PRIVATE method set shape to described length.
957  * This is called after describe to set the shape.
958  *
959  *************************************************************************
960  */
describeShape()961 void View::describeShape()
962 {
963   m_shape.clear();
964   m_shape.push_back(m_schema.dtype().number_of_elements());
965 }
966 
967 /*
968  *************************************************************************
969  *
970  * PRIVATE method set shape from user input.
971  *
972  *************************************************************************
973  */
describeShape(int ndims,const IndexType * shape)974 void View::describeShape(int ndims, const IndexType* shape)
975 {
976   m_shape.clear();
977   for(int i = 0; i < ndims; i++)
978   {
979     m_shape.push_back(shape[i]);
980   }
981 }
982 
983 /*
984  *************************************************************************
985  *
986  * PRIVATE method copy the contents of this into a undescribed EMPTY view.
987  *
988  *************************************************************************
989  */
copyView(View * copy) const990 void View::copyView(View* copy) const
991 {
992   SLIC_ASSERT_MSG(copy->m_state == EMPTY && !copy->isDescribed(),
993                   SIDRE_VIEW_LOG_PREPEND
994                     << "copyView can only copy into undescribed view "
995                     << "with empty state.");
996 
997   if(isDescribed())
998   {
999     copy->describe(m_schema.dtype());
1000   }
1001 
1002   switch(m_state)
1003   {
1004   case EMPTY:
1005     // Nothing more to do
1006     break;
1007   case STRING:
1008   case SCALAR:
1009     copy->m_node = m_node;
1010     copy->m_state = m_state;
1011     copy->m_is_applied = true;
1012     break;
1013   case EXTERNAL:
1014     copy->setExternalDataPtr(m_external_ptr);
1015     break;
1016   case BUFFER:
1017     copy->attachBuffer(m_data_buffer);
1018     break;
1019   default:
1020     SLIC_ASSERT_MSG(false,
1021                     SIDRE_VIEW_LOG_PREPEND << "View is in unexpected state: "
1022                                            << getStateStringName(m_state));
1023   }
1024 }
1025 
1026 /*
1027  *************************************************************************
1028  *
1029  * PRIVATE method returns true if view can allocate data; else false.
1030  *
1031  * This method does not need to emit the view state as part of it's
1032  * checking.  The caller functions are already printing out the view
1033  * state if this function returns false.
1034  *************************************************************************
1035  */
isAllocateValid() const1036 bool View::isAllocateValid() const
1037 {
1038   bool rv = false;
1039 
1040   switch(m_state)
1041   {
1042   case EMPTY:
1043     rv = isDescribed();
1044     break;
1045   case STRING:
1046   case SCALAR:
1047   case EXTERNAL:
1048     SLIC_CHECK_MSG(false,
1049                    SIDRE_VIEW_LOG_PREPEND
1050                      << "Allocate is not valid for view in '"
1051                      << getStateStringName(m_state) << "' state.");
1052     break;
1053   case BUFFER:
1054     rv = isDescribed() && m_data_buffer->getNumViews() == 1;
1055     break;
1056   default:
1057     SLIC_ASSERT_MSG(false,
1058                     SIDRE_VIEW_LOG_PREPEND << "View is in unexpected state: "
1059                                            << getStateStringName(m_state));
1060   }
1061 
1062   return rv;
1063 }
1064 
1065 /*
1066  *************************************************************************
1067  *
1068  * PRIVATE method returns true if apply is a valid operation on view;
1069  * else false.
1070  *
1071  * For an EXTERNAL view, assume user provided m_external_ptr and
1072  * description are consistent. This includes m_external_ptr == NULL.
1073  *
1074  *************************************************************************
1075  */
isApplyValid() const1076 bool View::isApplyValid() const
1077 {
1078   bool rv = false;
1079 
1080   if(!isDescribed())
1081   {
1082     SLIC_CHECK_MSG(
1083       false,
1084       SIDRE_VIEW_LOG_PREPEND
1085         << "Apply is not valid. View does not have a description.");
1086     return rv;
1087   }
1088 
1089   switch(m_state)
1090   {
1091   case EMPTY:
1092   case STRING:
1093   case SCALAR:
1094     SLIC_CHECK_MSG(false,
1095                    SIDRE_VIEW_LOG_PREPEND
1096                      << "Apply is not valid for View with state '"
1097                      << getStateStringName(m_state) << "'.'");
1098     break;
1099   case EXTERNAL:
1100     SLIC_ASSERT(m_external_ptr != nullptr);
1101     rv = isDescribed();
1102     break;
1103   case BUFFER:
1104     rv =
1105       0 <= getTotalBytes() && getTotalBytes() <= m_data_buffer->getTotalBytes();
1106     SLIC_CHECK_MSG(
1107       0 <= getTotalBytes(),
1108       SIDRE_VIEW_LOG_PREPEND << "Apply is not valid on data with zero length.");
1109     SLIC_CHECK_MSG(getTotalBytes() <= m_data_buffer->getTotalBytes(),
1110                    SIDRE_VIEW_LOG_PREPEND
1111                      << "Apply is not valid. "
1112                      << "View's datatype length exceeds bytes in buffer.");
1113     break;
1114   default:
1115     SLIC_ASSERT_MSG(false,
1116                     SIDRE_VIEW_LOG_PREPEND << "View is in unexpected state: "
1117                                            << getStateStringName(m_state));
1118   }
1119 
1120   return rv;
1121 }
1122 
1123 /*
1124  *************************************************************************
1125  *
1126  * PRIVATE method returns string name of given view state enum value.
1127  *
1128  *************************************************************************
1129  */
getStateStringName(State state)1130 char const* View::getStateStringName(State state)
1131 {
1132   char const* ret_string = NULL;
1133 
1134   switch(state)
1135   {
1136   case EMPTY:
1137     ret_string = "EMPTY";
1138     break;
1139   case BUFFER:
1140     ret_string = "BUFFER";
1141     break;
1142   case EXTERNAL:
1143     ret_string = "EXTERNAL";
1144     break;
1145   case SCALAR:
1146     ret_string = "SCALAR";
1147     break;
1148   case STRING:
1149     ret_string = "STRING";
1150     break;
1151   default:
1152     ret_string = "UNKNOWN";
1153   }
1154 
1155   return ret_string;
1156 }
1157 
1158 /*
1159  *************************************************************************
1160  *
1161  * PRIVATE method returns state enum value when given string with a
1162  * state name.
1163  *
1164  *************************************************************************
1165  */
getStateId(const std::string & name) const1166 View::State View::getStateId(const std::string& name) const
1167 {
1168   State res = EMPTY;
1169   if(name == "EMPTY")
1170   {
1171     res = EMPTY;
1172   }
1173   else if(name == "BUFFER")
1174   {
1175     res = BUFFER;
1176   }
1177   else if(name == "EXTERNAL")
1178   {
1179     res = EXTERNAL;
1180   }
1181   else if(name == "SCALAR")
1182   {
1183     res = SCALAR;
1184   }
1185   else if(name == "STRING")
1186   {
1187     res = STRING;
1188   }
1189   else if(name == "UNKNOWN")
1190   {
1191     res = EMPTY;
1192   }
1193 
1194   return res;
1195 }
1196 
1197 /*
1198  *************************************************************************
1199  *
1200  * PRIVATE method to copy view data to given Conduit node using
1201  * given set of ids to maintain correct association of data buffers
1202  * to data views.
1203  *
1204  *************************************************************************
1205  */
exportTo(conduit::Node & data_holder,std::set<IndexType> & buffer_indices) const1206 void View::exportTo(conduit::Node& data_holder,
1207                     std::set<IndexType>& buffer_indices) const
1208 {
1209   data_holder["state"] = getStateStringName(m_state);
1210   exportAttribute(data_holder);
1211 
1212   switch(m_state)
1213   {
1214   case EMPTY:
1215     if(isDescribed())
1216     {
1217       exportDescription(data_holder);
1218     }
1219     break;
1220   case BUFFER:
1221   {
1222     IndexType buffer_id = getBuffer()->getIndex();
1223     data_holder["buffer_id"] = buffer_id;
1224     if(isDescribed())
1225     {
1226       exportDescription(data_holder);
1227     }
1228     data_holder["is_applied"] = static_cast<unsigned char>(m_is_applied);
1229     buffer_indices.insert(buffer_id);
1230     break;
1231   }
1232   case EXTERNAL:
1233     if(isDescribed())
1234     {
1235       exportDescription(data_holder);
1236     }
1237     else
1238     {
1239       // If there is no description, make it an EMPTY view
1240       data_holder["state"] = getStateStringName(EMPTY);
1241     }
1242     break;
1243   case SCALAR:
1244   case STRING:
1245     data_holder["value"] = getNode();
1246     break;
1247   default:
1248     SLIC_ASSERT_MSG(false,
1249                     SIDRE_VIEW_LOG_PREPEND << "View is in unexpected state: "
1250                                            << getStateStringName(m_state));
1251   }
1252 }
1253 
1254 /*
1255  *************************************************************************
1256  * TODO
1257  *
1258  *************************************************************************
1259  */
importFrom(conduit::Node & data_holder,const std::map<IndexType,IndexType> & buffer_id_map)1260 void View::importFrom(conduit::Node& data_holder,
1261                       const std::map<IndexType, IndexType>& buffer_id_map)
1262 {
1263   m_state = getStateId(data_holder["state"].as_string());
1264   importAttribute(data_holder);
1265 
1266   switch(m_state)
1267   {
1268   case EMPTY:
1269     importDescription(data_holder);
1270     break;
1271   case BUFFER:
1272   {
1273     // If view has a buffer, the easiest way to restore it is to use a series of
1274     // API calls.
1275     // Start from scratch
1276     m_state = EMPTY;
1277 
1278     IndexType old_buffer_id = data_holder["buffer_id"].to_int64();
1279     bool is_applied = data_holder["is_applied"].as_unsigned_char();
1280 
1281     SLIC_ASSERT_MSG(buffer_id_map.find(old_buffer_id) != buffer_id_map.end(),
1282                     SIDRE_VIEW_LOG_PREPEND << "Buffer id map is old."
1283                                            << "New id entry for buffer "
1284                                            << old_buffer_id);
1285 
1286     Buffer* buffer =
1287       m_owning_group->getDataStore()->getBuffer(buffer_id_map.at(old_buffer_id));
1288 
1289     importDescription(data_holder);
1290     attachBuffer(buffer);
1291     if(is_applied)
1292     {
1293       apply();
1294     }
1295     break;
1296   }
1297   case EXTERNAL:
1298     importDescription(data_holder);
1299     break;
1300   case SCALAR:
1301   case STRING:
1302     m_node = data_holder["value"];
1303     m_schema.set(m_node.schema());
1304     m_is_applied = true;
1305     break;
1306   default:
1307     SLIC_ASSERT_MSG(false,
1308                     SIDRE_VIEW_LOG_PREPEND << "View is in unexpected state: "
1309                                            << getStateStringName(m_state));
1310   }
1311 }
1312 
1313 /*
1314  *************************************************************************
1315  *
1316  * Import Node holding an array into a View with an attached Buffer.
1317  *
1318  *************************************************************************
1319  */
importArrayNode(const Node & array)1320 View* View::importArrayNode(const Node& array)
1321 {
1322   conduit::DataType array_dtype = array.dtype();
1323 
1324   if(array_dtype.is_number())
1325   {
1326     if(m_state == BUFFER)
1327     {
1328       setBufferViewToEmpty();
1329     }
1330     if(m_state == EMPTY)
1331     {
1332       Buffer* buff = m_owning_group->getDataStore()->createBuffer();
1333 
1334       conduit::index_t num_ele = array_dtype.number_of_elements();
1335       conduit::index_t ele_bytes = DataType::default_bytes(array_dtype.id());
1336 
1337       buff->allocate((TypeID)array_dtype.id(), num_ele);
1338 
1339       // copy the data in a way that matches
1340       // to compact representation of the buffer
1341       conduit::uint8* data_ptr = (conduit::uint8*)buff->getVoidPtr();
1342       for(conduit::index_t i = 0; i < num_ele; i++)
1343       {
1344         memcpy(data_ptr, array.element_ptr(i), ele_bytes);
1345         data_ptr += ele_bytes;
1346       }
1347 
1348       attachBuffer(buff);
1349 
1350       // it is important to not use the data type directly
1351       // it could contain offsets that are no longer
1352       // valid our new buffer
1353       apply((TypeID)array_dtype.id(), array_dtype.number_of_elements());
1354     }
1355     else
1356     {
1357       SLIC_CHECK_MSG(m_state == EMPTY,
1358                      SIDRE_VIEW_LOG_PREPEND
1359                        << "Unable to import array Node to View with state: "
1360                        << getStateStringName(m_state));
1361     }
1362   }
1363   else
1364   {
1365     SLIC_CHECK_MSG(array_dtype.is_number(),
1366                    SIDRE_VIEW_LOG_PREPEND
1367                      << "Unable to import array from Node of type: "
1368                      << array_dtype.name());
1369   }
1370 
1371   return this;
1372 }
1373 
1374 /*
1375  *************************************************************************
1376  *
1377  * PRIVATE method to save view's description to a conduit tree.
1378  * The shape information is only written if there is more than
1379  * one dimension.
1380  *
1381  *************************************************************************
1382  */
exportDescription(conduit::Node & data_holder) const1383 void View::exportDescription(conduit::Node& data_holder) const
1384 {
1385   data_holder["schema"] = m_schema.to_json();
1386   if(getNumDimensions() > 1)
1387   {
1388     data_holder["shape"].set(m_shape);
1389   }
1390 }
1391 
1392 /*
1393  *************************************************************************
1394  *
1395  * PRIVATE method to restore a view's description from a conduit tree.
1396  *
1397  *************************************************************************
1398  */
importDescription(conduit::Node & data_holder)1399 void View::importDescription(conduit::Node& data_holder)
1400 {
1401   if(data_holder.has_path("schema"))
1402   {
1403     conduit::Schema schema(data_holder["schema"].as_string());
1404     describe(schema.dtype());
1405     if(data_holder.has_path("shape"))
1406     {
1407       Node& n = data_holder["shape"];
1408       IndexType* shape = n.value();
1409       int ndims = n.dtype().number_of_elements();
1410       describeShape(ndims, shape);
1411     }
1412   }
1413 }
1414 
1415 /*
1416  *************************************************************************
1417  *
1418  * PRIVATE method to save view's attributes to a conduit tree.
1419  * Only add "attribute" Node if the View has any attributes.
1420  *
1421  *************************************************************************
1422  */
exportAttribute(conduit::Node & data_holder) const1423 void View::exportAttribute(conduit::Node& data_holder) const
1424 {
1425   IndexType aidx = getFirstValidAttrValueIndex();
1426 
1427   if(aidx == InvalidIndex)
1428   {
1429     return;
1430   }
1431 
1432   Node& node = data_holder["attribute"];
1433   node.set(DataType::object());
1434 
1435   while(indexIsValid(aidx))
1436   {
1437     const Attribute* attr = getAttribute(aidx);
1438 
1439     node[attr->getName()] = getAttributeNodeRef(attr);
1440 
1441     aidx = getNextValidAttrValueIndex(aidx);
1442   }
1443 }
1444 
1445 /*
1446  *************************************************************************
1447  *
1448  * PRIVATE method to restore a view's attributes from a conduit tree.
1449  *
1450  *************************************************************************
1451  */
importAttribute(conduit::Node & data_holder)1452 void View::importAttribute(conduit::Node& data_holder)
1453 {
1454   if(data_holder.has_path("attribute"))
1455   {
1456     conduit::NodeIterator attrs_itr = data_holder["attribute"].children();
1457     while(attrs_itr.has_next())
1458     {
1459       Node& n_attr = attrs_itr.next();
1460       std::string attr_name = attrs_itr.name();
1461 
1462       Attribute* attr = getAttribute(attr_name);
1463       if(attr != nullptr)
1464       {
1465         m_attr_values.setNode(attr, n_attr);
1466       }
1467     }
1468   }
1469 }
1470 
1471 /*
1472  *************************************************************************
1473  *
1474  * Rename this View with a new string name.
1475  *
1476  *************************************************************************
1477  */
rename(const std::string & new_name)1478 bool View::rename(const std::string& new_name)
1479 {
1480   bool do_rename = true;
1481   if(new_name != m_name)
1482   {
1483     Group* parent = getOwningGroup();
1484     SLIC_CHECK(parent != nullptr);
1485 
1486     if(new_name.empty())
1487     {
1488       SLIC_WARNING(SIDRE_VIEW_LOG_PREPEND
1489                    << "Cannot rename View to an empty string.");
1490       do_rename = false;
1491     }
1492     else if(new_name.find(parent->getPathDelimiter()) != std::string::npos)
1493     {
1494       SLIC_WARNING(SIDRE_VIEW_LOG_PREPEND
1495                    << "Cannot rename View " << getPathName() << " to path name '"
1496                    << new_name << "'. Only strings without path delimiters can "
1497                    << "be passed into the rename method.");
1498       do_rename = false;
1499     }
1500     else if(parent->hasGroup(new_name) || parent->hasView(new_name))
1501     {
1502       SLIC_WARNING(SIDRE_VIEW_LOG_PREPEND
1503                    << "Parent group '" << parent->getPathName()
1504                    << "' already has a child object named " << new_name << ". "
1505                    << "View " << getPathName() << " will not be renamed.");
1506       do_rename = false;
1507     }
1508     else
1509     {
1510       View* detached_view = parent->detachView(m_name);
1511       SLIC_CHECK(detached_view == this);
1512 
1513       m_name = new_name;
1514 
1515       View* attached_view = parent->attachView(detached_view);
1516       AXOM_UNUSED_VAR(attached_view);
1517       SLIC_CHECK(attached_view == this);
1518     }
1519   }
1520 
1521   return do_rename;
1522 }
1523 
1524 /*
1525  *************************************************************************
1526  *
1527  * Return pointer to Attribute from Attribute index.
1528  *
1529  *************************************************************************
1530  */
getAttribute(IndexType idx)1531 Attribute* View::getAttribute(IndexType idx)
1532 {
1533   Attribute* attr = getOwningGroup()->getDataStore()->getAttribute(idx);
1534   return attr;
1535 }
1536 
1537 /*
1538  *************************************************************************
1539  *
1540  * Return pointer to Attribute from Attribute index.
1541  *
1542  *************************************************************************
1543  */
getAttribute(IndexType idx) const1544 const Attribute* View::getAttribute(IndexType idx) const
1545 {
1546   const Attribute* attr = getOwningGroup()->getDataStore()->getAttribute(idx);
1547   return attr;
1548 }
1549 
1550 /*
1551  *************************************************************************
1552  *
1553  * Return pointer to Attribute from Attribute name.
1554  *
1555  *************************************************************************
1556  */
getAttribute(const std::string & name)1557 Attribute* View::getAttribute(const std::string& name)
1558 {
1559   Attribute* attr = getOwningGroup()->getDataStore()->getAttribute(name);
1560   return attr;
1561 }
1562 
1563 /*
1564  *************************************************************************
1565  *
1566  * Return pointer to Attribute from Attribute name.
1567  *
1568  *************************************************************************
1569  */
getAttribute(const std::string & name) const1570 const Attribute* View::getAttribute(const std::string& name) const
1571 {
1572   const Attribute* attr = getOwningGroup()->getDataStore()->getAttribute(name);
1573   return attr;
1574 }
1575 
1576 /*
1577  *************************************************************************
1578  *
1579  * Set Attribute for a View from Attribute name.
1580  *
1581  *************************************************************************
1582  */
setAttributeString(IndexType idx,const std::string & value)1583 bool View::setAttributeString(IndexType idx, const std::string& value)
1584 {
1585   const Attribute* attr = getAttribute(idx);
1586 
1587   if(attr == nullptr)
1588   {
1589     return false;
1590   }
1591 
1592   return m_attr_values.setString(attr, value);
1593 }
1594 
1595 /*
1596  *************************************************************************
1597  *
1598  * Set Attribute for a View from Attribute name.
1599  *
1600  *************************************************************************
1601  */
setAttributeString(const std::string & name,const std::string & value)1602 bool View::setAttributeString(const std::string& name, const std::string& value)
1603 {
1604   const Attribute* attr = getAttribute(name);
1605 
1606   if(attr == nullptr)
1607   {
1608     return false;
1609   }
1610 
1611   return m_attr_values.setString(attr, value);
1612 }
1613 
1614 /*
1615  *************************************************************************
1616  *
1617  * Set Attribute for a View from Attribute pointer.
1618  *
1619  *************************************************************************
1620  */
setAttributeString(const Attribute * attr,const std::string & value)1621 bool View::setAttributeString(const Attribute* attr, const std::string& value)
1622 {
1623   if(attr == nullptr)
1624   {
1625     SLIC_CHECK_MSG(attr != nullptr,
1626                    SIDRE_VIEW_LOG_PREPEND
1627                      << "setAttributeString: called with a null Attribute");
1628     return false;
1629   }
1630 
1631   return m_attr_values.setString(attr, value);
1632 }
1633 
1634 /*
1635  *************************************************************************
1636  *
1637  * Return a string attribute from the Attribute index.
1638  *
1639  * If the value has not been explicitly set, return the current default.
1640  *
1641  *************************************************************************
1642  */
getAttributeString(IndexType idx) const1643 const char* View::getAttributeString(IndexType idx) const
1644 {
1645   const Attribute* attr = getAttribute(idx);
1646 
1647   if(attr == nullptr)
1648   {
1649     return nullptr;
1650   }
1651 
1652   return m_attr_values.getString(attr);
1653 }
1654 
1655 /*
1656  *************************************************************************
1657  *
1658  * Return a string attribute from the Attribute name.
1659  *
1660  * If the value has not been explicitly set, return the current default.
1661  *
1662  *************************************************************************
1663  */
getAttributeString(const std::string & name) const1664 const char* View::getAttributeString(const std::string& name) const
1665 {
1666   const Attribute* attr = getAttribute(name);
1667 
1668   if(attr == nullptr)
1669   {
1670     return nullptr;
1671   }
1672 
1673   return m_attr_values.getString(attr);
1674 }
1675 
1676 /*
1677  *************************************************************************
1678  *
1679  * Return a string attribute from the Attribute pointer.
1680  *
1681  * If the value has not been explicitly set, return the current default.
1682  *
1683  *************************************************************************
1684  */
getAttributeString(const Attribute * attr) const1685 const char* View::getAttributeString(const Attribute* attr) const
1686 {
1687   if(attr == nullptr)
1688   {
1689     SLIC_CHECK_MSG(attr != nullptr,
1690                    SIDRE_VIEW_LOG_PREPEND
1691                      << "getAttributeString: called with a null Attribute");
1692     return nullptr;
1693   }
1694 
1695   return m_attr_values.getString(attr);
1696 }
1697 
1698 /*
1699  *************************************************************************
1700  *
1701  * PRIVATE method to return a valid umpire::Allocator ID.
1702  *
1703  *************************************************************************
1704  */
getValidAllocatorID(int allocID)1705 int View::getValidAllocatorID(int allocID)
1706 {
1707 #ifdef AXOM_USE_UMPIRE
1708   if(allocID == INVALID_ALLOCATOR_ID)
1709   {
1710     allocID = getOwningGroup()->getDefaultAllocatorID();
1711   }
1712 #endif
1713 
1714   return allocID;
1715 }
1716 
1717 } /* end namespace sidre */
1718 } /* end namespace axom */
1719