text: #ifndef STORM_ARRAY_TS_GROWABLE_ARRAY_HPP
  #define STORM_ARRAY_TS_GROWABLE_ARRAY_HPP
  
  #include "storm/array/TSFixedArray.hpp"
  #include <algorithm>
  #include <cstdint>
  #include <cstring>
  #include <new>
  
  template <class T>
  class TSGrowableArray : public TSFixedArray<T> {
      public:
      uint32_t m_chunk = 0;
  
      uint32_t Add(uint32_t count, const T* data);
      uint32_t Add(uint32_t count, uint32_t incr, const T* data);
      uint32_t CalcChunkSize(uint32_t count);
      void GrowToFit(uint32_t index, int32_t zero);
      T* New(void);
      void Reserve(uint32_t count, int32_t round);
      uint32_t RoundToChunk(uint32_t count, uint32_t chunk);
      void SetCount(uint32_t count);
  };
  
  template <class T>
  uint32_t TSGrowableArray<T>::Add(uint32_t count, const T* data) {
      this->Reserve(count, 1);
  
      for (int32_t i = 0; i < count; i++) {
          T* element = &this->m_data[this->m_count + i];
          *element = data[i];
      }
  
      this->m_count += count;
      return this->m_count - count;
  }
  
  template <class T>
  uint32_t TSGrowableArray<T>::Add(uint32_t count, uint32_t incr, const T* data) {
      this->Reserve(count, 1);
  
      const char* dataptr = reinterpret_cast<const char*>(data);
  
      for (int32_t i = 0; i < count; i++) {
          T* element = &this->m_data[this->m_count + i];
          *element = *reinterpret_cast<const T*>(dataptr);
          dataptr += incr;
      }
  
      this->m_count += count;
      return this->m_count - count;
  }
  
  template <class T>
  uint32_t TSGrowableArray<T>::CalcChunkSize(uint32_t count) {
      uint32_t maxChunk = std::max(static_cast<int32_t>(256 / sizeof(T)), 8);
  
      if (count >= maxChunk) {
          this->m_chunk = maxChunk;
          return maxChunk;
      }
  
      uint32_t result = count;
  
      for (uint32_t i = count & (count - 1); i; i &= i - 1) {
          result = i;
      }
  
      if (result < 1) {
          result = 1;
      }
  
      return result;
  }
  
  template <class T>
  void TSGrowableArray<T>::GrowToFit(uint32_t index, int32_t zero) {
      uint32_t count = this->m_count;
  
      if (index >= count) {
          this->Reserve(index - count + 1, 1);
  
          if (zero) {
              memset(&this->m_data[count], 0, sizeof(T) * (index - count + 1));
          }
  
          this->m_count = index + 1;
      }
  }
  
  template <class T>
  T* TSGrowableArray<T>::New() {
      this->Reserve(1, 1);
      void* element = &this->m_data[this->m_count++];
      return new (element) T();
  }
  
  template <class T>
  void TSGrowableArray<T>::Reserve(uint32_t count, int32_t round) {
      if (count + this->m_count > this->m_alloc) {
          if (round) {
              uint32_t chunk = this->m_chunk;
  
              if (!chunk) {
                  chunk = this->CalcChunkSize(count + this->m_count);
              }
  
              count = this->RoundToChunk(count, chunk);
          }
  
          this->ReallocData(count + this->m_count);
      }
  }
  
  template <class T>
  uint32_t TSGrowableArray<T>::RoundToChunk(uint32_t count, uint32_t chunk) {
      if (count % chunk) {
          return chunk - count % chunk + count;
      } else {
          return count;
      }
  }
  
  template <class T>
  void TSGrowableArray<T>::SetCount(uint32_t count) {
      if (count > this->m_count) {
          // Expand size
          this->Reserve(count - this->m_count, 1);
  
          T* element;
  
          for (int32_t i = this->m_count; i < count; ++i) {
              element = &this->m_data[i];
              new (element) T();
          }
      }
  
      this->m_count = count;
  }
  
  #endif
  