/* ---- This file is part of SECONDO. Copyright (C) 2019, 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 ---- */ #include "IntSet.h" #include "Attribute.h" #include #include #include "NestedList.h" extern NestedList* nl; namespace collection{ IntSet::IntSet(const IntSet& src):Attribute(src),value(0),size(src.size){ if(size>0){ value = new int[size]; memcpy((char*)value, src.value,size*sizeof(int)); } } IntSet::IntSet(IntSet&& src): Attribute(src), value(src.value), size(src.size) { src.size = 0; src.value = 0; } IntSet::IntSet(const std::set& src):Attribute(true), value(0){ setTo(src); } IntSet& IntSet::operator=(const IntSet& src) { Attribute::operator=(src); if(this->size != src.size){ delete[] value; value = 0; this->size = src.size; if(size > 0){ value = new int[size]; } } if(size > 0){ memcpy((char*)value, src.value,size*sizeof(int)); } return *this; } IntSet& IntSet::operator=(IntSet&& src) { Attribute::operator=(src); delete[] value; size = src.size; value = src.value; src.size = 0; src.value = 0; return *this; } int IntSet::Compare(const IntSet& arg) const { if(!IsDefined()){ return arg.IsDefined()?-1:0; } if(!arg.IsDefined()){ return 1; } if(size != arg.size){ return size < arg.size ? -1 : 1; } for(size_t i=0;i arg.value[i]) return 1; } return 0; } size_t IntSet::HashValue() const { if(!IsDefined() ) return 0; if(value==nullptr) return 42; unsigned int step = size / 5; if(step<1) step = 1; size_t pos = 0; size_t res = 0; while(pos < size){ res += value[pos]; pos += step; } return res; } Word IntSet::In(const ListExpr typeInfo, const ListExpr le1, const int errorPos, ListExpr& errorInfo, bool& correct) { ListExpr le = le1; Word res((void*)0); if(listutils::isSymbolUndefined(le)){ res.addr = new IntSet(false); correct = true; return res; } if(nl->AtomType(le) != NoAtom){ correct = false; return res; } std::set tmp; while(!nl->IsEmpty(le)){ ListExpr f = nl->First(le); le = nl->Rest(le); if(nl->AtomType(f)!=IntType){ correct = false; return res; } tmp.insert(nl->IntValue(f)); } IntSet* r = new IntSet(tmp); res.addr = r; correct = true; return res; } ListExpr IntSet::Out(const ListExpr typeInfo, Word value) { IntSet* is = (IntSet*) value.addr; if(!is->IsDefined()){ return listutils::getUndefined(); } if(is->size == 0){ return nl->TheEmptyList(); } ListExpr res = nl->OneElemList( nl->IntAtom(is->value[0])); ListExpr last = res; for(unsigned int i=1;isize;i++){ last = nl->Append(last, nl->IntAtom(is->value[i])); } return res; } bool IntSet::Open( SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value){ bool def; if(!valueRecord.Read(&def, sizeof(bool), offset)){ return false; } offset += sizeof(bool); if(!def){ value.addr = new IntSet(false); return true; } size_t size; if(!valueRecord.Read(&size, sizeof(size_t), offset)){ return false; } offset+=sizeof(size_t); if(size==0){ value.addr = new IntSet(0,0); return true; } int* v = new int[size]; if(!valueRecord.Read(v,size*sizeof(int),offset)){ return false; } value.addr = new IntSet(size,v); return true; } bool IntSet::Save(SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value) { IntSet* is = (IntSet*) value.addr; bool def = is->IsDefined(); if(!valueRecord.Write(&def, sizeof(bool), offset)){ return false; } offset += sizeof(bool); if(!def){ return true; } size_t size = is->size; if(!valueRecord.Write(&size, sizeof(size_t), offset)){ return false; } offset += sizeof(size_t); if(is->size>0){ if(!valueRecord.Write(is->value, sizeof(int) * is->size, offset)){ return false; } offset += sizeof(int) * is->size; } return true; } std::ostream& IntSet::Print( std::ostream& os ) const { if(!IsDefined()){ os << "undefined"; return os; } os << "{"; for(size_t i=0;i0) os << ", "; os << value[i]; } os << "}"; return os; } void IntSet::Rebuild(char* buffer, size_t sz) { if(value!=nullptr){ delete[] value; value = nullptr; } size = 0; bool def; size_t offset = 0; memcpy(&def,buffer + offset, sizeof(bool)); offset += sizeof(bool); if(!def){ SetDefined(false); return; } SetDefined(true); memcpy(&size, buffer+offset, sizeof(size_t)); offset += sizeof(size_t); if(size > 0){ value = new int[size]; memcpy(value, buffer+offset, size * sizeof(int)); offset += size * sizeof(int); } } void IntSet::setTo(const std::set& src){ clear(); SetDefined(true); if(src.size()>0){ size = src.size(); value = new int[size]; auto it = src.begin(); size_t pos = 0; while(it!=src.end()) { value[pos] = *it; it++; pos++; } } } void IntSet::setTo(const std::vector& src) { clear(); SetDefined(true); if(src.size()>0){ size = src.size(); value = new int[size]; auto it = src.begin(); size_t pos = 0; while(it!=src.end()) { value[pos] = *it; it++; pos++; } } } IntSet IntSet::add(const IntSet& is) const{ if(!IsDefined() || !is.IsDefined()){ IntSet res(false); return res; } std::vector v; size_t p1 = 0; size_t p2 = 0; while( p1 < size && p2 < is.size){ if(value[p1] < is.value[p2]){ v.push_back(value[p1]); p1++; } else if(value[p1] > is.value[p2]){ v.push_back(is.value[p2]); p2++; } else { v.push_back(value[p1]); p1++; p2++; } } while( p1 < size){ v.push_back(value[p1]); p1++; } while( p2 < is.size){ v.push_back(is.value[p2]); p2++; } IntSet res(true); res.setTo(v); return res; } IntSet IntSet::minus(const IntSet& is) const{ if(!IsDefined() || !is.IsDefined()){ IntSet res(false); return res; } std::vector v; size_t p1 = 0; size_t p2 = 0; while( p1 < size && p2 < is.size){ if(value[p1] < is.value[p2]){ v.push_back(value[p1]); p1++; } else if(value[p1] > is.value[p2]){ p2++; } else { p1++; p2++; } } while( p1 < size){ v.push_back(value[p1]); p1++; } IntSet res(true); res.setTo(v); return res; } IntSet IntSet::sdiff(const IntSet& is) const{ if(!IsDefined() || !is.IsDefined()){ IntSet res(false); return res; } std::vector v; size_t p1 = 0; size_t p2 = 0; while( p1 < size && p2 < is.size){ if(value[p1] < is.value[p2]){ v.push_back(value[p1]); p1++; } else if(value[p1] > is.value[p2]){ v.push_back(is.value[p2]); p2++; } else { p1++; p2++; } } while( p1 < size){ v.push_back(value[p1]); p1++; } while( p2 < is.size){ v.push_back(is.value[p2]); p2++; } IntSet res(true); res.setTo(v); return res; } IntSet IntSet::intersection(const IntSet& is) const { if(!IsDefined() || !is.IsDefined()){ IntSet res(false); return res; } std::vector v; size_t p1 = 0; size_t p2 = 0; while( p1 < size && p2 < is.size){ if(value[p1] < is.value[p2]){ p1++; } else if(value[p1] > is.value[p2]){ p2++; } else { v.push_back(value[p1]); p1++; p2++; } } IntSet res(true); res.setTo(v); return res; } bool IntSet::contains( const int i) const { if(!IsDefined() || size==0){ return false; } int min = 0; int max = size -1; while(max > min){ int mid = (max + min) / 2; int mv = value[mid]; if(mv == i){ return true; } if(mv < i){ min = mid + 1; } else { max = mid-1; } } return value[min] == i; } bool IntSet::minCommon(const IntSet& is, int& result) const{ result = 0; if(!IsDefined() || !is.IsDefined()){ return false; } size_t p1 = 0; size_t p2 = 0; while( p1 < size && p2 < is.size){ if(value[p1] < is.value[p2]){ p1++; } else if(value[p1] > is.value[p2]){ p2++; } else { result = value[p1]; return true; } } return false; } } // end of namespace std::ostream& operator<<(std::ostream& out, const collection::IntSet& is){ return is.Print(out); }