/* ---- This file is part of SECONDO. Copyright (C) 2004-2009, University in Hagen, Faculty of Mathematics and Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SECONDO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- */ #pragma once #include #include "AttrArray.h" #include "Attribute.h" #include #include #include "NestedList.h" #include "ReadWrite.h" #include "Shared.h" #include "SpatialAttrArray.h" #include extern NestedList *nl; namespace CRelAlgebra { template class SimpleFSAttrArrayIterator; /* Class template that allows easy implementation of ~AttrArray~s with entries of fixed size. For an example see ~LongInts~. */ template class SimpleFSAttrArray : public AttrArray { public: typedef typename T::AttributeType AttributeType; SimpleFSAttrArray() : m_count(0), m_size(sizeof(SimpleFSAttrArray)), m_capacity(0), m_values(nullptr) { } SimpleFSAttrArray(Reader &source) : SimpleFSAttrArray(source, source.ReadOrThrow()) { } SimpleFSAttrArray(Reader &source, uint64_t rowCount) : m_count(rowCount), m_size(sizeof(SimpleFSAttrArray) + (rowCount * sizeof(T))), m_capacity(rowCount), m_data(rowCount * sizeof(T)), m_values((T*)m_data.GetPointer()) { const uint64_t size = m_data.GetCapacity(); if (size > 0) { source.ReadOrThrow(m_data.GetPointer(), size); } } SimpleFSAttrArray(const SimpleFSAttrArray &array, const SharedArray &filter) : AttrArray(filter), m_count(array.m_count), m_size(array.m_size), m_capacity(array.m_capacity), m_data(array.m_data), m_values(array.m_values) { } virtual ~SimpleFSAttrArray() { } virtual AttrArray *Filter(SharedArray filter) const { return new SimpleFSAttrArray(*this, filter); } virtual uint64_t GetCount() const { return m_count; } virtual uint64_t GetSize() const { return m_size; } virtual void Save(Writer &target, bool includeHeader = true) const { if (includeHeader) { target.WriteOrThrow(m_count); } if (m_count > 0) { target.WriteOrThrow(m_data.GetPointer(), m_count * sizeof(T)); } } virtual void Append(const AttrArray &array, uint64_t row) { Append(((SimpleFSAttrArray&)array).m_values[row]); } virtual void Append(Attribute &value) { Append(T((AttributeType&)value)); } void Append(const T &value) { uint64_t capacity = m_capacity, count = m_count++; T *values; if (capacity == count) { if (capacity == 0) { capacity = 1; m_data = SharedArray(sizeof(T)); values = m_values = (T*)m_data.GetPointer(); } else { const uint64_t newCapacity = capacity + capacity, newByteCapacity = newCapacity * sizeof(T); char *data = new char[newByteCapacity]; memcpy(data, m_data.GetPointer(), m_data.GetCapacity()); capacity = newCapacity; m_data = SharedArray(data, newByteCapacity); m_values = values = (T*)data; } m_capacity = capacity; } else { values = m_values; } new (values + count) T(value); m_size += sizeof(T); } virtual void Remove() { --m_count; m_size -= sizeof(T); } virtual void Clear() { m_count = 0; m_size = sizeof(SimpleFSAttrArray); } const T &GetAt(uint64_t index) const { return m_values[index]; } const T &operator[](uint64_t index) const { return m_values[index]; } virtual bool IsDefined(uint64_t row) const { return m_values[row].IsDefined(); } virtual int Compare(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { const T &value = ((SimpleFSAttrArray&)arrayB).m_values[rowB]; return m_values[rowA].Compare(value); } virtual int Compare(uint64_t row, Attribute &value) const { return m_values[row].Compare((AttributeType&)value); } virtual int CompareAlmost(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { const T &value = ((const SimpleFSAttrArray&)arrayB).GetAt(rowB); return TCompareAlmost(GetAt(rowA), value); } virtual int CompareAlmost(uint64_t row, Attribute &value) const { return TCompareAlmost(GetAt(row), (const AttributeType&)value); } virtual bool Equals(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { const T &value = ((SimpleFSAttrArray&)arrayB).m_values[rowB]; return m_values[rowA].Equals(value); } virtual bool Equals(uint64_t row, Attribute &value) const { return m_values[row].Equals((AttributeType&)value); } virtual bool EqualsAlmost(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { const T &value = ((const SimpleFSAttrArray&)arrayB).GetAt(rowB); return TEqualsAlmost(GetAt(rowA), value); } virtual bool EqualsAlmost(uint64_t row, Attribute &value) const { return TEqualsAlmost(GetAt(row), (const AttributeType&)value); } virtual uint64_t GetHash(uint64_t row) const { return m_values[row].GetHash(); } virtual Attribute *GetAttribute(uint64_t row, bool clone = true) const { return GetAt(row).GetAttribute(clone); } SimpleFSAttrArrayIterator GetIterator() const { return SimpleFSAttrArrayIterator(*this); } SimpleFSAttrArrayIterator begin() const { return GetIterator(); } SimpleFSAttrArrayIterator end() const { return SimpleFSAttrArrayIterator(); } private: friend class SimpleFSAttrArrayIterator; uint64_t m_count, m_size, m_capacity; SharedArray m_data; T *m_values; SimpleFSAttrArray(const SimpleFSAttrArray &instance) = delete; template static int TCompareAlmost(const T &entry, V &value) { return entry.CompareAlmost(value); } template static bool TEqualsAlmost(const T &entry, V &value) { return entry.EqualsAlmost(value); } }; /* Iterator over the entries of a SimpleFSAttrArray. */ template class SimpleFSAttrArrayIterator { public: SimpleFSAttrArrayIterator() : m_instance(nullptr), m_current(nullptr), m_end(nullptr) { } SimpleFSAttrArrayIterator(const SimpleFSAttrArray &instance) : m_instance(&instance), m_current(instance.m_values), m_end(m_current + instance.m_count) { } bool IsValid() const { return m_current < m_end; } const T &Get() const { return *m_current; } bool MoveToNext() { if (IsValid()) { ++m_current; return IsValid(); } return false; } const T &operator * () { return Get(); } SimpleFSAttrArrayIterator &operator ++ () { MoveToNext(); return *this; } bool operator == (const SimpleFSAttrArrayIterator &other) const { return !(*this != other); } bool operator != (const SimpleFSAttrArrayIterator &other) const { if (m_current < m_end) { if (other.m_current < other.m_end) { return m_current != other.m_current || m_instance != other.m_instance; } return true; } return other.m_current < other.m_end; } private: const SimpleFSAttrArray *m_instance; T *m_current, *m_end; }; class SimpleVSAttrArrayEntry { public: char *data; uint64_t size; }; template class SimpleVSAttrArray : public AttrArray { public: typedef typename T::AttributeType AttributeType; SimpleVSAttrArray() : m_header({0, 0}), m_dataEnd(nullptr), m_size(sizeof(SimpleVSAttrArray)) { } SimpleVSAttrArray(Reader &source) : SimpleVSAttrArray(source, source.ReadOrThrow
()) { } SimpleVSAttrArray(Reader &source, uint64_t rowCount) : SimpleVSAttrArray(source, Header({rowCount, source.ReadOrThrow()})) { } SimpleVSAttrArray(const SimpleVSAttrArray &array, const SharedArray &filter) : AttrArray(filter), m_header(array.m_header), m_data(array.m_data), m_dataEnd(array.m_dataEnd), m_positions(array.m_positions), m_size(array.m_size) { } virtual ~SimpleVSAttrArray() { } virtual AttrArray *Filter(SharedArray filter) const { return new SimpleVSAttrArray(*this, filter); } const T GetAt(uint64_t index) const { return T(GetEntry(index)); } const T operator [](uint64_t index) const { return T(GetEntry(index)); } virtual uint64_t GetCount() const { return m_header.count; } virtual uint64_t GetSize() const { return m_size; } virtual void Save(Writer &target, bool includeHeader = true) const { if (includeHeader) { target.WriteOrThrow(m_header); } else { target.WriteOrThrow(m_header.dataSize); } if (m_header.count > 0) { target.WriteOrThrow(m_data.GetPointer(), m_header.dataSize); target.WriteOrThrow((char*)m_positions.GetPointer(), m_header.count * sizeof(uint64_t)); } } virtual void Append(const AttrArray &array, uint64_t row) { const SimpleVSAttrArrayEntry source = ((const SimpleVSAttrArray&)array).GetEntry(row), target = AppendEntry(source.size); memcpy(target.data, source.data, target.size); } virtual void Append(Attribute &value) { AttributeType &attribute = (AttributeType&)value; T::Write(AppendEntry(T::GetSize(attribute)), attribute); } virtual void Remove() { const uint64_t oldDataSize = m_header.dataSize, newDataSize = m_positions[--m_header.count]; m_header.dataSize = newDataSize; m_size -= (oldDataSize - newDataSize) + sizeof(uint64_t); m_dataEnd = m_data.GetPointer() + newDataSize; } virtual void Clear() { m_header.count = 0; m_header.dataSize = 0; m_size = sizeof(SimpleVSAttrArray); m_dataEnd = m_data.GetPointer(); } virtual bool IsDefined(uint64_t row) const { return GetAt(row).IsDefined(); } virtual int Compare(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { const T &value = ((const SimpleVSAttrArray&)arrayB).GetAt(rowB); return GetAt(rowA).Compare(value); } virtual int Compare(uint64_t row, Attribute &value) const { return GetAt(row).Compare((AttributeType&)value); } virtual int CompareAlmost(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { const T &value = ((const SimpleVSAttrArray&)arrayB).GetAt(rowB); return TCompareAlmost(GetAt(rowA), value); } virtual int CompareAlmost(uint64_t row, Attribute &value) const { return TCompareAlmost(GetAt(row), (const AttributeType&)value); } virtual bool Equals(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { const T &value = ((const SimpleVSAttrArray&)arrayB).GetAt(rowB); return GetAt(rowA).Equals(value); } virtual bool Equals(uint64_t row, Attribute &value) const { return GetAt(row).Equals((AttributeType&)value); } virtual bool EqualsAlmost(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { const T &value = ((const SimpleVSAttrArray&)arrayB).GetAt(rowB); return TEqualsAlmost(GetAt(rowA), value); } virtual bool EqualsAlmost(uint64_t row, Attribute &value) const { return TEqualsAlmost(GetAt(row), (const AttributeType&)value); } virtual uint64_t GetHash(uint64_t row) const { return GetAt(row).GetHash(); } virtual Attribute *GetAttribute(uint64_t row, bool clone = true) const { return GetAt(row).GetAttribute(clone); } private: class Header { public: uint64_t count, dataSize; }; Header m_header; SharedArray m_data; char* m_dataEnd; SharedArray m_positions; uint64_t m_size; SimpleVSAttrArray(Reader &source, const Header &header) : m_header(header), m_data(header.dataSize), m_dataEnd(m_data.GetPointer() + header.dataSize), m_positions(header.count), m_size(sizeof(SimpleVSAttrArray) + header.dataSize + (header.count * sizeof(uint64_t))) { char * data = m_data.GetPointer(); uint64_t * positions = m_positions.GetPointer(); source.ReadOrThrow(data, m_data.GetCapacity()); source.ReadOrThrow((char*)positions, m_positions.GetCapacity() * sizeof(uint64_t)); } SimpleVSAttrArray(const SimpleVSAttrArray &instance) = delete; template static int TCompareAlmost(const T &entry, V &value) { return entry.CompareAlmost(value); } template static bool TEqualsAlmost(const T &entry, V &value) { return entry.EqualsAlmost(value); } SimpleVSAttrArrayEntry GetEntry(uint64_t row) const { const uint64_t position = m_positions[row], nextRow = row + 1, size = nextRow < m_header.count ? m_positions[nextRow] - position : m_header.dataSize - position; return {m_data.GetPointer() + position, size}; } SimpleVSAttrArrayEntry AppendEntry(const uint64_t valueSize) { const uint64_t dataSize = m_header.dataSize, count = m_header.count++, capacity = m_data.GetCapacity(), freeCapacity = capacity - dataSize; //Add new positions entry //Provide space if neccessery if (m_positions.GetCapacity() == count) { if (count == 0) { m_positions = SharedArray(1); m_positions[0] = 0; } else { const uint64_t newCapacity = count + count; uint64_t *positions = new uint64_t[newCapacity]; positions[count] = dataSize; memcpy(positions, m_positions.GetPointer(), count * sizeof(uint64_t)); m_positions = SharedArray(positions, newCapacity); } } else { m_positions[count] = dataSize; } char *dataEnd; //Provide space for the new value if (freeCapacity < valueSize) { const uint64_t diffCapacity = valueSize - freeCapacity, newCapacity = capacity == 0 ? diffCapacity : capacity + std::max(capacity, diffCapacity); char *data = new char[newCapacity]; if (dataSize > 0) { memcpy(data, m_data.GetPointer(), dataSize); } m_data = SharedArray(data, newCapacity); dataEnd = data + dataSize; } else { dataEnd = m_dataEnd; } m_header.dataSize = dataSize + valueSize; m_dataEnd = dataEnd + valueSize; m_size += valueSize + sizeof(uint64_t); return {dataEnd, valueSize}; } }; template class SimpleSpatialVSAttrArray : public SpatialAttrArray { public: SimpleSpatialVSAttrArray() { } SimpleSpatialVSAttrArray(Reader &source) : m_array(source) { } SimpleSpatialVSAttrArray(Reader &source, uint64_t rowCount) : m_array(source, rowCount) { } SimpleSpatialVSAttrArray(const SimpleSpatialVSAttrArray &array, const SharedArray &filter) : m_array(array.m_array, filter) { } virtual ~SimpleSpatialVSAttrArray() { } virtual AttrArray *Filter(SharedArray filter) const { return new SimpleSpatialVSAttrArray(*this, filter); } const T GetAt(uint64_t index) const { return m_array.GetAt(index); } const T operator [](uint64_t index) const { return m_array.GetAt(index); } virtual uint64_t GetCount() const { return m_array.GetCount(); } virtual uint64_t GetSize() const { return m_array.GetSize(); } virtual void Save(Writer &target, bool includeHeader = true) const { m_array.Save(target, includeHeader); } virtual void Append(const AttrArray &array, uint64_t row) { m_array.Append(((const SimpleSpatialVSAttrArray&)array).m_array, row); } virtual void Append(Attribute &value) { m_array.Append(value); } virtual void Remove() { m_array.Remove(); } virtual void Clear() { m_array.Clear(); } virtual bool IsDefined(uint64_t row) const { return m_array.IsDefined(row); } virtual int Compare(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { return m_array.Compare(rowA, ((const SimpleSpatialVSAttrArray&)arrayB).m_array, rowB); } virtual int Compare(uint64_t row, Attribute &value) const { return m_array.Compare(row, value); } virtual bool Equals(uint64_t rowA, const AttrArray &arrayB, uint64_t rowB) const { return m_array.Equals(rowA, ((const SimpleSpatialVSAttrArray&)arrayB).m_array, rowB); } virtual bool Equals(uint64_t row, Attribute &value) const { return m_array.Equals(row, value); } virtual uint64_t GetHash(uint64_t row) const { return m_array.GetAt(row).GetHash(); } virtual Attribute *GetAttribute(uint64_t row, bool clone = true) const { return m_array.GetAt(row).GetAttribute(clone); } virtual Rectangle GetBoundingBox( uint64_t row, const Geoid *geoid = nullptr) const { return m_array.GetAt(row).GetBoundingBox(); } virtual double GetDistance(uint64_t row, const Rectangle& rect, const Geoid *geoid = nullptr) const { return m_array.GetAt(row).GetDistance(rect, geoid); } virtual bool Intersects(uint64_t row, const Rectangle& rect, const Geoid *geoid = nullptr) const { return m_array.GetAt(row).Intersects(rect, geoid); } virtual bool IsEmpty(uint64_t row) const { return m_array.GetAt(row).IsEmpty(); } private: SimpleVSAttrArray m_array; }; }