/********************************************************************** * * dbclass.cpp -- * Copyright (C) 1999-2008 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program 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. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ #include "dbclass.h" #include "OIDtools.h" #include "unitool.h" dbclass::~dbclass() {} // May be overwritten by subclasses; returns true if exists bool dbclass::exists (const text_t& key) { text_t data; return getkeydata (key, data); } // May be overwritten by subclasses; returns true on success bool dbclass::getinfo (const text_t& key, infodbclass &info) { text_t data; if (!getkeydata(key, data)) return false; // Use getinfoline() to parse the data value into the infodbclass object text_t::iterator data_iterator = data.begin(); text_t ikey, ivalue; info.clear(); while (getinfoline(data_iterator, data.end(), ikey, ivalue)) { info.addinfo(ikey, ivalue); } return true; } // returns true on success bool dbclass::getinfoline (text_t::iterator &here, text_t::iterator end, text_t &key, text_t &value) { key.clear(); value.clear(); // ignore white space while (here != end && is_unicode_space (*here)) ++here; // get the '<' if (here == end || *here != '<') return false; ++here; // get the key while (here != end && *here != '>') { key.push_back(*here); ++here; } // get the '>' if (here == end || *here != '>') return false; ++here; // get the value while (here != end && *here != '\n') { if (*here == '\\') { // found escape character ++here; if (here != end) { if (*here == 'n') value.push_back ('\n'); else if (*here == 'r') value.push_back ('\r'); else value.push_back(*here); } } else { // a normal character value.push_back(*here); } ++here; } return true; } // returns true on success bool dbclass::setinfo (const text_t &key, const infodbclass &info) { text_t subkey; text_t data; // get all the keys and values infodbclass::const_iterator info_here = info.begin(); infodbclass::const_iterator info_end = info.end(); while (info_here != info_end) { // add the key subkey.clear(); subkey.push_back('<'); text_t::const_iterator subkey_here = (*info_here).first.begin(); text_t::const_iterator subkey_end = (*info_here).first.end(); while (subkey_here != subkey_end) { if (*subkey_here == '>') { subkey.push_back('\\'); subkey.push_back('>'); } else if (*subkey_here == '\n') { subkey.push_back('\\'); subkey.push_back('n'); } else if (*subkey_here == '\r') { subkey.push_back('\\'); subkey.push_back('r'); } else if (*subkey_here == '\\') { subkey.push_back('\\'); subkey.push_back('\\'); } else { subkey.push_back (*subkey_here); } ++subkey_here; } subkey.push_back('>'); // add the values text_tarray::const_iterator subvalue_here = (*info_here).second.begin(); text_tarray::const_iterator subvalue_end = (*info_here).second.end(); while (subvalue_here != subvalue_end) { data += subkey; text_t::const_iterator thissubvalue_here = (*subvalue_here).begin(); text_t::const_iterator thissubvalue_end = (*subvalue_here).end(); while (thissubvalue_here != thissubvalue_end) { if (*thissubvalue_here == '>') { data.push_back('\\'); data.push_back('>'); } else if (*thissubvalue_here == '\n') { data.push_back('\\'); data.push_back('n'); } else if (*thissubvalue_here == '\r') { data.push_back('\\'); data.push_back('r'); } else if (*thissubvalue_here == '\\') { data.push_back('\\'); data.push_back('\\'); } else { data.push_back (*thissubvalue_here); } ++thissubvalue_here; } data.push_back('\n'); ++subvalue_here; } ++info_here; } return setkeydata(key, data); } // replaces the .fc, .lc, .pr, .rt, .ns and .ps syntax (first child, // last child, parent, root, next sibling, previous sibling) // it expects child, parent, etc. to exist if syntax has been used // so you should test before using text_t dbclass::translate_OID (const text_t &inOID, infodbclass &info) { if (inOID.size() < 4) return inOID; if (findchar (inOID.begin(), inOID.end(), '.') == inOID.end()) return inOID; text_t OID = inOID; text_tarray tailarray; text_t tail = substr (OID.end()-3, OID.end()); if (tail == ".rt") { get_top (inOID, OID); return OID; } while (tail == ".fc" || tail == ".lc" || tail == ".pr" || tail == ".ns" || tail == ".ps") { tailarray.push_back(tail); OID.erase (OID.end()-3, OID.end()); tail = substr (OID.end()-3, OID.end()); if (tail == ".rt") { get_top (inOID, OID); return OID; } } if (tailarray.empty()) return inOID; text_tarray::const_iterator begin = tailarray.begin(); text_tarray::const_iterator here = tailarray.end() - 1; while (here >= begin) { if (*here == ".fc") get_first_child (OID, info); else if (*here == ".lc") get_last_child (OID, info); else if (*here == ".pr") OID = get_parent (OID); else if (*here == ".ns") get_next_sibling (OID, info); else if (*here == ".ps") get_previous_sibling (OID, info); if (here == begin) break; --here; } return OID; } void dbclass::get_first_child (text_t &OID, infodbclass &info) { text_t firstchild; if (getinfo (OID, info)) { text_t &contains = info["contains"]; if (!contains.empty()) { text_t parent = OID; getdelimitstr (contains.begin(), contains.end(), ';', firstchild); if (firstchild.empty()) OID = contains; else OID = firstchild; if (*(OID.begin()) == '"') translate_parent (OID, parent); } } } void dbclass::get_last_child (text_t &OID, infodbclass &info) { text_tarray children; if (getinfo (OID, info)) { text_t &contains = info["contains"]; if (!contains.empty()) { text_t parent = OID; splitchar (contains.begin(), contains.end(), ';', children); OID = children.back(); if (*(OID.begin()) == '"') translate_parent (OID, parent); } } } void dbclass::get_next_sibling (text_t &OID, infodbclass &info) { text_tarray siblings; text_t parent = get_parent (OID); if (getinfo (parent, info)) { text_t &contains = info["contains"]; if (!contains.empty()) { splitchar (contains.begin(), contains.end(), ';', siblings); text_tarray::const_iterator here = siblings.begin(); text_tarray::const_iterator end = siblings.end(); text_t shrunk_OID = OID; shrink_parent (shrunk_OID); while (here != end) { if (*here == shrunk_OID && (here+1 != end)) { OID = *(here+1); if (*(OID.begin()) == '"') translate_parent (OID, parent); break; } ++here; } } } } void dbclass::get_previous_sibling (text_t &OID, infodbclass &info) { text_tarray siblings; text_t parent = get_parent (OID); if (getinfo (parent, info)) { text_t &contains = info["contains"]; if (!contains.empty()) { splitchar (contains.begin(), contains.end(), ';', siblings); text_tarray::const_iterator here = siblings.begin(); text_tarray::const_iterator end = siblings.end(); text_t shrunk_OID = OID; shrink_parent (shrunk_OID); while (here != end) { if (*here == shrunk_OID && (here != siblings.begin())) { OID = *(here-1); if (*(OID.begin()) == '"') translate_parent (OID, parent); break; } ++here; } } } }