/* * This file is a part of CMSLU -- Content Management System like Unix * and is not publicly distributed * * Copyright (c) 2008, Tomasz Sowa * All rights reserved. * */ #include "dirs.h" void Dirs::Clear() { dir_table.Clear(); } void Dirs::CheckRootDir() { DirContainer::ParentIterator i; long roots = 0; for( i=dir_table.FindFirstParent(-1) ; i!=dir_table.ParentEnd() ; i=dir_table.NextParent(i) ) ++roots; if( roots == 0 ) { log << log1 << "Dirs: there is no a root dir in the database" << logend; Clear(); } else if( roots > 1 ) { log << log1 << "Dirs: there are more than one root dir in the database" << logend; Clear(); } } void Dirs::ReadDirs() { Clear(); db.GetDirs(dir_table); CheckRootDir(); } bool Dirs::GetRootDir(Item ** item) { DirContainer::Iterator root = dir_table.GetRoot(); if( root == dir_table.End() ) return false; *item = &(*root); return true; } bool Dirs::GetDir(const std::string & name, long parent, Item ** item) { DirContainer::ParentIterator i = dir_table.FindFirstParent(parent); for( ; i!=dir_table.ParentEnd() ; i = dir_table.NextParent(i) ) if( i->second->url == name ) { *item = &(*i->second); return true; } return false; } bool Dirs::ExtractName(const char * & s, std::string & name) { name.clear(); // skipping first slashes (can be more than one) for( ; *s == '/' ; ++s); for( ; *s != 0 && *s != '/' ; ++s) name += *s; return !name.empty(); } // !! moze lepiej zwracac wskaznik do Item i kiedy nie ma katalogu to zwracac 0 ? bool Dirs::GetDir(const std::string & path, Item ** item) { DirContainer::Iterator root = dir_table.GetRoot(); if( root == dir_table.End() ) // ops, we do not have a root dir return false; Item * pitem = &(*root); std::string name; const char * s = path.c_str(); while( ExtractName(s, name) ) { if( !GetDir(name, pitem->id, &pitem) ) return false; } *item = pitem; return true; } // !! ten interfejs jes bylejaki // !! moze lepiej zwracac id i kiedy nie ma katalogu to -1 (przeciez to jest wartosc ktora nie moze pojawic sie w indeksie) bool Dirs::GetDirId(const std::string & path, long * id) { Item * pitem; if( !GetDir(path, &pitem) ) return false; *id = pitem->id; return true; } bool Dirs::GetDirId(const std::string & name, long parent, long * id) { Item * pitem; if( !GetDir(name, parent, &pitem) ) return false; *id = pitem->id; return true; } bool Dirs::IsDir(long id) { DirContainer::Iterator i = dir_table.FindId(id); if( i == dir_table.End() ) return false; return true; } bool Dirs::GetDirChilds(long parent, std::vector & childs_table) { if( parent != -1 && !IsDir(parent) ) return false; DirContainer::ParentIterator i = dir_table.FindFirstParent(parent); for( ; i != dir_table.ParentEnd() ; i = dir_table.NextParent(i) ) childs_table.push_back( *i->second ); return true; } bool Dirs::GetDirChilds(long parent, std::vector & childs_table) { if( parent != -1 && !IsDir(parent) ) return false; DirContainer::ParentIterator i = dir_table.FindFirstParent(parent); for( ; i != dir_table.ParentEnd() ; i = dir_table.NextParent(i) ) childs_table.push_back( &(*i->second) ); return true; } // dodatkowo moze metoda AppendPath dodajaca sciezke do biezacego stringa? // albo tutaj stringa nie czyscic? // O(m * log n) (m- how many parts are in 'id') bool Dirs::MakePath(long id, std::string & path) { DirContainer::Iterator i; path = '/'; while( true ) { i = dir_table.FindId(id); if( i == dir_table.End() ) return false; if( i->parent_id == -1 ) return true; id = i->parent_id; path.insert(0, i->url); path.insert(path.begin(), '/'); } } // with exceptions Item * Dirs::GetDirT(const std::string & path) { Item * pitem; if( !GetDir(path, &pitem) ) throw Error(Error::incorrect_dir); return pitem; } Item * Dirs::GetDirT(const std::string & name, long parent) { Item * pitem; if( !GetDir(name, parent, &pitem) ) throw Error(Error::incorrect_dir); return pitem; } long Dirs::GetDirIdT(const std::string & path) { long id; if( !GetDirId(path, &id) ) throw Error(Error::incorrect_dir); return id; } long Dirs::GetDirIdT(const std::string & name, long parent) { long id; if( !GetDirId(name, parent, &id) ) throw Error(Error::incorrect_dir); return id; } // !! nowy interfejs Item * Dirs::GetRootDir() { DirContainer::Iterator root = dir_table.GetRoot(); if( root == dir_table.End() ) return 0; return &(*root); } Item * Dirs::GetDir(const std::string & name, long parent) { DirContainer::ParentIterator i = dir_table.FindFirstParent(parent); for( ; i!=dir_table.ParentEnd() ; i = dir_table.NextParent(i) ) if( i->second->url == name ) return &(*i->second); return 0; } Item * Dirs::GetDir(const std::string & path) { DirContainer::Iterator root = dir_table.GetRoot(); if( root == dir_table.End() ) // ops, we do not have a root dir return 0; Item * pitem = &(*root); std::string name; const char * s = path.c_str(); while( ExtractName(s, name) ) { pitem = GetDir(name, pitem->id); if( !pitem ) return 0; } return pitem; } Item * Dirs::GetDir(long id) { DirContainer::Iterator i = dir_table.FindId(id); if( i == dir_table.End() ) return 0; return &(*i); }