/* This file is part of SECONDO. Copyright (C) 2011, University in Hagen, Department of 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 */ #include #include "sstring.h" #include "SecondoCatalog.h" using namespace std; namespace raster2 { std::string stype_helper::name(){ return TYPE_NAME_SSTRING(); } sstring::sstring() : m_bDelete(false), m_psint(new sint()), m_pUniqueStringArray(new UniqueStringArray(true)), m_minimum(UNDEFINED_STRING_INDEX()), m_maximum(UNDEFINED_STRING_INDEX()) {} sstring::sstring(sint* psint, UniqueStringArray* pUniqueStringArray, int minimum, int maximum) : m_bDelete(false), m_psint(psint), m_pUniqueStringArray(pUniqueStringArray), m_minimum(minimum), m_maximum(maximum) {} sstring::~sstring() { if (m_bDelete) { m_psint->destroy(); m_pUniqueStringArray->Destroy(); } delete m_psint; delete m_pUniqueStringArray; } void sstring::clear(){ m_psint->clear(); m_minimum=UNDEFINED_STRING_INDEX(); m_maximum=UNDEFINED_STRING_INDEX(); } bool sstring::isDefined() const{ return m_psint->isDefined(); } void sstring::setDefined( const bool _defined){ if(_defined != isDefined()){ m_psint->setDefined(_defined); if(!_defined){ m_minimum=UNDEFINED_STRING_INDEX(); m_maximum=UNDEFINED_STRING_INDEX(); } } } void sstring::destroy() { m_bDelete = true; } sint::storage_type& sstring::getStorage() { return m_psint->getStorage(); } string sstring::atlocation(double x, double y) const { string value = UNDEFINED_STRING(); if(m_psint != 0 && m_pUniqueStringArray != 0) { int nLocationIndex = m_psint->atlocation(x, y); if(nLocationIndex >= 0) { bool bOK = m_pUniqueStringArray->GetUniqueString(nLocationIndex, value); assert(bOK); } } return value; } void sstring::setatlocation(double x, double y, const string& value) { if(m_psint != 0 && m_pUniqueStringArray != 0 && value.empty() == false) { int nStringIndex = m_pUniqueStringArray->AddString(value); if(nStringIndex != UNDEFINED_STRING_INDEX()) { m_psint->setatlocation(x, y, nStringIndex); } } } bool sstring::isUndefined(const std::string& t) { return stype_helper::isUndefined(t); } stype_helper::wrapper_type sstring::wrap (const std::string& t) { return stype_helper::wrap(t); } std::string sstring::unwrap(const CcString& w) { return stype_helper::unwrap(w); } sstring* sstring::atrange(const Rect& rRect) const { sstring* result = new sstring(); result->setGrid(getGrid()); index_type from = m_psint->getGrid().getIndex(rRect.MinD(0), rRect.MinD(1)); index_type to = m_psint->getGrid().getIndex(rRect.MaxD(0), rRect.MaxD(1)); std::string value; for (riter_type rit = m_psint->iterate_regions(from, to), re = m_psint->end_regions(); rit != re; ++rit) { index_type from = *rit; index_type to = *rit + sint::riter_type::region_size; for (index_type i = from; i < to; i.increment(from, to)) { m_pUniqueStringArray->GetUniqueString(m_psint->get(i), value); result->set(i, value); } } return result; } Rect sstring::bbox() const { Rect boundingBox(false); if((m_psint != 0) && isDefined()) { boundingBox = m_psint->bbox(); } return boundingBox; } string sstring::getMinimum() const { std::string result = UNDEFINED_STRING(); if ( (m_minimum != UNDEFINED_STRING_INDEX()) && isDefined()) { m_pUniqueStringArray->GetUniqueString(m_minimum, result); } return result; } string sstring::getMaximum() const { std::string result = UNDEFINED_STRING(); if ((m_maximum != UNDEFINED_STRING_INDEX()) && isDefined()) { m_pUniqueStringArray->GetUniqueString(m_maximum, result); } return result; } grid2 sstring::getGrid() const { grid2 grid2; if(m_psint != 0) { grid2 = m_psint->getGrid(); } return grid2; } void sstring::setGrid(const grid2& rGrid) { m_psint->setGrid(rGrid); } sstring::riter_type sstring::begin_regions() const { assert(m_psint != 0); return m_psint->getStorage().begin_regions(); } sstring::riter_type sstring::end_regions() const { assert(m_psint != 0); return m_psint->getStorage().end_regions(); } sstring::riter_type sstring::iterate_regions(const index_type& from, const index_type& to) const { assert(m_psint != 0); return m_psint->iterate_regions(from, to); } void sstring::set(const index_type& i, const std::string& value) { assert(m_psint != 0); assert(m_pUniqueStringArray != 0); if (value == UNDEFINED_STRING()) { m_psint->getStorage()[i] = UNDEFINED_INT(); return; } int index = m_pUniqueStringArray->GetUniqueStringIndex(value); if (index == UNDEFINED_STRING_INDEX()) { std::string minimum = UNDEFINED_STRING(); if (m_minimum != UNDEFINED_STRING_INDEX()) { m_pUniqueStringArray->GetUniqueString(m_minimum, minimum); } std::string maximum = UNDEFINED_STRING(); if (m_maximum != UNDEFINED_STRING_INDEX()) { m_pUniqueStringArray->GetUniqueString(m_maximum, maximum); } index = m_pUniqueStringArray->AddString(value); if (m_minimum == UNDEFINED_STRING_INDEX()) { m_minimum = index; } else if (!stype_helper::isUndefined(value)) { if (value < minimum) { m_minimum = index; } } if (m_maximum == UNDEFINED_STRING_INDEX()) { m_maximum = index; } else if (!stype_helper::isUndefined(value)) { if (value > maximum) { m_maximum = index; } } } m_psint->getStorage()[i] = index; } std::string sstring::get(const index_type& i) const { assert(m_psint != 0); assert(m_pUniqueStringArray != 0); std::string result = stype_helper::getUndefined(); int index = m_psint->getStorage()[i]; if (index >= 0) { m_pUniqueStringArray->GetUniqueString(index, result); } return result; } void sstring::setCacheSize(size_t size) { m_psint->setCacheSize(size); } void sstring::flushCache() { m_psint->flushCache(); } const string sstring::BasicType() { return TYPE_NAME_SSTRING(); } const bool sstring::checkType(const ListExpr type) { return listutils::isSymbol(type, BasicType()); } void* sstring::Cast(void* pVoid) { return new (pVoid) sstring; } Word sstring::Clone(const ListExpr typeInfo, const Word& w) { Word word = SetWord(Address(0)); sstring* psstring = static_cast(w.addr); if(psstring != 0) { SecondoCatalog* pSecondoCatalog = SecondoSystem::GetCatalog(); if(pSecondoCatalog != 0) { ListExpr numericType = pSecondoCatalog->NumericType( NList(sint::BasicType()).listExpr()); word = SetWord(psstring->m_psint); sint* psint = static_cast(sint::Clone(numericType, word).addr); numericType = pSecondoCatalog->NumericType( NList(UniqueStringArray::BasicType()).listExpr()); word = SetWord(psstring->m_pUniqueStringArray); UniqueStringArray* pUniqueStringArray = static_cast(UniqueStringArray::Clone(numericType, word).addr); if(psint != 0 && pUniqueStringArray != 0) { word = SetWord(new sstring(psint, pUniqueStringArray, psstring->m_minimum, psstring->m_maximum)); } } } return word; } void sstring::Close(const ListExpr typeInfo, Word& w) { sstring* psstring = static_cast(w.addr); if(psstring != 0) { delete psstring; w = SetWord(Address(0)); } } Word sstring::Create(const ListExpr typeInfo) { Word w = SetWord(new sstring()); return w; } void sstring::Delete(const ListExpr typeInfo, Word& w) { sstring* psstring = static_cast(w.addr); if(psstring != 0) { delete psstring; w = SetWord(Address(0)); } } TypeConstructor sstring::getTypeConstructor() { TypeConstructor typeConstructorsstring( sstring::BasicType(), // type name function sstring::Property, // property function describing signature sstring::Out, // out function sstring::In, // in function 0, // save to list function 0, // restore from list function sstring::Create, // create function sstring::Delete, // delete function sstring::Open, // open function sstring::Save, // save function sstring::Close, // close function sstring::Clone, // clone function sstring::Cast, // cast function sstring::SizeOfObj, // sizeofobj function sstring::KindCheck); // kindcheck function typeConstructorsstring.AssociateKind(Kind::SIMPLE()); return typeConstructorsstring; } Word sstring::In(const ListExpr typeInfo, const ListExpr instance, const int errorPos, ListExpr& errorInfo, bool& correct) { if(listutils::isSymbolUndefined(instance)){ correct = true; sstring* res = new sstring(); res->setDefined(false); return Word(res); } Word w = SetWord(Address(0)); NList nlist(instance); NList sintList; grid2 grid; std::pair sizes; string minimum = UNDEFINED_STRING(); string maximum = UNDEFINED_STRING(); UniqueStringArray* pUniqueStringArray = new UniqueStringArray(true); try { if (nlist.isAtom()) { throw util::parse_error ("Expected list as first element, got an atom."); } NList grid2list = nlist.elem(1); nlist.rest(); if (grid2list.length() != 3) { throw util::parse_error ("Type mismatch: list for grid2 is too short or too long."); } if (!grid2list.isReal(1) || !grid2list.isReal(2) || !grid2list.isReal(3)) { throw util::parse_error( "Type mismatch: expected 3 reals as grid2 sublist."); } if (grid2list.elem(3).realval() <= 0) { throw util::parse_error( "The length in a grid2 must be larger than 0."); } sintList.append(grid2list); if (!nlist.isEmpty()) { NList sizelist = nlist.elem(1); nlist.rest(); if (sizelist.length() != 2) { throw util::parse_error( "Type mismatch: list for partial grid sizes is too short."); } if ( sizelist.isInt(1) && sizelist.isInt(2) && sizelist.elem(1).intval() > 0 && sizelist.elem(2).intval() > 0) { sintList.append(sizelist); sizes.first = sizelist.elem(1).intval(); sizes.second = sizelist.elem(2).intval(); } else { throw util::parse_error("Type mismatch: " "partial grid size must contain two positive integers."); } } while(!nlist.isEmpty()) { NList sintPartialList; sint::index_type root; NList pagelist = nlist.first(); nlist.rest(); if(pagelist.length() != 3) { throw util::parse_error("Type mismatch: " "partial grid content must contain three elements."); } if(pagelist.isInt(1) && pagelist.isInt(2)) { root[0] = pagelist.elem(1).intval(); root[1] = pagelist.elem(2).intval(); } else { throw util::parse_error("Type mismatch: " "partial grid content must start with two integers."); } sintPartialList.append(pagelist.elem(1)); sintPartialList.append(pagelist.elem(2)); pagelist.rest(); pagelist.rest(); NList valuelist = pagelist.first(); if(valuelist.length() != Cardinal(sizes.first) * Cardinal(sizes.second)) { throw util::parse_error("Type mismatch: " "list for partial grid values is too short or too long."); } NList sintValueList; for(int row = 0; row < sizes.first; ++row) { for(int column = 0; column < sizes.second; ++column) { string value; int i = row * sizes.first + column + 1; if(valuelist.elem(i).isSymbol(Symbol::UNDEFINED())) { sintValueList.append(valuelist.elem(i)); } else if(stype_helper::check(valuelist.elem(i))) { value = stype_helper::parse(valuelist.elem(i)); if(stype_helper::isUndefined(minimum) || value < minimum) { minimum = value; } if(stype_helper::isUndefined(maximum) || value > maximum) { maximum = value; } int nUniqueStringIndex = pUniqueStringArray->AddString(value); sintValueList.append(NList(nUniqueStringIndex)); } else { throw util::parse_error("Type mismatch: " "list value in partial grid has wrong type."); } } } sintPartialList.append(sintValueList); sintList.append(sintPartialList); } } catch(util::parse_error& e) { delete pUniqueStringArray; cmsg.inFunError(e.what()); correct = false; return w; } w = sint::In(typeInfo, sintList.listExpr(), errorPos, errorInfo, correct); if(correct == true) { sint* psint = static_cast(w.addr); if(psint != 0) { std::list l = pUniqueStringArray->GetUniqueStringArray(); l.sort(); int minimum = pUniqueStringArray->GetUniqueStringIndex(l.front()); int maximum = pUniqueStringArray->GetUniqueStringIndex(l.back()); sstring* psstring = new sstring(psint, pUniqueStringArray, minimum, maximum); correct = true; w = SetWord(psstring); } } else { delete pUniqueStringArray; } return w; } bool sstring::KindCheck(ListExpr type, ListExpr& errorInfo) { bool bRetVal = false; if(nl != 0) { bRetVal = nl->IsEqual(type, sstring::BasicType()); } return bRetVal; } bool sstring::Open(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value) { int minimum, maximum; valueRecord.SetPos(offset); valueRecord.Read(minimum); valueRecord.Read(maximum); offset = valueRecord.GetPos(); bool bRetVal = true; SecondoCatalog* pSecondoCatalog = SecondoSystem::GetCatalog(); if(pSecondoCatalog != 0) { ListExpr numericType = pSecondoCatalog->NumericType( NList(sint::BasicType()).listExpr()); Word w = SetWord(Address(0)); bRetVal &= sint::Open(valueRecord, offset, numericType, w); sint* psint = static_cast(w.addr); numericType = pSecondoCatalog->NumericType(NList( UniqueStringArray::BasicType()).listExpr()); w = SetWord(Address(0)); bRetVal &= UniqueStringArray::Open(valueRecord, offset, numericType, w); UniqueStringArray* pUniqueStringArray = static_cast (w.addr); if(psint != 0 && pUniqueStringArray != 0) { sstring* psstring = new sstring(psint, pUniqueStringArray, minimum, maximum); if(psstring != 0) { value = SetWord(psstring); } } } return bRetVal; } bool sstring::Save(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value) { bool bRetVal = true; sstring* psstring = static_cast(value.addr); if(psstring != 0) { valueRecord.SetPos(offset); valueRecord.Write(psstring->m_minimum); valueRecord.Write(psstring->m_maximum); offset = valueRecord.GetPos(); SecondoCatalog* pSecondoCatalog = SecondoSystem::GetCatalog(); if(pSecondoCatalog != 0) { ListExpr numericType = pSecondoCatalog->NumericType( NList(sint::BasicType()).listExpr()); Word w = SetWord(psstring->m_psint); bRetVal &= sint::Save(valueRecord, offset, numericType, w); numericType = pSecondoCatalog->NumericType( NList(UniqueStringArray::BasicType()).listExpr()); w = SetWord(psstring->m_pUniqueStringArray); bRetVal &= UniqueStringArray::Save(valueRecord, offset, numericType, w); } } return bRetVal; } ListExpr sstring::Out(ListExpr typeInfo, Word value) { sstring* psstring = static_cast(value.addr); if(!psstring->isDefined()){ return nl->SymbolAtom(Symbol::UNDEFINED()); } ListExpr pListExpr = 0; if(nl != 0) { if(psstring != 0) { NList result; NList gridlist; const grid2& rGrid = psstring->m_psint->getGrid(); gridlist.append(rGrid.getOriginX()); gridlist.append(rGrid.getOriginY()); gridlist.append(rGrid.getLength()); result.append(gridlist); NList tilesizelist; const sint::index_type& size = sint::riter_type::region_size; sint::index_type index; int element; sint::storage_type& storage = psstring->m_psint->getStorage(); RasterRegion<2> bb = storage.bbox(); sint::index_type sz = bb.Max - bb.Min; if (sz[0] <= size[0] && sz[1] <= size[1]) { tilesizelist.append(1); tilesizelist.append(1); result.append(tilesizelist); for (sint::iter_type it = storage.begin(), e = storage.end(); it != e; ++it) { element = *it; NList partiallist; partiallist.append(it.getIndex()[0]); partiallist.append(it.getIndex()[1]); NList valuelist; if(stype_helper::isUndefined(element)) { valuelist.append(NList(Symbol::UNDEFINED())); } else { bool bOK = false; string uniqueString; bOK = psstring ->m_pUniqueStringArray ->GetUniqueString(element, uniqueString); if(bOK == true) { valuelist.append(NList(uniqueString, true, false)); } } partiallist.append(valuelist); result.append(partiallist); } } else { tilesizelist.append(size[0]); tilesizelist.append(size[1]); result.append(tilesizelist); for(sint::riter_type rit = storage.begin_regions(), re = storage.end_regions(); rit != re; ++rit) { NList partiallist; partiallist.append((*rit)[0]); partiallist.append((*rit)[1]); NList valuelist; for(int row = 0; row < size[0]; ++row) { for(int column = 0; column < size[1]; ++column) { index = *rit + sint::index_type((int[]){row, column}); element = storage[index]; if(stype_helper::isUndefined(element)) { valuelist.append(NList(Symbol::UNDEFINED())); } else { bool bOK = false; string uniqueString; bOK = psstring ->m_pUniqueStringArray ->GetUniqueString(element, uniqueString); if(bOK == true) { valuelist.append(NList(uniqueString, true, false)); } } } } partiallist.append(valuelist); result.append(partiallist); } } pListExpr = result.listExpr(); } } return pListExpr; } ListExpr sstring::Property() { NList property; if (property.isEmpty()) { NList names; names.append(NList(std::string("Signature"), true)); names.append(NList(std::string("Example Type List"), true)); names.append(NList(std::string("ListRep"), true)); names.append(NList(std::string("Example List"), true)); names.append(NList(std::string("Remarks"), true)); NList values; values.append(NList(std::string("-> DATA"), true)); values.append(NList(BasicType(), true)); values.append(NList( std::string( "((x y l) (szx szy) ((ix iy (v*)))*)"), true)); values.append(NList( std::string("((0 0 1) (2 2) ((5 5 (\"A\" \"B\" \"A\" \"C\"))))"), true)); values.append(NList(std::string(""), true)); property = NList(names, values); } return property.listExpr(); } int sstring::SizeOfObj() { return sizeof(sstring); } void swap(raster2::sstring& a, raster2::sstring& b) { std::swap(a.m_bDelete, b.m_bDelete); std::swap(a.m_psint, b.m_psint); std::swap(a.m_pUniqueStringArray, b.m_pUniqueStringArray); } }