Files
secondo/Algebras/CRel/SimpleAttrArray.h
2026-01-23 17:03:45 +08:00

866 lines
20 KiB
C++

/*
----
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 <algorithm>
#include "AttrArray.h"
#include "Attribute.h"
#include <cstdint>
#include <cstring>
#include "NestedList.h"
#include "ReadWrite.h"
#include "Shared.h"
#include "SpatialAttrArray.h"
#include <string>
extern NestedList *nl;
namespace CRelAlgebra
{
template <class T>
class SimpleFSAttrArrayIterator;
/*
Class template that allows easy implementation of ~AttrArray~s with entries
of fixed size.
For an example see ~LongInts~.
*/
template <class T>
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<uint64_t>())
{
}
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<const uint64_t> &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<const uint64_t> filter) const
{
return new SimpleFSAttrArray<T>(*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<T>&)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<char>(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<char>(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<T>&)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<T>&)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<T>&)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<T>&)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<T> GetIterator() const
{
return SimpleFSAttrArrayIterator<T>(*this);
}
SimpleFSAttrArrayIterator<T> begin() const
{
return GetIterator();
}
SimpleFSAttrArrayIterator<T> end() const
{
return SimpleFSAttrArrayIterator<T>();
}
private:
friend class SimpleFSAttrArrayIterator<T>;
uint64_t m_count,
m_size,
m_capacity;
SharedArray<char> m_data;
T *m_values;
SimpleFSAttrArray(const SimpleFSAttrArray &instance) = delete;
template <class V>
static int TCompareAlmost(const T &entry, V &value)
{
return entry.CompareAlmost(value);
}
template <class V>
static bool TEqualsAlmost(const T &entry, V &value)
{
return entry.EqualsAlmost(value);
}
};
/*
Iterator over the entries of a SimpleFSAttrArray<T>.
*/
template <class T>
class SimpleFSAttrArrayIterator
{
public:
SimpleFSAttrArrayIterator() :
m_instance(nullptr),
m_current(nullptr),
m_end(nullptr)
{
}
SimpleFSAttrArrayIterator(const SimpleFSAttrArray<T> &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<T> *m_instance;
T *m_current,
*m_end;
};
class SimpleVSAttrArrayEntry
{
public:
char *data;
uint64_t size;
};
template <class T>
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<Header>())
{
}
SimpleVSAttrArray(Reader &source, uint64_t rowCount) :
SimpleVSAttrArray(source,
Header({rowCount, source.ReadOrThrow<uint64_t>()}))
{
}
SimpleVSAttrArray(const SimpleVSAttrArray &array,
const SharedArray<const uint64_t> &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<const uint64_t> filter) const
{
return new SimpleVSAttrArray<T>(*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<T>&)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<T>&)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<T>&)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<T>&)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<T>&)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<char> m_data;
char* m_dataEnd;
SharedArray<uint64_t> 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 <class V>
static int TCompareAlmost(const T &entry, V &value)
{
return entry.CompareAlmost(value);
}
template <class V>
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<uint64_t>(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<uint64_t>(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<char>(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 T>
class SimpleSpatialVSAttrArray : public SpatialAttrArray<T::dimension>
{
public:
SimpleSpatialVSAttrArray()
{
}
SimpleSpatialVSAttrArray(Reader &source) :
m_array(source)
{
}
SimpleSpatialVSAttrArray(Reader &source, uint64_t rowCount) :
m_array(source, rowCount)
{
}
SimpleSpatialVSAttrArray(const SimpleSpatialVSAttrArray &array,
const SharedArray<const uint64_t> &filter) :
m_array(array.m_array, filter)
{
}
virtual ~SimpleSpatialVSAttrArray()
{
}
virtual AttrArray *Filter(SharedArray<const uint64_t> filter) const
{
return new SimpleSpatialVSAttrArray<T>(*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<T>&)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<T::dimension> GetBoundingBox(
uint64_t row, const Geoid *geoid = nullptr) const
{
return m_array.GetAt(row).GetBoundingBox();
}
virtual double GetDistance(uint64_t row,
const Rectangle<T::dimension>& rect,
const Geoid *geoid = nullptr) const
{
return m_array.GetAt(row).GetDistance(rect, geoid);
}
virtual bool Intersects(uint64_t row, const Rectangle<T::dimension>& 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<T> m_array;
};
}