diff options
Diffstat (limited to 'akregator/src/mk4storage')
328 files changed, 51798 insertions, 0 deletions
diff --git a/akregator/src/mk4storage/Makefile.am b/akregator/src/mk4storage/Makefile.am new file mode 100644 index 000000000..4f2ebfae5 --- /dev/null +++ b/akregator/src/mk4storage/Makefile.am @@ -0,0 +1,30 @@ +kde_module_LTLIBRARIES = libakregator_mk4storage_plugin.la + +SUBDIRS = metakit + +INCLUDES = \ + -I$(top_srcdir)/akregator/src \ + -I$(top_srcdir)/akregator/src/mk4storage/metakit/include \ + $(all_includes) + +libakregator_mk4storage_plugin_la_LIBADD = \ + $(top_builddir)/akregator/src/mk4storage/metakit/src/libmetakitlocal.la \ + $(top_builddir)/akregator/src/librss/librsslocal.la \ + ../libakregatorprivate.la \ + $(LIB_KFILE) \ + $(LIB_KDECORE) + +libakregator_mk4storage_plugin_la_LDFLAGS = \ + $(KDE_PLUGIN) \ + $(all_libraries) + +libakregator_mk4storage_plugin_la_SOURCES = feedstoragemk4impl.cpp \ + storagemk4impl.cpp \ + storagefactorymk4impl.cpp \ + mk4plugin.cpp + +METASOURCES = AUTO + +kde_services_DATA = akregator_mk4storage_plugin.desktop + +kde_kcfg_DATA = mk4config.kcfg diff --git a/akregator/src/mk4storage/akregator_mk4storage_plugin.desktop b/akregator/src/mk4storage/akregator_mk4storage_plugin.desktop new file mode 100644 index 000000000..c7d899a7a --- /dev/null +++ b/akregator/src/mk4storage/akregator_mk4storage_plugin.desktop @@ -0,0 +1,109 @@ +[Desktop Entry] +Type=Service +Name=Metakit storage backend +Name[af]=Metakit stoor agterkant +Name[bg]=Приставка за архивиране Metakit +Name[ca]=Dorsal de emmagatzematge Metakit +Name[cs]=Metakit úložiště +Name[da]=Metakit lagringsgrænseflade +Name[de]=Metakit Archiv-Modul +Name[el]=Σύστημα υποστήριξης αποθήκευσης Metakit +Name[eo]=Metakit datumstora maŝino +Name[es]=Dorsal de almacenamiento Metakit +Name[et]=Metakiti salvestamisrakendus +Name[eu]=Metakit-en biltegiratze euskarria +Name[fa]=پشتیبان ذخیرهگاه Metakit +Name[fi]=Metakit-tallennusajuri +Name[fr]=Stockage avec Metakit +Name[fy]=Metakit-opslachefterein +Name[gl]=Manexador do almacenador Metakit +Name[hu]=Metakit tároló +Name[is]=Metakit geymslu bakendi +Name[it]=Backend archiviazione metakit +Name[ja]=メタキットストレージバックエンド +Name[ka]=Metakit მეხსიერების ბუფერი +Name[kk]=Metakit архивтеу бағдарламасы +Name[km]=កម្មវិធីខាងក្រោយសម្រាប់រក្សាទុក (Metakit) +Name[ko]=Metakit 저장소 백엔드 +Name[lt]=Metakit saugojimo programinė sąsaja +Name[ms]=Hujung belakang storan Metakit +Name[nb]=Metakit lagringsbakstykke +Name[nds]=Metakit-Archivmoduul +Name[ne]=मेटाकिट भण्डारण ब्याकइन्ड +Name[nl]=Metakit-opslagbackend +Name[nn]=Metakit-lagringsbakstykke +Name[pl]=System przechowywania Metakit +Name[pt]=Infra-estrutura de armazenamento Metakit +Name[pt_BR]=Mecanismo de armazenamento Metakit +Name[ru]=Движок Metakit +Name[sl]=Shranjevanje Metakit +Name[sr]=Систем за смештање Мета комплета +Name[sr@Latn]=Sistem za smeštanje Meta kompleta +Name[sv]=Metakit lagringsgränssnitt +Name[tr]=Metakit depolama arka ucu +Name[uk]=Програма зберігання Metakit +Name[zh_CN]=Metakit 存储后端 +Name[zh_TW]=Metakit 儲存後端介面 +X-KDE-Library=libakregator_mk4storage_plugin +Comment=Plugin for Akregator +Comment[af]=Inprop module vir Akregator +Comment[be]=Утулка для Akregator +Comment[bg]=Приставка за Akregator +Comment[br]=Lugent evit Akregator +Comment[ca]=Endollable per a l'Akregator +Comment[cs]=Modul pro Akregator +Comment[de]=Modul für Akregator +Comment[el]=Πρόσθετο για το Akregator +Comment[eo]=Kromprogramo por Akregator +Comment[es]=Extensión para Akregator +Comment[et]=Akregatori plugin +Comment[eu]=Akregator-en plugina +Comment[fa]=وصله برای Akregator +Comment[fi]=Liitännäinen Akregatoriin +Comment[fr]=Module pour Akregator +Comment[fy]=Plugin foar Akregator +Comment[ga]=Breiseán Akregator +Comment[gl]=Extensión para Akregator +Comment[he]=תוסף עבור Akregator +Comment[hu]=Akregator bővítőmodul +Comment[is]=Íforrit fyrir Akregator +Comment[it]=Plugin per Akregator +Comment[ja]=Akregator 用プラグイン +Comment[ka]=Akregator-ის მოდული +Comment[kk]=Akregator-дың плагин модулі +Comment[km]=កម្មវិធីជំនួយ Akregator +Comment[ko]=Akregator 플러그인 +Comment[lt]=Akregator skirtas priedas +Comment[mk]=Приклучок за Akregator +Comment[ms]=Plugin untuk Akregator +Comment[nb]=Programtillegg for Akregator +Comment[nds]=Moduul för Akregator +Comment[ne]=एक्रिगेटरका लागि प्लगइन +Comment[nl]=Plugin voor Akregator +Comment[nn]=Programtillegg til Akregator +Comment[pl]=Wtyczka dla Akregatora +Comment[pt]='Plugin' para o Akregator +Comment[pt_BR]=Plug-in para o Akregator +Comment[ru]=Модуль Akregator +Comment[se]=Lassemoduvla Akregatorii +Comment[sk]=Modul pre Akregator +Comment[sl]=Vstavek za Akregator +Comment[sr]=Прикључак за Akregator +Comment[sr@Latn]=Priključak za Akregator +Comment[sv]=Insticksprogram för Akregator +Comment[tr]=Akregator Eklentisi +Comment[uk]=Втулок для Akregator +Comment[uz]=Akregator uchun plagin +Comment[uz@cyrillic]=Akregator учун плагин +Comment[zh_CN]=Akregator 插件 +Comment[zh_TW]=Akregator 外掛程式 +ServiceTypes=Akregator/Plugin + +X-KDE-akregator-plugintype=storage +X-KDE-akregator-name=metakit +X-KDE-akregator-authors=Frank Osterfeld +X-KDE-akregator-email=frank.osterfeld@kdemail.net +X-KDE-akregator-rank=255 +X-KDE-akregator-version=1 +X-KDE-akregator-framework-version=1 + diff --git a/akregator/src/mk4storage/feedstoragemk4impl.cpp b/akregator/src/mk4storage/feedstoragemk4impl.cpp new file mode 100644 index 000000000..521f9f326 --- /dev/null +++ b/akregator/src/mk4storage/feedstoragemk4impl.cpp @@ -0,0 +1,871 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "feedstoragemk4impl.h" +#include "storagemk4impl.h" + +#include "../article.h" +#include "../utils.h" +#include "../librss/article.h" +#include "../librss/document.h" +#include <mk4.h> + +#include <qdom.h> +#include <qfile.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kstandarddirs.h> + +namespace Akregator { +namespace Backend { + +class FeedStorageMK4Impl::FeedStorageMK4ImplPrivate +{ + public: + FeedStorageMK4ImplPrivate() : + modified(false), + pguid("guid"), + ptitle("title"), + pdescription("description"), + plink("link"), + pcommentsLink("commentsLink"), + ptag("tag"), + pEnclosureType("enclosureType"), + pEnclosureUrl("enclosureUrl"), + pcatTerm("catTerm"), + pcatScheme("catScheme"), + pcatName("catName"), + pauthor("author"), + phash("hash"), + pguidIsHash("guidIsHash"), + pguidIsPermaLink("guidIsPermaLink"), + pcomments("comments"), + pstatus("status"), + ppubDate("pubDate"), + pHasEnclosure("hasEnclosure"), + pEnclosureLength("enclosureLength"), + ptags("tags"), + ptaggedArticles("taggedArticles"), + pcategorizedArticles("categorizedArticles"), + pcategories("categories") + {} + + QString url; + c4_Storage* storage; + StorageMK4Impl* mainStorage; + c4_View archiveView; + + c4_Storage* catStorage; + c4_View catView; + c4_Storage* tagStorage; + c4_View tagView; + bool autoCommit; + bool modified; + bool taggingEnabled; + bool convert; + QString oldArchivePath; + c4_StringProp pguid, ptitle, pdescription, plink, pcommentsLink, ptag, pEnclosureType, pEnclosureUrl, pcatTerm, pcatScheme, pcatName, pauthor; + c4_IntProp phash, pguidIsHash, pguidIsPermaLink, pcomments, pstatus, ppubDate, pHasEnclosure, pEnclosureLength; + c4_ViewProp ptags, ptaggedArticles, pcategorizedArticles, pcategories; +}; + +void FeedStorageMK4Impl::convertOldArchive() +{ + if (!d->convert) + return; + + d->convert = false; + QFile file(d->oldArchivePath); + + if ( !file.open(IO_ReadOnly) ) + return; + + QTextStream stream(&file); + stream.setEncoding(QTextStream::UnicodeUTF8); + QString data=stream.read(); + QDomDocument xmldoc; + + if (!xmldoc.setContent(data)) + return; + + RSS::Document doc(xmldoc); + + RSS::Article::List d_articles = doc.articles(); + RSS::Article::List::ConstIterator it = d_articles.begin(); + RSS::Article::List::ConstIterator en = d_articles.end(); + + int unr = 0; + for (; it != en; ++it) + { + Article a(*it, this); + if (a.status() != Article::Read) + unr++; + } + + setUnread(unr); + markDirty(); + commit(); +} + +FeedStorageMK4Impl::FeedStorageMK4Impl(const QString& url, StorageMK4Impl* main) +{ + d = new FeedStorageMK4ImplPrivate; + d->autoCommit = main->autoCommit(); + d->url = url; + d->mainStorage = main; + d->taggingEnabled = main->taggingEnabled(); + + QString url2 = url; + + if (url.length() > 255) + { + url2 = url.left(200) + QString::number(Akregator::Utils::calcHash(url), 16); + } + + kdDebug() << url2 << endl; + QString t = url2; + QString t2 = url2; + QString filePath = main->archivePath() +"/"+ t.replace("/", "_").replace(":", "_"); + d->oldArchivePath = KGlobal::dirs()->saveLocation("data", "akregator/Archive/") + t2.replace("/", "_").replace(":", "_") + ".xml"; + + d->convert = !QFile::exists(filePath + ".mk4") && QFile::exists(d->oldArchivePath); + d->storage = new c4_Storage((filePath + ".mk4").local8Bit(), true); + + d->archiveView = d->storage->GetAs("articles[guid:S,title:S,hash:I,guidIsHash:I,guidIsPermaLink:I,description:S,link:S,comments:I,commentsLink:S,status:I,pubDate:I,tags[tag:S],hasEnclosure:I,enclosureUrl:S,enclosureType:S,enclosureLength:I,categories[catTerm:S,catScheme:S,catName:S],author:S]"); + + c4_View hash = d->storage->GetAs("archiveHash[_H:I,_R:I]"); + d->archiveView = d->archiveView.Hash(hash, 1); // hash on guid + + d->tagStorage = 0; + + if (d->taggingEnabled) + { + d->tagStorage = new c4_Storage((filePath + ".mk4___TAGS").local8Bit(), true); + d->tagView = d->tagStorage->GetAs("tagIndex[tag:S,taggedArticles[guid:S]]"); + hash = d->tagStorage->GetAs("archiveHash[_H:I,_R:I]"); + d->tagView = d->tagView.Hash(hash, 1); // hash on tag + } + //d->catStorage = new c4_Storage((filePath + ".mk4___CATEGORIES").local8Bit(), true); + //d->catView = d->catStorage->GetAs("catIndex[catTerm:S,catScheme:S,catName:S,categorizedArticles[guid:S]]"); +} + + +FeedStorageMK4Impl::~FeedStorageMK4Impl() +{ + delete d->storage; + if (d->taggingEnabled) + delete d->tagStorage; +// delete d->catStorage; + delete d; d = 0; +} + +void FeedStorageMK4Impl::markDirty() +{ + if (!d->modified) + { + d->modified = true; + // Tell this to mainStorage + d->mainStorage->markDirty(); + } +} + +void FeedStorageMK4Impl::commit() +{ + if (d->modified) + { + d->storage->Commit(); + if (d->taggingEnabled) + d->tagStorage->Commit(); +// d->catStorage->Commit(); + } + d->modified = false; +} + +void FeedStorageMK4Impl::rollback() +{ + d->storage->Rollback(); + if (d->taggingEnabled) + d->tagStorage->Rollback(); +// d->catStorage->Rollback(); +} + +void FeedStorageMK4Impl::close() +{ + if (d->autoCommit) + commit(); +} +int FeedStorageMK4Impl::unread() +{ + return d->mainStorage->unreadFor(d->url); +} +void FeedStorageMK4Impl::setUnread(int unread) +{ + d->mainStorage->setUnreadFor(d->url, unread); +} + +int FeedStorageMK4Impl::totalCount() +{ + return d->mainStorage->totalCountFor(d->url); +} + +void FeedStorageMK4Impl::setTotalCount(int total) +{ + d->mainStorage->setTotalCountFor(d->url, total); +} + +int FeedStorageMK4Impl::lastFetch() +{ + return d->mainStorage->lastFetchFor(d->url); +} + +void FeedStorageMK4Impl::setLastFetch(int lastFetch) +{ + d->mainStorage->setLastFetchFor(d->url, lastFetch); +} + +QStringList FeedStorageMK4Impl::articles(const QString& tag) +{ + QStringList list; + if (tag.isNull()) // return all articles + { + int size = d->archiveView.GetSize(); + for (int i = 0; i < size; i++) // fill with guids + list += QString(d->pguid(d->archiveView.GetAt(i))); + } + else if (d->taggingEnabled) + { + c4_Row tagrow; + d->ptag(tagrow) = tag.utf8().data(); + int tagidx = d->tagView.Find(tagrow); + if (tagidx != -1) + { + tagrow = d->tagView.GetAt(tagidx); + c4_View tagView = d->ptaggedArticles(tagrow); + int size = tagView.GetSize(); + for (int i = 0; i < size; i++) + list += QString(d->pguid(tagView.GetAt(i))); + } + + } + return list; +} + +QStringList FeedStorageMK4Impl::articles(const Category& cat) +{ + QStringList list; + /* + c4_Row catrow; + d->pcatTerm(catrow) = cat.term.utf8().data(); + d->pcatScheme(catrow) = cat.scheme.utf8().data(); + + int catidx = d->catView.Find(catrow); + if (catidx != -1) + { + catrow = d->catView.GetAt(catidx); + c4_View catView = d->pcategorizedArticles(catrow); + int size = catView.GetSize(); + for (int i = 0; i < size; i++) + list += QString(d->pguid(catView.GetAt(i))); + } + */ + return list; +} + +void FeedStorageMK4Impl::addEntry(const QString& guid) +{ + c4_Row row; + d->pguid(row) = guid.ascii(); + if (!contains(guid)) + { + d->archiveView.Add(row); + markDirty(); + setTotalCount(totalCount()+1); + } +} + +bool FeedStorageMK4Impl::contains(const QString& guid) +{ + return findArticle(guid) != -1; +} + +int FeedStorageMK4Impl::findArticle(const QString& guid) +{ + c4_Row findrow; + d->pguid(findrow) = guid.ascii(); + return d->archiveView.Find(findrow); +} + +void FeedStorageMK4Impl::deleteArticle(const QString& guid) +{ + + int findidx = findArticle(guid); + if (findidx != -1) + { + QStringList list = tags(guid); + for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) + removeTag(guid, *it); + setTotalCount(totalCount()-1); + d->archiveView.RemoveAt(findidx); + markDirty(); + } +} + +int FeedStorageMK4Impl::comments(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? d->pcomments(d->archiveView.GetAt(findidx)) : 0; +} + +QString FeedStorageMK4Impl::commentsLink(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? QString(d->pcommentsLink(d->archiveView.GetAt(findidx))) : ""; +} + +bool FeedStorageMK4Impl::guidIsHash(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? d->pguidIsHash(d->archiveView.GetAt(findidx)) : false; +} + +bool FeedStorageMK4Impl::guidIsPermaLink(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? d->pguidIsPermaLink(d->archiveView.GetAt(findidx)) : false; +} + +uint FeedStorageMK4Impl::hash(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? d->phash(d->archiveView.GetAt(findidx)) : 0; +} + + +void FeedStorageMK4Impl::setDeleted(const QString& guid) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + + c4_Row row; + row = d->archiveView.GetAt(findidx); + QStringList list = tags(guid); + for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) + removeTag(guid, *it); + d->pdescription(row) = ""; + d->ptitle(row) = ""; + d->plink(row) = ""; + d->pauthor(row) = ""; + d->pcommentsLink(row) = ""; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +QString FeedStorageMK4Impl::link(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? QString(d->plink(d->archiveView.GetAt(findidx))) : ""; +} + +uint FeedStorageMK4Impl::pubDate(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? d->ppubDate(d->archiveView.GetAt(findidx)) : 0; +} + +int FeedStorageMK4Impl::status(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? d->pstatus(d->archiveView.GetAt(findidx)) : 0; +} + +void FeedStorageMK4Impl::setStatus(const QString& guid, int status) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->pstatus(row) = status; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +QString FeedStorageMK4Impl::title(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? QString::fromUtf8(d->ptitle(d->archiveView.GetAt(findidx))) : ""; +} + +QString FeedStorageMK4Impl::description(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? QString::fromUtf8(d->pdescription(d->archiveView.GetAt(findidx))) : ""; +} + + +void FeedStorageMK4Impl::setPubDate(const QString& guid, uint pubdate) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->ppubDate(row) = pubdate; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::setGuidIsHash(const QString& guid, bool isHash) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->pguidIsHash(row) = isHash; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::setLink(const QString& guid, const QString& link) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->plink(row) = !link.isEmpty() ? link.ascii() : ""; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::setHash(const QString& guid, uint hash) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->phash(row) = hash; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::setTitle(const QString& guid, const QString& title) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->ptitle(row) = !title.isEmpty() ? title.utf8().data() : ""; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::setDescription(const QString& guid, const QString& description) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->pdescription(row) = !description.isEmpty() ? description.utf8().data() : ""; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::setAuthor(const QString& guid, const QString& author) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->pauthor(row) = !author.isEmpty() ? author.utf8().data() : ""; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +QString FeedStorageMK4Impl::author(const QString& guid) +{ + int findidx = findArticle(guid); + return findidx != -1 ? QString::fromUtf8(d->pauthor(d->archiveView.GetAt(findidx))) : ""; +} + + +void FeedStorageMK4Impl::setCommentsLink(const QString& guid, const QString& commentsLink) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->pcommentsLink(row) = !commentsLink.isEmpty() ? commentsLink.utf8().data() : ""; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::setComments(const QString& guid, int comments) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->pcomments(row) = comments; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + + +void FeedStorageMK4Impl::setGuidIsPermaLink(const QString& guid, bool isPermaLink) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->pguidIsPermaLink(row) = isPermaLink; + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::addCategory(const QString& /*guid*/, const Category& /*cat*/) +{ + return; + /* + int findidx = findArticle(guid); + if (findidx == -1) + return; + + c4_Row row; + row = d->archiveView.GetAt(findidx); + c4_View catView = d->pcategories(row); + c4_Row findrow; + + d->pcatTerm(findrow) = cat.term.utf8().data(); + d->pcatScheme(findrow) = cat.scheme.utf8().data(); + + int catidx = catView.Find(findrow); + if (catidx == -1) + { + d->pcatName(findrow) = cat.name.utf8().data(); + catidx = catView.Add(findrow); + d->pcategories(row) = catView; + d->archiveView.SetAt(findidx, row); + + // add to category->articles index + c4_Row catrow; + d->pcatTerm(catrow) = cat.term.utf8().data(); + d->pcatScheme(catrow) = cat.scheme.utf8().data(); + d->pcatName(catrow) = cat.name.utf8().data(); + + int catidx2 = d->catView.Find(catrow); + + if (catidx2 == -1) + { + catidx2 = d->catView.Add(catrow); + } + + c4_Row catrow2 = d->catView.GetAt(catidx2); + c4_View catView2 = d->pcategorizedArticles(catrow2); + + c4_Row row3; + d->pguid(row3) = guid.ascii(); + int guididx = catView2.Find(row3); + if (guididx == -1) + { + guididx = catView2.Add(row3); + catView2.SetAt(guididx, row3); + d->pcategorizedArticles(catrow2) = catView2; + d->catView.SetAt(catidx2, catrow2); + } + + markDirty(); + } + */ +} + +QValueList<Category> FeedStorageMK4Impl::categories(const QString& /*guid*/) +{ + + QValueList<Category> list; + return list; + /* + if (!guid.isNull()) // return categories for an article + { + int findidx = findArticle(guid); + if (findidx == -1) + return list; + + c4_Row row; + row = d->archiveView.GetAt(findidx); + c4_View catView = d->pcategories(row); + int size = catView.GetSize(); + + for (int i = 0; i < size; ++i) + { + Category cat; + + cat.term = QString::fromUtf8(d->pcatTerm(catView.GetAt(i))); + cat.scheme = QString::fromUtf8(d->pcatScheme(catView.GetAt(i))); + cat.name = QString::fromUtf8(d->pcatName(catView.GetAt(i))); + + list += cat; + } + } + else // return all categories in the feed + { + int size = d->catView.GetSize(); + for (int i = 0; i < size; i++) + { + c4_Row row = d->catView.GetAt(i); + + Category cat; + cat.term = QString(d->pcatTerm(row)); + cat.scheme = QString(d->pcatScheme(row)); + cat.name = QString(d->pcatName(row)); + + list += cat; + } + } + + return list;*/ +} + +void FeedStorageMK4Impl::addTag(const QString& guid, const QString& tag) +{ + if (!d->taggingEnabled) + return; + + int findidx = findArticle(guid); + if (findidx == -1) + return; + + c4_Row row; + row = d->archiveView.GetAt(findidx); + c4_View tagView = d->ptags(row); + c4_Row findrow; + d->ptag(findrow) = tag.utf8().data(); + int tagidx = tagView.Find(findrow); + if (tagidx == -1) + { + tagidx = tagView.Add(findrow); + d->ptags(row) = tagView; + d->archiveView.SetAt(findidx, row); + + // add to tag->articles index + c4_Row tagrow; + d->ptag(tagrow) = tag.utf8().data(); + int tagidx2 = d->tagView.Find(tagrow); + if (tagidx2 == -1) + tagidx2 = d->tagView.Add(tagrow); + tagrow = d->tagView.GetAt(tagidx2); + c4_View tagView2 = d->ptaggedArticles(tagrow); + + c4_Row row3; + d->pguid(row3) = guid.ascii(); + int guididx = tagView2.Find(row3); + if (guididx == -1) + { + guididx = tagView2.Add(row3); + tagView2.SetAt(guididx, row3); + d->ptaggedArticles(tagrow) = tagView2; + d->tagView.SetAt(tagidx2, tagrow); + } + markDirty(); + } +} + +void FeedStorageMK4Impl::removeTag(const QString& guid, const QString& tag) +{ + if (!d->taggingEnabled) + return; + + int findidx = findArticle(guid); + if (findidx == -1) + return; + + c4_Row row; + row = d->archiveView.GetAt(findidx); + c4_View tagView = d->ptags(row); + c4_Row findrow; + d->ptag(findrow) = tag.utf8().data(); + int tagidx = tagView.Find(findrow); + if (tagidx != -1) + { + tagView.RemoveAt(tagidx); + d->ptags(row) = tagView; + d->archiveView.SetAt(findidx, row); + + // remove from tag->articles index + c4_Row tagrow; + d->ptag(tagrow) = tag.utf8().data(); + int tagidx2 = d->tagView.Find(tagrow); + if (tagidx2 != -1) + { + tagrow = d->tagView.GetAt(tagidx2); + c4_View tagView2 = d->ptaggedArticles(tagrow); + + c4_Row row3; + d->pguid(row3) = guid.ascii(); + int guididx = tagView2.Find(row3); + if (guididx != -1) + { + tagView2.RemoveAt(guididx); + d->ptaggedArticles(tagrow) = tagView2; + d->tagView.SetAt(tagidx2, tagrow); + } + } + + markDirty(); + } +} + +QStringList FeedStorageMK4Impl::tags(const QString& guid) +{ + QStringList list; + + if (!d->taggingEnabled) + return list; + + if (!guid.isNull()) // return tags for an articles + { + int findidx = findArticle(guid); + if (findidx == -1) + return list; + + c4_Row row; + row = d->archiveView.GetAt(findidx); + c4_View tagView = d->ptags(row); + int size = tagView.GetSize(); + + for (int i = 0; i < size; ++i) + list += QString::fromUtf8(d->ptag(tagView.GetAt(i))); + } + else // return all tags in the feed + { + int size = d->tagView.GetSize(); + for (int i = 0; i < size; i++) + list += QString(d->ptag(d->tagView.GetAt(i))); + } + + return list; +} + +void FeedStorageMK4Impl::add(FeedStorage* source) +{ + QStringList articles = source->articles(); + for (QStringList::ConstIterator it = articles.begin(); it != articles.end(); ++it) + copyArticle(*it, source); + setUnread(source->unread()); + setLastFetch(source->lastFetch()); + setTotalCount(source->totalCount()); +} + +void FeedStorageMK4Impl::copyArticle(const QString& guid, FeedStorage* source) +{ + if (!contains(guid)) + addEntry(guid); + setComments(guid, source->comments(guid)); + setCommentsLink(guid, source->commentsLink(guid)); + setDescription(guid, source->description(guid)); + setGuidIsHash(guid, source->guidIsHash(guid)); + setGuidIsPermaLink(guid, source->guidIsPermaLink(guid)); + setHash(guid, source->hash(guid)); + setLink(guid, source->link(guid)); + setPubDate(guid, source->pubDate(guid)); + setStatus(guid, source->status(guid)); + setTitle(guid, source->title(guid)); + setAuthor(guid, source->author(guid)); + + QStringList tags = source->tags(guid); + for (QStringList::ConstIterator it = tags.begin(); it != tags.end(); ++it) + addTag(guid, *it); +} + +void FeedStorageMK4Impl::setEnclosure(const QString& guid, const QString& url, const QString& type, int length) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->pHasEnclosure(row) = true; + d->pEnclosureUrl(row) = !url.isEmpty() ? url.utf8().data() : ""; + d->pEnclosureType(row) = !type.isEmpty() ? type.utf8().data() : ""; + d->pEnclosureLength(row) = length; + + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::removeEnclosure(const QString& guid) +{ + int findidx = findArticle(guid); + if (findidx == -1) + return; + c4_Row row; + row = d->archiveView.GetAt(findidx); + d->pHasEnclosure(row) = false; + d->pEnclosureUrl(row) = ""; + d->pEnclosureType(row) = ""; + d->pEnclosureLength(row) = -1; + + d->archiveView.SetAt(findidx, row); + markDirty(); +} + +void FeedStorageMK4Impl::enclosure(const QString& guid, bool& hasEnclosure, QString& url, QString& type, int& length) +{ + int findidx = findArticle(guid); + if (findidx == -1) + { + hasEnclosure = false; + url = QString::null; + type = QString::null; + length = -1; + return; + } + c4_Row row = d->archiveView.GetAt(findidx); + hasEnclosure = d->pHasEnclosure(row); + url = d->pEnclosureUrl(row); + type = d->pEnclosureType(row); + length = d->pEnclosureLength(row); +} + +void FeedStorageMK4Impl::clear() +{ + d->storage->RemoveAll(); + if (d->taggingEnabled) + d->tagStorage->RemoveAll(); + setUnread(0); + markDirty(); +} + +} // namespace Backend +} // namespace Akregator diff --git a/akregator/src/mk4storage/feedstoragemk4impl.h b/akregator/src/mk4storage/feedstoragemk4impl.h new file mode 100644 index 000000000..d27933d0f --- /dev/null +++ b/akregator/src/mk4storage/feedstoragemk4impl.h @@ -0,0 +1,107 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#ifndef FEEDSTORAGEMK4IMPL_H +#define FEEDSTORAGEMK4IMPL_H + +#include "feedstorage.h" +namespace Akregator { +namespace Backend { + +class StorageMK4Impl; +class FeedStorageMK4Impl : public FeedStorage +{ + public: + FeedStorageMK4Impl(const QString& url, StorageMK4Impl* main); + virtual ~FeedStorageMK4Impl(); + + + virtual void add(FeedStorage* source); + virtual void copyArticle(const QString& guid, FeedStorage* source); + virtual void clear(); + + virtual int unread(); + virtual void setUnread(int unread); + virtual int totalCount(); + virtual int lastFetch(); + virtual void setLastFetch(int lastFetch); + + virtual QStringList articles(const QString& tag=QString::null); + + virtual QStringList articles(const Category& cat); + + virtual bool contains(const QString& guid); + virtual void addEntry(const QString& guid); + virtual void deleteArticle(const QString& guid); + virtual int comments(const QString& guid); + virtual QString commentsLink(const QString& guid); + virtual void setCommentsLink(const QString& guid, const QString& commentsLink); + virtual void setComments(const QString& guid, int comments); + virtual bool guidIsHash(const QString& guid); + virtual void setGuidIsHash(const QString& guid, bool isHash); + virtual bool guidIsPermaLink(const QString& guid); + virtual void setGuidIsPermaLink(const QString& guid, bool isPermaLink); + virtual uint hash(const QString& guid); + virtual void setHash(const QString& guid, uint hash); + virtual void setDeleted(const QString& guid); + virtual QString link(const QString& guid); + virtual void setLink(const QString& guid, const QString& link); + virtual uint pubDate(const QString& guid); + virtual void setPubDate(const QString& guid, uint pubdate); + virtual int status(const QString& guid); + virtual void setStatus(const QString& guid, int status); + virtual QString title(const QString& guid); + virtual void setTitle(const QString& guid, const QString& title); + virtual QString description(const QString& guid); + virtual void setDescription(const QString& guid, const QString& description); + virtual void setEnclosure(const QString& guid, const QString& url, const QString& type, int length); + virtual void removeEnclosure(const QString& guid); + virtual void enclosure(const QString& guid, bool& hasEnclosure, QString& url, QString& type, int& length); + + virtual void addTag(const QString& guid, const QString& tag); + virtual void removeTag(const QString& guid, const QString& tag); + virtual QStringList tags(const QString& guid=QString::null); + + virtual void addCategory(const QString& guid, const Category& category); + virtual QValueList<Category> categories(const QString& guid=QString::null); + + virtual void setAuthor(const QString& guid, const QString& author); + virtual QString author(const QString& guid); + + virtual void close(); + virtual void commit(); + virtual void rollback(); + + virtual void convertOldArchive(); + private: + void markDirty(); + /** finds article by guid, returns -1 if not in archive **/ + int findArticle(const QString& guid); + void setTotalCount(int total); + class FeedStorageMK4ImplPrivate; + FeedStorageMK4ImplPrivate* d; +}; + +} +} +#endif // FEEDSTORAGEMK4IMPL_H diff --git a/akregator/src/mk4storage/metakit/CHANGES b/akregator/src/mk4storage/metakit/CHANGES new file mode 100644 index 000000000..160c4bad9 --- /dev/null +++ b/akregator/src/mk4storage/metakit/CHANGES @@ -0,0 +1,1690 @@ +2004-01-26 ############################################ MK 2.4.9.3 + + Maintenance release, consolidates past 9 months of changes/tweaks. + + Fixed test for "__name__" in python/metakit.py to run a quick test. + +2004-01-22 Fixed refcount problem with temp rows in Mk4tcl + + This was a long-standing bug: "mk::row create" did not work right + because the tracking of temporary rows was completely messed up. + Added test case for Tcl (mk6.8), fixes FB14, BTS#78, and BTS#29. + +2004-01-21 Documentation updates + + Updated copyright notices to 2004, and udated to Doxygen 1.3.5 for + a new set of C++ documentation. In anticipation of next release. + +2004-01-20 Don't trip over duplicate property names + + Added code in c4_Field constructor to avoid crashing when there is a + duplicate property name in the format description string. Duplicate + names are now ignored (there is no good way to report errors at this + point). Avoids an even bigger problem: conflicting property types. + + Added test s49 to detect this case (FB20, reported by Brian Kelley). + +2004-01-18 Fixed rare but very serious subview resizing bug + + Fixed rare but serious file damaging bug, when resizing a comitted + subview to empty, committing, and then resizing back to containing + data. Added new s48 test to force this bug to the surface. + + Fortunately this usage pattern *never* happens in blocked views! + Fixes are at the end of c4_FormatV::Insert and c4_FormatV::Remove. + +2004-01-16 Gracefully deal with bad property type specifiers + + When GetAs is a called with a bad description, such as for example + "myview[name:A]", the release code would crash on a null pointer + dereference at some point. Changed so the code now treats any type + it does not know about as "I" (works a bit better than using "S"). + + The debug build still hits an assertion, as before. Added s47 test. + +2004-01-03 Fixed typo in PyView.cpp + + Forgot to fix closing brace after the 2003-12-11 mods. + +2003-12-21 Fixed Mk4too sorting on subview of length 1 + + There was a silly bug when sorting on subviews in the new Mk4too + interface (not in Mk4tcl), which returns a view, instead of a list + of integers. In the case of 1 row, optimization was done wrongly, + omitting the sort as well as the remapping. Fixed. + + Oomk needs to be patched to work around this (don't sort if n=1). + +2003-12-13 Tweak to avoid two unisgned/signed compiler warnings + + In remap.cpp, compiled in debug mode on Win32 (DWORD vs. t4_i32). + +2003-12-11 Checked in numerous changes to Mk4py by Nicholas Riley + + All changes are local to the python/directory - for details, see + http://www.equi4.com/pipermail/metakit/2003-September/001407.html + With a big thank you to Nicholas for contributing these improvements. + +2003-11-23 Bumped to Python 2.3, doc tweaks, lots of name fixes + + Adjusted makefile to now look for Python 2.3 by default. + Regenerated config files. Fixed obsolete links in the doc files. + + Got rid of tons of Metakit "interCap" cases, should be Metakit. + This affects a huge number of source files and one #define (which + has been defined twice for compatibility: d4_MetakitLibraryVersion). + Use "cvs diff -i" to see real changes, other than case swapping. + +2003-10-28 Get rid of --enable-python, check in c22.txt + + It's not valid, but some files mentioned it. Use --with-python. + Forgot to check in the new c22.txt file added earlier this month. + +2003-10-16 Added note to Tcl docs + + Added a note to doc/tcl.html on how to load a MK datafiles stored in + another one, as needed when using VFS for example. + +2003-10-10 Added c22 test + + Added test to make sure groubpy/select bug is not present in the C++ + core (bts #75 reports the bug found for Mk4tcl/Mk4too). + +2003-10-01 Fixed bugs in Tcl test suite + + The tests in tcl/test/ were incorrectly closing non-test datafiles, + such as the "exe" one open while tclkit runs, and needed when a + slave is created which needs to re-run init.tcl etc from VFS. + +2003-09-30 Python 2.3.1 & cleanup + + Tweaked PWONumber.h and PyRowRef.cpp and MSVC6 project so it can + compile Mk4py for Python 2.3.1 again. Windows binary uploaded. + + Removed the win/msvc60/tests/ directory, it's no longer needed. + +2003-09-20 Autoconf and libtool rebuilds + + In an attempt to stay ahead of version trouble and other nonsense, + the autoconf / configure and libtool files have been regenerated. + Autoconf is at 2.57 and libtoolize is at 1.4.3 on this dev system. + +2003-08-26 Documentation fix + + Fixed install comments for Mk4py, as reported in bts #59. + +2003-07-17 Fixes to Mk4py (Gordon) + + Fix crash when db.description(nm) is called for missing view "nm". + Fix wrap - for the special case of wrapping a list of primitives + (eg, ints, floats, strings) in a single property "view". + +2003-07-11 Fix for Linux not finding .lai file + + Posted for RH 8.0 on MK mailing list by Jeff Web on July 3rd. + +2003-07-01 Fixed "Metakit" (preferred) vs "Metakit" (obsolete) + + Get rid of InterCappedWords. Time to grow up, d00d... + +2003-06-06 Fix to Mk4py for case (in)sensitivity. + + When using a dict (or keyword args), makeRow now gets the + names from the dict's keys and gets the properties by name. + This allows case insensitive matching. Note that using an + instance still requires that the instance attributes have + names that match (case sensitive) with the view. + +2003-05-15 Add distutils setup.py script (Gordon). + + Tested on Linux & Windows (MSVC). + You can now do a plain configure / make (without python) + then cd python; python setup.py build | install + +2003-05-08 Fixed array bound bug when not using mmap-ed files + + There was an incorrect test, when dealing with a new file and + memory mapping is not enabled (which is uncommon, these days). + Thanks to V Demarco for catching and resolving this bug. + +2003-04-28 Sourceforge + + Synced to SF's CVS, see http://sourceforge.net/projects/metakit + +2003-04-25 Autoconf/libtool update + + Did "autoreconf -force" with autoconf 2.5.7 and libtool 1.4.3, as + suggested by Gerfried Fuchs/Ryan Murray. Some Makefile.in tweaks. + +2003-04-22 Fixes to Mk4py (Gordon). + + Make view.append(instance) work again. + Fix recursively adding subview data. + Make properties compare properly. + Initial (incomplete) unittest based test script. + +2003-03-16 ############################################ MK 2.4.9.2 + + Also allow passing pairs to "mk::row append" as a list (Mk4tcl). + +2003-03-10 Fixes for sparc64 configure and AIX strcasecmp + + Both changes contributed by Andreas Kupries. + +2003-03-07 Fix more bugs in blocked view, add 64-bit Sparc support + + The blocked viewer deletion was STILL incorrect. Fixed bad offset + calculations, added several more assertion checks, and added a new + m07 test case which checks for numerous cases of deletion overlap, + i.e. cases where multi-row deletions cross subview boundaries. + + Added __sparc9 #define to mk4.h (thanks again, Andreas K) + +2003-03-05 Fixed two potential races in C++ threaded build + + There was a serious bug in view.cpp, whereby Unix (p)thread locks + were non-functional in release mode (#define NDEBUG). Yikes! + + In addition the logic was flawed (both Unix and Windows), failing to + protect from indexing while sPropNames / sPropCounts were being + resized (i.e. a realloc). Added explicit locking to all affected + paths, and removed the now obsolete count locks (i.e. AddRef). + + Thanks to Murat Berk for chasing this and explaining the problem. + + This bug "only" affects C++ builds. Tcl and Python each have an + extra layer on top which means there can be no races inside MK. + +2003-03-03 ############################################ MK 2.4.9.1 + + Moving to a new 4-level bugfix release number. + +2003-03-02 Fixes to Mk4py (gmcm) + + Modify some recent patches that were Python 2.2 only so they would + still work with 2.1. Add a view.properties() method (returning a + dict of propname -> Property) for cases where a property is masked + by a method name. + +2003-03-01 Reverted changes in Mk4py/scxx, avoid Mk4tcl warning + + One was in SCXX, PWONumber.h - ouch and apologies (jcw). Changed + comparison logic in mk4too.cpp (64-bit ints, new code). + +2003-02-28 Fixed relaxed layout in Mk4tcl, several Mk4py fixes + + Use list operators to convert a Tcl layout to MK format. This used + to crash, Tcl test 6.7 added to verify the fix. Changed test 3.1 to + use a different notation for nested defs (^). + + Added to ViewerAsSeq, to allow v1+v2+v3 (thanks Michael Scharf). + Also fixed several mem leaks - thx again! + +2003-02-27 Added support for HPUX aCC "long long" + + Added #ifdef's to mk4.h to match autoconf HAVE_LONG_LONG settings. + Tweaks to configure.in by Andreas K to better support HP/UX (thx!). + +2003-02-26 Added 64-bit int support to Mk4tcl, fix mingw + + The "L" type was not exposed, though Tcl >= 8.4 has "wide" ints! + Will now support 64-bit ints, if built against a Tcl 8.4+ header, but + still defaults to without for use in Tcl's <= 8.3. + + Fix _strdup #ifdef in univ.cpp when compiled from mingw on win32. + +2003-02-24 Break was missing in switch Mk4py + + Fixed a serious problem, which must have come from editing too + wildly (Mk4py needs a test suite!). + +2003-02-20 Remove a stray include, remove CR's + + Remove "#include <stdio.h>" from remap.cpp, leftover from debugging. + Also removed CR's left behind from editing under Windows (doh!). + +2003-02-18 ############################################## MK 2.4.9 + + This is mostly a bug fix release (some features added to Mk4tcl). + +2003-02-18 Fixed a bug in blocked view deletion, and hash byteorder + + There was an off-by-one error in the deletion of multiple rows + which span more than an entire subview block. Test m06 is ok now. + Also added consistency checks (when compiled in debug mode). + + Fixed a too-strict assertion in mk4tcl.cpp, Item destructor. + + Fixed a byte-order sensitivity in hash views for numeric properties. + +2003-02-17 Configure tweaks for hpux/ia64 + + Re-instated hpux changes by A. Kupries, for ia64, also -lpthread. + +2003-02-14 Bug found in blocked viewer modification + + Added test m06 to catch a problem first detected in the Tcl test + suite (test 5.7) - recoded to C++. This is a show-stopper for the + upcoming 2.4.9 release - fixing it is now a top priority. + +2003-02-14 Some changes to OO interface in Tcl + + The OO "select" cmd now returns a view, not a list of row #'s. + Added "product" and "rename" operators, they were not exposed. + +2003-02-14 Enable stdio buffering + + On platforms where stdio is used, the setbuf(..., 0) calls have been + removed (fileio.cpp). This improves performance, and lets caller set + up whatever buffering they like. + +2003-02-07 Tweaks to restore broken MK ports + + Fixes by A. Kupries to fix MK builds I broke (Itanium/HPUX). + +2003-02-07 Changed code to avoid compiler warning + + In remap.cpp, LookDict(), add return at end to avoid a mistaken + compiler warning (on AIX 5.1). No effect on runtime behavior. + +2003-02-02 Work around optimizer bug in gcc 3.2.1 + + The sign-extension in c4_ColOfInts::Get_16r was not being done right + with -O2 on Linux. This only manifests itself with files having + reversed bytes (e.g. PowerPC/Mac). Changed code to use a local temp + buffer instead. This bug was the reason why some starkits failed to + load when created on Mac and used on Linux. + +2003-01-24 Fixed cleanup order bug in Mk4tcl + + There was a long-standing bug in Mk4tcl, in which cleanup order of + MkPath objects caused them to access their MkWorkspace parent even + though it was already deleted. This may have caused some of the + crash-on-exit bugs in the past. + +2003-01-22 Add missing -lstdc++ + + For unknown reasons, the current make failed to produce shared libs + with libstdc++ linked in - manually added to LDFLAGS again. + +2003-01-19 Tweak to temp object use + + Two changes in handler.cpp to avoid bug in compilers which get the + cleanup logic of temp objects wrong (thx, Dan Gregory). + +2003-01-17 Add synonym for mk4tcl "info" command + + To avoid a name clash, "$view info" can now also be written as + "$view properties" (or an abbreviation of that). + +2003-01-16 Allow access to root view in Mk4tcl + + Access to root view (i.e. the storage object itself) was not + allowed - added a small change to allow this (MkPath::AttachView). + +2003-01-15 Use strdup + + On Unix, use strdup i.s.o own code for _strdup, see univ.cpp. + Perhaps it's time to start reversing the names, and make unix std. + +2003-01-10 Build improvements, Mk4py long and Mac improvements + + Merged changes submitted by Nicholas Riley (thanks!) into CVS: + - changes to build Mk4py on MacOS X (framework/dylib) + - support 'L' fields, handle overflow, throw exceptions + - the beginnings of a test suite for Mk4py (in python/test/) + + Separated PPC and 68K projects (Mac classic), because PPC is now + built with 8.3 (Carbon support), while 68K requires 6.3. The x86 + cross-compile-from-mac projects have been dropped. + +2003-01-09 String compare tweak, Mac Carbon runtime mmap code + + Use strcasecmp on unix, instead of own code (string.cpp). + + Added code based on Paul Snively's contributed patch to recognize + running under OSX, so carbon apps can benefit from mmapped files. + All changes are within fileio.cpp, requires CW8 to build this way. + Added "PPC Carbon" target to cw.mcp, derived from "PPC DLL" one. + +2002-12-23 Tweak for Borland builder 5 & 6 + + Changed #ifdef line 22 in univ.cpp (fix by S. Cusack). + +2002-12-09 Fixed bug in selection view change propagation + + Fixed a bug when a row is inserted in a view on which a selection + depends, when the inserted position is not part of the derived one. + This looks like an oversight in 2.3/2.4 changes, and must have been + in there for quite some time. Added new n14 test to verify this. + +2002-12-02 Fixed bug in MK old-file format conversion + + Fixed bug in on-the-fly conversion of old 1.x/2.0.x format files. + +2002-11-24 Fixed Mk4tcl threaded build + + Release and reclaim mutex lock while calling eval inside loops. + Added "--enable-threads" option to configure script. + +2002-11-22 Configure tweak for HPUX/Itanium + + Removed ia64 check in configure.in, now that libtool has been fixed. + +2002-11-16 Tweaks to compile on Mac + + Small changes to the source code to avoid errors from the MWCW 8.x + compilers. Omit stricmp and strdup with CW version >= 8. + +2002-11-04 Fixed typo in Makefile + + This prevented Mk4py from getting installed (thanks F. Majid). + +2002-11-03 ############################################## MK 2.4.8 + + Reverted non-portable change in Makefile to copy to "Mk4tcl.*". + +2002-10-28 Workaround for bugs on ARM/WinCE and HP/UX, Mk4tcl/WinCE + + Turn off c4_ColofInts::Set_8i optimization when compiling for ARM on + WinCE using EVC3. All regression tests now pass (on ARM & x86emu). + + On HP/UX, enable copying in fileio.cpp, line 265, so a write is not + done directly from a mmap'ed file (this can hang a process, hard). + + Added a "mktcl" subproject to msevc3, to build "Mk4tcl.dll". + +2002-10-27 Added multi-thread support for Unix + + Added changes to support same appartment-threading model on Unix as + on Win32 (pthreads based). This merely adds support to allow safe + use of the current "each datafile in one thread" design on Unix. All + changes in view.cpp (thank you, M. Berk). Define q4_MULTI to enable. + +2002-10-26 Merged WinCE changes + + Merged changes to build MK for WinCE using MS Embedded VC 3.0. + These changes are based on Joseph Tate's modifications (thanks!). + +2002-10-21 Updated autoconf & libtool (on teevie) + + Files in unix/ regenerated with autoconf 2.53a and libtool 1.4.1. + +2002-10-16 Added "dup" subcommand to Mk4tcl OO + + There was no way to duplicate a view in the mk4tcl OO interface. + Needed to properly deal with re-use / ref counts - added "dup". + +2002-10-11 Cast widened in Mk4tcl, support q4_TINY def for Mk4tcl + + Changed cast from int to long, to avoid compiler warning on some + 64-bit machines (mk4tcl.cpp, line 2013). + + Remove float/double code when q4_TINY is defined, also in Mk4tcl. + +2002-10-10 Makefile tweaks + + Removed duplicate flags from CXXFLAGS definition. + +2002-10-09 Fixed blocked/subview bug, tweak for the ARM platform + + Blocked viewers were not doing the right thing when rows had subviews + in them - fixed the logic, and add a new m05 test to verify it all. + + Fixed a signed-char bug which prevented MK from passing all tests on + the ARM, in this case the Compaq iPaq PDA with Linux and gcc 2.95.4. + +2002-10-07 Tweak to prevent gcc compiler bug + + Added intermediate temp var in derived.cpp to prevent gcc -O failure. + +2002-10-04 Config and makefile adjustments + + Adjusted configure.in to use ".sl" for HP-UX, and ".dll" for Cygwin. + + Changed "install -d" to "mkdir -p" (2x) in Makefile.in, since the + former is not supported by all incarnations of install (A Kupries). + + Added @CXXFLAGS@ to the end of "CXXFLAGS =" lines in Makefile.in, + as suggested by Donal K. Fellows. Used for his IRIX(64) builds. + + Added logic to build properly on HP-UX, including a small assembly + file (!) which allows loading C++ shared lib from C, as needed in + Tcl - with thanks to Andreas Kupries for solving and patching this. + +2002-09-25 Build tweaks for Mac OS X + + Applied patches by Daniel Steffen to deal with ".dylib" (thanks!). + + Use -O i.s.o. -O2, which caused test b27 to fail on OS X (gcc 3.1). + +2002-09-09 More 64-bit platforms recognized + + Added #ifdefs for more 64-bit platforms, thanks to Reinhard Max. + +2002-09-08 Make tweaks for HP-UX + + Tweaks to build on HP-UX / 9000 (added __hpux #ifdef in header.h). + +2002-09-03 Fixed Mac OSX build problem + + Compile Mk4tcl lib with stubs only if building the shared lib. + Ignore strip errors (fails with Mk4tcl.so on OSX / dyld libs). + +2002-07-01 Python and Tcl installation improved + + Now installs Python Mk4py.so and metakit.py in the most common dir + location by default, i.e. "/usr/local/lib/python2.2/site-packages". + Locations can be overridden through $pyincludedir and $pylibdir. + + For Tcl, "make install" now constructs a standard package dir, i.e. + "/usr/local/lib/Mk4tcl/" with entries "Mk4tcl.so" and "pkgIndex.tcl". + Locations can be overridden through $tclincludedir and $tcllibdir. + +2002-05-30 ############################################## MK 2.4.7 + + Fix CONST84 logic so source compiles under both Tcl 8.3 and 8.4. + Fix creation of tests/CVS/ so diff in regression tests won't fail. + +2002-05-14 Fixed an adaptive int insert/delete bug + + Another bug in the 2.3/2.4 codebase, related to adaptive integers. + + Symptom: one int entry has incorrect bytes after insert/delete. + + Scenario: ints are 1..8 bits, and an odd number are added/removed, + leaving an odd-sized internal "gap". Then store a 16/32 bit value, + forcing resizing. Once this is done, there will be one value which + cannot be properly read or set because its data is split *across* the + gap (commit is ok and removes the problem). Fix in column.{h,cpp}, + with a new regression test s46 added to make sure things are ok now. + + Let's hope that this is truly the *last* deeply embarrassing bug... + +2002-05-06 ############################################## MK 2.4.6 + + Recent bug fix was critical enough to warrant a new revision. + It is safest to avoid using versions 2.4.2 .. 2.4.5 altogether. + +2002-05-05 Fixed major bug in string/bytes after multiple commits + + Finally found a way to reproduce spurious bugs reported in the latest + revisions. It turns out that one of the optimizations of the past 2 + months (no exact details) caused memo's to be tracked incorrectly in + their free space use. This causes trouble with strings over 10 Kb + (or smaller if there are over 1000 rows). + + The bug is forced by new (frightfully short) test cases s44 + s45. + Fixed by performing a slightly less agressive optimization in the + c4_FormatB::Commit (which is also shared with strings, type 'S'). + + Removed a "--exclude" from diff, which is not portable enough. + +2002-05-01 Added support for Windows CE + + Patches submitted by Joseph Tate (thank you!), with minor tweaks. + +2002-04-29 ############################################## MK 2.4.5 + + Various bug fixes, fixed a number of platform issues. + +2002-04-28 Fix small-int re-use view bug + + A nasty bug was reported by VPI which caused upper bytes to be + truncated from int values. The problem appears when storing ints of + 1..4 bits in a view, then clearing the view (so a gap is placed past + the end of the column), then adding a row with an int of 2 or more + bytes. This uncovered a bug in forgetting to truncate columns with + sub-byte int storage. Now fixed, added regression test s43. + + This bug could also have affected string and byte storage, since + these use int columns to store item sizes. Under very specific + conditions, it may have lead to truncated or even mixed-up values. + +2002-04-27 Fix nested mk4tcl loop bug + + Loops would exit prematurely when nested - due to objc/objv being + overwritten in the inner loop. Affects mk4tcl.cpp and mk4too.cpp. + +2002-04-10 Fix bug introduced in recent blocked viewer optimization + + Murphy was at it again. The bug affected the way row inserts and + deletes were done, and can cause incorrect data to be copied. It is + relatively hard to reproduce (the test dataset was 12 Mb), but the + change explains things fully and is in fact very small. + +2002-04-02 Fix bug in debug code + + In remap.cpp line 531, a debug assertion was moved in the wrong way. + +2002-04-01 Backed out to libtool 1.4d, fix test diff and Tcl const + + Backed out to the more official 1.4d release of libtool (instead of + the CVS version, which is adding "tags" we will not need anyway). + The unix/Makefile.in has been simplified, back to how it used to be. + + Fixed the "diff" call at the end of "make test" so that it no longer + generates extra output if things match and now fails if they do not. + + Added fix to allow compiling mk4tcl.cpp with "pre-constified" Tcl + code, thanks to a tip by Don Porter (see "grep CONST84 mk4tcl.*"). + +2002-03-31 ############################################## MK 2.4.4 + + Various bug fixes and (blocked view) performance enhacements. + +2002-03-28 More blocked optimizations, IRIX tweaks + + Switched Slot() to binary search. This seems to slow down a few + percentage point for smaller views, but with 5 millions rows this is + reported to make a huge difference (from code by Zhang Dehua). + + Added header "bool" fix by Erik Hofman so MK compiles on IRIX (SGI). + +2002-03-27 Added definitions for AIX + + Added six operators defs before c4_Cursor class, to avoid compile + errors on AIX. With apologies to Murat Berk for taking so long... + +2002-03-26 Re-instated the c4_View::RelocateRows operation + + Re-enabled code which supports efficient moves of rows from one view + to another - avoiding copying of subviews. Strings/memos are still + being copied for now. Also moved a slow test out into a new call + "c4_View::IsCompatibleWith", this must be checked to make sure that + RelocateRows can work. Passing incompatible views will still cause + an assertion in debug mode, but must be avoided in release builds. + + This change ought to have a dramatic effect on inserts/deletes for + blocked views with large subviews. Added examples/blockdels.tcl to + thoroughly exercise this new code and all boundary conditions. + +2002-03-22 Fixed a serious bug in serialization code + + When serializing string/bytes columns with large strings using the + c4_Storage::SaveTo function, memo's would sometimes not be written, + leading to a *damaged* datafile (and incorrect free-space tracking). + +2002-03-15 Better configure logic, "mk::view layout" fix + + Many tweaks to configures, makes, and libtool setup. Get rid of the + library version numbers and the special Mk4*.so targets. Instead of + Mk4tcl.so use libmk4tcl.so (likewise Mk4py.so is now libmk4py.so). + + Fixed "mk::view layout", it was broken by the 10-2-2002 change. + +2002-03-13 Extend partial access 'B' usage + + Added code to Access and Modify to simulate partial data access the + hard way when the underlying view does not support it (c4_Bytes + only), i.e. copy via full temp. Added test s41, doing partial access + on a blocked view. + +2002-03-12 Add test for serialized input + + The c4_Storage::LoadFrom() call (mk::file load) can be tricky. After + a commit, the header is adjusted so that reading from the start + works. This is not the case in commit-extend mode, where a load will + read th state as it was before extending - it cannot know there is + more. + + Added test s40 to verify this case. Also reorged a few more files + (tbasics and tstore4 split into 2 each). + + Added test in mk4tl.cpp so LoadFrom failure generates an error + return, instead of being ignored. + +2002-03-10 Tweaked March 8 fix a tad further + + The workaround implemented below wasn't 100% complete. + +2002-03-08 Workaround for file extend on Win + + There seems to be a bug when extending a file on at least NT4 with + NTFS (file server works fine). When extending the file in such a way + that a gap is created to save new data during commit, the file + appears to get rounded up to the next 512-byte boundary. At that + point, the datafile no longer has a valid end marker and is sort of + corrupt. + + Wrote workaround for Win32 builds, see persist.cpp notes names "March + 8, 2002". One way to force this bug is to run "mkhash Dmhs 250000" - + after row 150000, it asserts on bad filesize when built in debug mode + and run on NTFS. + +2002-02-19 Fixed over-aggressive optimization + + Change made on Feb 7 was releasing too many objects in a commit, + causing it to detach empty top-level views, even when in use. Fixed, + added s39 to test for this case. + +2002-02-10 Improve Mk4tcl's "mk::view layout" + + Avoid crash when asking for the layout of a non-existent view. Now + returns an error instead. + +2002-02-07 Fast commit with many empty subviews + + Avoid creating subviews when committing, if these are empty anyway. + Added new s38 test for this case. + +2002-02-02 Small optimizations + + Changed a few c4_Property instances to const& references to avoid + copying (2 in view.cpp, 2 in custom.cpp). + +2002-02-01 ############################################## MK 2.4.3 + + Bug-fix release, mostly. + + Python include path now upgraded to python2.2 (was 2.1). + +2002-01-31 Cross-platform serialization, Tcl + + There was a bug with serializing a datafile (SaveTo) when it was + created on a platform with reverse endian-ness. Fixed so serialized + data also flags reversed byte order. + + Tweaks to fix const changes in the latest Tcl cvs branch. Fixed a + recently-introduced UTF8 path bug in mk4tcl.cpp. + +2001-12-21 Optimized GetAs + + Now that GetAs is used so much more, optimize the common case where a + description does not require restructuring. Can lead to order-of + magnitude speed improvement in cases where a storage contains many + views. + +2001-12-20 Fixed bug in Locate, comparison issue + + Testing for the Mk4py changes uncovered a serious bug in + c4_View::Locate, causing it to sometimes return zero, even if there + are matching rows (thanks, Gordon). + + But a very fundamental weakness also showed up, being that row + comparisons (and that includes the C++ operators) have the confusing + property of not being symmetric in all cases. The problem occurs + when left- and right-hand sides do not contain the same (number of) + properties. In that case, the *left-hand* row participating in the + comparison determines which properties take part in a comparison. + + In the case of Locate, this caused improper comparisons. And it is + very easy to get bitten by this, such as here: c4_RowRef key = ...; + int n = view.Search(key); bool match = n >= 0 && view[n] == key; The + above code is *wrong*. The last line needs to be: bool match = n >= + 0 && key == view[n]; + + This is very clearly a design mistake. Comparisons should have been + *either* implemented *or* named differently. + + A new "m04" test has been added to the regression suite. + +2001-12-19 Changes to mk4py by Gordon McMillan + + Several changes and cleanups. Mk4py now has logic to track different + view categories, e.g. to make sure a R/O view is not being written + to. This should greatly reduce the number of silently ignored + incorrect calls, as well as crashes, and will produce appropriate + error messages instead. + +2001-12-18 Cleanup + + Cleaned up source comments and got rid of yet more warnings. + +2001-12-14 Fixed yet another case of crash-on-exit + + The new Unmapped() code of 2.4.2 forgot one case of cleaning up, + which has now been fixed (in c4_FormatB::Commit). + +2001-12-12 ############################################## MK 2.4.2 + + Better portability, hashing improved + + This release marks the consolidation of a number of changes, mostly + relating to better portability & hashing. The speed of commits with + many strings and subviews should be notably better. The Tcl + extension no longer needs a "stub" library to compile (it now has + that code itself), just std headers. + +2001-12-08 Changes to commit cleanup, Mac stuff + + Changed the logic of how ReleaseAllSegments gets called at the end of + commits. There was at least one case of leaving a column pointing + into mapped file space when it was about to be remapped. This should + fix a very long-tanding bug which shows itself as freeing unallocated + memory during commit or cleanup of the storage object. + + Changes to test coding and PyRowRef.cpp to deal with builds on + Macintosh (different issues for MacOS 9 and MacOS X). The + mac/cw.sea.hqx project has been upgraded to MW CW 6.3. Verified Tcl + 8.3.2 and Python 2.1.1 builds with CW6 on Mac. + +2001-12-06 Tweaks to Tcl interface + + More robust, added "$vw loop var ... {body}" object command. The + "$vw size" command now takes an optional newsize arg. + +2001-12-04 Tweaks to makefile and configure + + Tweaks, in preparation of an upcoming 2.4.2 release. + +2001-12-03 Changes in M4py, avoid gcc problem, hash + + The "-fomit-frame-pointer" option for gcc has been turned off, + because it causes problems with exception handling in Mk4py. All + failures in Mk4py now propagate properly to Python AFAIK. + + Simplified Mk4py - by removing a layer of exception handler classes + in scxx. Errors now set info and throw a plain int. + + The mkhash.cpp sample program exposed a problem with multi-key + hashing: the order of properties in the search key must match exactly + the order in the hash view itself. For now, this has been left as is + (it's easy to do, once you are aware of it). + +2001-11-30 Win MT fix, commit tweak, indent cleanup + + Drop static buffer in fileio.cpp (DataWrite), uses stack now, so the + code can be used in MT context even on Win 95/98. It does more + copying than would be needed for NT (2K?), alas. + + More changes in c4_FormatB::Commit to properly detect memo use in + blocked views. The recent changes introduced a bug which shows up + only with blocked views and large string/bytes items. Reported by + Steve Baxter with demo, new "m02" regression test. + + Changed fileio.cpp to turn off file buffering, this avoids a few + reads when writing and seeking a lot. It does not have as big an + impact as one might expect, but every little bit helps. + + Cleaned up new 2-space indentation in several source files. + + Added new "mk::file space" in Mk4tcl, to inspect the current file + space usage. This is only intended for internal testing. + +2001-11-28 Fixed memory leak in string/memo cleanup + + There was a mem-leak in c4_FormatB::Commit which showed up due to + yesterday's more extensive testing. Only showed up after a commit, + in string columns with widely varying item sizes. This caused + regression test s37 to fail in MFC-debug compile. + +2001-11-27 Major performance bug fix, and MT strings + + A serious problem has been resolved, which slowed down commits, and + prevented blocked views from committing efficiently. The reason was + that for string props, the string size was always being saved anew, + even if no changes in that view took place. This did not affect + proper operation, just speed, and was most noticeable with many + (sub-)views containing many string props. + + The solution is in src/format.cpp, the examples/mkhash.cpp code was + further adjusted to better expose and measure the effects. Thanks to + P. Baspeyras and S. Baxter for helping me resolve it. + + Another change was to alter the way empty strings are allocated in + the src/string.cpp code, making it compatible with multi- threaded + use and removing the remaining memory leak. + +2001-11-26 Fix in assertion check (blocked view) + + Corrected an off-by-one bug. Only shows up with debugging on, since + it's inside an assert(). Thanks to Steve Baxter. + +2001-11-25 More arg checking in Mk4py, locate + + Added more checks against incorrect usage, based on sample code by + Mitch Chapman. The "throw" code appears to be inconsistent when + called at top of *some* calls, using a workaround for now. + + Added "view.locate(key)" wrapper, returns (pos,count) tuple. + + Various source code formatting adjustments (indents and such). + +2001-11-04 Added alternate calls to c4_CustomViewer + + Added extra defs to "mk4.h" of Lookup and InsertRows which take a + "const c4_RowRef&" i.s.o. a c4_Cursor. Inlined in "mk4.inl". The + "c4_Cursor" datatype might one day become obsolete. + +2001-11-03 Removed tcl/kit/ and copyright notices + + Removed the entire tcl/kit/ tree, Tclkit will be distributed as + separate package from now on (the 2.4.1 release still builds ok). + + Also replaced all copyright notices by version Id's and an URL. + +2001-11-02 Fixed partial memo commit bug, makefile fix + + Modifying a small item as memo (i.e. through Modify) properly + committed a change, but subsequently left an incorrect pointer after + the commit. Fixed, and added test s37 to catch this case. + + Don't strip symbols from installed static libs (whoops!). + +2001-10-31 Fixed Mk4py error flag clear on delete + + When deleting rows, a slice was constructed from a PWOSequence, which + generates an otherwise harmless error when its length is checked. + The flag was not cleared, causing errors in subsequent Python + statements. Changed to a PWOTuple in PyView.cpp (2x). + +2001-10-26 Fixed Mk4tcl re-open test + + The tcl/test/mk1basic.tcl test #6 was reporting open failure on + non-Linux systems. Fixed, the code works, the message was wrong. + +2001-10-19 Rearranged some demo files, Lua binding + + Rearranged some of the demos/samples from the python/ and tcl/ areas, + and placed them in examples/ instead, for consistency. + + Added "selmap.tcl" to illustrate how to turn select into a view. + + Added a basic Lua binding (incomplete, but it's a start) in lua/. + +2001-10-18 Fixed recent hash bug, and add to ordered + + The recent "fix" to deal with hash misses introduced a huge bug, + causing the mapping to be recalculated on each insertion. + + Adding to an ordered view did not always work, because the code was + based on SetAtGrow, which is not suitable for an ordered view in + which the row position is determined implicitly. Fixed by changing + c4_View::Add to use c4_View::InsertAt instead. + +2001-10-14 ############################################## MK 2.4.1 + + Custom-extended Tclkit, and threading + + Minor kitInit.c change allows wrapping apps as a "custom-extended" + version of Tclkit. Enable threaded Tcl build on Unix. + + This release consolidates the most recent fixes and code tweaks. + +2001-09-27 Fix temp storage open in Mk4tcl + + A recent change made it impossible to open temporary storages from + Tcl ("mk::file open db") - <blush> - now fixed again. + +2001-09-19 Bug fixes + + Fixed a problem during commit, when memo's are modified, causing them + to be stored inline again. This caused a late reference to mapped + memory - leading to intermittent crashes on commit. + + Changes/fixes in mk4tcl.cpp, to prevent a problem when a datafile is + re-opened again under the same name later on. Old references could + in some cases end up stale - leading to crashes much later. + +2001-09-05 Bug fixes + + Hashing bug fixed: failed to terminate when looking for a missing key + after a hash collision. The fill count was not being tracked + properly to enforce that there is always at least one unused slot. + + Fixed bug when setting a string from a higher row: the data gets + trashed, because too little copying was done while creating a gap. + This bug may have led to some other cases of "damaged" datafiles. + Solved by copying input data in c4_FormatB::SetOne(). + + Fixed long-standing bug with commit-after-load, by now doing a full + view/subview copy. This is inefficient, but it avoids all sorts of + mapping/strategy problems. This also fixes test s33 (at last!). + + Added regression tests b27, c21, m01, and s36 to check above fixes. + +2001-06-29 ############################################## MK 2.4.0 + + More changes to the Mk4py interface + + - allow setting a row to a value if the row has a single property + - there is an unexplained crash when setting slices with wrong type + +2001-06-22 Changes to the Mk4py interface + + Modifications and fixes gratefully accepted from John Barnard: + - c4_LongProp support ('L' datatype) + - row.__attrs__ returns the list of all properties + - row.__view__ returns the container view of the row + - row.__index__ returns current position in view + - view.setsize(n) added, extends/truncates number of rows + - generalized makerow to allow any sequence, not just lists + + Changed PyRowRef to inc/dec the reference it has to the underlying + view. Should prevent dangling pointer problems, such as deleting a + storage while rows are still in use. This adds a little overhead. + + Fixed a PyErr_Clear issue when accessing non-existent properties. + +2001-06-12 Close DB filedesc on exec + + Added an fcntl call to fileio.cpp, so that on Unix database file + decriptors are closed on exec (relevant when doing "exec ... &"). + +2001-05-30 Fixed mem-leak in Mk4tcl + + A long-standing bug, in TclSelector::ExactKeyProps. + +2001-05-28 Security fix in Tclkit + + See end of the tcl/kit/README file for deatils. + +2001-03-30 Fixed long-standing commit bug + + There was an intermittent bug in c4_Persist::Commit, when properties + were "restructured away" (dropped). The bug was hard to track down, + because it depended on what address ranges the O/S assigned to + mem-maps. Might also fix other spurious commit/exit crashes. + +2001-03-29 ############################################## MK 2.3.4 + + The "last" release candidate + + Now checked into its *new* CVS home at equi4.com. Mailings list(s) + have also been moved to this site. + +2001-03-28 Fix Win build, broken on Mar 27 + + Dropped kBufMax from mk4.h, it caused compiler errors in MSVC6 - + switched to "sizeof" in a couple of places. This error was + introduced by the double-fix of 3/27. + +2001-03-28 Allow builds of Tclkit with Sun CC + + Integrated a few changes provided by D.J. Hagberg. Note: the + M-solaris.sh and M-dyn.sh scripts need to be manually edited when + choosing between CC and gcc. + +2001-03-27 Double-alignment bug on Solaris + + Two changes (c4_Bytes in mk4.h and src/column.h) to fix an alignment + problem for 8-byte doubles on Solaris. This caused tests b17, b23, + b24, s22, and s28 to fail. + +2001-03-26 Fixed cross-platform commit bug + + There was a nasty bug in the 2.3.x code, which wrote incorrect field + sizes when committing to a datafile with a different byte order + (i.e. created on a machine using different endian-ness from the one + doing commit). + +2001-02-14 Removed file events from Tclkit + + Changed kit/rechan.cpp to not generate file events. This avoids a + bug in Tclkit whereby an open file can generate a continuous stream + of file events as long as the file is open - the console will seem + to be frozen, though "close $file" does work and fixes it. + +2000-12-13 Added missing c4_LongRef export + + Added a line in mk4dll.h to resolve references to the new + c4_LongProp/c4_LongRef datatype on Windows. + +2000-12-04 Fixed conversion bug + + There was a bug in c4_FormatV::OldDefine, causing MK to crash when + trying to convert an old-format file with empty subviews in it. Bug + introduced on 14 Nov. + +2000-12-02 Fixes in Tclkit code + + Fixed a Tcl-level bug causing memory leaks for all compressed files + stored with MK opened for reading. + + Disabled event sources (mk4tcl.cpp and rechan.cpp) to avoid a GUI + freeze-up while a fake file is open. + +2000-11-16 Simplified c4_Storage + + Made some changes so that a c4_Storage no longer has a separate + c4_Persist* copy. As a result, a storage can now be reconstructed + from any root-level view. This generalizes views, and prepares for + a merge. + +2000-11-14 Fixed mem leak in conversion code + + The conversion code from pre 2.3 files had a memory leak in + c4_FormatV::OldDefine, causing f06 to leak, as well as several + subsequent erroneous leak reports. Changed a few "new" to "d4_new" + calls along the way. + + Remove FlipBytes members, they are no longer needed. + +2000-11-08 Tclkit now in the distribution + + The "Tclkit" project has been merged into Metakit. Details and + updated build info at "tcl/kit/README". The SourceForge CVS + repository is up to date again. + + Mk4py: improved number conversion and error handling. + +2000-11-03 ############################################## MK 2.3.3 + + First final release candidate + + Yes, there will probably be a second one as well... + +2000-10-31 Improved error handling + + More logic added to catch errors in flush and streams. This affects + the C++ core as well as Mk4py and Mk4tcl. API of c4_Stream::Write + changed to return success flag. + +2000-10-30 Added autocommit call to Mk4tcl + + To better support VFS, Mk4tcl now has a new command "mk::file + autocommit <db>" to force commit on close. + +2000-10-26 Changes to compile with Borland C++ + + Minor tweaks to compile with Borland C++ Builder 4.0, which does not + support "long long". A new Kitviewer has been built (new code to + replace c4_View::Describe). + +2000-10-03 Fixes for Alpha Unix + + Moved _item in column.h up to fix alignment sensitivity. Config.h + did not get SIZE_LONG right on Alpha Unix (0?). + +2000-09-27 Contributed fixes and Python 2.0b2 + + Adjusted makefile to build with Python 2.0b2 release. + + Source code tweaks to avoid DEC CXX 5.7 compiler errors. Add + no-inherit flags for Win32 to not leak file handles. + +2000-08-27 Allow derived row deletes in Mk4py + + Added code to PyView.cpp to handle deletes (and slice deletes) in + derived views, see "examples/derived.py". + +2000-07-30 Major auto-convert 1.8.6 file bug + + Bug in on-the-fly conversion of bytes properties ('B') in pre-2.0 + datafiles (i.e. 1.8.6 and earlier) resolved. + + Unfortunately, this bug can not be 100% unambiguously fixed. The + new code *will* properly detect most cases, and convert both 1.8.6 + and 2.0 datafiles on the fly, but especially for views with only a + few rows and at most a few bytes of data per row - the conversion + *might* fail. + + In this case, MK will have to be compiled with a define to force it + to either assume all old datafiles are 1.8.6 (-Dq4_OLD_IS_PRE_V2), + or to assume that they are always 2.0 (-Dq4_OLD_IS_ALWAYS_V2). If + you are currently using MK 1.8.6, then you should *skip* the update + to 2.01, and consider updating to 2.3.x. This way you never have + any 2.0 files around, and can force all your code to handle 1.8.6 + files properly (by using "-Dq4_OLD_IS_PRE_V2"). + + See src/format.cpp, c4_FormatB::OldDefine for details. + + This bug *only* applies to bytes properties in pre-2.0 data files. + Conversion of 2.0x files is unaffected. + +2000-07-25 Fixed new self-referential views + + The new recursive / self-referential view definition style has been + fixed, e.g. "view[data:S,self[^]]" will now let you store a tree of + arbitrary depth, with each 'self' subview having data and self + properties. See the demo in "examples/selfref.py" to see how this + all works. + +2000-07-22 Fixed bug in double restructuring + + Solved a very long-standing bug in restructuring, which caused + incorrect (non-zero, small) default values when a c4_DoubleProp was + added to a view which already had rows. + +2000-07-18 Added remapwith and pair to Mk4py + + Exposed C++'s c4_View::RemapWith as v1.remapwith(v2), and + c4_View::Pair as v1.pair(v2) in the Mk4py Python binding. Added + pair.py, remap.py, and wrap.py in "examples/" dir. + +2000-07-12 Added metakit.py wrapper + + Added "metakit.py" script to wrap Mk4py, including a new + metakit.dump() to pretty-print views. More utility code will be + added over time. The preferred way to use Metakit from Python is + now "import metakit". + +2000-07-06 Conversion fix, warning cleanup + + Fixed on-the fly conversion of old datafiles. The free space was + not managed properly - changed to never touch any data inside the + file during conversion. + + Some source code change to get the compile through gcc flags + "-fguiding-decls -Wall -pedantic -Wno-unused". The only remaining + complaint is about using "long long". + +2000-07-04 MkSQL subtree, "indexed" mapped viewer + + Added the sql and mksql subtrees to the distribution, with Gordon + McMillan's MkSQL engine, written in Python. The "isql.py" script is + a simple interactive shell around it. + + Started work on a new viewer which maintains a persistent index (as + a one-int-prop permutation), see src/remap.cpp. + +2000-07-03 Mk4tcl fixes + + Fixed view rename problem and "delete end" (Matt Newman). Adjusted + the tests in tcl/test/mk5object.tcl accordingly. + +2000-06-30 Tequila fixes + + Close fix and failure handler (Steve Landers). + +2000-06-29 ############################################## MK 2.3.2 + + First beta release + + The new release is 99% feature-complete. What remains is to further + document C++/Python/Tcl use and to fix bugs. + + Python sample code in "python/aside.py" and "python/find.py". Tcl + samples in "tcl/test/mk5object.tcl" and "tcl/mapped.tcl". + +2000-06-28 Hash/blocked/ordered: changes and fixes + + Changed hash insertion to insert at specified position. This makes + it possible to use hashes "under" ordered views. For best + performance, insert rows at end of hash views. + +2000-06-26 Documentation, example, Mk4tcl OO fixes + + Moved C++ member documentation out of "mk4.h" header. Added + examples/ directory, with a find.py timing example. Fixed bugs in + new Mk4tcl: "$vw find" and "$vw delete end". Added tests for new + Mk4tcl OO interface: ":mk5object.test". + +2000-06-16 Improved modifiable custom viewers + + The Pair and Slice viewers now support set/insert/remove, while + RemapWith/Concat/Rename support setting values. + +2000-06-15 Many changes to the Tcl code, hashing + + Contributed by Matt Newman, it adds support for most custom viewers, + including the new hash etc. Added a fast find. Caveat: most old + custom viewers are still not modifiable. + + Hash calculation improved, far less collisions than before. + + Blocked viewer seems to work. Ordered on top is sub-optimal. + +2000-06-12 GetUpperLimit, Blocked, Ordered, mk4too + + Removed c4_View::GetUpperLimit (it's equivalent to GetSize-1 and was + not being used anywhere). + + Start implementing c4_BlockedViewer, a simple balanced/blocked + nested data structure. Also started on a c4_OrderedViewer, which + keeps the underlying view sorted during changes. These two can be + combined to implement an efficient 2-level btree. + + Adopted code by Matt Newman for oo-cmd's for Mk4tcl views. First + trials work, started to extend with new custom viewers. + +2000-06-09 Change case of a few Mk4py members + + Changed all top-level members in the Python interface to lower case: + storage, property, view, wrap (will break existing code). + + Fix bounds check in Mk4tcl.cpp for commit/rollback (new code). + + Whoops, forgot to add new src/remap.{h,cpp} to the cvs tree. + +2000-06-08 Implemented hash lookup + + Added a new virtual c4_Sequence::RestrictSearch, which lets a view + take over searching (used by c4_View::Find). The result is that the + new hash viewer gives a huge speedup for finds. Find requests which + require linear scanning are unaffected. + +2000-06-07 Documentation extraction based on Doxygen + + The automatically generated output from Doxygen is working out well + and looking pretty, added "src/doxy.h" with more comments. + +2000-06-05 Started hash and btree custom viewers + + The hash implementation is nearly done, also usable from Python. + Btrees are being implemented as fixed 2-level for now. + +2000-06-01 Fixes + + Fixed crash when opening missing file r/o new in 2.3.1 alpha. Fixed + incorrect on-the-fly-conversion of 2.0 format subviews. Added + "storage.aside(storage)" to the Python interface. + +2000-05-30 Fixed commit-aside + + The new commit-aside code was botched by recent changes. Fixed + SetAside to pick up new root seq, changed by implicit rollback. + Note that a commit-aside is not finished until you *also* commit the + secondary file containing all newly generated changes. + + Fixed bug in c4_BytesRef::Access, introduced in 2.3.1 alpha. + +2000-05-29 Added new 64-bit long datatype + + Added support for 64-bit longs (type 'L'), and c4_LongProp, etc. + This type is not autosizing, it always uses 8 bytes per entry. Uses + "long long" or "__int64", else defines struct with 2 longs. This is + not yet correct for platforms which have no 64b ints. No regression + tests or Python/Tcl interfaces yet. + +2000-05-28 Better file mark scanning + + Added c4_Strategy::EndOfData, to determine the logical end of a + Metakit datafile. This call can be used to check whether a file + contains any data, and whether a commit-extend has been performed. + Old-style scripted documents (with preamble) can now be opened. + Changed strategy class, DataSeek has been merged with read/write. + Removed c4_LoadContext, LoadIt member moved to c4_Persist. + +2000-05-27 Tweaked configuration define's + + Make the release build the default (no assertions, use inlines). + Enable booleans for gnuc by default (it's pretty standard by now). + Added extra include path to better find Python's includes. + +2000-05-26 Fixed Tcl dependency + + Changed configure script to no longer look for Tcl if the + "--with-tcl=..." parameter is not specified. + +2000-05-25 ############################################## MK 2.3.1 + + First alpha release + + Officially, this is "Metakit 2.3.1 alpha" (ignore "2.3.0" in mk4.h). + All alpha's are 2.3.1 (beta's will be 2.3.2, finals start at 2.3.5). + Builds on Linux/Mac/Win appear ok - as do Mk4py, Mk4tcl, and Tclkit. + +2000-05-06 Massive changes to the core + + To summarize the main issues: management info is now stored in such + a way that it need not be read in right away - file open is now + instant. The S(tring) datatype is now stored as B, making it far + more scalable (API/use is unchanged). Storage objects now derived + from views, both can be initialized from a stream (data will be kept + in a buffer, beware of potentially large memory use). + + Several file format changes are "for future expansion". + +2000-05-05 Fixed builds without Tcl + + In 2.0.1, the make would fail if there was no Tcl to build with, or + not an appropriate release. Changed Makefile to report and skip Tcl + builds in that case. + +2000-04-06 Fixed a nasty restructure/mmap bug + + When a property is deleted by a restructure, then committed, then + later committed again, a problem can cause MK to crash. It has only + been detected in debug builds, but the problem turns out to be a + fundamental one (only happens with memory-mapped files, if the file + is resized). Fix in next rel (c4_HandlerSeq::DetachFromStorage). + +2000-04-02 Memo properties are no longer needed + + The M datatype is gone from the public API (and now illegal). + Everything binary should now be stored in B(ytes) properties, which + then adaptively decide which internal format to use, based on a + simple heuristic (which will be refined later). Existing datafiles + will automatically convert from M to B. The partial Access and + Modify calls now also work on B items. + +2000-03-30 Minor change in c4_Strategy + + Dropped the _keepAfterCommit flag in c4_Strategy, it probably has + never been used and it interferes with new features. + +2000-03-27 Change in API for creating storages + + It is no longer possible to create a storage and define its + structure with a single call. Instead, open a storage in r/w mode + (i.e. "1") and then call the (now public) SetStructure member to + define the structure of all views. This change is necessary to + prepare for the upcoming "commit-aside" logic. + +2000-03-23 File format changes (in progress) + + The new file format has an incompatible header, so old code will not + recognize new datafiles. Major changes are: added a file tail + marker, the serialized format is now a very good way to compress + datafiles, since it can be efficiently opened in on-demand/mmap'ed + mode. The new format supports several planned features. Code to + convert existing files on-the-fly will be added before this change + is released. + +2000-03-19 Added c4_Strategy::FileSize + + The Strategy::FileSize call is used for a file format change. + +2000-03-18 Added c4_View::Locate + + Locate returns the number of matching rows, and optionally the + position of the first one, using binary search. Like the + c4_View::Search function, it requires the view to be sorted. + +2000-03-17 ############################################## MK 2.01 + + Maintenance release, it's solid + + Updated MK version number to 2.01, this maintenance release + represents a very stable version. + + Small change to b07 test to avoid evaluation order problems. + + Added unix/metakit.spec file for RPM, thanks to Sean Summers. + +2000-03-16 Drop Store, fix deep copy, drop segments + + c4_Storage::Store never worked properly under all conditions. It's + been deprecated for some time and has now been removed. Made a + handful of changes to test- and demo code to drop it. + + Duplicating a view with deep copy never worked, because it used the + buggy Store call as well. Changed to use recursion. + + Dropped support for segmented tree-walk storage, which hasn't been + used since 1.5 (use a commit with 2.0 to convert files). This is + necessary to prepare for some file format changes. + +2000-03-15 Modifiable custom viewers, other tweaks + + A start has been made with making custom viewers updatable. The new + methods are Set, InsertAt, RemoveAt, and Move, but the number of + viewers which implement this is still limited. Mk4py has been + adjusted to allow "set" on wrapped views. + + Removed c4_Strategy::DataLoad, it was only used in one place. Small + optimization of the 2 calls to c4_Streamer::NextByte. Get rid of / + disallow read calls on memory mapped files. + +2000-03-14 Makefile tweaks, non-commits smarter + + Changed from --enable-tcl to --with-tcl=DIR, because the old + approach only worked with Tcl installed in a standard place. + + Commits of a R/O file now fail. Also, if no changes have been made, + a commit will no longer write anything to file. + +2000-03-13 Several new commands added to Mk4py + + Several changes were submitted by Gordon McMillan, which add better + support for his upcoming SQL engine. + +2000-03-12 Allow embedding MK datafile at end of EXE + + Mk4tcl was changed to look for an optional trailer for quick access + to the start offset. This makes it possible to append datafiles to + executables, even if they are larger than 4 Kb. + +2000-02-29 Fixed rare bug with lots of memo fields + + There was a bug in free space management (persist.cpp), which can + only occur when exactly 7500 free space gaps are present, and a + commit crosses the threshold. There was also a small mistake in + that same code causing a bit of free space waste. + +2000-02-24 Added proxy support to Tequila + + Tequila can now be used as basic client/server setup for Tcl + scripts. See tcl/tequila/README for details and an example. + +2000-02-04 Fixed mk::views (Mk4tcl) + + The mk::views command failed to list the first view in the file + (this bug was introduced by changes in MK 1.99). + +2000-01-02 Adjusted y2k + + Copyright and license dates adjusted. + +1999-12-26 More Mk4py changes + + Added sortrev, and fixed "select(low,high)". Docs updated. + +1999-12-23 New view operators in Mk4py + + Added rename, project, groupby, and counts operators to Mk4py. + These were already part of the C++ core. + +1999-12-22 Avoid GetId inline warning + + Reordered GetId in "mk4.inl" to avoid (harmless) inline warning. + +1999-12-21 Checked-in Catfish and Kitviewer sources + + Added win/catfish and win/kitviewer areas. Catfish was built with + MSVC 1.52, so the win/msvc152 area has also been added. + + Kitviewer requires Borland C++ Builder 4.0 to build (using VCL), it + has been adjusted to now also recognize scripted documents. + +1999-12-20 Bug fix in set-after-get situations + + A bug has surfaced when setting string/byte/memo values which span a + 4 Kb block boundary. The bug can only happen if data is first + fetched and subsequently changed. The affected code is in + src/format.cpp (3x). Added Tcl test 5.5 to catch this. + +1999-12-19 Mac tweaks + + Changes to make the Mac versions build from the CVS repository. The + Mac can also cross-compile Windows libraries using MWCW 5. + +1999-12-17 Add the Tequila example + + Added the Tequila global Tcl array data server, see tcl/tequila/. + +1999-12-15 MK 2.0 Official Open Source release + + Removed a bad assertion from FormatX::Compare. + + Several new services set up on the excellent SourceForge.com site. + +1999-12-14 Documentation added + + The C++ API documentation has been added to the distribution, as + well as a document describing the file format details of Metakit. + +1999-12-13 Bug fix affecting c4_View::Description + + There was a problem with c4_ViewScanner::Describe, due to a change + from c4_String to (const char*). Now c4_View::Store works again. + +1999-12-12 MK 1.99 New release, as open source software + + The major change is that Metakit has been released as open source + software, based on the liberal X/MIT-style license. Commercial + support remains unchanged for all recent commercial customers, and + for those who purchase the Enterprise License. The Universal Source + license has been terminated, because full source code is now freely + downloadable by anyone from the website. + + Sources and documentation files have been adjusted accordingly. + +1999-12-08 MK 1.9h Bool support for gcc/egcs, minor fix + + Clear _field after delete in c4_HandlerSeq::DefineRoot. This + triggered an assertion on Linux, when compiled in debug mode. + + Added pre-processor logic to detect whether gcc supports bools. + + Removed all indentation from #define's, #ifdef's, etc. This was + done after a report that some compilers can get confused by this. + +1999-12-06 Derived view row copy fix + + There was a problem when using SetAt with derived views as source, + due to a remapping problem. Fixed viewx.cpp, added new test b25. + +1999-11-25 MK 1.9g Makefile changes, thread-safe Mk4tcl + + Renamed options to --enable-python and --enable-tcl, both now off by + default, since most people probably don't want to enable both. + + The new "-shared" changes to make Mk4tcl thread-safe have been + folded into the main source code. + +1999-11-22 Channel improvements Mk4tcl + + There was a close conflict in mk::channel, also several changes to + improve mk::channel fileevent handling. + +1999-11-19 Bug fix in Mk4tcl + + There was an array overrun when mk::get was called without fields. + Added code to avoid this. + +1999-11-11 Mk4tcl exit handling + + Simplified Mk4tcl exit handling, fixes "interp delete" crash. Added + new mk5fixed.4 test to catch this case. + +1999-11-10 Mk4tcl shared and multi-threaded access + + Made a first experimental version of Mk4tcl (1.2.1, not announced) + which allows sharing a database between interpreters and threads. + +1999-11-09 STL, MkWrap, compare caching + + Tweaked the makefile to support STL builds (also adjusted README). + + Fixed bug in MkWrap, calling storage.description() without args. + + Yet more fixes in comparisons, this is all one problem, caused by + changes in caching for ints, floats, and doubles. Added B24 test. + These (last?) problems occurred in custom / compound views. + +1999-11-08 MK 1.9f Fixed sort comparisons + + There was a cache problem with comparisons of int / float / double + sorts. Fixed, also added new B23 regression test to check for it. + +1999-11-07 Little nasty details + + Tweaked some make/project files. All regress tests and Tcl tests + now reported to really work on Solaris, Linux, Windows, and Mac. + Regression tests required more memory on Mac to get past L03 case. + +1999-11-06 MK 1.9e Big oops: Mk4tcl and MkWrap were broken! + + Fixed a c4_Strategy / c4_FileStrategy mixup in Mk4tcl and MkWrap. + +1999-11-05 Simplify c4_Storage + + Moved state out of c4_Storage and into c4_Persist, to prepare for + multi-thread wrappers. Made a new, simpler design to achieve that. + +1999-11-04 MK 1.9d Factor out stdio dependencies + + Moved all stdio dependencies out of core into new "fileio.cpp" src. + The mk4.h header no longer includes <stdio.h>, added new "mk4io.h" + header with a c4_FileStrategy class, derived from c4_Strategy. + + Also factored c4_Stream/c4_FileStream out of the c4_Strategy class. + This alters the API slightly, but makes it 100% portable/embeddable. + + Added "tcl/iohan.tcl", a simple wrapper for generic storage access: + locally, on a FTP server, in a local MK datafile, or using a remote + Tequila server (see http://www.equi4.com/tclkit/tequila.html). + +1999-11-03 Improved detach/restructure handling + + Changed detach to drop all persistent formathandlers, but leave the + number of rows intact. It will be much faster to destroy columns + than to delete (and propagate) rows. The result is that a pointer + to a view of which the underlying storage object goes away will end + up with the same number of rows as before, but no properties at all. + + Fixed a problem which would have occurred when properties are being + "restructured away" and then committed. The solution is to check + for this and delete all such properties at commit time. + + Moved Buffer() out of c4_HandlerSeq and c4_CustomSeq, and made the + new version in c4_Sequence allocate the c4_Bytes object lazily. + Faster, and decreases sequence object size (for lots of subviews). + + Mk4tcl, mk::layout now returns the proper layout even if the views + are empty. Solved by adding extra arg to c4_Storage::Description, + to return structure of a single top-level view. Fixes "mk8basic.1", + and the returned string now has one bogus list layer stripped off. + + MkWrap also adjusted with optional arg for storage.description(). + +1999-11-02 New Wrap code in MkWrap + + MkWrap, added new Wrap(seq,props,byPos) member, a c4_CustomViewer + which wraps any Python sequence as MK view (for use in joins, etc). + +1999-11-01 MK 1.9c Mk4tcl changes + + Mk4tcl, several changes: added "-size" option to mk::get to return + the size of prop value without fetching it (see new basic.9 test). + Added "-globnc" for case-insensitive globbing (for regexp, this is + available through the new (?i) metasytnax of Tcl 8.2 (see basic.10). + +1999-10-31 MK 1.9b Solved shared lib unload with Tcl 8.2 + + Changed property symbol table setup to avoid static initializers, to + work around a problem with shared library cleanup from Tcl 8.2. + Added new c4_Property::CleanupInternalData call to clean up 100% + (this code need not usually be called, only if memory is tracked). + This fixes the crash-on-exit bug in Mk4tcl (Linux and Solaris). + +1999-10-29 Make support for MkWrap and Mk4tcl + + Both MSVC and MWCW now also build Mk4tcl and MkWrap extensions. The + MWCW project compiles for Win and Mac *on* either Win or Mac. + Makefile extended to build Mk4tcl and MkWrap, added dist target. + Updated to latest Perceps 3.5 beta, started generating docs again. + +1999-10-27 MK 1.9a New build / directory structure + + Completely reworked the directory structure to simplify all builds. + Created new "builds/" area for all intermediate and output files. + New MSVC 6.0 project structure created in "win/msvc60/". + + Moved Mk4tcl to the "tcl/" top-level directory, and MkWrap to the + "python/" dir. The MkWrap code has been removed from the project. + + Removed c4_View::Match and the regular expression package, since it + can just as efficiently be done with a wrapper around MK, now that + string results no longer allocate a temporary copy. + + Started writing a Tcl-based test suite for use with Mk4tcl. + +MAJOR CHANGE SINCE 1.8.6 + + Merge handler.cpp and format.cpp classes to get rid of special-cased + in-memory version of handlers. This has major effects on how data + is kept for unattached views (they still exist, but no longer + special). The code is leaner and meaner, it passes all regression + tests. + +ALSO LISTED IN THE RELEASE HISTORY + + Added c4_MemoRef::Access and c4_Memoref::Modify for partial access + to memo fields. Avoids copying and allows inserts/deletes anywhere. + MkWrap and Mk4tcl have both been extended to allow using Memo fields + for simulated file IO (mk::channel for Tcl, MkMemoIO.py for Python). + + Added c4_Reference::GetSize to determine the size of a value without + accessing it. For ints, returns negated bit width if 1/2/4 bits. + + Added experimental c4_View::RelocateRows to move rows from one view + to another (both must be in same storage, with the same structure). + Moves do not involve any data copying w.r.t. subviews and memo's. + +The old release history is at http://www.equi4.com/metakit/history.html + +# vim: tw=72 diff --git a/akregator/src/mk4storage/metakit/Makefile.am b/akregator/src/mk4storage/metakit/Makefile.am new file mode 100644 index 000000000..af437a64d --- /dev/null +++ b/akregator/src/mk4storage/metakit/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/akregator/src/mk4storage/metakit/README b/akregator/src/mk4storage/metakit/README new file mode 100644 index 000000000..21edd0fc2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/README @@ -0,0 +1,153 @@ +The Metakit Library 2.4.9.3 Jan 2004 +============================================================================== + + +WHAT IT IS - Metakit is an embeddable database which runs on Unix, Windows, + Macintosh, and other platforms. It lets you build applications which + store their data efficiently, in a portable way, and which will not need a + complex runtime installation. In terms of the data model, Metakit takes + the middle ground between RDBMS, OODBMS, and flat-file databases - yet it + is quite different from each of them. + +TECHNOLOGY - Everything is stored variable-sized yet with efficient positional + row access. Changing an existing datafile structure is as simple as re- + opening it with that new structure. All changes are transacted, including + restructuring. You can mix and match software written in C++, Python, + and Tcl. Things can't get much more flexible... + +CORE - The Metakit core library is written in C++. It has a code footprint of + just over 100 Kb on Windows. It can be used as DLL, or linked statically. + Debug builds include extensive assertion checks to catch problems early. + +PYTHON - The binding for Python is called "Mk4py". It uses SCXX by Gordon + McMillan as C++ glue interface. The source is in directory "python/". + +TCL/TK - The MK extension for Tcl is called "Mk4tcl". It is being used in a + number of commercial projects. The source is in directory "tcl/". + +LICENSE AND SUPPORT - Metakit is now distributed as open source software (the + X/MIT-style license is at the end of this document). Commercial support + is available through an Enterprise License, see the URL mentioned below. + +DOCUMENTATION - All documentation uses HTML. The main page is "Metakit.html", + which leads to the rest of the documentation in the "doc/" directory. + The C++ API Reference is extracted from the source code using Doxygen. + +WEBSITE URLS - The main pages on the world wide web, for news and downloads: + Homepage: http://www.equi4.com/metakit.html + Python news: http://www.equi4.com/metakit/python.html + Tcl/Tk news: http://www.equi4.com/metakit/tcl.html + License info: http://www.equi4.com/mklicense.html + Contact info: http://www.equi4.com/contact.html + +ACKNOWLEDGEMENTS - Thanks to everyone who has helped shape and extend Metakit, + including Kyrill Denisenko, Mark Roseman, Gordon McMillan, Matt Newman, + Christian Tismer, John Bushakra, Steve Landers, Jacob Levy, John Barnard, + Nicholas Riley, Brian Kelley, and many more people who have reported bugs + and helped fix them. Last but not least, many thanks to all enterprise + license customers and all my clients for funding Metakit work. + + +INSTALLATION +============ + +(NOTE to Python users: ignore this and do "cd python; python setup.py ...") + +All platform builds and language bindings are designed to work from a single +common "builds/" directory. Where possible, that is - it turns out to be +impossible to keep build side-effects limited to *just* this directory +(CodeWarrior can't be told where to place its temp data, and Visual C++ still +alters a few files next to the project ".dsw" file, to name two offenders). + +UNIX + + It is no longer advised to build the Unix code in the "unix/" directory. + Instead, you should perform the following steps: + % cd builds + % ../unix/configure + % make + % make test + And optionally (this only installs the core lib, not script extensions): + % make install + + By switching to the "builds/" directory, you will keep the distribution + directory tree 100% unaltered. All changes are made in this subdir, and + all final build results are left behind in this same subdir. + + To build with STL containers and strings, you can do the following: + make CXXFLAGS='-Dq4_STD' test # add -O3 etc, as needed + + To build the Mk4tcl extension on Unix, change the configure to: + % ../unix/configure --with-tcl=<dir-where-tclConfig.sh-is> + + Use "../unix/configure --help" to find out about all the other settings. + +WINDOWS + + There is a "win/" directory which contains subdirectories for a number of + compiler systems. Metakit has been built with many different compilers + in the past (Microsoft, Borland, Watcom, Symantec, Metrowerks, Optima), + only a few are maintained (there are 12 configurations for MSVC6 alone!). + + The MS Visual C++ 6.0 project is "win/msvc60/mksrc.dsw", with subprojects + for the C++ demo (mkdemo), building dll's (mkdll), static libs (mklib), + regression tests (mktest), as well as Tcl (mktcl) and Python (mkpython). + It has been set up to place all intermediate files and final results in + the "builds/" subdirectory, even though you'll launch it from "win/". + + To build with STL containers and strings under MSVC, define "q4_STD". + To build with MFC containers and strings under MSVC, define "q4_MFC". + + The Metrowerks Codewarrior project is in the "mac/" directory, and can be + used to build both Mac and Windows versions (on either Mac *or* Windows). + The core libraries are built with "mac/cw5.mcp", demos / tests are built + with "cw5apps.mcp", Tcl is "cw5tcl.mcp", and Python is "cw5python.mcp". + + The Borland C++ Builder projects have not yet been incorporated in this + release, but the "KitViewer" application is an example of how to use BCB. + + The Cygwin build (B20.1 / gcc 2.95.2) is different, because it uses the + unix autoconf system, and must be launched as described above for UNIX. + I have upgraded to the latest development of libtool to be able to build + DLL's with Cygwin. You can build the "-mno-cygwin" version by editing + the Makefile by hand and adding that option to CXXFLAGS. + + Rob Bloodgood adds that the following GCC options are for maximum code + efficiency on x86 hardware: "-O2 -m486 -malign-loops=2 -malign-jumps=2". + I have not yet tried this myself, but am passing on the tip. + +MACINTOSH CLASSIC + + The Mac version requires Metrowerks CodeWarrior 6. See the info above + in the Windows section (MWCW is multi-platform). The projects are all + located in the "mac/" folder, which is also where MWCW will place its own + "... Data" folders with intermediate results. As with all other setups, + final results are made to end up in the "builds/" directory. + + +LICENSE AND COPYRIGHT STATEMENT +=============================== + +Copyright (c) 1996-2004 Jean-Claude Wippler + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +============================================================================== +-- Jean-Claude Wippler <jcw@equi4.com> diff --git a/akregator/src/mk4storage/metakit/include/mk4.h b/akregator/src/mk4storage/metakit/include/mk4.h new file mode 100644 index 000000000..33016dba0 --- /dev/null +++ b/akregator/src/mk4storage/metakit/include/mk4.h @@ -0,0 +1,1078 @@ +// mk4.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Main Metakit library include file + */ + +#ifndef __MK4_H__ +#define __MK4_H__ + +//--------------------------------------------------------------------------- +// +// TITLE +// +// The Metakit Library, by Jean-Claude Wippler, Equi4 Software, NL. +// +// DESCRIPTION +// +// Structured data storage with commit / rollback and on-demand loading. +// +// ACKNOWLEDGEMENTS +// +// To Liesbeth and Myra, for making this possible. +// +//--------------------------------------------------------------------------- +// +// NAMING CONVENTIONS PREFIX REMARKS +// +// Compile time options q4_ Always defined as 1 or 0, capitalized +// Preprocessor defines d4_ Use with "#ifdef" or "#if defined()" +// Classes c4_ Classes, listed at start of headers +// Typedefs t4_ Type definitions, if outside classes +// Global functions f4_ Internal, these are rarely defined +// +// Member functions Start in uppercase +// Instance variables _ And start in lowercase +// Static members _ And start in uppercase +// +// Local variable names Start in lowercase +// Formal parameter names Start lowercase, end with underscore +// +//--------------------------------------------------------------------------- + + /// Current release = 100 * major + 10 * minor + maintenance +#define d4_MetakitLibraryVersion 249 // 2.4.9.3 release, Jan 26, 2004 +#define d4_MetaKitLibraryVersion d4_MetakitLibraryVersion // compat, yuck + +//--------------------------------------------------------------------------- +// Declarations in this file + + class c4_View; // a view on underlying data + class c4_Cursor; // an index into a view + class c4_RowRef; // a reference to a row + class c4_Row; // one row in a view + class c4_Bytes; // used to pass around generic data + class c4_Storage; // manages view persistence + class c4_CustomViewer; // used for customizable views + class c4_Stream; // abstract stream class + class c4_Strategy; // system and file interface + + class c4_Property; // for access inside rows + class c4_IntProp; + class c4_LongProp; + class c4_FloatProp; + class c4_DoubleProp; + class c4_StringProp; + class c4_BytesProp; + class c4_ViewProp; + + // Everything below is part of the implementation, not for public use + + class c4_Sequence; // a collection of rows + + class c4_Reference; // refers to the actual data values + class c4_IntRef; + class c4_LongRef; + class c4_FloatRef; + class c4_DoubleRef; + class c4_BytesRef; + class c4_StringRef; + class c4_ViewRef; + + class c4_Dependencies; // not defined here + class c4_Handler; // not defined here + class c4_Notifier; // not defined here + class c4_Persist; // not defined here + +//--------------------------------------------------------------------------- + + // determine whether we need to include "mk4dll.h" to link as DLL +#if defined (MKDLL_EXPORTS) && !defined (q4_KITDLL) +#define q4_KITDLL 1 +#endif + + // omit floats and doubles in small model 16-bit Intel builds +#if defined (_DOS) && defined (_M_I86SM) && !defined (q4_TINY) +#define q4_TINY 1 +#endif + + // and here's the other end of the scale... +#if !defined (_WIN32) && !defined (q4_LONG64) +#if (defined (_PA_RISC2_0) && defined(__hpux)) || defined (__powerpc64__) || defined(__sparcv9) || \ + defined (__x86_64__) || defined (__s390x__) || defined (__alpha) || defined (__mips64) || \ + (defined (__ia64) && (!defined (__HP_aCC) || defined(__LP64__))) +#define q4_LONG64 1 +#endif +#endif + + // default to inlining for maximum performance +#if !defined (q4_INLINE) +#define q4_INLINE 1 +#endif + +//--------------------------------------------------------------------------- + + // Borland C++ and C++ Builder +#if defined (__BORLANDC__) + // by default, if runtime is linked as a DLL, then so is Metakit +#if defined (_RTLDLL) && !defined (q4_KITDLL) +#define q4_KITDLL 1 +#endif + + // Borland 5.0 supports the bool datatype +#if __BORLANDC__ >= 0x500 +#define q4_BOOL 1 +#endif +#endif // __BORLANDC__ + + // IRIX supports the bool datatype + // define before gcc to cover both the gcc and MipsPRO compiler +#if defined (sgi) +#define q4_BOOL 1 +#undef bool +#undef true +#undef false +#endif + + // GNU gcc/egcs +#if defined (__GNUC__) +#ifndef q4_BOOL +#define q4_BOOL 1 +#endif +#ifndef HAVE_LONG_LONG +#define HAVE_LONG_LONG 1 +#endif +#endif + + // HP aCC +#if defined (__HP_aCC) +#ifndef HAVE_LONG_LONG +#define HAVE_LONG_LONG 1 +#endif +#endif + + // Metrowerks CodeWarrior +#if defined (__MWERKS__) +#if __option(bool) +#define q4_BOOL 1 // bool datatype is optionally supported + // undef, these conflict with c4_Storage::c4_Storage overloading +#undef bool +#undef true +#undef false +#endif +#endif + + // Microsoft Visual C++ +#if defined (_MSC_VER) + // MSVC 5.0 supports the bool datatype, MSVC 4.x has no namespaces +#if _MSC_VER >= 1100 +#define q4_BOOL 1 +#define LONG_LONG __int64 +#else +#define q4_NO_NS 1 +#endif + + // a kludge to avoid having to use ugly DLL exprt defs in this header +#pragma warning(disable: 4273) // inconsistent dll linkage +#endif // _MSC_VER + +//--------------------------------------------------------------------------- +// Other definitions needed by the public Metakit library header files + +#if !q4_BOOL && !q4_STD // define a bool datatype +#define false 0 +#define true 1 +#define bool int +#endif + +#if q4_KITDLL // add declaration specifiers +#include "mk4dll.h" +#endif + +#if q4_INLINE // enable inline expansion +#define d4_inline inline +#else +#define d4_inline +#endif + +typedef unsigned char t4_byte; // create typedefs for t4_byte, etc. + +#if q4_LONG64 +typedef int t4_i32; // if longs are 64b, then int must be 32b +#else +typedef long t4_i32; // if longs aren't 64b, then they are 32b +#endif + +#if q4_LONG64 // choose a way to represent 64b integers +typedef long t4_i64; +#elif defined (LONG_LONG) +typedef LONG_LONG t4_i64; +#elif HAVE_LONG_LONG +typedef long long t4_i64; +#else +struct t4_i64 { long l1; long l2; }; +bool operator== (const t4_i64 a_, const t4_i64 b_); +bool operator< (const t4_i64 a_, const t4_i64 b_); +#endif + +//--------------------------------------------------------------------------- + +class c4_View +{ +protected: + c4_Sequence* _seq; + +public: +/* Construction / destruction / assignment */ + c4_View (c4_Sequence* =0); + c4_View (c4_CustomViewer*); + c4_View (c4_Stream*); + c4_View (const c4_Property& property_); + c4_View (const c4_View&); + ~c4_View (); + + c4_View& operator= (const c4_View&); + c4_Persist* Persist() const; // added 16-11-2000 to simplify c4_Storage + +/* Getting / setting the number of rows */ + int GetSize() const; + void SetSize(int, int =-1); + + void RemoveAll(); + +/*: Getting / setting individual elements */ + c4_RowRef GetAt(int) const; + c4_RowRef operator[] (int) const; + + void SetAt(int, const c4_RowRef&); + c4_RowRef ElementAt(int); + + bool GetItem(int, int, c4_Bytes&) const; + void SetItem(int, int, const c4_Bytes&) const; + +/* These can increase the number of rows */ + void SetAtGrow(int, const c4_RowRef&); + int Add(const c4_RowRef&); + +/* Insertion / deletion of rows */ + void InsertAt(int, const c4_RowRef&, int =1); + void RemoveAt(int, int =1); + void InsertAt(int, const c4_View&); + + bool IsCompatibleWith(const c4_View&) const; + void RelocateRows(int, int, c4_View&, int); + +/* Dealing with the properties of this view */ + int NumProperties() const; + const c4_Property& NthProperty(int) const; + int FindProperty(int); + int FindPropIndexByName(const char*) const; + c4_View Duplicate() const; + c4_View Clone() const; + int AddProperty(const c4_Property&); + c4_View operator, (const c4_Property&) const; + + const char* Description() const; + +/* Derived views */ + c4_View Sort() const; + c4_View SortOn(const c4_View&) const; + c4_View SortOnReverse(const c4_View&, const c4_View&) const; + + c4_View Select(const c4_RowRef&) const; + c4_View SelectRange(const c4_RowRef&, const c4_RowRef&) const; + + c4_View Project(const c4_View&) const; + c4_View ProjectWithout(const c4_View&) const; + + int GetIndexOf(const c4_RowRef&) const; + int RestrictSearch(const c4_RowRef&, int&, int&); + +/* Custom views */ + c4_View Slice(int, int =-1, int =1) const; + c4_View Product(const c4_View&) const; + c4_View RemapWith(const c4_View&) const; + c4_View Pair(const c4_View&) const; + c4_View Concat(const c4_View&) const; + c4_View Rename(const c4_Property&, const c4_Property&) const; + + c4_View GroupBy(const c4_View&, const c4_ViewProp&) const; + c4_View Counts(const c4_View&, const c4_IntProp&) const; + c4_View Unique() const; + + c4_View Union(const c4_View&) const; + c4_View Intersect(const c4_View&) const; + c4_View Different(const c4_View&) const; + c4_View Minus(const c4_View&) const; + + c4_View JoinProp(const c4_ViewProp&, bool =false) const; + c4_View Join(const c4_View&, const c4_View&, bool =false) const; + + c4_View ReadOnly() const; + c4_View Hash(const c4_View&, int =1) const; + c4_View Blocked() const; + c4_View Ordered(int =1) const; + c4_View Indexed(const c4_View&, const c4_View&, bool =false) const; + +/* Searching */ + int Find(const c4_RowRef&, int =0) const; + int Search(const c4_RowRef&) const; + int Locate(const c4_RowRef&, int* =0) const; + +/* Comparing view contents */ + int Compare(const c4_View&) const; + + friend bool operator== (const c4_View&, const c4_View&); + friend bool operator!= (const c4_View&, const c4_View&); + friend bool operator< (const c4_View&, const c4_View&); + friend bool operator> (const c4_View&, const c4_View&); + friend bool operator<= (const c4_View&, const c4_View&); + friend bool operator>= (const c4_View&, const c4_View&); + +protected: + void _IncSeqRef(); + void _DecSeqRef(); + + /// View references are allowed to peek inside view objects + friend class c4_ViewRef; + + // DROPPED: Structure() const; + // DROPPED: Description(const c4_View& view_); +}; + +//--------------------------------------------------------------------------- + +#if defined(os_aix) && defined(compiler_ibmcxx) && (compiler_ibmcxx > 500) + bool operator== (const c4_RowRef& a_, const c4_RowRef& b_); + bool operator!= (const c4_RowRef& a_, const c4_RowRef& b_); + bool operator<= (const c4_RowRef& a_, const c4_RowRef& b_); + bool operator>= (const c4_RowRef& a_, const c4_RowRef& b_); + bool operator> (const c4_RowRef& a_, const c4_RowRef& b_); + bool operator< (const c4_RowRef& a_, const c4_RowRef& b_); +#endif + +class c4_Cursor +{ +public: + /// Pointer to the sequence + c4_Sequence* _seq; + /// Current index into the sequence + int _index; + +/* Construction / destruction / dereferencing */ + /// Construct a new cursor + c4_Cursor (c4_Sequence&, int); + + /// Dereference this cursor to "almost" a row + c4_RowRef operator* () const; + + /// This is the same as *(cursor + offset) + c4_RowRef operator[] (int) const; + +/* Stepping the iterator forwards / backwards */ + /// Pre-increment the cursor + c4_Cursor& operator++ (); + /// Post-increment the cursor + c4_Cursor operator++ (int); + /// Pre-decrement the cursor + c4_Cursor& operator-- (); + /// Post-decrement the cursor + c4_Cursor operator-- (int); + + /// Advance by a given offset + c4_Cursor& operator+= (int); + /// Back up by a given offset + c4_Cursor& operator-= (int); + + /// Subtract a specified offset + c4_Cursor operator- (int) const; + /// Return the distance between two cursors + int operator- (c4_Cursor) const; + + /// Add specified offset + friend c4_Cursor operator+ (c4_Cursor, int); + /// Add specified offset to cursor + friend c4_Cursor operator+ (int, c4_Cursor); + +/* Comparing row positions */ + /// Return true if both cursors are equal + friend bool operator== (c4_Cursor, c4_Cursor); + /// Return true if both cursors are not equal + friend bool operator!= (c4_Cursor, c4_Cursor); + /// True if first cursor is less than second cursor + friend bool operator< (c4_Cursor, c4_Cursor); + /// True if first cursor is greater than second cursor + friend bool operator> (c4_Cursor, c4_Cursor); + /// True if first cursor is less or equal to second cursor + friend bool operator<= (c4_Cursor, c4_Cursor); + /// True if first cursor is greater or equal to second cursor + friend bool operator>= (c4_Cursor, c4_Cursor); + +/* Comparing row contents */ + /// Return true if the contents of both rows are equal + friend bool operator== (const c4_RowRef&, const c4_RowRef&); + /// Return true if the contents of both rows are not equal + friend bool operator!= (const c4_RowRef&, const c4_RowRef&); + /// True if first row is less than second row + friend bool operator< (const c4_RowRef&, const c4_RowRef&); + /// True if first row is greater than second row + friend bool operator> (const c4_RowRef&, const c4_RowRef&); + /// True if first row is less or equal to second row + friend bool operator<= (const c4_RowRef&, const c4_RowRef&); + /// True if first row is greater or equal to second row + friend bool operator>= (const c4_RowRef&, const c4_RowRef&); +}; + +//--------------------------------------------------------------------------- + +class c4_RowRef +{ + /// A row reference is a cursor in disguise + c4_Cursor _cursor; + +public: +/* General operations */ + /// Assign the value of another row to this one + c4_RowRef operator= (const c4_RowRef&); + /// Return the cursor associated to this row + c4_Cursor operator& () const; + /// Return the underlying container view + c4_View Container() const; + +protected: + /// Constructor, not for general use + c4_RowRef (c4_Cursor); + + friend class c4_Cursor; + friend class c4_Row; +}; + +//--------------------------------------------------------------------------- +/// An entry in a collection with copy semantics. +// +// Rows can exist by themselves and as contents of views. Row assignment +// implies that a copy of the contents of the originating row is made. +// +// A row is implemented as an unattached view with exactly one element. + +class c4_Row : public c4_RowRef +{ +public: + /// Construct a row with no properties + c4_Row (); + /// Construct a row from another one + c4_Row (const c4_Row&); + /// Construct a row copy from a row reference + c4_Row (const c4_RowRef&); + /// Destructor + ~c4_Row (); + + /// Assign a copy of another row to this one + c4_Row& operator= (const c4_Row&); + /// Copy another row to this one + c4_Row& operator= (const c4_RowRef&); + + /// Add all properties and values into this row + void ConcatRow(const c4_RowRef&); + /// Return a new row which is the concatenation of two others + friend c4_Row operator+ (const c4_RowRef&, const c4_RowRef&); + +private: + static c4_Cursor Allocate(); + static void Release(c4_Cursor); +}; + +//--------------------------------------------------------------------------- + +class c4_Bytes +{ + union { + t4_byte _buffer [16]; + double _aligner; // on a Sparc, the int below wasn't enough... + }; + + t4_byte* _contents; + int _size; + bool _copy; + +public: + c4_Bytes (); + c4_Bytes (const void*, int); + c4_Bytes (const void*, int, bool); + c4_Bytes (const c4_Bytes&); + ~c4_Bytes (); + + c4_Bytes& operator= (const c4_Bytes&); + void Swap(c4_Bytes&); + + int Size() const; + const t4_byte* Contents() const; + + t4_byte* SetBuffer(int); + t4_byte* SetBufferClear(int); + + friend bool operator== (const c4_Bytes&, const c4_Bytes&); + friend bool operator!= (const c4_Bytes&, const c4_Bytes&); + +private: + void _MakeCopy(); + void _LoseCopy(); +}; + +//--------------------------------------------------------------------------- + +class c4_Storage : public c4_View +{ +public: + /// Construct streaming-only storage object + c4_Storage (); + /// Construct a storage using the specified strategy handler + c4_Storage (c4_Strategy&, bool =false, int =1); + /// Construct a storage object, keeping the current structure + c4_Storage (const char*, int); + /// Reconstruct a storage object from a suitable view + c4_Storage (const c4_View&); + /// Destructor, usually closes file, but does not commit by default + ~c4_Storage (); + + void SetStructure(const char*); + bool AutoCommit(bool =true); + c4_Strategy& Strategy() const; + const char* Description(const char* =0); + + bool SetAside(c4_Storage&); + c4_Storage* GetAside() const; + + bool Commit(bool =false); + bool Rollback(bool =false); + + c4_ViewRef View(const char*); + c4_View GetAs(const char*); + + bool LoadFrom(c4_Stream&); + void SaveTo(c4_Stream&); + + //DROPPED: c4_Storage (const char* filename_, const char* description_); + //DROPPED: c4_View Store(const char* name_, const c4_View& view_); + //DROPPED: c4_HandlerSeq& RootTable() const; + //DROPPED: c4_RowRef xContents() const; + +private: + void Initialize(c4_Strategy&, bool, int); +}; + +//--------------------------------------------------------------------------- + +class c4_Property +{ + short _id; + char _type; + +public: + /// Construct a new property with the give type and id + c4_Property (char, int); + /// Construct a new property with the give type and name + c4_Property (char, const char*); + ~c4_Property (); + + c4_Property (const c4_Property&); + void operator= (const c4_Property&); + + const char* Name() const; + char Type() const; + + int GetId() const; + + c4_Reference operator() (const c4_RowRef&) const; + + void Refs(int) const; + + c4_View operator, (const c4_Property&) const; + + static void CleanupInternalData(); +}; + + /// Integer properties. +class c4_IntProp : public c4_Property +{ +public: + /// Construct a new property + c4_IntProp (const char*); + /// Destructor + ~c4_IntProp (); + + /// Get or set an integer property in a row + c4_IntRef operator() (const c4_RowRef&) const; + /// Get an integer property in a row + t4_i32 Get(const c4_RowRef&) const; + /// Set an integer property in a row + void Set(const c4_RowRef&, t4_i32) const; + + /// Creates a row with one integer, shorthand for AsRow. + c4_Row operator[] (t4_i32) const; + /// Creates a row with one integer. + c4_Row AsRow(t4_i32) const; +}; + +#if !q4_TINY + + /// Long int properties. +class c4_LongProp : public c4_Property +{ +public: + /// Construct a new property + c4_LongProp (const char*); + /// Destructor + ~c4_LongProp (); + + /// Get or set a long int property in a row + c4_LongRef operator() (const c4_RowRef&) const; + /// Get a long int property in a row + t4_i64 Get(const c4_RowRef&) const; + /// Set a long int property in a row + void Set(const c4_RowRef&, t4_i64) const; + + /// Creates a row with one long int, shorthand for AsRow. + c4_Row operator[] (t4_i64) const; + /// Creates a row with one long int. + c4_Row AsRow(t4_i64) const; +}; + + /// Floating point properties. +class c4_FloatProp : public c4_Property +{ +public: + /// Construct a new property + c4_FloatProp (const char*); + /// Destructor + ~c4_FloatProp (); + + /// Get or set a floating point property in a row + c4_FloatRef operator() (const c4_RowRef&) const; + /// Get a floating point property in a row + double Get(const c4_RowRef&) const; + /// Set a floating point property in a row + void Set(const c4_RowRef&, double) const; + + /// Create a row with one floating point value, shorthand for AsRow + c4_Row operator[] (double) const; + /// Create a row with one floating point value + c4_Row AsRow(double) const; +}; + + /// Double precision properties. +class c4_DoubleProp : public c4_Property +{ +public: + /// Construct a new property. + c4_DoubleProp (const char*); + /// Destructor + ~c4_DoubleProp (); + + /// Get or set a double precision property in a row + c4_DoubleRef operator() (const c4_RowRef&) const; + /// Get a double precision property in a row + double Get(const c4_RowRef&) const; + /// Set a double precision property in a row + void Set(const c4_RowRef&, double) const; + + /// Create a row with one double precision value, shorthand for AsRow + c4_Row operator[] (double) const; + /// Create a row with one double precision value + c4_Row AsRow(double) const; +}; +#endif // !q4_TINY + + /// String properties. +class c4_StringProp : public c4_Property +{ +public: + /// Construct a new property + c4_StringProp (const char*); + /// Destructor + ~c4_StringProp (); + + /// Get or set a string property in a row + c4_StringRef operator() (const c4_RowRef&) const; + /// Get a string property in a row + const char* Get(const c4_RowRef&) const; + /// Set a string property in a row + void Set(const c4_RowRef&, const char*) const; + + /// Create a row with one string, shorthand for AsRow + c4_Row operator[] (const char*) const; + /// Create a row with one string + c4_Row AsRow(const char*) const; +}; + + /// Binary properties. +class c4_BytesProp : public c4_Property +{ +public: + /// Construct a new property + c4_BytesProp (const char*); + /// Destructor + ~c4_BytesProp (); + + /// Get or set a bytes property in a row + c4_BytesRef operator() (const c4_RowRef&) const; + /// Get a bytes property in a row + c4_Bytes Get(const c4_RowRef&) const; + /// Set a bytes property in a row + void Set(const c4_RowRef&, const c4_Bytes&) const; + + /// Create a row with one bytes object, shorthand for AsRow + c4_Row operator[] (const c4_Bytes&) const; + /// Create a row with one bytes object + c4_Row AsRow(const c4_Bytes&) const; +}; + + /// View properties. +class c4_ViewProp : public c4_Property +{ +public: + /// Construct a new property + c4_ViewProp (const char*); + /// Destructor + ~c4_ViewProp (); + + /// Get or set a view property in a row + c4_ViewRef operator() (const c4_RowRef&) const; + /// Get a view property in a row + c4_View Get(const c4_RowRef&) const; + /// Set a view property in a row + void Set(const c4_RowRef&, const c4_View&) const; + + /// Create a row with one view, shorthand for AsRow + c4_Row operator[] (const c4_View&) const; + /// Create a row with one view + c4_Row AsRow(const c4_View&) const; +}; + +//--------------------------------------------------------------------------- + +class c4_CustomViewer +{ +protected: + /// Constructor, must be overriden in derived class + c4_CustomViewer (); +public: + /// Destructor + virtual ~c4_CustomViewer (); + + /// Return the structure of this view (initialization, called once) + virtual c4_View GetTemplate() = 0; + /// Return the number of rows in this view + virtual int GetSize() = 0; + int Lookup(const c4_RowRef&, int&); + virtual int Lookup(c4_Cursor, int&); + /// Fetch one data item, return it as a generic data value + virtual bool GetItem(int, int, c4_Bytes&) = 0; + virtual bool SetItem(int, int, const c4_Bytes&); + bool InsertRows(int, const c4_RowRef&, int =1); + virtual bool InsertRows(int, c4_Cursor, int =1); + virtual bool RemoveRows(int, int =1); +}; + +//--------------------------------------------------------------------------- +/// A stream is a virtual helper class to serialize in binary form. + +class c4_Stream +{ +public: + virtual ~c4_Stream (); + + /// Fetch some bytes sequentially + virtual int Read(void*, int) = 0; + /// Store some bytes sequentially + virtual bool Write(const void*, int) = 0; +}; + +//--------------------------------------------------------------------------- +/// A strategy encapsulates code dealing with the I/O system interface. + +class c4_Strategy +{ +public: + c4_Strategy (); + virtual ~c4_Strategy (); + + virtual bool IsValid() const; + virtual int DataRead(t4_i32, void*, int); + virtual void DataWrite(t4_i32, const void*, int); + virtual void DataCommit(t4_i32); + virtual void ResetFileMapping(); + virtual t4_i32 FileSize(); + virtual t4_i32 FreshGeneration(); + + void SetBase(t4_i32); + t4_i32 EndOfData(t4_i32 =-1); + + /// True if the storage format is not native (default is false) + bool _bytesFlipped; + /// Error code of last failed I/O operation, zero if I/O was ok + int _failure; + /// First byte in file mapping, zero if not active + const t4_byte* _mapStart; + /// Number of bytes filled with active data + t4_i32 _dataSize; + /// All file positions are relative to this offset + t4_i32 _baseOffset; + /// The root position of the shallow tree walks + t4_i32 _rootPos; + /// The size of the root column + t4_i32 _rootLen; +}; + +//--------------------------------------------------------------------------- +/// A sequence is an abstract base class for views on ranges of records. +// +// Sequences represent arrays of rows (or indexed collections / tables). +// Insertion and removal of entries is allowed, but could take linear time. +// A reference count is maintained to decide when the object should go away. + +class c4_Sequence +{ + /// Reference count + int _refCount; + /// Pointer to dependency list, or null if nothing depends on this + c4_Dependencies* _dependencies; + +protected: + /// Optimization: cached property index + int _propertyLimit; + /// Optimization: property map for faster access + short* _propertyMap; // see c4_HandlerSeq::Reset() + /// allocated on first use by c4_Sequence::Buffer() + c4_Bytes* _tempBuf; + +public: +/* General */ + /// Abstract constructor + c4_Sequence (); + + virtual int Compare(int, c4_Cursor) const; + virtual bool RestrictSearch(c4_Cursor, int&, int&); + void SetAt(int, c4_Cursor); + virtual int RemapIndex(int, const c4_Sequence*) const; + +/* Reference counting */ + void IncRef(); + void DecRef(); + int NumRefs() const; + +/* Adding / removing rows */ + /// Return the current number of rows + virtual int NumRows() const = 0; + void Resize(int, int =-1); + + virtual void InsertAt(int, c4_Cursor, int =1); + virtual void RemoveAt(int, int =1); + virtual void Move(int, int); + +/* Properties */ + int NthPropId(int) const; + int PropIndex(int); + int PropIndex(const c4_Property&); + + /// Return the number of data handlers in this sequence + virtual int NumHandlers() const = 0; + /// Return a reference to the N-th handler in this sequence + virtual c4_Handler& NthHandler(int) const = 0; + /// Return the context of the N-th handler in this sequence + virtual const c4_Sequence* HandlerContext(int) const = 0; + /// Add the specified data handler to this sequence + virtual int AddHandler(c4_Handler*) = 0; + /// Create a handler of the appropriate type + virtual c4_Handler* CreateHandler(const c4_Property&) = 0; + + virtual const char* Description(); + +/* Element access */ + /// Return width of specified data item + virtual int ItemSize(int, int); + /// Retrieve one data item from this sequence + virtual bool Get(int, int, c4_Bytes&); + /// Store a data item into this sequence + virtual void Set(int, const c4_Property&, const c4_Bytes&); + +/* Dependency notification */ + void Attach(c4_Sequence*); + void Detach(c4_Sequence*); + /// Return a pointer to the dependencies, or null + c4_Dependencies* GetDependencies() const; + + virtual c4_Notifier* PreChange(c4_Notifier&); + virtual void PostChange(c4_Notifier&); + + const char* UseTempBuffer(const char*); + +protected: + virtual ~c4_Sequence (); + + void ClearCache(); + +public: //! for c4_Table::Sequence setup + virtual void SetNumRows(int) = 0; + virtual c4_Persist* Persist() const; + + c4_Bytes& Buffer(); + +private: + c4_Sequence (const c4_Sequence&); // not implemented + void operator= (const c4_Sequence&); // not implemented +}; + +//--------------------------------------------------------------------------- +/// A reference is used to get or set typed data, using derived classes. +// +// Objects of this class are only intended to be used as a temporary handle +// while getting and setting properties in a row. They are normally only +// constructed as result of function overload operators: "property (row)". + +class c4_Reference +{ +protected: + /// The cursor which points to the data + c4_Cursor _cursor; + /// The property associated to this reference + const c4_Property& _property; + +public: + /// Constructor + c4_Reference (const c4_RowRef&, const c4_Property&); + + /// Assignment of one data item + c4_Reference& operator= (const c4_Reference&); + + /// Return width of the referenced data item + int GetSize() const; + /// Retrieve the value of the referenced data item + bool GetData(c4_Bytes&) const; + /// Store a value into the referenced data item + void SetData(const c4_Bytes&) const; + + /// Return true if the contents of both references is equal + friend bool operator== (const c4_Reference&, const c4_Reference&); + /// Return true if the contents of both references is not equal + friend bool operator!= (const c4_Reference&, const c4_Reference&); + +private: + void operator& () const; // not implemented +}; + +//--------------------------------------------------------------------------- + + /// Used to get or set integer values. +class c4_IntRef : public c4_Reference +{ +public: + /// Constructor + c4_IntRef (const c4_Reference&); + /// Get the value as integer + operator t4_i32 () const; + /// Set the value to the specified integer + c4_IntRef& operator= (t4_i32); +}; + +#if !q4_TINY + + /// Used to get or set long int values. +class c4_LongRef : public c4_Reference +{ +public: + /// Constructor + c4_LongRef (const c4_Reference&); + /// Get the value as long int + operator t4_i64 () const; + /// Set the value to the specified long int + c4_LongRef& operator= (t4_i64); +}; + + /// Used to get or set floating point values. +class c4_FloatRef : public c4_Reference +{ +public: + /// Constructor + c4_FloatRef (const c4_Reference&); + /// Get the value as floating point + operator double () const; + /// Set the value to the specified floating point + c4_FloatRef& operator= (double); +}; + + /// Used to get or set double precision values. +class c4_DoubleRef : public c4_Reference +{ +public: + /// Constructor + c4_DoubleRef (const c4_Reference&); + /// Get the value as floating point + operator double () const; + /// Set the value to the specified floating point + c4_DoubleRef& operator= (double); +}; + +#endif // !q4_TINY + + /// Used to get or set binary object values. +class c4_BytesRef : public c4_Reference +{ +public: + /// Constructor + c4_BytesRef (const c4_Reference&); + /// Get the value as binary object + operator c4_Bytes () const; + /// Set the value to the specified binary object + c4_BytesRef& operator= (const c4_Bytes&); + + /// Fetch data from the memo field, up to end if length is zero + c4_Bytes Access(t4_i32, int =0) const; + /// Store data, resize by diff_ bytes, return true if successful + bool Modify(const c4_Bytes&, t4_i32, int =0) const; +}; + + /// Used to get or set string values. +class c4_StringRef : public c4_Reference +{ +public: + /// Constructor + c4_StringRef (const c4_Reference&); + /// Get the value as string + operator const char* () const; + /// Set the value to the specified string + c4_StringRef& operator= (const char*); +}; + + /// Used to get or set view values. +class c4_ViewRef : public c4_Reference +{ +public: + /// Constructor + c4_ViewRef (const c4_Reference&); + /// Get the value as view + operator c4_View () const; + /// Set the value to the specified view + c4_ViewRef& operator= (const c4_View&); +}; + +//--------------------------------------------------------------------------- +// Debug logging option, can generate log of changes for one/all properties + +#if q4_LOGPROPMODS +FILE* f4_LogPropMods(FILE* fp_, int propId_); +#else +#define f4_LogPropMods(a,b) 0 +#endif + +//--------------------------------------------------------------------------- + +#if q4_INLINE +#include "mk4.inl" +#endif + +//--------------------------------------------------------------------------- + +#endif // __MK4_H__ diff --git a/akregator/src/mk4storage/metakit/include/mk4.inl b/akregator/src/mk4storage/metakit/include/mk4.inl new file mode 100644 index 000000000..1c717a367 --- /dev/null +++ b/akregator/src/mk4storage/metakit/include/mk4.inl @@ -0,0 +1,874 @@ +// mk4.inl -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Public definitions which are usually inlined + */ + +///////////////////////////////////////////////////////////////////////////// +// Reordered inlines so they are always defined before their first use + +d4_inline c4_Cursor c4_RowRef::operator& () const +{ + return _cursor; +} + +/** Return a unique id for this property + * + * A property object in fact merely represents an entry in a globally + * maintained symbol table. Each property is assigned a unique id, + * which remains valid as long as some reference to that property + * exists. In general, property id's remain unique as long as the + * application runs. Do not store id's on file, since they are + * not guaranteed to remain the same across program invocations. + * All properties with the same name are given the same id. + */ +d4_inline int c4_Property::GetId() const +{ + return _id; +} + +////////////////////////////////////////////////////////////////////////////////// + +#if !q4_LONG64 && !defined (LONG_LONG) && !HAVE_LONG_LONG + +d4_inline bool operator== (const t4_i64 a_, const t4_i64 b_) +{ + return a_.l1 == b_.l1 && a_.l2 == b_.l2; +} + +d4_inline bool operator< (const t4_i64 a_, const t4_i64 b_) +{ + return a_.l2 < b_.l2 || a_.l2 == b_.l2 && a_.l2 < b_.l2; +} + +#endif + +////////////////////////////////////////////////////////////////////////////////// +// c4_View + +/// Returns the number of entries in this view. +d4_inline int c4_View::GetSize() const +{ + return _seq->NumRows(); +} + +/** Change the size of this view + * Since views act like dynamic arrays, you can quickly + * change their size. Increasing the size will append rows + * with zero/empty values, while decreasing it will delete + * the last rows. The growBy_ parameter is currently unused. + */ +d4_inline void c4_View::SetSize(int newSize_, int growBy_) +{ + _seq->Resize(newSize_, growBy_); +} + +/// Removes all entries (sets size to zero). +d4_inline void c4_View::RemoveAll() +{ + SetSize(0); +} + +/// Return a pointer to the persistence handler, or zero +d4_inline c4_Persist* c4_View::Persist() const +{ + return _seq->Persist(); +} + +/** + * Change the value of the specified entry. If the new value has + * other properties, these will be added to the underlying view. + * + * @param index_ the zero-based row index + * @param newElem_ the row to copy to this view + */ +d4_inline void c4_View::SetAt(int index_, const c4_RowRef& newElem_) +{ + _seq->SetAt(index_, &newElem_); +} + +/** + * Insert a copy of the contents of another view. This is identical to + * inserting the specified number of default entries and then setting + * each of them to the new element value passed as argument. + */ +d4_inline void c4_View::InsertAt( + int index_, ///< zero-based row index + const c4_RowRef& newElem_, ///< the value to insert + int count_ ///< number of copies to insert, must be > 0 + ) +{ + _seq->InsertAt(index_, &newElem_, count_); +} + +/** + * Remove entries starting at the given index. Entries which have + * other view references may cause these views to be deleted if their + * reference counts drop to zero because of this removal. + * + * @param index_ the zero-based row index + * @param count_ the number of entries to remove + */ +d4_inline void c4_View::RemoveAt(int index_, int count_) +{ + _seq->RemoveAt(index_, count_); +} + +/** Return the number of properties present in this view. + * @return A non-negative integer + */ +d4_inline int c4_View::NumProperties() const +{ + return _seq->NumHandlers(); +} + +/** Find the index of a property, given its id + * @param propId_ Unique id associated to a specific propoerty + * @return The index of the property, or -1 of it was not found + */ +d4_inline int c4_View::FindProperty(int propId_) +{ + return _seq->PropIndex(propId_); +} + + /// Return a decription if there is a fixed structure, else zero +d4_inline const char* c4_View::Description() const +{ + return _seq->Description(); +} + + /// Increase the reference count of the associated sequence +d4_inline void c4_View::_IncSeqRef() +{ + _seq->IncRef(); +} + + /// Decrease the reference count of the associated sequence +d4_inline void c4_View::_DecSeqRef() +{ + _seq->DecRef(); +} + +/// Destructor, decrements reference count +d4_inline c4_View::~c4_View () +{ + _DecSeqRef(); +} + + /// Return true if the contents of both views are equal +d4_inline bool operator== (const c4_View& a_, const c4_View& b_) +{ + return a_.GetSize() == b_.GetSize() && a_.Compare(b_) == 0; +} + + /// Return true if the contents of both views are not equal +d4_inline bool operator!= (const c4_View& a_, const c4_View& b_) +{ + return !(a_ == b_); +} + + /// True if first view is less than second view +d4_inline bool operator< (const c4_View& a_, const c4_View& b_) +{ + return a_.Compare(b_) < 0; +} + + /// True if first view is greater than second view +d4_inline bool operator> (const c4_View& a_, const c4_View& b_) +{ + return b_ < a_; +} + + /// True if first view is less or equal to second view +d4_inline bool operator<= (const c4_View& a_, const c4_View& b_) +{ + return !(b_ < a_); +} + + /// True if first view is greater or equal to second view +d4_inline bool operator>= (const c4_View& a_, const c4_View& b_) +{ + return !(a_ < b_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_Cursor + +/** Constructs a new cursor. + * + * Cursor cannot be created without an underlying view, but you could + * define a global "nullView" object and then initialize the cursor with + * "&nullView[0]". This works because cursors need not point to a valid row. + */ +d4_inline c4_Cursor::c4_Cursor (c4_Sequence& seq_, int index_) + : _seq (&seq_), _index (index_) +{ +} + +/// Pre-increments the cursor. +d4_inline c4_Cursor& c4_Cursor::operator++ () +{ + ++_index; + return *this; +} + +/// Post-increments the cursor. +d4_inline c4_Cursor c4_Cursor::operator++ (int) +{ + return c4_Cursor (*_seq, _index++); +} + +/// Pre-decrements the cursor. +d4_inline c4_Cursor& c4_Cursor::operator-- () +{ + --_index; + return *this; +} + +/// Post-decrements the cursor. +d4_inline c4_Cursor c4_Cursor::operator-- (int) +{ + return c4_Cursor (*_seq, _index--); +} + +/// Advances by a given offset. +d4_inline c4_Cursor& c4_Cursor::operator+= (int offset_) +{ + _index += offset_; + return *this; +} + +/// Backs up by a given offset. +d4_inline c4_Cursor& c4_Cursor::operator-= (int offset_) +{ + _index -= offset_; + return *this; +} + +/// Subtracts a specified offset. +d4_inline c4_Cursor c4_Cursor::operator- (int offset_) const +{ + return c4_Cursor (*_seq, _index - offset_); +} + +/// Returns the distance between two cursors. +d4_inline int c4_Cursor::operator- (c4_Cursor cursor_) const +{ + return _index - cursor_._index; +} + +/// Add a specified offset. +d4_inline c4_Cursor operator+ (c4_Cursor cursor_, int offset_) +{ + return c4_Cursor (*cursor_._seq, cursor_._index + offset_); +} + +/// Adds specified offset to cursor. +d4_inline c4_Cursor operator+ (int offset_, c4_Cursor cursor_) +{ + return cursor_ + offset_; +} + +d4_inline bool operator== (c4_Cursor a_, c4_Cursor b_) +{ + return a_._seq == b_._seq && a_._index == b_._index; +} + +d4_inline bool operator!= (c4_Cursor a_, c4_Cursor b_) +{ + return !(a_ == b_); +} + +d4_inline bool operator< (c4_Cursor a_, c4_Cursor b_) +{ + return a_._seq < b_._seq || + a_._seq == b_._seq && a_._index < b_._index; +} + +d4_inline bool operator> (c4_Cursor a_, c4_Cursor b_) +{ + return b_ < a_; +} + +d4_inline bool operator<= (c4_Cursor a_, c4_Cursor b_) +{ + return !(b_ < a_); +} + +d4_inline bool operator>= (c4_Cursor a_, c4_Cursor b_) +{ + return !(a_ < b_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_RowRef + +d4_inline c4_RowRef::c4_RowRef (c4_Cursor cursor_) + : _cursor (cursor_) +{ +} + +d4_inline c4_RowRef c4_RowRef::operator= (const c4_RowRef& rowRef_) +{ + if (_cursor != rowRef_._cursor) + _cursor._seq->SetAt(_cursor._index, &rowRef_); + + return *this; +} + +d4_inline c4_View c4_RowRef::Container() const +{ + return _cursor._seq; +} + +d4_inline bool operator== (const c4_RowRef& a_, const c4_RowRef& b_) +{ + return (&a_)._seq->Compare((&a_)._index, &b_) == 0; +} + +d4_inline bool operator!= (const c4_RowRef& a_, const c4_RowRef& b_) +{ + return !(a_ == b_); +} + +d4_inline bool operator< (const c4_RowRef& a_, const c4_RowRef& b_) +{ + // 25-5-1998: don't exchange a and b, this comparison is -not- symmetric + return (&a_)._seq->Compare((&a_)._index, &b_) < 0; +} + +d4_inline bool operator> (const c4_RowRef& a_, const c4_RowRef& b_) +{ + // 25-5-1998: don't exchange a and b, this comparison is -not- symmetric + return (&a_)._seq->Compare((&a_)._index, &b_) > 0; +} + +d4_inline bool operator<= (const c4_RowRef& a_, const c4_RowRef& b_) +{ + return !(a_ > b_); +} + +d4_inline bool operator>= (const c4_RowRef& a_, const c4_RowRef& b_) +{ + return !(a_ < b_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_Bytes + + /// Construct an empty binary object +d4_inline c4_Bytes::c4_Bytes () + : _size (0), _copy (false) +{ + _contents = 0; // moved out of intializers for DEC CXX 5.7 +} + + /// Construct an object with contents, no copy +d4_inline c4_Bytes::c4_Bytes (const void* buf_, int len_) + : _size (len_), _copy (false) +{ + _contents = (t4_byte*) buf_; // moved out of intializers for DEC CXX 5.7 +} + +/// Returns a pointer to the contents. +d4_inline const t4_byte* c4_Bytes::Contents() const +{ + return _contents; +} + +/// Returns the number of bytes of its contents. +d4_inline int c4_Bytes::Size() const +{ + return _size; +} + +d4_inline void c4_Bytes::_LoseCopy() +{ + if (_copy) + delete [] (char*) _contents; +} + +/// Returns true if the contents of both objects is not equal. +d4_inline bool operator!= (const c4_Bytes& a_, const c4_Bytes& b_) +{ + return !(a_ == b_); +} + +/// Destructor, if a copy was made, it will be released here. +d4_inline c4_Bytes::~c4_Bytes () +{ + _LoseCopy(); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_Reference + +d4_inline c4_Reference::c4_Reference (const c4_RowRef& rowRef_, + const c4_Property& prop_) + : _cursor (&rowRef_), _property (prop_) +{ +} + +d4_inline int c4_Reference::GetSize() const +{ + return _cursor._seq->ItemSize(_cursor._index, _property.GetId()); +} + +d4_inline bool c4_Reference::GetData(c4_Bytes& buf_) const +{ + return _cursor._seq->Get(_cursor._index, _property.GetId(), buf_); +} + +d4_inline void c4_Reference::SetData(const c4_Bytes& buf_) const +{ + _cursor._seq->Set(_cursor._index, _property, buf_); +} + +d4_inline bool operator!= (const c4_Reference& a_, const c4_Reference& b_) +{ + return !(a_ == b_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_IntRef + +d4_inline c4_IntRef::c4_IntRef (const c4_Reference& value_) + : c4_Reference (value_) +{ +} + +///////////////////////////////////////////////////////////////////////////// +#if !q4_TINY +///////////////////////////////////////////////////////////////////////////// +// c4_LongRef + +d4_inline c4_LongRef::c4_LongRef (const c4_Reference& value_) + : c4_Reference (value_) +{ +} + +///////////////////////////////////////////////////////////////////////////// +// c4_FloatRef + +d4_inline c4_FloatRef::c4_FloatRef (const c4_Reference& value_) + : c4_Reference (value_) +{ +} + +///////////////////////////////////////////////////////////////////////////// +// c4_DoubleRef + +d4_inline c4_DoubleRef::c4_DoubleRef (const c4_Reference& value_) + : c4_Reference (value_) +{ +} + +///////////////////////////////////////////////////////////////////////////// +#endif // !q4_TINY +///////////////////////////////////////////////////////////////////////////// +// c4_BytesRef + +d4_inline c4_BytesRef::c4_BytesRef (const c4_Reference& value_) + : c4_Reference (value_) +{ +} + +///////////////////////////////////////////////////////////////////////////// +// c4_StringRef + +d4_inline c4_StringRef::c4_StringRef (const c4_Reference& value_) + : c4_Reference (value_) +{ +} + +///////////////////////////////////////////////////////////////////////////// +// c4_ViewRef + +d4_inline c4_ViewRef::c4_ViewRef (const c4_Reference& value_) + : c4_Reference (value_) +{ +} + +///////////////////////////////////////////////////////////////////////////// +// c4_Property + +d4_inline c4_Property::c4_Property (char type_, int id_) + : _id ((short) id_), _type (type_) +{ +} + + /// Get or set this untyped property in a row +d4_inline c4_Reference c4_Property::operator() (const c4_RowRef& rowRef_) const +{ + return c4_Reference (rowRef_, *this); +} + + /// Return a view like the first, with a property appended to it +d4_inline c4_View c4_Property::operator, (const c4_Property& prop_) const +{ + return c4_View (*this), prop_; +} + + /// Return the type of this property +d4_inline char c4_Property::Type() const +{ + return _type; +} + +///////////////////////////////////////////////////////////////////////////// +// c4_IntProp + +d4_inline c4_IntProp::c4_IntProp (const char* name_) + : c4_Property ('I', name_) +{ +} + +d4_inline c4_IntProp::~c4_IntProp () +{ +} + +d4_inline c4_IntRef c4_IntProp::operator() (const c4_RowRef& rowRef_) const +{ + return c4_Reference (rowRef_, *this); +} + +d4_inline t4_i32 c4_IntProp::Get(const c4_RowRef& rowRef_) const +{ + return operator() (rowRef_); +} + +d4_inline void c4_IntProp::Set(const c4_RowRef& rowRef_, t4_i32 value_) const +{ + operator() (rowRef_) = value_; +} + +d4_inline c4_Row c4_IntProp::AsRow(t4_i32 value_) const +{ + c4_Row row; + operator() (row) = value_; + return row; +} + +d4_inline c4_Row c4_IntProp::operator[] (t4_i32 value_) const +{ + return AsRow(value_); +} + +///////////////////////////////////////////////////////////////////////////// +#if !q4_TINY +///////////////////////////////////////////////////////////////////////////// +// c4_LongProp + +d4_inline c4_LongProp::c4_LongProp (const char* name_) + : c4_Property ('L', name_) +{ +} + +d4_inline c4_LongProp::~c4_LongProp () +{ +} + +d4_inline c4_LongRef c4_LongProp::operator() (const c4_RowRef& rowRef_) const +{ + return c4_Reference (rowRef_, *this); +} + +d4_inline t4_i64 c4_LongProp::Get(const c4_RowRef& rowRef_) const +{ + return operator() (rowRef_); +} + +d4_inline void c4_LongProp::Set(const c4_RowRef& rowRef_, t4_i64 value_) const +{ + operator() (rowRef_) = value_; +} + +d4_inline c4_Row c4_LongProp::AsRow(t4_i64 value_) const +{ + c4_Row row; + operator() (row) = value_; + return row; +} + +d4_inline c4_Row c4_LongProp::operator[] (t4_i64 value_) const +{ + return AsRow(value_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_FloatProp + +d4_inline c4_FloatProp::c4_FloatProp (const char* name_) + : c4_Property ('F', name_) +{ +} + +d4_inline c4_FloatProp::~c4_FloatProp () +{ +} + +d4_inline c4_FloatRef c4_FloatProp::operator() (const c4_RowRef& rowRef_) const +{ + return c4_Reference (rowRef_, *this); +} + +d4_inline double c4_FloatProp::Get(const c4_RowRef& rowRef_) const +{ + return operator() (rowRef_); +} + +d4_inline void c4_FloatProp::Set(const c4_RowRef& rowRef_, double value_) const +{ + operator() (rowRef_) = value_; +} + +d4_inline c4_Row c4_FloatProp::AsRow(double value_) const +{ + c4_Row row; + operator() (row) = value_; + return row; +} + +d4_inline c4_Row c4_FloatProp::operator[] (double value_) const +{ + return AsRow(value_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_DoubleProp + +d4_inline c4_DoubleProp::c4_DoubleProp (const char* name_) + : c4_Property ('D', name_) +{ +} + +d4_inline c4_DoubleProp::~c4_DoubleProp () +{ +} + +d4_inline c4_DoubleRef c4_DoubleProp::operator() (const c4_RowRef& rowRef_) const +{ + return c4_Reference (rowRef_, *this); +} + +d4_inline double c4_DoubleProp::Get(const c4_RowRef& rowRef_) const +{ + return operator() (rowRef_); +} + +d4_inline void c4_DoubleProp::Set(const c4_RowRef& rowRef_, double value_) const +{ + operator() (rowRef_) = value_; +} + +d4_inline c4_Row c4_DoubleProp::AsRow(double value_) const +{ + c4_Row row; + operator() (row) = value_; + return row; +} + +d4_inline c4_Row c4_DoubleProp::operator[] (double value_) const +{ + return AsRow(value_); +} + +///////////////////////////////////////////////////////////////////////////// +#endif // !q4_TINY +///////////////////////////////////////////////////////////////////////////// +// c4_BytesProp + +d4_inline c4_BytesProp::c4_BytesProp (const char* name_) + : c4_Property ('B', name_) +{ +} + +d4_inline c4_BytesProp::~c4_BytesProp () +{ +} + +d4_inline c4_BytesRef c4_BytesProp::operator() (const c4_RowRef& rowRef_) const +{ + return c4_Reference (rowRef_, *this); +} + +d4_inline c4_Bytes c4_BytesProp::Get(const c4_RowRef& rowRef_) const +{ + return operator() (rowRef_); +} + +d4_inline void c4_BytesProp::Set(const c4_RowRef& rowRef_, const c4_Bytes& value_) const +{ + operator() (rowRef_) = value_; +} + +d4_inline c4_Row c4_BytesProp::AsRow(const c4_Bytes& value_) const +{ + c4_Row row; + operator() (row) = value_; + return row; +} + +d4_inline c4_Row c4_BytesProp::operator[] (const c4_Bytes& value_) const +{ + return AsRow(value_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_StringProp + +d4_inline c4_StringProp::c4_StringProp (const char* name_) + : c4_Property ('S', name_) +{ +} + +d4_inline c4_StringProp::~c4_StringProp () +{ +} + +d4_inline c4_StringRef c4_StringProp::operator() (const c4_RowRef& rowRef_) const +{ + return c4_Reference (rowRef_, *this); +} + +d4_inline const char* c4_StringProp::Get(const c4_RowRef& rowRef_) const +{ + return operator() (rowRef_); +} + +d4_inline void c4_StringProp::Set(const c4_RowRef& rowRef_, const char* value_) const +{ + operator() (rowRef_) = value_; +} + +d4_inline c4_Row c4_StringProp::AsRow(const char* value_) const +{ + c4_Row row; + operator() (row) = value_; + return row; +} + +d4_inline c4_Row c4_StringProp::operator[] (const char* value_) const +{ + return AsRow(value_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_ViewProp + +d4_inline c4_ViewProp::c4_ViewProp (const char* name_) + : c4_Property ('V', name_) +{ +} + +d4_inline c4_ViewProp::~c4_ViewProp () +{ +} + +d4_inline c4_ViewRef c4_ViewProp::operator() (const c4_RowRef& rowRef_) const +{ + return c4_Reference (rowRef_, *this); +} + +d4_inline c4_View c4_ViewProp::Get(const c4_RowRef& rowRef_) const +{ + return operator() (rowRef_); +} + +d4_inline void c4_ViewProp::Set(const c4_RowRef& rowRef_, const c4_View& value_) const +{ + operator() (rowRef_) = value_; +} + +d4_inline c4_Row c4_ViewProp::AsRow(const c4_View& value_) const +{ + c4_Row row; + operator() (row) = value_; + return row; +} + +d4_inline c4_Row c4_ViewProp::operator[] (const c4_View& value_) const +{ + return AsRow(value_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_Strategy + + /// True if we can do I/O with this object +d4_inline bool c4_Strategy::IsValid() const +{ + return false; +} + +///////////////////////////////////////////////////////////////////////////// +// c4_CustomViewer + +d4_inline c4_CustomViewer::c4_CustomViewer() +{ +} + +d4_inline int c4_CustomViewer::Lookup(const c4_RowRef& r_, int& n_) +{ + return Lookup(&r_, n_); // c4_Cursor +} + +d4_inline bool c4_CustomViewer::InsertRows(int p_, const c4_RowRef& r_, int n_) +{ + return InsertRows(p_, &r_, n_); // c4_Cursor +} + +///////////////////////////////////////////////////////////////////////////// +// c4_Sequence + +d4_inline c4_Dependencies* c4_Sequence::GetDependencies() const +{ + return _dependencies; +} + +///////////////////////////////////////////////////////////////////////////// +// Reordered inlines so they are always used after their definition + +/// Dereferences this cursor to "almost" a row. +d4_inline c4_RowRef c4_Cursor::operator* () const +{ + return *(c4_Cursor*) this; // cast avoids a const problem with BCPP 4.52 +} + +/// This is the same as *(cursor + offset). +d4_inline c4_RowRef c4_Cursor::operator[] (int offset_) const +{ + return *(*this + offset_); +} + +/// Returns a reference to specified entry, for use as RHS or LHS +d4_inline c4_RowRef c4_View::GetAt(int index_) const +{ + return * c4_Cursor (*_seq, index_); +} + +/** Element access, shorthand for GetAt + * @return A reference to the specified row in the view. + * This reference can be used on either side of the assignment operator. + */ +d4_inline c4_RowRef c4_View::operator[] ( + int index_ ///< zero-based row index + ) const +{ + return GetAt(index_); +} + +/** Element access, shorthand for GetAt + * @return A reference to the specified row in the view. + * This reference can be used on either side of the assignment operator. + */ +d4_inline c4_RowRef c4_View::ElementAt( + int index_ ///< zero-based row index + ) +{ + return GetAt(index_); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/include/mk4dll.h b/akregator/src/mk4storage/metakit/include/mk4dll.h new file mode 100644 index 000000000..979971fac --- /dev/null +++ b/akregator/src/mk4storage/metakit/include/mk4dll.h @@ -0,0 +1,112 @@ +// mk4dll.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ +// +// Import declarations for DLLs + +#ifndef __MK4_H__ +#error This file is included by "mk4.h", it cannot be used standalone +#endif + +#ifndef d4_DLL +#ifdef _WIN32 +#ifdef _USRDLL +#define d4_DLL __declspec(dllexport) +#else +#define d4_DLL __declspec(dllimport) +#endif +#else +#define d4_DLL +#endif +#endif + +#ifndef d4_DLLSPEC +#ifdef _MSC_VER +#define d4_DLLSPEC(t) d4_DLL t +#else +#define d4_DLLSPEC(t) t d4_DLL +#endif +#endif + +///////////////////////////////////////////////////////////////////////////// +// Declarations in this file + + class d4_DLL c4_Bytes; + class d4_DLL c4_BytesProp; + class d4_DLL c4_BytesRef; + class d4_DLL c4_Cursor; + class d4_DLL c4_CustomViewer; + class d4_DLL c4_DoubleProp; + class d4_DLL c4_DoubleRef; + class d4_DLL c4_FileStrategy; + class d4_DLL c4_FileStream; + class d4_DLL c4_FloatProp; + class d4_DLL c4_FloatRef; + class d4_DLL c4_IntProp; + class d4_DLL c4_IntRef; + class d4_DLL c4_LongRef; + class d4_DLL c4_Property; + class d4_DLL c4_Reference; + class d4_DLL c4_Row; + class d4_DLL c4_RowRef; + class d4_DLL c4_Sequence; + class d4_DLL c4_Storage; + class d4_DLL c4_Strategy; + class d4_DLL c4_Stream; + class d4_DLL c4_StringProp; + class d4_DLL c4_StringRef; + class d4_DLL c4_View; + class d4_DLL c4_ViewProp; + class d4_DLL c4_ViewRef; + +#if !q4_MFC + class d4_DLL c4_String; +#endif + +///////////////////////////////////////////////////////////////////////////// + + d4_DLLSPEC(bool) operator== (const c4_View& a_, const c4_View& b_); + d4_DLLSPEC(bool) operator!= (const c4_View& a_, const c4_View& b_); + d4_DLLSPEC(bool) operator< (const c4_View& a_, const c4_View& b_); + d4_DLLSPEC(bool) operator> (const c4_View& a_, const c4_View& b_); + d4_DLLSPEC(bool) operator<= (const c4_View& a_, const c4_View& b_); + d4_DLLSPEC(bool) operator>= (const c4_View& a_, const c4_View& b_); + + d4_DLLSPEC(bool) operator== (c4_Cursor a_, c4_Cursor b_); + d4_DLLSPEC(bool) operator!= (c4_Cursor a_, c4_Cursor b_); + d4_DLLSPEC(bool) operator< (c4_Cursor a_, c4_Cursor b_); + d4_DLLSPEC(bool) operator> (c4_Cursor a_, c4_Cursor b_); + d4_DLLSPEC(bool) operator<= (c4_Cursor a_, c4_Cursor b_); + d4_DLLSPEC(bool) operator>= (c4_Cursor a_, c4_Cursor b_); + d4_DLLSPEC(c4_Cursor) operator+ (c4_Cursor cursor_, int offset_); + d4_DLLSPEC(c4_Cursor) operator+ (int offset_, c4_Cursor cursor_); + + d4_DLLSPEC(bool) operator== (const c4_RowRef& a_, const c4_RowRef& b_); + d4_DLLSPEC(bool) operator!= (const c4_RowRef& a_, const c4_RowRef& b_); + d4_DLLSPEC(bool) operator< (const c4_RowRef& a_, const c4_RowRef& b_); + d4_DLLSPEC(bool) operator> (const c4_RowRef& a_, const c4_RowRef& b_); + d4_DLLSPEC(bool) operator<= (const c4_RowRef& a_, const c4_RowRef& b_); + d4_DLLSPEC(bool) operator>= (const c4_RowRef& a_, const c4_RowRef& b_); + d4_DLLSPEC(c4_Row) operator+ (const c4_RowRef& a_, const c4_RowRef& b_); + + d4_DLLSPEC(bool) operator== (const c4_Bytes& a_, const c4_Bytes& b_); + d4_DLLSPEC(bool) operator!= (const c4_Bytes& a_, const c4_Bytes& b_); + + d4_DLLSPEC(bool) operator== (const c4_Reference&, const c4_Reference&); + d4_DLLSPEC(bool) operator!= (const c4_Reference&, const c4_Reference&); + +#if !q4_MFC + d4_DLLSPEC(c4_String) operator+ (const c4_String&, const c4_String&); + d4_DLLSPEC(c4_String) operator+ (const c4_String&, const char*); + d4_DLLSPEC(c4_String) operator+ (const char*, const c4_String&); + + d4_DLLSPEC(bool) operator== (const c4_String&, const c4_String&); + d4_DLLSPEC(bool) operator!= (const c4_String&, const c4_String&); + d4_DLLSPEC(bool) operator== (const c4_String& s1, const char* s2); + d4_DLLSPEC(bool) operator== (const char* s1, const c4_String& s2); + d4_DLLSPEC(bool) operator!= (const c4_String& s1, const char* s2); + d4_DLLSPEC(bool) operator!= (const char* s1, const c4_String& s2); +#endif + +///////////////////////////////////////////////////////////////////////////// + diff --git a/akregator/src/mk4storage/metakit/include/mk4io.h b/akregator/src/mk4storage/metakit/include/mk4io.h new file mode 100644 index 000000000..d70db9c52 --- /dev/null +++ b/akregator/src/mk4storage/metakit/include/mk4io.h @@ -0,0 +1,66 @@ +// mk4io.h -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Declaration of the file stream and strategy classes. + */ + +#ifndef __MK4IO_H__ +#define __MK4IO_H__ + +#include <stdio.h> + +///////////////////////////////////////////////////////////////////////////// +/// A file stream can be used to serialize using the stdio library. + +class c4_FileStream : public c4_Stream +{ +public: + c4_FileStream (FILE* stream_, bool owned_ =false); + virtual ~c4_FileStream (); + + virtual int Read(void* buffer_, int length_); + virtual bool Write(const void* buffer_, int length_); + + FILE* _stream; + bool _owned; +}; + +///////////////////////////////////////////////////////////////////////////// +/// A file strategy encapsulates code dealing with all file I/O. + +class c4_FileStrategy : public c4_Strategy +{ +public: + /// Construct a new strategy object + c4_FileStrategy (FILE* file_ =0); + virtual ~c4_FileStrategy (); + + /// True if we can do I/O with this object + virtual bool IsValid() const; + /// Open a data file by name + virtual bool DataOpen(const char* fileName_, int mode_); + /// Read a number of bytes + virtual int DataRead(t4_i32 pos_, void* buffer_, int length_); + /// Write a number of bytes, return true if successful + virtual void DataWrite(t4_i32 pos_, const void* buffer_, int length_); + /// Flush and truncate file + virtual void DataCommit(t4_i32 newSize_); + /// Support for memory-mapped files + virtual void ResetFileMapping(); + /// Report total size of the datafile + virtual t4_i32 FileSize(); + /// Return a good value to use as fresh generation counter + virtual t4_i32 FreshGeneration(); + +protected: + /// Pointer to file object + FILE* _file; + /// Pointer to same file object, if it must be deleted at end + FILE* _cleanup; +}; + +///////////////////////////////////////////////////////////////////////////// + +#endif // __MK4IO_H__ diff --git a/akregator/src/mk4storage/metakit/include/mk4str.h b/akregator/src/mk4storage/metakit/include/mk4str.h new file mode 100644 index 000000000..7124a29ea --- /dev/null +++ b/akregator/src/mk4storage/metakit/include/mk4str.h @@ -0,0 +1,181 @@ +// mk4str.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Declarations of the string package. + */ + +#ifndef __MK4STR_H__ +#define __MK4STR_H__ + +///////////////////////////////////////////////////////////////////////////// + +#if q4_MFC // Microsoft Foundation Classes + +#ifdef _WINDOWS +#include <afxwin.h> +#else +#include <afxcoll.h> +#endif + +#if _MSC_VER == 800 +// MSVC 1.52 thinks a typedef has no constructor, use define instead +#define c4_String CString +#elif _MSC_VER >= 1300 +// VC 7.0 does not like "class" (6-2-2002, Zhang Dehua) +typedef CString c4_String; +#else +typedef class CString c4_String; +#endif + +#elif q4_STD // STL and standard strings + +#include <string> + +#if !defined (d4_std) // the default is to use namespaces +#define d4_std std +#endif + + /// STL-based string class, modeled after the MFC version +class c4_String : public d4_std::string +{ + typedef d4_std::string string; + +public: + c4_String (); + c4_String (char ch, int nDup =1); + c4_String (const char* str); + c4_String (const void* ptr, int len); + c4_String (const d4_std::string& s); + c4_String (const c4_String& s); + ~c4_String (); + + const c4_String& operator= (const c4_String&); + + operator const char* () const; + + char operator[] (int i) const; + + friend c4_String operator+ (const c4_String&, const c4_String&); + friend c4_String operator+ (const c4_String&, const char*); + friend c4_String operator+ (const char*, const c4_String&); + + const c4_String& operator+= (const c4_String& s); + const c4_String& operator+= (const char* s); + + int GetLength() const; + bool IsEmpty() const; + void Empty(); + + c4_String Mid(int nFirst, int nCount =25000) const; + c4_String Left(int nCount) const; + c4_String Right(int nCount) const; + + int Compare(const char* str) const; + int CompareNoCase(const char* str) const; + + bool operator< (const c4_String& str) const; + + int Find(char ch) const; + int ReverseFind(char ch) const; + int FindOneOf(const char* set) const; + + int Find(const char* sub) const; + + c4_String SpanIncluding(const char* set) const; + c4_String SpanExcluding(const char* set) const; +}; + +bool operator== (const c4_String&, const c4_String&); +bool operator!= (const c4_String&, const c4_String&); + +d4_inline bool operator== (const c4_String& s1, const char* s2); +d4_inline bool operator== (const char* s1, const c4_String& s2); + +d4_inline bool operator!= (const c4_String& s1, const char* s2); +d4_inline bool operator!= (const char* s1, const c4_String& s2); + +#else // Universal replacement classes + + /// An efficient string class, modeled after the MFC version +class c4_String +{ +public: + c4_String (); + c4_String (char ch, int nDup =1); + c4_String (const char* str); + c4_String (const unsigned char* str); + c4_String (const void* ptr, int len); + c4_String (const c4_String& s); + ~c4_String (); + + const c4_String& operator= (const c4_String&); + + operator const char* () const; + operator const unsigned char* () const; + + char operator[] (int i) const; + + friend c4_String operator+ (const c4_String&, const c4_String&); + friend c4_String operator+ (const c4_String&, const char*); + friend c4_String operator+ (const char*, const c4_String&); +// friend c4_String operator+ (const c4_String&, char); +// friend c4_String operator+ (char, const c4_String&); + + const c4_String& operator+= (const c4_String& s); + const c4_String& operator+= (const char* s); +// const c4_String& operator+= (char c); + + int GetLength() const; + bool IsEmpty() const; + void Empty(); // free up the data + + c4_String Mid(int nFirst, int nCount =25000) const; + c4_String Left(int nCount) const; // first nCount chars + c4_String Right(int nCount) const; // last nCount chars + + friend bool operator== (const c4_String&, const c4_String&); // memcmp + friend bool operator!= (const c4_String&, const c4_String&); // opposite + + // only defined for strings having no zero bytes inside them: + + int Compare(const char* str) const; // strcmp + int CompareNoCase(const char* str) const; // stricmp + + bool operator< (const c4_String& str) const; + + int Find(char ch) const; // strchr + int ReverseFind(char ch) const; // strrchr + int FindOneOf(const char* set) const; // strpbrk + + int Find(const char* sub) const; // strstr + + c4_String SpanIncluding(const char* set) const; // strspn + c4_String SpanExcluding(const char* set) const; // strcspn + +private: + void Init(const void* p, int n); + const char* Data() const; + int FullLength() const; + + unsigned char* _value; +}; + +bool operator== (const c4_String& s1, const char* s2); +bool operator== (const char* s1, const c4_String& s2); + +bool operator!= (const c4_String& s1, const char* s2); +bool operator!= (const char* s1, const c4_String& s2); + +#endif // q4_MFC elif q4_STD else q4_UNIV + +///////////////////////////////////////////////////////////////////////////// + +#if q4_INLINE +#include "mk4str.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + +#endif // __MK4STR_H__ diff --git a/akregator/src/mk4storage/metakit/include/mk4str.inl b/akregator/src/mk4storage/metakit/include/mk4str.inl new file mode 100644 index 000000000..4f95fa514 --- /dev/null +++ b/akregator/src/mk4storage/metakit/include/mk4str.inl @@ -0,0 +1,299 @@ +// mk4str.inl -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Members of the string package which are usually inlined + */ + +///////////////////////////////////////////////////////////////////////////// +// c4_String + +#if q4_MFC // Microsoft Foundation Classes + +#elif q4_STD // STL and standard strings + +/// Construct empty string +d4_inline c4_String::c4_String () +{ +} + +d4_inline c4_String::c4_String (char ch_, int nDup_) + : string (nDup_, ch_) +{ +} + +d4_inline c4_String::c4_String (const char* str_) + : string (str_) +{ +} + +d4_inline c4_String::c4_String (const void* ptr_, int len_) + : string ((const char*) ptr_, len_) +{ +} + +d4_inline c4_String::c4_String (const d4_std::string& s_) + : string (s_) +{ +} + +d4_inline c4_String::c4_String (const c4_String& s_) + : string (s_) +{ +} + +d4_inline c4_String::~c4_String () +{ +} + +d4_inline const c4_String& c4_String::operator= (const c4_String& s_) +{ + *(string*) this = s_; + return *this; +} + +d4_inline c4_String::operator const char* () const +{ + return c_str(); +} + +d4_inline char c4_String::operator[] (int i) const +{ + return at(i); +} + +d4_inline c4_String operator+ (const c4_String& a_, const c4_String& b_) +{ + return (d4_std::string) a_ + (d4_std::string) b_; +} + +d4_inline c4_String operator+ (const c4_String& a_, const char* b_) +{ + return (d4_std::string) a_ + (d4_std::string) b_; +} + +d4_inline c4_String operator+ (const char* a_, const c4_String& b_) +{ + return (d4_std::string) a_ + (d4_std::string) b_; +} + +d4_inline const c4_String& c4_String::operator+= (const c4_String& s_) +{ + *(string*) this += s_; + return *this; +} + +d4_inline const c4_String& c4_String::operator+= (const char* s_) +{ + *(string*) this += s_; + return *this; +} + +d4_inline int c4_String::GetLength() const +{ + return length(); +} + +d4_inline bool c4_String::IsEmpty() const +{ + return empty(); +} + +d4_inline void c4_String::Empty() +{ + erase(); +} + +d4_inline c4_String c4_String::Left(int nCount_) const +{ + if (nCount_ > length()) + nCount_ = length(); + return substr(0, nCount_); +} + +d4_inline c4_String c4_String::Right(int nCount_) const +{ + if (nCount_ > length()) + nCount_ = length(); + return substr(length() - nCount_, nCount_); +} + +d4_inline int c4_String::Compare(const char* str_) const +{ + return compare(str_); +} + +d4_inline bool c4_String::operator< (const c4_String& str_) const +{ + return compare(str_) < 0; +} + +d4_inline int c4_String::Find(char ch_) const +{ + return find(ch_); +} + +d4_inline int c4_String::ReverseFind(char ch_) const +{ + return rfind(ch_); +} + +d4_inline int c4_String::FindOneOf(const char* set_) const +{ + return find_first_of(set_); +} + +d4_inline int c4_String::Find(const char* sub_) const +{ + return find(sub_); +} + +d4_inline c4_String c4_String::SpanIncluding(const char* set_) const +{ + return substr(0, find_first_not_of(set_)); +} + +d4_inline c4_String c4_String::SpanExcluding(const char* set_) const +{ + return substr(0, find_first_of(set_)); +} + +d4_inline bool operator== (const c4_String& a_, const c4_String& b_) +{ + return (d4_std::string) a_ == (d4_std::string) b_; +} + +d4_inline bool operator!= (const c4_String& a_, const c4_String& b_) +{ + return (d4_std::string) a_ != (d4_std::string) b_; +} + +d4_inline bool operator== (const c4_String& a_, const char* b_) +{ + return (d4_std::string) a_ == (d4_std::string) b_; +} + +d4_inline bool operator== (const char* a_, const c4_String& b_) +{ + return (d4_std::string) a_ == (d4_std::string) b_; +} + +d4_inline bool operator!= (const c4_String& a_, const char* b_) +{ + return (d4_std::string) a_ != (d4_std::string) b_; +} + +d4_inline bool operator!= (const char* a_, const c4_String& b_) +{ + return (d4_std::string) a_ != (d4_std::string) b_; +} + +#else // Universal replacement classes + +/// Construct empty string +d4_inline c4_String::c4_String () +{ + Init(0, 0); +} + +/// Construct string from Pascal-style <count,chars...> data +d4_inline c4_String::c4_String (const unsigned char* ptr) +{ + Init(ptr + 1, ptr ? *ptr : 0); +} + +/// Construct string from a specified area in memory +d4_inline c4_String::c4_String (const void* ptr, int len) +{ + Init(ptr, len); +} + +d4_inline const c4_String& c4_String::operator+= (const c4_String& s) +{ + return *this = *this + s; +} + +d4_inline const c4_String& c4_String::operator+= (const char* s) +{ + return *this += (c4_String) s; +} + +d4_inline const char* c4_String::Data() const +{ + return (const char*) (_value + 2); +} + +d4_inline c4_String::operator const char* () const +{ + return Data(); +} + +d4_inline c4_String::operator const unsigned char* () const +{ + return (unsigned char*) Data() - 1; +} + +d4_inline char c4_String::operator[] (int i) const +{ + return Data()[i]; +} + +d4_inline int c4_String::GetLength() const +{ + return _value[1] != 255 ? _value[1] : FullLength(); +} + +d4_inline bool c4_String::IsEmpty() const +{ + return GetLength() == 0; +} + +d4_inline void c4_String::Empty() +{ + *this = ""; +} + +d4_inline bool c4_String::operator< (const c4_String& a) const +{ + return Compare(a) < 0; +} + +d4_inline c4_String operator+ (const char* a, const c4_String& b) +{ + return (c4_String) a + b; +} + +d4_inline c4_String operator+ (const c4_String& a, const char* b) +{ + return a + (c4_String) b; +} + +d4_inline bool operator== (const char* a, const c4_String& b) +{ + return b.Compare(a) == 0; +} + +d4_inline bool operator== (const c4_String& a, const char* b) +{ + return a.Compare(b) == 0; +} + +d4_inline bool operator!= (const c4_String& a, const c4_String& b) +{ + return !(a == b); +} + +d4_inline bool operator!= (const char* a, const c4_String& b) +{ + return b.Compare(a) != 0; +} + +d4_inline bool operator!= (const c4_String& a, const char* b) +{ + return a.Compare(b) != 0; +} + +#endif // q4_UNIV + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/Makefile.am b/akregator/src/mk4storage/metakit/src/Makefile.am new file mode 100644 index 000000000..e428fe930 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/Makefile.am @@ -0,0 +1,10 @@ +INCLUDES = -I$(srcdir)/../include + +noinst_LTLIBRARIES = libmetakitlocal.la + +noinst_HEADERS = borc.h column.h column.inl custom.h derived.h field.h field.inl format.h gnuc.h handler.h handler.inl header.h mfc.h \ + msvc.h mwcw.h persist.h remap.h std.h store.h store.inl univ.h univ.inl win.h + +libmetakitlocal_la_SOURCES = column.cpp custom.cpp derived.cpp field.cpp fileio.cpp format.cpp handler.cpp persist.cpp remap.cpp std.cpp store.cpp \ + string.cpp table.cpp univ.cpp view.cpp viewx.cpp + diff --git a/akregator/src/mk4storage/metakit/src/borc.h b/akregator/src/mk4storage/metakit/src/borc.h new file mode 100644 index 000000000..2b881fc90 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/borc.h @@ -0,0 +1,33 @@ +// borc.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Configuration header for Borland C++ + */ + +#define q4_BORC 1 + + // get rid of several common warning messages +#if !q4_STRICT +#pragma warn -aus // 'identifier' is assigned a value that is never used +#pragma warn -par // Parameter 'parameter' is never used. +#pragma warn -sig // Conversion may lose significant digits +#pragma warn -use // 'identifier' declared but never used +#endif + +#if __BORLANDC__ >= 0x500 +#define q4_BOOL 1 // supports the bool datatype + // undo previous defaults, because q4_BOOL is not set early enough +#undef false +#undef true +#undef bool +#endif + +#if !defined (q4_EXPORT) +#define q4_EXPORT 1 // requires export/import specifiers +#endif + +#if defined (__MT__) +#define q4_MULTI 1 // uses multi-threading +#endif diff --git a/akregator/src/mk4storage/metakit/src/column.cpp b/akregator/src/mk4storage/metakit/src/column.cpp new file mode 100644 index 000000000..2d191c645 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/column.cpp @@ -0,0 +1,1533 @@ +// column.cpp -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Implements c4_Column, c4_ColOfInts, and c4_ColIter + */ + +#include "header.h" +#include "column.h" +#include "persist.h" + +#if !q4_INLINE +#include "column.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + +#if !HAVE_MEMMOVE && !HAVE_BCOPY + // in case we have no library memmove, or one that can't handle overlap + + void f4_memmove (void* to_, const void* from_, int n_) + { + char* to = (char*) to_; + const char* from = (const char*) from_; + + if (to + n_ <= from || from + n_ <= to) + memcpy(to, from, n_); + else if (to < from) + while (--n_ >= 0) + *to++ = *from++; + else if (to > from) + while (--n_ >= 0) + to[n_] = from[n_]; + } +#endif + +///////////////////////////////////////////////////////////////////////////// +// c4_Column + +c4_Column::c4_Column (c4_Persist* persist_) + : _position (0), _size (0), _persist (persist_), _gap (0), + _slack (0), _dirty (false) +{ +} + +#if q4_CHECK + + // debugging version to verify that the internal data is consistent + void c4_Column::Validate() const + { + d4_assert(0 <= _slack && _slack < kSegMax); + + if (_segments.GetSize() == 0) + return; // ok, not initialized + + d4_assert(_gap <= _size); + + int n = fSegIndex(_size + _slack); + d4_assert(n == _segments.GetSize() - 1); + + t4_byte* p = (t4_byte*) _segments.GetAt(n); + + if (fSegRest(_size + _slack) == 0) + d4_assert(p == 0); + else + d4_assert(p != 0); + + while (--n >= 0) { + t4_byte* p = (t4_byte*) _segments.GetAt(n); + d4_assert(p != 0); + } + } + +#else + + // nothing, so inline this thing to avoid even the calling overhead + d4_inline void c4_Column::Validate() const + { + } + +#endif + +c4_Column::~c4_Column () +{ + Validate(); + ReleaseAllSegments(); + + // this is needed to remove this column from the cache + d4_assert(_slack == 0); + FinishSlack(); + + _slack = -1; // bad value in case we try to set up again (!) +} + +c4_Strategy& c4_Column::Strategy() const +{ + d4_assert(_persist != 0); + + return _persist->Strategy(); +} + +bool c4_Column::IsMapped() const +{ + return _position > 1 && _persist != 0 && Strategy()._mapStart != 0; +} + +bool c4_Column::UsesMap(const t4_byte* ptr_) const +{ + // the most common falsifying case is checked first + return _persist != 0 && ptr_ >= Strategy()._mapStart && + Strategy()._dataSize != 0 && // added 2003-05-08, thx V DeMarco + ptr_ - Strategy()._mapStart < Strategy()._dataSize; +} + +bool c4_Column::RequiresMap() const +{ + if (_persist != 0 && Strategy()._mapStart != 0) + for (int i = _segments.GetSize(); --i >= 0; ) + if (UsesMap((t4_byte*) _segments.GetAt(i))) + return true; + return false; +} + +void c4_Column::ReleaseSegment(int index_) +{ + t4_byte* p = (t4_byte*) _segments.GetAt(index_); + if (!UsesMap(p)) + delete [] p; +} + +void c4_Column::ReleaseAllSegments() +{ + //for (int i = 0; i < _segments.GetSize(); ++i) + for (int i = _segments.GetSize(); --i >= 0; ) + ReleaseSegment(i); // last one might be a null pointer + + _segments.SetSize(0); + + _gap = 0; + _slack = 0; + + if (_size == 0) + _position = 0; + + _dirty = false; +} + + //@func Define where data is on file, or setup buffers (opt cleared). +void c4_Column::SetLocation(t4_i32 pos_, t4_i32 size_) +{ + d4_assert(size_ > 0 || pos_ == 0); + + ReleaseAllSegments(); + + _position = pos_; + _size = size_; + + // There are two position settings: + // + // 0 = raw buffer, no file access + // >1 = file position from where data can be loaded on demand + + _dirty = pos_ == 0; +} + +void c4_Column::PullLocation(const t4_byte*& ptr_) +{ + d4_assert(_segments.GetSize() == 0); + + _size = PullValue(ptr_); + _position = 0; + if (_size > 0) { + _position = PullValue(ptr_); + if (_position > 0) { + d4_assert(_persist != 0); + _persist->OccupySpace(_position, _size); + } + } + + _dirty = false; +} + + //@func How many contiguous bytes are there at a specified position. +int c4_Column::AvailAt(t4_i32 offset_) const +{ + d4_assert(offset_ <= _size); + d4_assert(_gap <= _size); + + t4_i32 limit = _gap; + + if (offset_ >= _gap) { + offset_ += _slack; + limit = _size + _slack; + } + + int count = kSegMax - fSegRest(offset_); + if (offset_ + count > limit) + count = (int) (limit - offset_); + + // either some real data or it must be at the very end of all data + d4_assert(0 < count && count <= kSegMax || + count == 0 && offset_ == _size + _slack); + return count; +} + +void c4_Column::SetupSegments() +{ + d4_assert(_segments.GetSize() == 0); + d4_assert(_gap == 0); + d4_assert(_slack == 0); + + // The last entry in the _segments array is either a partial block + // or a null pointer, so calling "fSegIndex(_size)" is always allowed. + + int n = fSegIndex(_size) + 1; + _segments.SetSize(n); + + // treat last block differently if it is a partial entry + int last = n; + if (fSegRest(_size)) + --last; // this block is partial, size is 1 .. kSegMax-1 + else + --n; // the last block is left as a null pointer + + int id = -1; + if (_position < 0) { // special aside id, figure out the real position + d4_assert(_persist != 0); + id = ~_position; + _position = _persist->LookupAside(id); + d4_assert(_position >= 0); + } + + if (IsMapped()) { + // setup for mapped files is quick, just fill in the pointers + d4_assert(_position > 1); + d4_assert(_position + (n-1) * kSegMax <= Strategy()._dataSize); + const t4_byte* map = Strategy()._mapStart + _position; + + for (int i = 0; i < n; ++i) { + _segments.SetAt(i, (t4_byte*) map); // loses const + map += kSegMax; + } + } else { + int chunk = kSegMax; + t4_i32 pos = _position; + + // allocate buffers, load them if necessary + for (int i = 0; i < n; ++i) { + if (i == last) + chunk = fSegRest(_size); + + t4_byte* p = d4_new t4_byte [chunk]; + _segments.SetAt(i, p); + + if (_position > 0) { + d4_dbgdef(int n =) + Strategy().DataRead(pos, p, chunk); + d4_assert(n == chunk); + pos += chunk; + } + } + } + + if (id >= 0) { + d4_assert(_persist != 0); + _persist->ApplyAside(id, *this); + } + + Validate(); +} + + //@func Makes sure the requested data is in a modifiable buffer. +t4_byte* c4_Column::CopyNow(t4_i32 offset_) +{ + d4_assert(offset_ <= _size); + + _dirty = true; + + const t4_byte* ptr = LoadNow(offset_); + if (UsesMap(ptr)) { + if (offset_ >= _gap) + offset_ += _slack; + + // this will only force creation of a buffer + ptr = CopyData(offset_, offset_, 0); + d4_assert(!UsesMap(ptr)); + } + + return (t4_byte*) ptr; +} + + //@func Copies data, creating a buffer if needed. Must be in single segment. +t4_byte* c4_Column::CopyData(t4_i32 to_, t4_i32 from_, int count_) +{ + int i = fSegIndex(to_); + t4_byte* p = (t4_byte*) _segments.GetAt(i); + + if (UsesMap(p)) { + int n = kSegMax; + if (fSegOffset(i) + n > _size + _slack) + n = (int) (_size + _slack - fSegOffset(i)); + + d4_assert(n > 0); + + t4_byte* q = d4_new t4_byte [n]; + memcpy(q, p, n); // some copying can be avoided, overwritten below... + _segments.SetAt(i, q); + + p = q; + } + + p += fSegRest(to_); + + if (count_ > 0) { + d4_assert(fSegIndex(to_ + count_ - 1) == i); + + const t4_byte* src = (const t4_byte*) _segments.GetAt(fSegIndex(from_)); + d4_memmove(p, src + fSegRest(from_), count_); + } + + return p; +} + + /* + * Resizing a segmented vector can be a complicated operation. + * For now, simply making it work in all cases is the first priority. + * + * A major simplification - and good performance improvement - is caused + * by the trick of maintaining a "gap" in the data, which can be "moved" + * around to allow fast insertion as well as simple (delayed) deletion. + * + * The only complexity comes from the fact that the gap must end up being + * less than one full segment in size. Therefore, insertion and removal + * across segment boundaries needs to handle a variety of situations. + * + * Since complete segments can be inserted quickly, this approach avoids + * lots of copying when consecutive insertions/deletions are clustered. + * Even random changes move half as much (on average) as without a gap. + * + * The price is the overhead of up to one segment of empty space, and the + * complexity of this code (all the magic is within this c4_Column class). + */ + +void c4_Column::MoveGapUp(t4_i32 dest_) +{ + d4_assert(dest_ <= _size); + d4_assert(_gap < dest_); + d4_assert(_slack > 0); + + // forward loop to copy contents down, in little pieces if need be + while (_gap < dest_) { + int n = kSegMax - fSegRest(_gap); + t4_i32 curr = _gap + n; + if (curr > dest_) + curr = dest_; + + // copy to [_gap..curr), which is inside one segment + d4_assert(_gap < curr); + d4_assert(fSegIndex(_gap) == fSegIndex(curr - 1)); + + // copy from [_gap + _slack .. curr + _slack), of the same size + t4_i32 fromBeg = _gap + _slack; + t4_i32 fromEnd = curr + _slack; + + while (fromBeg < fromEnd) { + int k = kSegMax - fSegRest(fromBeg); + if (fromBeg + k > fromEnd) + k = (int) (fromEnd - fromBeg); + + d4_assert(k > 0); + + CopyData(_gap, fromBeg, k); + + _gap += k; + fromBeg += k; + } + + _gap = curr; + } + + d4_assert(_gap == dest_); +} + +void c4_Column::MoveGapDown(t4_i32 dest_) +{ + d4_assert(dest_ <= _size); + d4_assert(_gap > dest_); + d4_assert(_slack > 0); + + // reverse loop to copy contents up, in little pieces if need be + t4_i32 toEnd = _gap + _slack; + t4_i32 toBeg = dest_ + _slack; + + while (toEnd > toBeg) { + int n = fSegRest(toEnd); + t4_i32 curr = toEnd - (n ? n : kSegMax); + if (curr < toBeg) + curr = toBeg; + + // copy to [curr..toEnd), which is inside one segment + d4_assert(curr < toEnd); + d4_assert(fSegIndex(curr) == fSegIndex(toEnd - 1)); + + // copy from [fromBeg .. _gap), which has the same size + t4_i32 fromBeg = _gap - (toEnd - curr); + + while (_gap > fromBeg) { + int k = fSegRest(_gap); + if (k == 0) + k = kSegMax; + if (_gap - k < fromBeg) + k = (int) (_gap - fromBeg); + + d4_assert(k > 0); + + toEnd -= k; + _gap -= k; + + CopyData(toEnd, _gap, k); + } + } + + d4_assert(_gap == dest_); +} + +void c4_Column::MoveGapTo(t4_i32 pos_) +{ + d4_assert(pos_ <= _size); + + if (_slack == 0) // if there is no real gap, then just move it + _gap = pos_; + else if (_gap < pos_) // move the gap up, ie. some bytes down + MoveGapUp(pos_); + else if (_gap > pos_) // move the gap down, ie. some bytes up + if (_gap - pos_ > _size - _gap + fSegRest(pos_)) { + RemoveGap(); // it's faster to get rid of the gap instead + _gap = pos_; + } + else // normal case, move some bytes up + MoveGapDown(pos_); + + d4_assert(_gap == pos_); + + Validate(); +} + +void c4_Column::RemoveGap() +{ + if (_slack > 0) { + if (_gap < _size) + MoveGapUp(_size); + + d4_assert(_gap == _size); // the gap is now at the end + d4_assert(_slack < kSegMax); + + // Case 1: gap is at start of segment + // ================================== + // + // G G+S + // + // | | + // :----+xx: + // | | + // + // i i+1 (limit) + // + // Case 2: gap is inside segment + // ============================= + // + // G G+S + // + // | | + // :--+--+x: + // | | + // + // i i+1 (limit) + // + // Case 3: gap runs to end of segment + // ================================== + // + // G G+S + // + // | | + // :--+----:0000000: + // | | | + // + // i i+1 i+2 (limit) + // + // Case 4: gap is across two segments + // ================================== + // + // G G+S + // + // | | + // :--+----:-+xxxxx: + // | | | + // + // i i+1 i+2 (limit) + + int i = fSegIndex(_gap); + int n = fSegRest(_gap); + + if (n == 0) { // case 1 + ReleaseSegment(i); + _segments.SetAt(i, 0); + } else { + if (n + _slack > kSegMax) // case 4 + ReleaseSegment(i+1); + + // truncate rest of segment + t4_byte* p = d4_new t4_byte [n]; + memcpy(p, _segments.GetAt(i), n); + + ReleaseSegment(i); + _segments.SetAt(i, p); + _segments.SetSize(i + 1); + } + + _slack = 0; + } + + Validate(); +} + +void c4_Column::Grow(t4_i32 off_, t4_i32 diff_) +{ + d4_assert(off_ <= _size); + d4_assert(diff_ > 0); + + if (_segments.GetSize() == 0) + SetupSegments(); + + Validate(); + + _dirty = true; + + // move the gap so it starts where we want to insert + MoveGapTo(off_); + + t4_i32 bigSlack = _slack; + if (bigSlack < diff_) { // only do more if this isn't good enough + // number of segments to insert + int n = fSegIndex(diff_ - _slack + kSegMax - 1); + d4_assert(n > 0); + + int i1 = fSegIndex(_gap); + int i2 = fSegIndex(_gap + _slack); + + bool moveBack = false; + + if (i2 > i1) // cases 3 and 4 + ++i1; + else if (fSegRest(_gap)) // case 2 + moveBack = true; + + _segments.InsertAt(i1, 0, n); + for (int i = 0; i < n; ++i) + _segments.SetAt(i1 + i, d4_new t4_byte [(int) kSegMax]); + + bigSlack += fSegOffset(n); + + if (moveBack) { + d4_assert(i1 == fSegIndex(_gap)); + + // we have inserted too low, move bytes in front of gap back + CopyData(fSegOffset(i1), fSegOffset(i1 + n), fSegRest(_gap)); + } + } + + d4_assert(diff_ <= bigSlack && bigSlack < diff_ + kSegMax); + + _gap += diff_; + _slack = (int) (bigSlack - diff_); + _size += diff_; + + FinishSlack(); +} + +void c4_Column::Shrink(t4_i32 off_, t4_i32 diff_) +{ + d4_assert(off_ <= _size); + d4_assert(diff_ > 0); + + if (_segments.GetSize() == 0) + SetupSegments(); + + Validate(); + + _dirty = true; + + // the simplification here is that we have in fact simply *two* + // gaps and we must merge them together and end up with just one + + if (_slack > 0) { + if (_gap < off_) // if too low, move the gap up + MoveGapTo(off_); + else if (off_ + diff_ < _gap) // if too high, move down to end + MoveGapTo(off_ + diff_); + + // the gap is now inside, or adjacent to, the deleted area + d4_assert(off_ <= _gap && _gap <= off_ + diff_); + } + + _gap = off_; + + // check whether the merged gap would cross a segment boundary + int i1 = fSegIndex(_gap); + int i2 = fSegIndex(_gap + _slack + diff_); + + // drop complete segments, not a partially filled boundary + if (fSegRest(_gap)) + ++i1; + + // moved up (was after the next if in the 1.7 May 28 build) + _slack += diff_; + _size -= diff_; + + int n = i2 - i1; + if (n > 0) { + for (int i = i1; i < i2; ++i) + ReleaseSegment(i); + + _segments.RemoveAt(i1, n); + + // the logic in 1.7 of May 28 was warped (the assert "fix" was wrong) + d4_assert(_slack >= fSegOffset(n)); + _slack -= fSegOffset(n); + } + + d4_assert(0 <= _slack && _slack < 2 * kSegMax); + + // if the gap is at the end, get rid of a partial segment after it + if (_gap == _size) { + int i = fSegIndex(_size + _slack); + if (i != fSegIndex(_gap)) { + d4_assert(i == fSegIndex(_gap) + 1); + d4_assert(i == _segments.GetSize() - 1); + + ReleaseSegment(i); + _segments.SetAt(i, 0); + + _slack -= fSegRest(_size + _slack); + + d4_assert(_slack < kSegMax); + d4_assert(fSegRest(_gap + _slack) == 0); + } + } + + // the slack may still be too large to leave as is + if (_slack >= kSegMax) { + // move the bytes just after the end of the gap one segment down + int x = fSegRest(_gap + _slack); + int r = kSegMax - x; + if (_gap + r > _size) + r = (int) (_size - _gap); + + CopyData(_gap, _gap + _slack, r); + + int i = fSegIndex(_gap + kSegMax - 1); + ReleaseSegment(i); + + if (r + x < kSegMax) + _segments.SetAt(i, 0); + else + _segments.RemoveAt(i); + + _slack -= r + x; + _gap += r; + } + + // if we have no data anymore, make sure not to use the file map either + if (_size == 0 && _slack > 0) + CopyNow(0); + + FinishSlack(); +} + +void c4_Column::FinishSlack() +{ + Validate(); + + // optimization: if partial end segment easily fits in slack, move it down + t4_i32 gapEnd = _gap + _slack; + if (!fSegRest(gapEnd) && gapEnd >= _size + 500) { + // slack is at least 500 bytes more than the partial end segment + // also, the gap must end exactly on a segment boundary + int i = fSegIndex(gapEnd); + d4_assert(i == _segments.GetSize() - 1); + + int n = _size - _gap; + CopyData(gapEnd - n, gapEnd, n); + + ReleaseSegment(i); + _segments.SetAt(i, 0); + + _slack -= n; + d4_assert(_slack >= 500); + + Validate(); + } +} + +void c4_Column::SaveNow(c4_Strategy& strategy_, t4_i32 pos_) +{ + if (_segments.GetSize() == 0) + SetupSegments(); + + // write all segments + c4_ColIter iter (*this, 0, _size); + while (iter.Next(kSegMax)) { + int n = iter.BufLen(); + strategy_.DataWrite(pos_, iter.BufLoad(), n); + if (strategy_._failure != 0) + break; + pos_ += n; + } +} + +const t4_byte* c4_Column::FetchBytes(t4_i32 pos_, int len_, c4_Bytes& buffer_, bool forceCopy_) +{ + d4_assert(len_ > 0); + d4_assert(pos_ + len_ <= ColSize()); + d4_assert(0 <= _slack && _slack < kSegMax); + + c4_ColIter iter (*this, pos_, pos_ + len_); + iter.Next(); + + // most common case, all bytes are inside the same segment + if (!forceCopy_ && iter.BufLen() == len_) + return iter.BufLoad(); + + t4_byte* p = buffer_.SetBuffer(len_); + do { + d4_assert(iter.BufLen() > 0); + memcpy(p, iter.BufLoad(), iter.BufLen()); + p += iter.BufLen(); + } while (iter.Next()); + d4_assert(p == buffer_.Contents() + len_); + + return buffer_.Contents(); +} + +void c4_Column::StoreBytes(t4_i32 pos_, const c4_Bytes& buffer_) +{ + int n = buffer_.Size(); + if (n > 0) { + d4_assert(pos_ + n <= ColSize()); + + c4_ColIter iter (*this, pos_, pos_ + n); + + const t4_byte* p = buffer_.Contents(); + while (iter.Next(n)) { + d4_assert(iter.BufLen() > 0); + memcpy(iter.BufSave(), p, iter.BufLen()); + p += iter.BufLen(); + } + d4_assert(p == buffer_.Contents() + n); + } +} + + /* + PushValue and PullValue deal with variable-sized storage of + one unsigned integer value of up to 32 bits. Depending on the + magnitude of the integer, 1..6 bytes are used to represent it. + Each byte holds 7 significant bits and one continuation bit. + This saves storage, but it is also byte order independent. + Negative values are stored as a zero byte plus positive value. + */ + +t4_i32 c4_Column::PullValue(const t4_byte*& ptr_) +{ + t4_i32 mask = *ptr_ ? 0 : ~0; + + t4_i32 v = 0; + for (;;) { + v = (v << 7) + *ptr_; + if (*ptr_++ & 0x80) + break; + } + + return mask ^ (v - 0x80); // oops, last byte had bit 7 set +} + +void c4_Column::PushValue(t4_byte*& ptr_, t4_i32 v_) +{ + if (v_ < 0) { + v_ = ~v_; + *ptr_++ = 0; + } + + int n = 0; + do + n += 7; + while ((v_ >> n) && n < 32); + + while (n) { + n -= 7; + t4_byte b = (t4_byte) ((v_ >> n) & 0x7F); + if (!n) + b |= 0x80; // set bit 7 on the last byte + *ptr_++ = b; + } +} + +void c4_Column::InsertData(t4_i32 index_, t4_i32 count_, bool clear_) +{ + d4_assert(index_ <= ColSize()); + + if (count_ > 0) { + Grow(index_, count_); + + // clear the contents, in separate chunks if necessary + if (clear_) { + c4_ColIter iter (*this, index_, index_ + count_); + while (iter.Next()) + memset(iter.BufSave(), 0, iter.BufLen()); + } + } +} + +void c4_Column::RemoveData(t4_i32 index_, t4_i32 count_) +{ + d4_assert(index_ + count_ <= ColSize()); + + if (count_ > 0) + Shrink(index_, count_); +} + +///////////////////////////////////////////////////////////////////////////// + +void c4_ColOfInts::Get_0b(int) +{ + *(t4_i32*) _item = 0; +} + +void c4_ColOfInts::Get_1b(int index_) +{ + t4_i32 off = index_ >> 3; + d4_assert(off < ColSize()); + + *(t4_i32*) _item = (*LoadNow(off) >> (index_ & 7)) & 0x01; +} + +void c4_ColOfInts::Get_2b(int index_) +{ + t4_i32 off = index_ >> 2; + d4_assert(off < ColSize()); + + *(t4_i32*) _item = (*LoadNow(off) >> ((index_ & 3) << 1)) & 0x03; +} + +void c4_ColOfInts::Get_4b(int index_) +{ + t4_i32 off = index_ >> 1; + d4_assert(off < ColSize()); + + *(t4_i32*) _item = (*LoadNow(off) >> ((index_ & 1) << 2)) & 0x0F; +} + +void c4_ColOfInts::Get_8i(int index_) +{ + t4_i32 off = index_; + d4_assert(off < ColSize()); + + *(t4_i32*) _item = *(const signed char*) LoadNow(off); +} + +void c4_ColOfInts::Get_16i(int index_) +{ + t4_i32 off = index_ * (t4_i32) 2; + d4_assert(off + 2 <= ColSize()); + + const t4_byte* vec = LoadNow(off); + + _item[0] = vec[0]; + _item[1] = vec[1]; + + *(t4_i32*) _item = *(const short*) _item; +} + +void c4_ColOfInts::Get_16r(int index_) +{ + t4_i32 off = index_ * (t4_i32) 2; + d4_assert(off + 2 <= ColSize()); + + const t4_byte* vec = LoadNow(off); + + // 2003-02-02 - gcc 3.2.1 on linux (!) fails to compile this + // sign-extension trick properly, use a temp buffer instead: + //*(t4_i32*) _item = *(const short*) _item; + + t4_byte temp[2]; + temp[1] = vec[0]; + temp[0] = vec[1]; + *(t4_i32*) _item = *(const short*) temp; +} + +void c4_ColOfInts::Get_32i(int index_) +{ + t4_i32 off = index_ * (t4_i32) 4; + d4_assert(off + 4 <= ColSize()); + + const t4_byte* vec = LoadNow(off); + + _item[0] = vec[0]; + _item[1] = vec[1]; + _item[2] = vec[2]; + _item[3] = vec[3]; +} + +void c4_ColOfInts::Get_32r(int index_) +{ + t4_i32 off = index_ * (t4_i32) 4; + d4_assert(off + 4 <= ColSize()); + + const t4_byte* vec = LoadNow(off); + + _item[3] = vec[0]; + _item[2] = vec[1]; + _item[1] = vec[2]; + _item[0] = vec[3]; +} + +void c4_ColOfInts::Get_64i(int index_) +{ + t4_i32 off = index_ * (t4_i32) 8; + d4_assert(off + 8 <= ColSize()); + + const t4_byte* vec = LoadNow(off); + + for (int i = 0; i < 8; ++i) + _item[i] = vec[i]; +} + +void c4_ColOfInts::Get_64r(int index_) +{ + t4_i32 off = index_ * (t4_i32) 8; + d4_assert(off + 8 <= ColSize()); + + const t4_byte* vec = LoadNow(off); + + for (int i = 0; i < 8; ++i) + _item[7-i] = vec[i]; +} + +///////////////////////////////////////////////////////////////////////////// + + static int fBitsNeeded(t4_i32 v) + { + if ((v >> 4) == 0) { + static int bits[] = { 0, 1, 2, 2, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4 }; + return bits[(int) v]; + } + + if (v < 0) // first flip all bits if bit 31 is set + v = ~ v; // ... bit 31 is now always zero + + // then check if bits 15-31 used (32b), 7-31 used (16b), else (8b) + return v >> 15 ? 32 : v >> 7 ? 16 : 8; + } + +bool c4_ColOfInts::Set_0b(int, const t4_byte* item_) +{ + t4_i32 v = *(const t4_i32*) item_; + return v == 0; +} + +bool c4_ColOfInts::Set_1b(int index_, const t4_byte* item_) +{ + t4_i32 v = *(const t4_i32*) item_; + + t4_i32 off = index_ >> 3; + d4_assert(off < ColSize()); + + index_ &= 7; + + t4_byte* p = CopyNow(off); + *p = (*p & ~(1 << index_)) | (((t4_byte) v & 1) << index_); + + return (v >> 1) == 0; +} + +bool c4_ColOfInts::Set_2b(int index_, const t4_byte* item_) +{ + t4_i32 v = *(const t4_i32*) item_; + + t4_i32 off = index_ >> 2; + d4_assert(off < ColSize()); + + const int n = (index_ & 3) << 1; + + t4_byte* p = CopyNow(off); + *p = (*p & ~(0x03 << n)) | (((t4_byte) v & 0x03) << n); + + return (v >> 2) == 0; +} + +bool c4_ColOfInts::Set_4b(int index_, const t4_byte* item_) +{ + t4_i32 v = *(const t4_i32*) item_; + + t4_i32 off = index_ >> 1; + d4_assert(off < ColSize()); + + const int n = (index_ & 1) << 2; + + t4_byte* p = CopyNow(off); + *p = (*p & ~(0x0F << n)) | (((t4_byte) v & 0x0F) << n); + + return (v >> 4) == 0; +} + +// avoid a bug in MS EVC 3.0's code gen for ARM (i.e. WinCE) +#ifdef _ARM_ +#pragma optimize("g",off) +#endif + +bool c4_ColOfInts::Set_8i(int index_, const t4_byte* item_) +{ + t4_i32 v = *(const t4_i32*) item_; + + t4_i32 off = index_; + d4_assert(off < ColSize()); + + *(char*) CopyNow(off) = (char) v; + + return v == (signed char) v; +} + +#ifdef _ARM_ +#pragma optimize("",on) +#endif + +bool c4_ColOfInts::Set_16i(int index_, const t4_byte* item_) +{ + t4_i32 v = *(const t4_i32*) item_; + + t4_i32 off = index_ * (t4_i32) 2; + d4_assert(off + 2 <= ColSize()); + + *(short*) CopyNow(off) = (short) v; + + return v == (short) v; +} + +bool c4_ColOfInts::Set_16r(int index_, const t4_byte* item_) +{ + t4_i32 v = *(const t4_i32*) item_; + + t4_byte buf [2]; + *(short*) buf = (short) v; + + t4_i32 off = index_ * (t4_i32) 2; + d4_assert(off + 2 <= ColSize()); + + t4_byte* vec = CopyNow(off); + + vec[1] = buf[0]; + vec[0] = buf[1]; + + return v == (short) v; +} + +bool c4_ColOfInts::Set_32i(int index_, const t4_byte* item_) +{ + t4_i32 v = *(const t4_i32*) item_; + + t4_i32 off = index_ * (t4_i32) 4; + d4_assert(off + 4 <= ColSize()); + + *(t4_i32*) CopyNow(off) = (t4_i32) v; + + return true; +} + +bool c4_ColOfInts::Set_32r(int index_, const t4_byte* item_) +{ + t4_i32 off = index_ * (t4_i32) 4; + d4_assert(off + 4 <= ColSize()); + + t4_byte* vec = CopyNow(off); + + vec[3] = item_[0]; + vec[2] = item_[1]; + vec[1] = item_[2]; + vec[0] = item_[3]; + + return true; +} + +bool c4_ColOfInts::Set_64i(int index_, const t4_byte* item_) +{ + t4_i32 off = index_ * (t4_i32) 8; + d4_assert(off + 8 <= ColSize()); + + t4_byte* vec = CopyNow(off); + + for (int i = 0; i < 8; ++i) + vec[i] = item_[i]; + + return true; +} + +bool c4_ColOfInts::Set_64r(int index_, const t4_byte* item_) +{ + t4_i32 off = index_ * (t4_i32) 8; + d4_assert(off + 8 <= ColSize()); + + t4_byte* vec = CopyNow(off); + + for (int i = 0; i < 8; ++i) + vec[7-i] = item_[i]; + + return true; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_ColOfInts::c4_ColOfInts (c4_Persist* persist_, int width_) + : c4_Column (persist_), + _getter (&c4_ColOfInts::Get_0b), _setter (&c4_ColOfInts::Set_0b), + _currWidth (0), _dataWidth (width_), _numRows (0), _mustFlip (false) +{ +} + +void c4_ColOfInts::ForceFlip() +{ + _mustFlip = true; +} + +int c4_ColOfInts::RowCount() const +{ + d4_assert(_numRows >= 0); + + return _numRows; +} + +int c4_ColOfInts::CalcAccessWidth(int numRows_, t4_i32 colSize_) +{ + d4_assert(numRows_ > 0); + + int w = (int) ((colSize_ << 3) / numRows_); + + // deduce sub-byte sizes for small vectors, see c4_ColOfInts::Set + if (numRows_ <= 7 && 0 < colSize_ && colSize_ <= 6) { + static t4_byte realWidth [][6] = { + // sz = 1: 2: 3: 4: 5: 6: + { 8, 16, 1, 32, 2, 4 }, // n = 1 + { 4, 8, 1, 16, 2, 0 }, // n = 2 + { 2, 4, 8, 1, 0, 16 }, // n = 3 + { 2, 4, 0, 8, 1, 0 }, // n = 4 + { 1, 2, 4, 0, 8, 0 }, // n = 5 + { 1, 2, 4, 0, 0, 8 }, // n = 6 + { 1, 2, 0, 4, 0, 0 }, // n = 7 + }; + + w = realWidth [numRows_-1] [(int) colSize_ - 1]; + d4_assert(w > 0); + } + + return (w & (w - 1)) == 0 ? w : -1; +} + +void c4_ColOfInts::SetRowCount(int numRows_) +{ + _numRows = numRows_; + if (numRows_ > 0) { + int w = CalcAccessWidth(numRows_, ColSize()); + d4_assert(w >= 0); + SetAccessWidth(w); + } +} + +void c4_ColOfInts::FlipBytes() +{ + if (_currWidth > 8) { + int step = _currWidth >> 3; + + c4_ColIter iter (*this, 0, ColSize()); + while (iter.Next(step)) { + t4_byte* data = iter.BufSave(); + d4_assert(data != 0); + + for (int j = 0; j < step; ++j) { + t4_byte c = data[j]; + data[j] = data[step-j-1]; + data[step-j-1] = c; + } + } + } +} + +void c4_ColOfInts::SetAccessWidth(int bits_) +{ + d4_assert((bits_ & (bits_ - 1)) == 0); + + int l2bp1 = 0; // "log2 bits plus one" needed to represent value + while (bits_) { + ++l2bp1; + bits_ >>= 1; + } + d4_assert(0 <= l2bp1 && l2bp1 < 8); + + _currWidth = (1 << l2bp1) >> 1; + + if (l2bp1 > 4 && (_mustFlip || Persist() != 0 && Strategy()._bytesFlipped)) + l2bp1 += 3; // switch to the trailing entries for byte flipping + + // Metrowerks Codewarrior 11 is dumb, it requires the "&c4_ColOfInts::" + + static tGetter gTab [] = + { + &c4_ColOfInts::Get_0b, // 0: 0 bits/entry + &c4_ColOfInts::Get_1b, // 1: 1 bits/entry + &c4_ColOfInts::Get_2b, // 2: 2 bits/entry + &c4_ColOfInts::Get_4b, // 3: 4 bits/entry + + &c4_ColOfInts::Get_8i, // 4: 8 bits/entry + &c4_ColOfInts::Get_16i, // 5: 16 bits/entry + &c4_ColOfInts::Get_32i, // 6: 32 bits/entry + &c4_ColOfInts::Get_64i, // 7: 64 bits/entry + + &c4_ColOfInts::Get_16r, // 8: 16 bits/entry, reversed + &c4_ColOfInts::Get_32r, // 9: 32 bits/entry, reversed + &c4_ColOfInts::Get_64r, // 10: 64 bits/entry, reversed + }; + + static tSetter sTab [] = + { + &c4_ColOfInts::Set_0b, // 0: 0 bits/entry + &c4_ColOfInts::Set_1b, // 1: 1 bits/entry + &c4_ColOfInts::Set_2b, // 2: 2 bits/entry + &c4_ColOfInts::Set_4b, // 3: 4 bits/entry + + &c4_ColOfInts::Set_8i, // 4: 8 bits/entry + &c4_ColOfInts::Set_16i, // 5: 16 bits/entry + &c4_ColOfInts::Set_32i, // 6: 32 bits/entry + &c4_ColOfInts::Set_64i, // 7: 64 bits/entry + + &c4_ColOfInts::Set_16r, // 8: 16 bits/entry, reversed + &c4_ColOfInts::Set_32r, // 9: 32 bits/entry, reversed + &c4_ColOfInts::Set_64r, // 10: 64 bits/entry, reversed + }; + + d4_assert(l2bp1 < sizeof gTab / sizeof *gTab); + + _getter = gTab[l2bp1]; + _setter = sTab[l2bp1]; + + d4_assert(_getter != 0 && _setter != 0); +} + +int c4_ColOfInts::ItemSize(int) +{ + return _currWidth >= 8 ? _currWidth >> 3 : - _currWidth; +} + +const void* c4_ColOfInts::Get(int index_, int& length_) +{ + d4_assert(sizeof _item >= _dataWidth); + + (this->*_getter)(index_); + + length_ = _dataWidth; + return _item; +} + +void c4_ColOfInts::Set(int index_, const c4_Bytes& buf_) +{ + d4_assert(buf_.Size() == _dataWidth); + + if ((this->*_setter)(index_, buf_.Contents())) + return; + + d4_assert(buf_.Size() == sizeof (t4_i32)); + + int n = fBitsNeeded(*(const t4_i32*) buf_.Contents()); + if (n > _currWidth) { + int k = RowCount(); + + t4_i32 oldEnd = ColSize(); + t4_i32 newEnd = ((t4_i32) k * n + 7) >> 3; + + if (newEnd > oldEnd) { + InsertData(oldEnd, newEnd - oldEnd, _currWidth == 0); + + // 14-5-2002: need to get rid of gap in case it risks not being a + // multiple of the increased size (bug, see s46 regression test) + // + // Example scenario: gap size is odd, data gets resized to 2/4-byte + // ints, data at end fits without moving gap to end, then we end + // up with a vector that has an int split *across* the gap - this + // commits just fine, but access to that split int is now bad. + // + // Lesson: need stricter/simpler consistency, it's way too complex! + if (n > 8) + RemoveGap(); + } + + // data value exceeds width, expand to new size and repeat + if (_currWidth > 0) { + d4_assert(n % _currWidth == 0); // must be expanding by a multiple + + // To expand, we start by inserting a new appropriate chunk + // at the end, and expand the entries in place (last to first). + + tGetter oldGetter = _getter; + SetAccessWidth(n); + + d4_assert(sizeof _item >= _dataWidth); + + // this expansion in place works because it runs backwards + while (--k >= 0) { + (this->*oldGetter)(k); + (this->*_setter)(k, _item); + } + } else { + if (_dataWidth > (int) sizeof (t4_i32)) + n = _dataWidth << 3; // don't trust setter result, use max instead + + SetAccessWidth(n); + } + + // now repeat the failed call to _setter + /* bool f = */ (this->*_setter)(index_, buf_.Contents()); + //? d4_assert(f); + } +} + +t4_i32 c4_ColOfInts::GetInt(int index_) +{ + int n; + const void* p = Get(index_, n); + d4_assert(n == sizeof (t4_i32)); + return *(const t4_i32*) p; +} + +void c4_ColOfInts::SetInt(int index_, t4_i32 value_) +{ + Set(index_, c4_Bytes (&value_, sizeof value_)); +} + +int c4_ColOfInts::DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_) +{ + d4_assert(b1_.Size() == sizeof (t4_i32)); + d4_assert(b2_.Size() == sizeof (t4_i32)); + + t4_i32 v1 = *(const t4_i32*) b1_.Contents(); + t4_i32 v2 = *(const t4_i32*) b2_.Contents(); + + return v1 == v2 ? 0 : v1 < v2 ? -1 : +1; +} + +void c4_ColOfInts::Insert(int index_, const c4_Bytes& buf_, int count_) +{ + d4_assert(buf_.Size() == _dataWidth); + d4_assert(count_ > 0); + + bool clear = true; + const t4_byte* ptr = buf_.Contents(); + + for (int i = 0; i < _dataWidth; ++i) + if (*ptr++) { + clear = false; + break; + } + + ResizeData(index_, count_, clear); + + if (!clear) + while (--count_ >= 0) + Set(index_++, buf_); +} + +void c4_ColOfInts::Remove(int index_, int count_) +{ + d4_assert(count_ > 0); + + ResizeData(index_, - count_); +} + +void c4_ColOfInts::ResizeData(int index_, int count_, bool clear_) +{ + _numRows += count_; + + if (!(_currWidth & 7)) { // not 1, 2, or 4 + const t4_i32 w = (t4_i32) (_currWidth >> 3); + if (count_ > 0) + InsertData(index_ * w, count_ * w, clear_); + else + RemoveData(index_ * w, - count_ * w); + return; + } + + d4_assert(_currWidth == 1 || _currWidth == 2 || _currWidth == 4); + + /* _currwidth 1: 2: 4: + * shiftPos 3 2 1 shift the offset right this much + * maskPos 7 3 1 mask the offset with this + */ + + const int shiftPos = _currWidth == 4 ? 1 : 4 - _currWidth; + const int maskPos = (1 << shiftPos) - 1; + + // the following code is similar to c4_Column::Resize, but at bit level + + // turn insertion into deletion by inserting entire bytes + if (count_ > 0) { + unsigned off = (unsigned) index_ >> shiftPos; + int gapBytes = (count_ + maskPos) >> shiftPos; + + InsertData(off, gapBytes, clear_); + + // oops, we might have inserted too low by a few entries + const int bits = (index_ & maskPos) * _currWidth; + if (bits) { + const int maskLow = (1 << bits) - 1; + + // move the first few bits to start of inserted range + t4_byte* p = CopyNow(off + gapBytes); + t4_byte one = *p & maskLow; + *p &= ~maskLow; + + * CopyNow(off) = one; + } + + index_ += count_; + count_ -= gapBytes << shiftPos; + d4_assert(count_ <= 0); + } + + // now perform a deletion using a forward loop to copy down + if (count_ < 0) { + c4_Bytes temp; + + while (index_ < _numRows) { + int length; + const void* ptr = Get(index_ - count_, length); + Set(index_++, c4_Bytes (ptr, length)); + } + } + else { + d4_assert(count_ == 0); + } + + FixSize(false); +} + +void c4_ColOfInts::FixSize(bool fudge_) +{ + int n = RowCount(); + t4_i32 needBytes = ((t4_i32) n * _currWidth + 7) >> 3; + + // use a special trick to mark sizes less than 1 byte in storage + if (fudge_ && 1 <= n && n <= 4 && (_currWidth & 7)) { + const int shiftPos = _currWidth == 4 ? 1 : 4 - _currWidth; + + static t4_byte fakeSizes [3][4] = { // n: 1: 2: 3: 4: + { 6, 1, 2, 2 }, // 4-bit entries: 4b 8b 12b 16b + { 5, 5, 1, 1 }, // 2-bit entries: 2b 4b 6b 8b + { 3, 3, 4, 5 }, // 1-bit entries: 1b 2b 3b 4b + }; + + // The idea is to use an "impossible" size (ie. 5, for n = 2) + // to give information about the current bit packing density. + d4_assert(needBytes <= 2); + needBytes = fakeSizes [shiftPos-1] [n-1]; + } + + t4_i32 currSize = ColSize(); + + if (needBytes < currSize) + RemoveData(needBytes, currSize - needBytes); + else if (needBytes > currSize) + InsertData(currSize, needBytes - currSize, true); +} + +///////////////////////////////////////////////////////////////////////////// + +bool c4_ColIter::Next() +{ + _pos += _len; + + _len = _column.AvailAt(_pos); + _ptr = _column.LoadNow(_pos); + + if (!_ptr) + _len = 0; + else if (_pos + _len >= _limit) + _len = _limit - _pos; + else { // 19990831 - optimization to avoid most copying + // while the end is adjacent to the next segment, extend it + while (_ptr + _len == _column.LoadNow(_pos + _len)) { + int n = _column.AvailAt(_pos + _len); + if (n == 0) + break; // may be a short column (strings) + + _len += n; + + if (_pos + _len >= _limit) { + _len = _limit - _pos; + break; + } + } + } + + return _len > 0; +} + +bool c4_ColIter::Next(int max_) +{ + _pos += _len; + + _len = _column.AvailAt(_pos); + _ptr = _column.LoadNow(_pos); + + if (!_ptr) + _len = 0; + else if (_pos + _len > _limit) + _len = _limit - _pos; + + if (_len <= 0) + return false; + + if (_len > max_) + _len = max_; + + return true; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/column.h b/akregator/src/mk4storage/metakit/src/column.h new file mode 100644 index 000000000..3f6e4f157 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/column.h @@ -0,0 +1,212 @@ +// column.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Definition of the column classes + */ + +#ifndef __COLUMN_H__ +#define __COLUMN_H__ + +///////////////////////////////////////////////////////////////////////////// +// Declarations in this file + + class c4_Column; // a column in a table + class c4_ColIter; // an iterator over column data + class c4_ColCache; // manages a cache for columns + + class c4_Persist; // not defined here + class c4_Strategy; // not defined here + +///////////////////////////////////////////////////////////////////////////// + +class c4_Column +{ + c4_PtrArray _segments; + t4_i32 _position; + t4_i32 _size; + c4_Persist* _persist; + t4_i32 _gap; + int _slack; + bool _dirty; + +public: + c4_Column (c4_Persist* persist_); + //: Constructs a column using the specified persistence manager. + ~c4_Column (); + + void SetBuffer(t4_i32); + //: Allocate a new buffer of the specified size. + + c4_Persist* Persist() const; + //: Returns persistence manager for this column, or zero. + c4_Strategy& Strategy() const; + //: Returns the associated strategy pointer. + t4_i32 Position() const; + //: Special access for the DUMP program. + t4_i32 ColSize() const; + //: Returns the number of bytes as stored on disk. + bool IsDirty() const; + //: Returns true if contents needs to be saved. + + void SetLocation(t4_i32, t4_i32); + //: Sets the position and size of this column on file. + void PullLocation(const t4_byte*& ptr_); + //: Extract position and size of this column. + + int AvailAt(t4_i32 offset_) const; + //: Returns number of bytes we can access at once. + const t4_byte* LoadNow(t4_i32); + //: Makes sure the data is loaded into memory. + t4_byte* CopyNow(t4_i32); + //: Makes sure a copy of the data is in memory. + void Grow(t4_i32, t4_i32); + //: Grows the buffer by inserting space. + void Shrink(t4_i32, t4_i32); + //: Shrinks the buffer by removing space. + void SaveNow(c4_Strategy&, t4_i32 pos_); + //: Save the buffer to file. + + const t4_byte* FetchBytes(t4_i32 pos_, int len_, c4_Bytes& buffer_, bool forceCopy_); + //: Returns pointer to data, use buffer only if non-contiguous. + void StoreBytes(t4_i32 pos_, const c4_Bytes& buffer_); + //: Stores a copy of the buffer in the column. + + bool RequiresMap() const; + void ReleaseAllSegments(); + + static t4_i32 PullValue(const t4_byte*& ptr_); + static void PushValue(t4_byte*& ptr_, t4_i32 v_); + + void InsertData(t4_i32 index_, t4_i32 count_, bool clear_); + void RemoveData(t4_i32 index_, t4_i32 count_); + void RemoveGap(); + + enum { kSegBits = 12, kSegMax = 1 << kSegBits, kSegMask = kSegMax - 1 }; + +private: + static int fSegIndex(t4_i32 offset_); + static t4_i32 fSegOffset(int index_); + static int fSegRest(t4_i32 offset_); + + bool UsesMap(const t4_byte*) const; + bool IsMapped() const; + + void ReleaseSegment(int); + void SetupSegments(); + void Validate() const; + void FinishSlack(); + + void MoveGapUp(t4_i32 pos_); + void MoveGapDown(t4_i32 pos_); + void MoveGapTo(t4_i32 pos_); + + t4_byte* CopyData(t4_i32, t4_i32, int); +}; + +///////////////////////////////////////////////////////////////////////////// + +class c4_ColOfInts : public c4_Column +{ +public: + c4_ColOfInts (c4_Persist* persist_, int width_ =sizeof (t4_i32)); + + int RowCount() const; + void SetRowCount(int numRows_); + + void FlipBytes(); + + int ItemSize(int index_); + const void* Get(int index_, int& length_); + void Set(int index_, const c4_Bytes& buf_); + + t4_i32 GetInt(int index_); + void SetInt(int index_, t4_i32 value_); + + void Insert(int index_, const c4_Bytes& buf_, int count_); + void Remove(int index_, int count_); + + static int CalcAccessWidth(int numRows_, t4_i32 colSize_); + + void SetAccessWidth(int bits_); + void FixSize(bool fudge_); + void ForceFlip(); + + static int DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_); + +private: + typedef void (c4_ColOfInts::*tGetter) (int); + typedef bool (c4_ColOfInts::*tSetter) (int, const t4_byte*); + + void Get_0b(int index_); + void Get_1b(int index_); + void Get_2b(int index_); + void Get_4b(int index_); + void Get_8i(int index_); + void Get_16i(int index_); + void Get_16r(int index_); + void Get_32i(int index_); + void Get_32r(int index_); + void Get_64i(int index_); + void Get_64r(int index_); + + bool Set_0b(int index_, const t4_byte* item_); + bool Set_1b(int index_, const t4_byte* item_); + bool Set_2b(int index_, const t4_byte* item_); + bool Set_4b(int index_, const t4_byte* item_); + bool Set_8i(int index_, const t4_byte* item_); + bool Set_16i(int index_, const t4_byte* item_); + bool Set_16r(int index_, const t4_byte* item_); + bool Set_32i(int index_, const t4_byte* item_); + bool Set_32r(int index_, const t4_byte* item_); + bool Set_64i(int index_, const t4_byte* item_); + bool Set_64r(int index_, const t4_byte* item_); + + void ResizeData(int index_, int count_, bool clear_ =false); + + tGetter _getter; + tSetter _setter; + + union { + t4_byte _item[8]; // holds temp result (careful with alignment!) + double _aligner; // needed for SPARC + }; + + int _currWidth; // number of bits used for one entry (0..64) + int _dataWidth; // number of bytes used for passing a value along + int _numRows; + bool _mustFlip; +}; + +///////////////////////////////////////////////////////////////////////////// + +class c4_ColIter +{ + c4_Column& _column; + t4_i32 _limit; + t4_i32 _pos; + int _len; + const t4_byte* _ptr; + +public: + c4_ColIter (c4_Column& col_, t4_i32 offset_, t4_i32 limit_); +// ~c4_ColIter (); + + bool Next(); + bool Next(int max_); + + const t4_byte* BufLoad() const; + t4_byte* BufSave(); + int BufLen() const; +}; + +///////////////////////////////////////////////////////////////////////////// + +#if q4_INLINE +#include "column.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/column.inl b/akregator/src/mk4storage/metakit/src/column.inl new file mode 100644 index 000000000..58f34437e --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/column.inl @@ -0,0 +1,89 @@ +// column.inl -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Inlined members of the column classes + */ + +///////////////////////////////////////////////////////////////////////////// +// c4_Column + +d4_inline int c4_Column::fSegIndex(t4_i32 offset_) +{ + // limited by max array: 1 << (kSegBits + 15) with 16-bit ints + return (int) (offset_ >> kSegBits); +} + +d4_inline t4_i32 c4_Column::fSegOffset(int index_) +{ + return (t4_i32) index_ << kSegBits; +} + +d4_inline int c4_Column::fSegRest(t4_i32 offset_) +{ + return ((int) offset_ & kSegMask); +} + +d4_inline c4_Persist* c4_Column::Persist() const +{ + return _persist; +} + +d4_inline t4_i32 c4_Column::Position() const +{ + return _position; +} + +d4_inline t4_i32 c4_Column::ColSize() const +{ + return _size; +} + +d4_inline bool c4_Column::IsDirty() const +{ + return _dirty; +} + +d4_inline void c4_Column::SetBuffer(t4_i32 length_) +{ + SetLocation(0, length_); + _dirty = true; +} + +d4_inline const t4_byte* c4_Column::LoadNow(t4_i32 offset_) +{ + if (_segments.GetSize() == 0) + SetupSegments(); + + if (offset_ >= _gap) + offset_ += _slack; + + t4_byte* ptr = (t4_byte*) _segments.GetAt(fSegIndex(offset_)); + return ptr + fSegRest(offset_); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_ColIter + +d4_inline c4_ColIter::c4_ColIter (c4_Column& col_, t4_i32 offset_, t4_i32 limit_) + : _column (col_), _limit (limit_), _pos (offset_), _len (0), _ptr (0) +{ +} + +d4_inline const t4_byte* c4_ColIter::BufLoad() const +{ + return _ptr; +} + +d4_inline t4_byte* c4_ColIter::BufSave() +{ + return _column.CopyNow(_pos); +} + +d4_inline int c4_ColIter::BufLen() const +{ + return _len; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/custom.cpp b/akregator/src/mk4storage/metakit/src/custom.cpp new file mode 100644 index 000000000..a6275cea7 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/custom.cpp @@ -0,0 +1,1066 @@ +// custom.cpp -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Implementation of many custom viewer classes + */ + +#include "header.h" + +#include "custom.h" +#include "format.h" + +///////////////////////////////////////////////////////////////////////////// + +class c4_CustomHandler : public c4_Handler +{ + c4_CustomSeq* _seq; + +public: + c4_CustomHandler (const c4_Property& prop_, c4_CustomSeq* seq_); + virtual ~c4_CustomHandler (); + + virtual int ItemSize(int index_); + virtual const void* Get(int index_, int& length_); + virtual void Set(int index_, const c4_Bytes& buf_); + + virtual void Insert(int index_, const c4_Bytes& buf_, int count_); + virtual void Remove(int index_, int count_); +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_CustomHandler::c4_CustomHandler (const c4_Property& prop_, + c4_CustomSeq* seq_) + : c4_Handler (prop_), _seq (seq_) +{ + d4_assert(_seq != 0); +} + +c4_CustomHandler::~c4_CustomHandler () +{ +} + +int c4_CustomHandler::ItemSize(int index_) +{ + c4_Bytes& buf = _seq->Buffer(); + + int colnum = _seq->PropIndex(Property().GetId()); + d4_assert(colnum >= 0); + + if (!_seq->DoGet(index_, colnum, buf)) + return 0; + + return buf.Size(); +} + +const void* c4_CustomHandler::Get(int index_, int& length_) +{ + c4_Bytes& buf = _seq->Buffer(); + + int colnum = _seq->PropIndex(Property().GetId()); + d4_assert(colnum >= 0); + + if (!_seq->DoGet(index_, colnum, buf)) + ClearBytes(buf); + + length_ = buf.Size(); + return buf.Contents(); +} + +void c4_CustomHandler::Set(int index_, const c4_Bytes& buf_) +{ + int colnum = _seq->PropIndex(Property().GetId()); + d4_assert(colnum >= 0); + + _seq->DoSet(index_, colnum, buf_); +} + +void c4_CustomHandler::Insert(int, const c4_Bytes&, int) +{ + d4_assert(0); //! not yet +} + +void c4_CustomHandler::Remove(int, int) +{ + d4_assert(0); //! not yet +} + +c4_Handler* c4_CustomSeq::CreateHandler(const c4_Property& prop_) +{ + return d4_new c4_CustomHandler (prop_, this); +} + +///////////////////////////////////////////////////////////////////////////// + +c4_CustomSeq::c4_CustomSeq (c4_CustomViewer* viewer_) + : c4_HandlerSeq (0), _viewer (viewer_), _inited (false) +{ + d4_assert(_viewer != 0); + + // set up handlers to match a template obtained from the viewer + c4_View v = viewer_->GetTemplate(); + + for (int i = 0; i < v.NumProperties(); ++i) + PropIndex(v.NthProperty(i)); + + _inited = true; +} + +c4_CustomSeq::~c4_CustomSeq () +{ + delete _viewer; +} + +int c4_CustomSeq::NumRows() const +{ + return _inited ? _viewer->GetSize() : 0; +} + +bool c4_CustomSeq::RestrictSearch(c4_Cursor cursor_, int& pos_, int& count_) +{ + if (count_ > 0) + { + int n; + int o = _viewer->Lookup(cursor_, n); + // a -1 result means: "don't know, please scan all" + if (o < 0) + return count_ > 0; + + if (n > 0) + { + if (pos_ < o) + { + count_ -= o - pos_; + pos_ = o; + } + + if (pos_ + count_ > o + n) + count_ = o + n - pos_; + + if (count_ > 0) + return true; + } + } + + count_ = 0; + return false; +} + +void c4_CustomSeq::InsertAt(int p_, c4_Cursor c_, int n_) +{ + _viewer->InsertRows(p_, c_, n_); +} + +void c4_CustomSeq::RemoveAt(int p_, int n_) +{ + _viewer->RemoveRows(p_, n_); +} + +void c4_CustomSeq::Move(int, int) +{ + d4_assert(false); //! not yet +} + +bool c4_CustomSeq::DoGet(int row_, int col_, c4_Bytes& buf_) const +{ + d4_assert(_inited); + + return _viewer->GetItem(row_, col_, buf_); +} + +void c4_CustomSeq::DoSet(int row_, int col_, const c4_Bytes& buf_) +{ + d4_assert(_inited); + + d4_dbgdef(const bool f =) + _viewer->SetItem(row_, col_, buf_); + d4_assert(f); +} + +///////////////////////////////////////////////////////////////////////////// + +/** @class c4_CustomViewer + * + * Abstract base class for definition of custom views. + * + * A custom view is a view which can be accessed like any other view, using + * row and property operations, but which is fully managed by a customized + * "viewer" class. The viewer will eventually handle all requests for the + * view, such as defining its structure and size, as well as providing the + * actual data values when requested. + * + * Custom views cannot propagate changes. + * + * To implement a custom view, you must derive your viewer from this base + * class and define each of the virtual members. Then create a new object + * of this type on the heap and pass it to the c4_View constructor. Your + * viewer will automatically be destroyed when the last reference to its + * view goes away. See the DBF2MK sample code for an example of a viewer. + */ + +c4_CustomViewer::~c4_CustomViewer () +{ +} + + /// Locate a row in this view, try to use native searches +int c4_CustomViewer::Lookup(c4_Cursor, int& count_) +{ + count_ = GetSize(); + return 0; // not implemented, return entire view range +} + + /// Store one data item, supplied as a generic data value +bool c4_CustomViewer::SetItem(int, int, const c4_Bytes&) +{ + return false; // default is not modifiable +} + + /// Insert one or more copies of a row (if possible) +bool c4_CustomViewer::InsertRows(int, c4_Cursor, int) +{ + return false; // default is not modifiable +} + + /// Remove one or more rows (this is not always possible) +bool c4_CustomViewer::RemoveRows(int, int) +{ + return false; // default is not modifiable +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_SliceViewer : public c4_CustomViewer +{ + c4_View _parent; + int _first, _limit, _step; + +public: + c4_SliceViewer (c4_Sequence& seq_, int first_, int limit_, int step_); + virtual ~c4_SliceViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); + bool SetItem(int row_, int col_, const c4_Bytes& buf_); + virtual bool InsertRows(int pos_, c4_Cursor value_, int count_=1); + virtual bool RemoveRows(int pos_, int count_=1); +}; + +c4_SliceViewer::c4_SliceViewer (c4_Sequence& seq_, int first_, int limit_, int step_) + : _parent (&seq_), _first (first_), _limit (limit_), _step (step_) +{ + d4_assert(_step != 0); +} + +c4_SliceViewer::~c4_SliceViewer () +{ +} + +c4_View c4_SliceViewer::GetTemplate() +{ + return _parent.Clone(); // could probably return _parent just as well +} + +int c4_SliceViewer::GetSize() +{ + int n = _limit >= 0 ? _limit : _parent.GetSize(); + if (n < _first) + n = _first; + + int k = _step < 0 ? -_step : _step; + return (n - _first + k - 1) / k; +} + +bool c4_SliceViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + row_ = _first + _step * (_step > 0 ? row_ : row_ - GetSize() + 1); + + return _parent.GetItem(row_, col_, buf_); +} + +bool c4_SliceViewer::SetItem(int row_, int col_, const c4_Bytes& buf_) +{ + row_ = _first + _step * (_step > 0 ? row_ : row_ - GetSize() + 1); + + _parent.SetItem(row_, col_, buf_); + return true; +} + +bool c4_SliceViewer::InsertRows(int pos_, c4_Cursor value_, int count_) +{ + if (_step != 1) + return false; + + pos_ = _first + _step * (_step > 0 ? pos_ : pos_ - GetSize() + 1); + if (_limit >= 0) + _limit += count_; + + _parent.InsertAt(pos_, *value_, count_); + return true; +} + +bool c4_SliceViewer::RemoveRows(int pos_, int count_) +{ + if (_step != 1) + return false; + + pos_ = _first + _step * (_step > 0 ? pos_ : pos_ - GetSize() + 1); + if (_limit >= 0) + _limit -= count_; + + _parent.RemoveAt(pos_, count_); + return true; +} + +c4_CustomViewer* f4_CustSlice(c4_Sequence& seq_, int first_, int limit_, int step_) +{ + return d4_new c4_SliceViewer (seq_, first_, limit_, step_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_ProductViewer : public c4_CustomViewer +{ + c4_View _parent, _argView, _template; + +public: + c4_ProductViewer (c4_Sequence& seq_, const c4_View& view_); + virtual ~c4_ProductViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); +}; + +c4_ProductViewer::c4_ProductViewer (c4_Sequence& seq_, const c4_View& view_) + : _parent (&seq_), _argView (view_), _template (_parent.Clone()) +{ + for (int i = 0; i < _argView.NumProperties(); ++i) + _template.AddProperty(_argView.NthProperty(i)); +} + +c4_ProductViewer::~c4_ProductViewer () +{ +} + +c4_View c4_ProductViewer::GetTemplate() +{ + return _template; +} + +int c4_ProductViewer::GetSize() +{ + return _parent.GetSize() * _argView.GetSize(); +} + +bool c4_ProductViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + c4_View v = _parent; + + if (col_ < v.NumProperties()) + { + row_ /= _argView.GetSize(); + } + else + { + v = _argView; + row_ %= _argView.GetSize(); + col_ = v.FindProperty(_template.NthProperty(col_).GetId()); + + d4_assert(col_ >= 0); + } + + return v.GetItem(row_, col_, buf_); +} + +c4_CustomViewer* f4_CustProduct(c4_Sequence& seq_, const c4_View& view_) +{ + return d4_new c4_ProductViewer (seq_, view_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_RemapWithViewer : public c4_CustomViewer +{ + c4_View _parent, _argView; + +public: + c4_RemapWithViewer (c4_Sequence& seq_, const c4_View& view_); + virtual ~c4_RemapWithViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); + bool SetItem(int row_, int col_, const c4_Bytes& buf_); +}; + +c4_RemapWithViewer::c4_RemapWithViewer (c4_Sequence& seq_, const c4_View& view_) + : _parent (&seq_), _argView (view_) +{ +} + +c4_RemapWithViewer::~c4_RemapWithViewer () +{ +} + +c4_View c4_RemapWithViewer::GetTemplate() +{ + return _parent.Clone(); // could probably return _parent just as well +} + +int c4_RemapWithViewer::GetSize() +{ + return _argView.GetSize(); +} + +bool c4_RemapWithViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + const c4_Property& map = _argView.NthProperty(0); + d4_assert(map.Type() == 'I'); + + row_ = ((const c4_IntProp&) map) (_argView[row_]); + + return _parent.GetItem(row_, col_, buf_); +} + +bool c4_RemapWithViewer::SetItem(int row_, int col_, const c4_Bytes& buf_) +{ + const c4_Property& map = _argView.NthProperty(0); + d4_assert(map.Type() == 'I'); + + row_ = ((const c4_IntProp&) map) (_argView[row_]); + + _parent.SetItem(row_, col_, buf_); + return true; +} + +c4_CustomViewer* f4_CustRemapWith(c4_Sequence& seq_, const c4_View& view_) +{ + return d4_new c4_RemapWithViewer (seq_, view_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_PairViewer : public c4_CustomViewer +{ + c4_View _parent, _argView, _template; + +public: + c4_PairViewer (c4_Sequence& seq_, const c4_View& view_); + virtual ~c4_PairViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); + bool SetItem(int row_, int col_, const c4_Bytes& buf_); + virtual bool InsertRows(int pos_, c4_Cursor value_, int count_=1); + virtual bool RemoveRows(int pos_, int count_=1); +}; + +c4_PairViewer::c4_PairViewer (c4_Sequence& seq_, const c4_View& view_) + : _parent (&seq_), _argView (view_), _template (_parent.Clone()) +{ + for (int i = 0; i < _argView.NumProperties(); ++i) + _template.AddProperty(_argView.NthProperty(i)); +} + +c4_PairViewer::~c4_PairViewer () +{ +} + +c4_View c4_PairViewer::GetTemplate() +{ + return _template; +} + +int c4_PairViewer::GetSize() +{ + return _parent.GetSize(); +} + +bool c4_PairViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + c4_View v = _parent; + + if (col_ >= v.NumProperties()) + { + v = _argView; + col_ = v.FindProperty(_template.NthProperty(col_).GetId()); + d4_assert(col_ >= 0); + } + + return v.GetItem(row_, col_, buf_); +} + +bool c4_PairViewer::SetItem(int row_, int col_, const c4_Bytes& buf_) +{ + c4_View v = _parent; + + if (col_ >= v.NumProperties()) + { + v = _argView; + col_ = v.FindProperty(_template.NthProperty(col_).GetId()); + d4_assert(col_ >= 0); + } + + v.SetItem(row_, col_, buf_); + return true; +} + +bool c4_PairViewer::InsertRows(int pos_, c4_Cursor value_, int count_) +{ + _parent.InsertAt(pos_, *value_, count_); + _argView.InsertAt(pos_, *value_, count_); + return true; +} + +bool c4_PairViewer::RemoveRows(int pos_, int count_) +{ + _parent.RemoveAt(pos_, count_); + _argView.RemoveAt(pos_, count_); + return true; +} + +c4_CustomViewer* f4_CustPair(c4_Sequence& seq_, const c4_View& view_) +{ + return d4_new c4_PairViewer (seq_, view_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_ConcatViewer : public c4_CustomViewer +{ + c4_View _parent, _argView; + +public: + c4_ConcatViewer (c4_Sequence& seq_, const c4_View& view_); + virtual ~c4_ConcatViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); + bool SetItem(int row_, int col_, const c4_Bytes& buf_); +}; + +c4_ConcatViewer::c4_ConcatViewer (c4_Sequence& seq_, const c4_View& view_) + : _parent (&seq_), _argView (view_) +{ +} + +c4_ConcatViewer::~c4_ConcatViewer () +{ +} + +c4_View c4_ConcatViewer::GetTemplate() +{ + return _parent.Clone(); // could probably return _parent just as well +} + +int c4_ConcatViewer::GetSize() +{ + return _parent.GetSize() + _argView.GetSize(); +} + +bool c4_ConcatViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + c4_View v = _parent; + + if (row_ >= _parent.GetSize()) + { + v = _argView; + row_ -= _parent.GetSize(); + col_ = v.FindProperty(_parent.NthProperty(col_).GetId()); + + if (col_ < 0) + return false; + } + + return v.GetItem(row_, col_, buf_); +} + +bool c4_ConcatViewer::SetItem(int row_, int col_, const c4_Bytes& buf_) +{ + c4_View v = _parent; + + if (row_ >= _parent.GetSize()) + { + v = _argView; + row_ -= _parent.GetSize(); + col_ = v.FindProperty(_parent.NthProperty(col_).GetId()); + d4_assert(col_ >= 0); + } + + v.SetItem(row_, col_, buf_); + return true; +} + +c4_CustomViewer* f4_CustConcat(c4_Sequence& seq_, const c4_View& view_) +{ + return d4_new c4_ConcatViewer (seq_, view_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_RenameViewer : public c4_CustomViewer +{ + c4_View _parent, _template; + +public: + c4_RenameViewer (c4_Sequence& seq_, const c4_Property& old_, + const c4_Property& new_); + virtual ~c4_RenameViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); + virtual bool SetItem(int row_, int col_, const c4_Bytes& buf_); + //virtual bool InsertRows(int pos_, c4_Cursor value_, int count_=1); + //virtual bool RemoveRows(int pos_, int count_=1); +}; + +c4_RenameViewer::c4_RenameViewer (c4_Sequence& seq_, const c4_Property& old_, + const c4_Property& new_) + : _parent (&seq_) +{ + for (int i = 0; i < _parent.NumProperties(); ++i) + { + const c4_Property& prop = _parent.NthProperty(i); + _template.AddProperty(prop.GetId() == old_.GetId() ? new_ : prop); + } +} + +c4_RenameViewer::~c4_RenameViewer () +{ +} + +c4_View c4_RenameViewer::GetTemplate() +{ + return _template; +} + +int c4_RenameViewer::GetSize() +{ + return _parent.GetSize(); +} + +bool c4_RenameViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + return _parent.GetItem(row_, col_, buf_); +} + +bool c4_RenameViewer::SetItem(int row_, int col_, const c4_Bytes& buf_) +{ + _parent.SetItem(row_, col_, buf_); + return true; +} + +c4_CustomViewer* f4_CustRename(c4_Sequence& seq_, const c4_Property& old_, + const c4_Property& new_) +{ + return d4_new c4_RenameViewer (seq_, old_, new_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_GroupByViewer : public c4_CustomViewer +{ + c4_View _parent, _keys, _sorted, _temp; + c4_Property _result; + c4_DWordArray _map; + + int ScanTransitions(int lo_, int hi_, + t4_byte* flags_, const c4_View& match_) const; + +public: + c4_GroupByViewer (c4_Sequence& seq_, const c4_View& keys_, + const c4_Property& result_); + virtual ~c4_GroupByViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); +}; + +c4_GroupByViewer::c4_GroupByViewer (c4_Sequence& seq_, const c4_View& keys_, + const c4_Property& result_) + : _parent (&seq_), _keys (keys_), _result (result_) +{ + _sorted = _parent.SortOn(_keys); + int n = _sorted.GetSize(); + + c4_Bytes temp; + t4_byte* buf = temp.SetBufferClear(n); + + int groups = 0; + if (n > 0) + { + ++buf[0]; // the first entry is always a transition + groups = 1 + ScanTransitions(1, n, buf, _sorted.Project(_keys)); + } + + // set up a map pointing to each transition + _map.SetSize(groups + 1); + int j = 0; + + for (int i = 0; i < n; ++i) + if (buf[i]) + _map.SetAt(j++, i); + + // also append an entry to point just past the end + _map.SetAt(j, n); + + d4_assert(_map.GetAt(0) == 0); + d4_assert(j == groups); +} + +c4_GroupByViewer::~c4_GroupByViewer () +{ +} + +int c4_GroupByViewer::ScanTransitions(int lo_, int hi_, + t4_byte* flags_, const c4_View& match_) const +{ + d4_assert(lo_ > 0); + + int m = hi_ - lo_; + d4_assert(m >= 0); + + // done if nothing left or if entire range is identical + if (m == 0 || match_ [lo_-1] == match_ [hi_-1]) + return 0; + + // range has a transition, done if it is exactly of size one + if (m == 1) + { + ++(flags_[lo_]); + return 1; + } + + // use binary splitting if the range has enough entries + if (m >= 5) + return ScanTransitions(lo_, lo_ + m / 2, flags_, match_) + + ScanTransitions(lo_ + m / 2, hi_, flags_, match_); + + // else use a normal linear scan + int n = 0; + + for (int i = lo_; i < hi_; ++i) + if (match_ [i] != match_ [i-1]) + { + ++(flags_[i]); + ++n; + } + + return n; +} + +c4_View c4_GroupByViewer::GetTemplate() +{ + c4_View v = _keys.Clone(); + v.AddProperty(_result); + + return v; +} + +int c4_GroupByViewer::GetSize() +{ + d4_assert(_map.GetSize() > 0); + + return _map.GetSize() - 1; +} + +bool c4_GroupByViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + if (col_ < _keys.NumProperties()) + return _sorted.GetItem(_map.GetAt(row_), col_, buf_); + + d4_assert(col_ == _keys.NumProperties()); + + t4_i32 count; + switch (_result.Type()) + { + case 'I': count = _map.GetAt(row_ + 1) - _map.GetAt(row_); + buf_ = c4_Bytes (&count, sizeof count, true); + break; + case 'V': _temp = _sorted.Slice(_map.GetAt(row_), _map.GetAt(row_ + 1)) + .ProjectWithout(_keys); + buf_ = c4_Bytes (&_temp, sizeof _temp, true); + break; + default: d4_assert(0); + } + + return true; +} + +c4_CustomViewer* f4_CustGroupBy(c4_Sequence& seq_, const c4_View& template_, + const c4_Property& result_) +{ + return d4_new c4_GroupByViewer (seq_, template_, result_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_JoinPropViewer : public c4_CustomViewer +{ + c4_View _parent, _template; + c4_ViewProp _sub; + int _subPos, _subWidth; + c4_DWordArray _base, _offset; + +public: + c4_JoinPropViewer (c4_Sequence& seq_, const c4_ViewProp& sub_, bool outer_); + virtual ~c4_JoinPropViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); +}; + +c4_JoinPropViewer::c4_JoinPropViewer (c4_Sequence& seq_, + const c4_ViewProp& sub_, bool outer_) + : _parent (&seq_), + _sub (sub_), _subPos (_parent.FindProperty(sub_.GetId())), _subWidth (0) +{ + d4_assert(_subPos >= 0); + + for (int k = 0; k < _parent.NumProperties(); ++k) + { + if (k != _subPos) + _template.AddProperty(_parent.NthProperty(k)); + else // if there are no rows, then this join does very little anyway + //! OOPS: if this is an unattached view, then the subviews can differ + if (_parent.GetSize() > 0) + { + c4_View view = sub_ (_parent[0]); + for (int l = 0; l < view.NumProperties(); ++l) + { + _template.AddProperty(view.NthProperty(l)); + ++_subWidth; + } + } + } + + _base.SetSize(0, 5); + _offset.SetSize(0, 5); + + for (int i = 0; i < _parent.GetSize(); ++i) + { + c4_View v = _sub (_parent[i]); + + int n = v.GetSize(); + if (n == 0 && outer_) + { + _base.Add(i); + _offset.Add(~ (t4_i32) 0); // special null entry for outer joins + } + else + for (int j = 0; j < n; ++j) + { + _base.Add(i); + _offset.Add(j); + } + } +} + +c4_JoinPropViewer::~c4_JoinPropViewer () +{ +} + +c4_View c4_JoinPropViewer::GetTemplate() +{ + return _template; +} + +int c4_JoinPropViewer::GetSize() +{ + return _base.GetSize(); +} + +bool c4_JoinPropViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + c4_View v = _parent; + int r = _base.GetAt(row_); + + if (col_ >= _subPos) + if (col_ >= _subPos + _subWidth) + { + col_ -= _subWidth - 1; + } + else + { + v = _sub (_parent[r]); + r = _offset.GetAt(row_); + if (r < 0) + return false; // if this is a null row in an outer join + + col_ = v.FindProperty(_template.NthProperty(col_).GetId()); + if (col_ < 0) + return false; // if subview doesn't have all properties + } + + return v.GetItem(r, col_, buf_); +} + +c4_CustomViewer* f4_CustJoinProp(c4_Sequence& seq_, + const c4_ViewProp& sub_, bool outer_) +{ + return d4_new c4_JoinPropViewer (seq_, sub_, outer_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_JoinViewer : public c4_CustomViewer +{ + c4_View _parent, _argView, _template; + c4_DWordArray _base, _offset; + +public: + c4_JoinViewer (c4_Sequence& seq_, const c4_View& keys_, + const c4_View& view_, bool outer_); + virtual ~c4_JoinViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); +}; + +c4_JoinViewer::c4_JoinViewer (c4_Sequence& seq_,const c4_View& keys_, + const c4_View& view_, bool outer_) + : _parent (&seq_), _argView (view_.SortOn(keys_)) +{ + // why not in GetTemplate, since we don't need to know this... + _template = _parent.Clone(); + for (int l = 0; l < _argView.NumProperties(); ++l) + _template.AddProperty(_argView.NthProperty(l)); + + c4_View sorted = _parent.SortOn(keys_).Project(keys_); + c4_View temp = _argView.Project(keys_); + + _base.SetSize(0, 5); + _offset.SetSize(0, 5); + + int j = 0, n = 0; + + for (int i = 0; i < sorted.GetSize(); ++i) + { + int orig = _parent.GetIndexOf(sorted[i]); + d4_assert(orig >= 0); + + if (i > 0 && sorted[i] == sorted[i-1]) + { + // if last key was same, repeat the same join + int last = _offset.GetSize() - n; + for (int k = 0; k < n; ++k) + { + _base.Add(orig); + _offset.Add(_offset.GetAt(last + k)); + } + } + else // no, this is a new combination + { + bool match = false; + + // advance until the temp view entry is >= this sorted entry + while (j < temp.GetSize()) + if (sorted[i] <= temp[j]) + { + match = sorted[i] == temp[j]; + break; + } + else + ++j; + + n = 0; + + if (match) + { + do { + _base.Add(orig); + _offset.Add(j); + ++n; + } while (++j < temp.GetSize() && temp[j] == temp[j-1]); + } + else if (outer_) + { + // no match, add an entry anyway if this is an outer join + _base.Add(orig); + _offset.Add(~ (t4_i32) 0); // special null entry + ++n; + } + } + } +} + +c4_JoinViewer::~c4_JoinViewer () +{ +} + +c4_View c4_JoinViewer::GetTemplate() +{ + return _template; +} + +int c4_JoinViewer::GetSize() +{ + return _base.GetSize(); +} + +bool c4_JoinViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + c4_View v = _parent; + int r = _base.GetAt(row_); + + if (col_ >= v.NumProperties()) + { + v = _argView; + r = _offset.GetAt(row_); + if (r < 0) + return false; // if this is a null row in an outer join + + col_ = v.FindProperty(_template.NthProperty(col_).GetId()); + if (col_ < 0) + return false; // if second view doesn't have all properties + } + + return v.GetItem(r, col_, buf_); +} + +#if 0 +bool c4_JoinViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + c4_View v = _parent; + + int o = 0; + int r = _offset.GetAt(row_); + + if (r < 0) + { + o = ~r; + if (o == 0) + return false; // if this is a null row in an outer join + r -= o; + } + + if (col_ >= v.NumProperties()) + { + v = _argView; + r = _o; + + col_ = v.FindProperty(_template.NthProperty(col_)); + if (col_ < 0) + return false; // if second view doesn't have all properties + } + + return v.GetItem(r, col_, buf_); +} +#endif + +c4_CustomViewer* f4_CustJoin(c4_Sequence& seq_, const c4_View& keys_, + const c4_View& view_, bool outer_) +{ + return d4_new c4_JoinViewer (seq_, keys_, view_, outer_); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/custom.h b/akregator/src/mk4storage/metakit/src/custom.h new file mode 100644 index 000000000..80555d3b6 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/custom.h @@ -0,0 +1,63 @@ +// custom.h -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Encapsulation of many custom viewer classes + */ + +#ifndef __CUSTOM_H__ +#define __CUSTOM_H__ + +#ifndef __FIELD_H__ +#include "field.h" +#endif +#ifndef __STORE_H__ +#include "handler.h" +#endif + +///////////////////////////////////////////////////////////////////////////// + +class c4_CustomSeq : public c4_HandlerSeq +{ + c4_CustomViewer* _viewer; + bool _inited; + +public: + c4_CustomSeq (c4_CustomViewer* viewer_); + virtual ~c4_CustomSeq (); + + virtual int NumRows() const; + + virtual bool RestrictSearch(c4_Cursor, int&, int&); + + virtual void InsertAt(int, c4_Cursor, int =1); + virtual void RemoveAt(int, int =1); + virtual void Move(int from_, int); + + bool DoGet(int row_, int col_, c4_Bytes& buf_) const; + void DoSet(int row_, int col_, const c4_Bytes& buf_); + +private: // this *is* used, as override + virtual c4_Handler* CreateHandler(const c4_Property&); +}; + +///////////////////////////////////////////////////////////////////////////// + + extern c4_CustomViewer* f4_CustSlice(c4_Sequence&, int, int , int); + extern c4_CustomViewer* f4_CustProduct(c4_Sequence&, const c4_View&); + extern c4_CustomViewer* f4_CustRemapWith(c4_Sequence&, const c4_View&); + extern c4_CustomViewer* f4_CustPair(c4_Sequence&, const c4_View&); + extern c4_CustomViewer* f4_CustConcat(c4_Sequence&, const c4_View&); + extern c4_CustomViewer* f4_CustRename(c4_Sequence&, + const c4_Property&, const c4_Property&); + extern c4_CustomViewer* f4_CustGroupBy(c4_Sequence&, + const c4_View&, const c4_Property&); + extern c4_CustomViewer* f4_CustJoinProp(c4_Sequence&, + const c4_ViewProp&, bool); + extern c4_CustomViewer* f4_CustJoin(c4_Sequence&, + const c4_View&, const c4_View&, bool); + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/derived.cpp b/akregator/src/mk4storage/metakit/src/derived.cpp new file mode 100644 index 000000000..3baf5e3e7 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/derived.cpp @@ -0,0 +1,1003 @@ +// derived.cpp -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Derived views are virtual views which track changes + */ + +#include "header.h" +#include "handler.h" +#include "store.h" +#include "derived.h" + +#include <stdlib.h> // qsort + +///////////////////////////////////////////////////////////////////////////// +// Implemented in this file + +// class c4_Sequence; + class c4_DerivedSeq; + class c4_FilterSeq; + class c4_SortSeq; + class c4_ProjectSeq; + +///////////////////////////////////////////////////////////////////////////// + +class c4_FilterSeq : public c4_DerivedSeq +{ +protected: + c4_DWordArray _rowMap; + c4_DWordArray _revMap; + c4_Row _lowRow; + c4_Row _highRow; + c4_Bytes _rowIds; + +protected: + c4_FilterSeq (c4_Sequence& seq_); + virtual ~c4_FilterSeq (); + + void FixupReverseMap(); + int PosInMap(int index_) const; + bool Match(int index_, c4_Sequence& seq_, + const int* =0, const int* =0) const; + bool MatchOne(int prop_, const c4_Bytes& data_) const; + +public: + c4_FilterSeq (c4_Sequence& seq_, c4_Cursor low_, c4_Cursor high_); + + virtual int RemapIndex(int, const c4_Sequence*) const; + + virtual int NumRows() const; + + virtual int Compare(int, c4_Cursor) const; + virtual bool Get(int, int, c4_Bytes&); + + virtual void InsertAt(int, c4_Cursor, int =1); + virtual void RemoveAt(int, int =1); + virtual void Set(int, const c4_Property&, const c4_Bytes&); + virtual void SetSize(int); + + virtual c4_Notifier* PreChange(c4_Notifier& nf_); + virtual void PostChange(c4_Notifier& nf_); +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_FilterSeq::c4_FilterSeq (c4_Sequence& seq_) + : c4_DerivedSeq (seq_) +{ + _rowMap.SetSize(_seq.NumRows()); + _revMap.SetSize(_seq.NumRows()); + d4_assert(NumRows() == _seq.NumRows()); + + for (int i = 0; i < NumRows(); ++i) + { + _rowMap.SetAt(i, i); + _revMap.SetAt(i, i); + } +} + +c4_FilterSeq::c4_FilterSeq (c4_Sequence& seq_, c4_Cursor low_, + c4_Cursor high_) + : c4_DerivedSeq (seq_), _lowRow (*low_), _highRow (*high_) +{ + d4_assert((&_lowRow)._index == 0); + d4_assert((&_highRow)._index == 0); + + // use a sneaky way to obtain the sequence pointers and indices + c4_Sequence* lowSeq = (& _lowRow)._seq; + c4_Sequence* highSeq = (& _highRow)._seq; + d4_assert(lowSeq && highSeq); + + // prepare column numbers to avoid looking them up on every row + // lowCols is a vector of column numbers to use for the low limits + // highCols is a vector of column numbers to use for the high limits + int nl = lowSeq->NumHandlers(), nh = highSeq->NumHandlers(); + c4_Bytes lowVec, highVec; + int* lowCols = (int*) lowVec.SetBufferClear(nl * sizeof (int)); + int* highCols = (int*) highVec.SetBufferClear(nh * sizeof (int)); + + for (int il = 0; il < nl; ++il) + lowCols[il] = seq_.PropIndex(lowSeq->NthPropId(il)); + for (int ih = 0; ih < nh; ++ih) + highCols[ih] = seq_.PropIndex(highSeq->NthPropId(ih)); + + // set _rowIds flag buffer for fast matching + { + int max = -1; + + { + for (int i1 = 0; i1 < nl; ++i1) + { + int n = lowSeq->NthPropId(i1); + if (max < n) + max = n; + } + for (int i2 = 0; i2 < nh; ++i2) + { + int n = highSeq->NthPropId(i2); + if (max < n) + max = n; + } + } + + t4_byte* p = _rowIds.SetBufferClear(max + 1); + + { + for (int i1 = 0; i1 < nl; ++i1) + p[lowSeq->NthPropId(i1)] |= 1; + for (int i2 = 0; i2 < nh; ++i2) + p[highSeq->NthPropId(i2)] |= 2; + } + } + + // now go through all rows and select the ones that are in range + + _rowMap.SetSize(_seq.NumRows()); // avoid growing, use safe upper bound + + int n = 0; + + for (int i = 0; i < _seq.NumRows(); ++i) + if (Match(i, _seq, lowCols, highCols)) + _rowMap.SetAt(n++, i); + + _rowMap.SetSize(n); + + FixupReverseMap(); +} + +c4_FilterSeq::~c4_FilterSeq () +{ +} + +void c4_FilterSeq::FixupReverseMap() +{ + int n = _seq.NumRows(); + + _revMap.SetSize(0); + + if (n > 0) + { + _revMap.InsertAt(0, ~ (t4_i32) 0, n); //! + + for (int i = 0; i < _rowMap.GetSize(); ++i) + _revMap.SetAt((int) _rowMap.GetAt(i), i); + } +} + +bool c4_FilterSeq::MatchOne(int prop_, const c4_Bytes& data_) const +{ + d4_assert(prop_ < _rowIds.Size()); + + t4_byte flag = _rowIds.Contents()[prop_]; + d4_assert(flag); + + if (flag & 1) + { + c4_Sequence* lowSeq = (& _lowRow)._seq; + + c4_Handler& h = lowSeq->NthHandler(lowSeq->PropIndex(prop_)); + if (h.Compare(0, data_) > 0) + return false; + } + + if (flag & 2) + { + c4_Sequence* highSeq = (& _highRow)._seq; + + c4_Handler& h = highSeq->NthHandler(highSeq->PropIndex(prop_)); + if (h.Compare(0, data_) < 0) + return false; + } + + return true; +} + +bool c4_FilterSeq::Match(int index_, c4_Sequence& seq_, + const int* lowCols_, const int* highCols_) const +{ + // use a sneaky way to obtain the sequence pointers and indices + c4_Sequence* lowSeq = (& _lowRow)._seq; + c4_Sequence* highSeq = (& _highRow)._seq; + d4_assert(lowSeq && highSeq); + + int nl = lowSeq->NumHandlers(), nh = highSeq->NumHandlers(); + + c4_Bytes data; + + // check each of the lower limits + for (int cl = 0; cl < nl; ++cl) + { + c4_Handler& hl = lowSeq->NthHandler(cl); + + int n = lowCols_ ? lowCols_[cl] + : seq_.PropIndex(lowSeq->NthPropId(cl)); + if (n >= 0) + { + c4_Handler& h = seq_.NthHandler(n); + const c4_Sequence* hc = seq_.HandlerContext(n); + int i = seq_.RemapIndex(index_, hc); + + h.GetBytes(i, data); + } + else + hl.ClearBytes(data); + + if (hl.Compare(0, data) > 0) + return false; + } + + // check each of the upper limits + for (int ch = 0; ch < nh; ++ch) + { + c4_Handler& hh = highSeq->NthHandler(ch); + + int n = highCols_ ? highCols_[ch] + : seq_.PropIndex(highSeq->NthPropId(ch)); + if (n >= 0) + { + c4_Handler& h = seq_.NthHandler(n); + const c4_Sequence* hc = seq_.HandlerContext(n); + int i = seq_.RemapIndex(index_, hc); + + h.GetBytes(i, data); + } + else + hh.ClearBytes(data); + + if (hh.Compare(0, data) < 0) + return false; + } + + return true; +} + +int c4_FilterSeq::RemapIndex(int index_, const c4_Sequence* seq_) const +{ + return seq_ == this ? index_ + : _seq.RemapIndex((int) _rowMap.GetAt(index_), seq_); +} + +int c4_FilterSeq::NumRows() const +{ + return _rowMap.GetSize(); +} + +int c4_FilterSeq::Compare(int index_, c4_Cursor cursor_) const +{ + return _seq.Compare((int) _rowMap.GetAt(index_), cursor_); +} + +bool c4_FilterSeq::Get(int index_, int propId_, c4_Bytes& bytes_) +{ + return _seq.Get((int) _rowMap.GetAt(index_), propId_, bytes_); +} + +void c4_FilterSeq::InsertAt(int, c4_Cursor, int) +{ + d4_assert(0); +} + +void c4_FilterSeq::RemoveAt(int, int) +{ + d4_assert(0); +} + +void c4_FilterSeq::Set(int, const c4_Property&, const c4_Bytes&) +{ + d4_assert(0); +} + +void c4_FilterSeq::SetSize(int) +{ + d4_assert(0); +} + +int c4_FilterSeq::PosInMap(int index_) const +{ + int i = 0; + + while (i < NumRows()) + if ((int) _rowMap.GetAt(i) >= index_) + break; + else + ++i; + + return i; +} + +c4_Notifier* c4_FilterSeq::PreChange(c4_Notifier& nf_) +{ + if (!GetDependencies()) + return 0; + + c4_Notifier* chg = d4_new c4_Notifier (this); + + bool pass = false; + + switch (nf_._type) + { + case c4_Notifier::kSet: + pass = nf_._propId >= _rowIds.Size() || + _rowIds.Contents()[nf_._propId] == 0; + // fall through... + + case c4_Notifier::kSetAt: + { + int r = (int) _revMap.GetAt(nf_._index); + + bool includeRow = r >= 0; + if (!pass) + if (nf_._type == c4_Notifier::kSetAt) + { + d4_assert(nf_._cursor != 0); + includeRow = Match(nf_._cursor->_index, + *nf_._cursor->_seq); + } + else // set just one property, and it's not in a row yet + includeRow = MatchOne(nf_._propId, *nf_._bytes); + + if (r >= 0 && !includeRow) + chg->StartRemoveAt(r, 1); + else if (r < 0 && includeRow) + chg->StartInsertAt(PosInMap(nf_._index), *nf_._cursor, 1); + else if (includeRow) + { + d4_assert(r >= 0); + + if (nf_._type == c4_Notifier::kSetAt) + chg->StartSetAt(r, *nf_._cursor); + else + chg->StartSet(r, nf_._propId, *nf_._bytes); + } + } + break; + + case c4_Notifier::kInsertAt: + { + int i = PosInMap(nf_._index); + + d4_assert(nf_._cursor != 0); + if (Match(nf_._cursor->_index, *nf_._cursor->_seq)) + chg->StartInsertAt(i, *nf_._cursor, nf_._count); + } + break; + + case c4_Notifier::kRemoveAt: + { + int i = PosInMap(nf_._index); + int j = PosInMap(nf_._index + nf_._count); + d4_assert(j >= i); + + if (j > i) + chg->StartRemoveAt(i, j - i); + } + break; + + case c4_Notifier::kMove: + { + int i = PosInMap(nf_._index); + bool inMap = i < NumRows() && (int) _rowMap.GetAt(i) == nf_._index; + + if (inMap && nf_._index != nf_._count) + chg->StartMove(i, PosInMap(nf_._count)); + } + break; + } + + return chg; +} + +void c4_FilterSeq::PostChange(c4_Notifier& nf_) +{ + bool pass = false; + + switch (nf_._type) + { + case c4_Notifier::kSet: + pass = nf_._propId >= _rowIds.Size() || + _rowIds.Contents()[nf_._propId] == 0; + // fall through... + + case c4_Notifier::kSetAt: + { + int r = (int) _revMap.GetAt(nf_._index); + + bool includeRow = r >= 0; + if (!pass) + if (nf_._type == c4_Notifier::kSetAt) + { + d4_assert(nf_._cursor != 0); + includeRow = Match(nf_._cursor->_index, + *nf_._cursor->_seq); + } + else // set just one property, and it's not in a row yet + includeRow = MatchOne(nf_._propId, *nf_._bytes); + + if (r >= 0 && !includeRow) + _rowMap.RemoveAt(r); + else if (r < 0 && includeRow) + _rowMap.InsertAt(PosInMap(nf_._index), nf_._index); + else + break; + + FixupReverseMap(); + } + break; + + case c4_Notifier::kInsertAt: + { + int i = PosInMap(nf_._index); + + if (Match(nf_._index, _seq)) + { + _rowMap.InsertAt(i, 0, nf_._count); + + for (int j = 0; j < nf_._count; ++j) + _rowMap.SetAt(i++, nf_._index + j); + } + + while (i < NumRows()) + _rowMap.ElementAt(i++) += nf_._count; + + FixupReverseMap(); + } + break; + + case c4_Notifier::kRemoveAt: + { + int i = PosInMap(nf_._index); + int j = PosInMap(nf_._index + nf_._count); + d4_assert(j >= i); + + if (j > i) + _rowMap.RemoveAt(i, j - i); + + while (i < NumRows()) + _rowMap.ElementAt(i++) -= nf_._count; + + FixupReverseMap(); + } + break; + + case c4_Notifier::kMove: + { + int i = PosInMap(nf_._index); + bool inMap = i < NumRows() && (int) _rowMap.GetAt(i) == nf_._index; + + if (inMap && nf_._index != nf_._count) + { + int j = PosInMap(nf_._count); + + _rowMap.RemoveAt(i); + + if (j > i) + --j; + + _rowMap.InsertAt(j, nf_._count); + + FixupReverseMap(); + } + } + break; + } +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_SortSeq : public c4_FilterSeq +{ +public: + typedef t4_i32 T; + + c4_SortSeq (c4_Sequence& seq_, c4_Sequence* down_); + virtual ~c4_SortSeq (); + + virtual c4_Notifier* PreChange(c4_Notifier& nf_); + virtual void PostChange(c4_Notifier& nf_); + +private: + struct c4_SortInfo + { + c4_Handler* _handler; + const c4_Sequence* _context; + c4_Bytes _buffer; + + int CompareOne(c4_Sequence& seq_, T a, T b) + { + _handler->GetBytes(seq_.RemapIndex((int) b, _context), _buffer, true); + return _handler->Compare(seq_.RemapIndex((int) a, _context), _buffer); + } + }; + + bool LessThan(T a, T b); + bool TestSwap( T& first , T& second ); + void MergeSortThis( T* ar, int size , T scratch[] ); + void MergeSort( T ar[] , int size ); + + virtual int Compare(int, c4_Cursor) const; + int PosInMap(c4_Cursor cursor_) const; + + c4_SortInfo* _info; + c4_Bytes _down; + int _width; +}; + +///////////////////////////////////////////////////////////////////////////// + +bool c4_SortSeq::LessThan(T a, T b) +{ + if (a == b) + return false; + + // go through each of the columns and compare values, but since + // handler access is used, we must be careful to remap indices + + c4_SortInfo* info; + + for (info = _info; info->_handler; ++info) + { + int f = info->CompareOne(_seq, a, b); + if (f) + { + int n = info - _info; + if (_width < n) + _width = n; + + return (_down.Contents()[n] ? -f : f) < 0; + } + } + + _width = info - _info; + return a < b; +} + +inline bool c4_SortSeq::TestSwap( T& first , T& second ) +{ + if ( LessThan( second , first ) ) + { + T temp = first; first = second; second = temp; + return true; + } + + return false; +} + +void c4_SortSeq::MergeSortThis( T* ar, int size , T scratch[] ) +{ + switch( size ) + { + //Handle the special cases for speed: + case 2: + TestSwap( ar[ 0 ] , ar[ 1 ] ); + break; + + case 3: + TestSwap( ar[ 0 ] , ar[ 1 ] ); + if ( TestSwap( ar[ 1 ] , ar[ 2 ] ) ) + TestSwap( ar[ 0 ] , ar[ 1 ] ); + break; + + case 4: + //Gotta optimize this.... + TestSwap( ar[ 0 ] , ar[ 1 ] ); + TestSwap( ar[ 2 ] , ar[ 3 ] ); + TestSwap( ar[ 0 ] , ar[ 2 ] ); + TestSwap( ar[ 1 ] , ar[ 3 ] ); + TestSwap( ar[ 1 ] , ar[ 2 ] ); + break; + + //Gotta do special case for list of five. + + default: + //Subdivide the list, recurse, and merge + { + int s1 = size / 2; + int s2 = size - s1; + T* from1_ = scratch; + T* from2_ = scratch + s1; + MergeSortThis( from1_ , s1 , ar ); + MergeSortThis( from2_ , s2 , ar + s1 ); + + T* to1_ = from1_ + s1; + T* to2_ = from2_ + s2; + + for (;;) + { + if ( LessThan( *from1_, *from2_) ) + { + *ar++ = *from1_++; + + if (from1_ >= to1_) + { + while( from2_ < to2_ ) + *ar++ = *from2_++; + break; + } + } + else + { + *ar++ = *from2_++; + + if (from2_ >= to2_) + { + while( from1_ < to1_ ) + *ar++ = *from1_++; + break; + } + } + } + } + } +} + +void c4_SortSeq::MergeSort( T ar[] , int size ) +{ + if ( size > 1 ) + { + T* scratch = d4_new T [size]; + memcpy(scratch , ar , size * sizeof (T)); + MergeSortThis(ar , size , scratch); + delete [] scratch; + } +} + +c4_SortSeq::c4_SortSeq (c4_Sequence& seq_, c4_Sequence* down_) + : c4_FilterSeq (seq_), _info (0), _width (-1) +{ + d4_assert(NumRows() == seq_.NumRows()); + + if (NumRows() > 0) + { + // down is a vector of flags, true to sort in reverse order + char* down = (char*) _down.SetBufferClear(NumHandlers()); + + // set the down flag for all properties to be sorted in reverse + if (down_) + for (int i = 0; i < NumHandlers(); ++i) + if (down_->PropIndex(NthPropId(i)) >= 0) + down[i] = 1; + + _width = -1; + int n = NumHandlers() + 1; + _info = d4_new c4_SortInfo [n]; + + int j; + + for (j = 0; j < NumHandlers(); ++j) + { + _info[j]._handler = & _seq.NthHandler(j); + _info[j]._context = _seq.HandlerContext(j); + } + + _info[j]._handler = 0; + + // everything is ready, go sort the row index vector + MergeSort((T*) &_rowMap.ElementAt(0), NumRows()); + + delete [] _info; + _info = 0; + + FixupReverseMap(); + } +} + +c4_SortSeq::~c4_SortSeq () +{ + d4_assert(!_info); +} + +int c4_SortSeq::Compare(int index_, c4_Cursor cursor_) const +{ + d4_assert(cursor_._seq != 0); + + const char* down = (const char*) _down.Contents(); + d4_assert(_down.Size() <= NumHandlers()); + + c4_Bytes data; + + for (int colNum = 0; colNum < NumHandlers(); ++colNum) + { + c4_Handler& h = NthHandler(colNum); + const c4_Sequence* hc = HandlerContext(colNum); + + if (!cursor_._seq->Get(cursor_._index, h.PropId(), data)) + h.ClearBytes(data); + + int f = h.Compare(RemapIndex(index_, hc), data); + if (f != 0) + return colNum < _down.Size() && down[colNum] ? -f : +f; + } + + return 0; +} + +int c4_SortSeq::PosInMap(c4_Cursor cursor_) const +{ + int i = 0; + + while (i < NumRows()) + if (Compare(i, cursor_) >= 0) + break; + else + ++i; + + d4_assert(i == NumRows() || Compare(i, cursor_) >= 0); + return i; +} + +c4_Notifier* c4_SortSeq::PreChange(c4_Notifier& /*nf_*/) +{ + if (!GetDependencies()) + return 0; + +#if 0 + c4_Notifier* chg = d4_new c4_Notifier (this); + + switch (nf_._type) + { + case c4_Notifier::kSetAt: + case c4_Notifier::kSet: + { + d4_assert(0); // also needs nested propagation + + /* + change can require a move *and* a change of contents + */ + } + break; + + case c4_Notifier::kInsertAt: + { + d4_assert(0); // this case isn't really difficult + } + break; + + case c4_Notifier::kRemoveAt: + { + d4_assert(0); // nested propagation is too difficult for now + // i.e. can only use sort as last derived view + /* + possible solution: + + if 1 row, simple + else if contig in map, also simple + else propagate reorder first, then delete contig + + it can be done here, as multiple notifications, + by simulating n-1 SetAt's of first row in others + needs some map juggling, allow temp dup entries? + + or perhaps more consistent with n separate removes + */ + } + break; + + case c4_Notifier::kMove: + { + // incorrect: may need to move if recnum matters (recs same) + } + break; + } + + return chg; +#endif + +// d4_assert(0); // fail, cannot handle a view dependent on this one yet + return 0; +} + +void c4_SortSeq::PostChange(c4_Notifier& nf_) +{ + switch (nf_._type) + { + case c4_Notifier::kSet: + if (_seq.PropIndex(nf_._propId) > _width) + break; // cannot affect sort order, valuable optimization + + case c4_Notifier::kSetAt: + { + int oi = (int) _revMap.GetAt(nf_._index); + d4_assert(oi >= 0); + + c4_Cursor cursor (_seq, nf_._index); + + // move the entry if the sort order has been disrupted + if ((oi > 0 && Compare(oi - 1, cursor) > 0) || + (oi+1 < NumRows() && Compare(oi+1, cursor) < 0)) + { + _rowMap.RemoveAt(oi); + _rowMap.InsertAt(PosInMap(cursor), nf_._index); + + FixupReverseMap(); + } + + _width = NumHandlers(); // sorry, no more optimization + } + break; + + case c4_Notifier::kInsertAt: + { + // if cursor was not set, it started out as a single Set + c4_Cursor cursor (_seq, nf_._index); + if (nf_._cursor) + cursor = *nf_._cursor; + + for (int n = 0; n < NumRows(); ++n) + if ((int) _rowMap.GetAt(n) >= nf_._index) + _rowMap.ElementAt(n) += nf_._count; + + int i = PosInMap(cursor); + _rowMap.InsertAt(i, 0, nf_._count); + + for (int j = 0; j < nf_._count; ++j) + _rowMap.SetAt(i++, nf_._index + j); + + FixupReverseMap(); + + _width = NumHandlers(); // sorry, no more optimization + } + break; + + case c4_Notifier::kRemoveAt: + { + int lo = nf_._index; + int hi = nf_._index + nf_._count; + + int j = 0; + for (int i = 0; i < NumRows(); ++i) + { + int n = (int) _rowMap.GetAt(i); + + if (n >= hi) + _rowMap.ElementAt(i) -= nf_._count; + + if (!(lo <= n && n < hi)) + _rowMap.SetAt(j++, _rowMap.GetAt(i)); + } + + d4_assert(j + nf_._count == NumRows()); + _rowMap.SetSize(j); + + FixupReverseMap(); + + _width = NumHandlers(); // sorry, no more optimization + } + break; + + case c4_Notifier::kMove: + { + // incorrect: may need to move if recnum matters (recs same) + } + break; + } +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_ProjectSeq : public c4_DerivedSeq +{ + c4_DWordArray _colMap; // a bit large, but bytes would be too small + bool _frozen; + int _omitCount; // if > 0 then this is a dynamic "project without" + +public: + c4_ProjectSeq (c4_Sequence& seq_, c4_Sequence& in_, bool, c4_Sequence* out_); + virtual ~c4_ProjectSeq (); + + virtual int NumHandlers() const; + virtual c4_Handler& NthHandler(int) const; + virtual const c4_Sequence* HandlerContext(int) const; + virtual int AddHandler(c4_Handler*); + + virtual bool Get(int, int, c4_Bytes&); + virtual void Set(int, const c4_Property&, const c4_Bytes&); +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_ProjectSeq::c4_ProjectSeq (c4_Sequence& seq_, c4_Sequence& in_, + bool reorder_, c4_Sequence* out_) + : c4_DerivedSeq (seq_), _frozen (!reorder_ && !out_), _omitCount (0) +{ + // build the array with column indexes + for (int j = 0; j < in_.NumHandlers(); ++j) + { + int propId = in_.NthPropId(j); + int idx = _seq.PropIndex(propId); + + // if the j'th property is in the sequence, add it + if (idx >= 0) + { + // but only if it's not in the out_ view + if (out_ && out_->PropIndex(propId) >= 0) + ++_omitCount; + else + _colMap.Add(idx); + } + } + + // if only reordering, append remaining columns from original view + if (reorder_) + { + for (int i = 0; i < _seq.NumHandlers(); ++i) + { + int propId = _seq.NthPropId(i); + + // only consider properties we did not deal with before + if (in_.PropIndex(propId) < 0) + _colMap.Add(i); + } + + d4_assert(_colMap.GetSize() == _seq.NumHandlers()); + } +} + +c4_ProjectSeq::~c4_ProjectSeq () +{ +} + +int c4_ProjectSeq::NumHandlers() const +{ + return _frozen ? _colMap.GetSize() : _seq.NumHandlers() - _omitCount; +} + +c4_Handler& c4_ProjectSeq::NthHandler(int colNum_) const +{ + int n = colNum_ < _colMap.GetSize() ? _colMap.GetAt(colNum_) : colNum_; + return _seq.NthHandler(n); +} + +const c4_Sequence* c4_ProjectSeq::HandlerContext(int colNum_) const +{ + int n = colNum_ < _colMap.GetSize() ? _colMap.GetAt(colNum_) : colNum_; + return _seq.HandlerContext(n); +} + +int c4_ProjectSeq::AddHandler(c4_Handler* handler_) +{ + int n = _seq.AddHandler(handler_); + return _frozen ? _colMap.Add(n) : n - _omitCount; +} + +bool c4_ProjectSeq::Get(int index_, int propId_, c4_Bytes& buf_) +{ + // fixed in 1.8: check that the property is visible + return PropIndex(propId_) >= 0 && _seq.Get(index_, propId_, buf_); +} + +void c4_ProjectSeq::Set(int index_, const c4_Property& prop_, const c4_Bytes& bytes_) +{ + int n = _seq.NumHandlers(); + _seq.Set(index_, prop_, bytes_); + + // if the number of handlers changed, then one must have been added + if (n != _seq.NumHandlers()) + { + d4_assert(n == _seq.NumHandlers() - 1); + + if (_frozen) + _colMap.Add(n); + } +} + +///////////////////////////////////////////////////////////////////////////// + +c4_Sequence* f4_CreateFilter(c4_Sequence& seq_, c4_Cursor l_, c4_Cursor h_) +{ + return d4_new c4_FilterSeq (seq_, l_, h_); +} + +c4_Sequence* f4_CreateSort(c4_Sequence& seq_, c4_Sequence* down_) +{ + return d4_new c4_SortSeq (seq_, down_); +} + +c4_Sequence* f4_CreateProject(c4_Sequence& seq_, c4_Sequence& in_, + bool reorder_, c4_Sequence* out_) +{ + return d4_new c4_ProjectSeq (seq_, in_, reorder_, out_); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/derived.h b/akregator/src/mk4storage/metakit/src/derived.h new file mode 100644 index 000000000..8bd934fc9 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/derived.h @@ -0,0 +1,25 @@ +// derived.h -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Encapsulation of derived view classes + */ + +#ifndef __DERIVED_H__ +#define __DERIVED_H__ + +///////////////////////////////////////////////////////////////////////////// +// Declarations in this file + + class c4_Cursor; // not defined here + class c4_Sequence; // not defined here + + extern c4_Sequence* f4_CreateFilter(c4_Sequence&, c4_Cursor, c4_Cursor); + extern c4_Sequence* f4_CreateSort(c4_Sequence&, c4_Sequence* =0); + extern c4_Sequence* f4_CreateProject(c4_Sequence&, c4_Sequence&, + bool, c4_Sequence* =0); + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/field.cpp b/akregator/src/mk4storage/metakit/src/field.cpp new file mode 100644 index 000000000..3867d6b5c --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/field.cpp @@ -0,0 +1,119 @@ +// field.cpp -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Implementation of the field structure tree + */ + +#include "header.h" +#include "field.h" + +#include <stdlib.h> // strtol + +#if !q4_INLINE +#include "field.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// +// Implemented in this file + + class c4_Field; + +///////////////////////////////////////////////////////////////////////////// +// c4_Field + +c4_Field::c4_Field (const char*& description_, c4_Field* parent_) + : _type (0) +{ + _indirect = this; + + size_t n = strcspn(description_, ",[]"); + const char* p = strchr(description_, ':'); + + if (p != 0 && p < description_ + n) { + _name = c4_String (description_, p - description_); + _type = p[1] & ~0x20; // force to upper case + } else { + _name = c4_String (description_, n); + _type = 'S'; + } + + description_ += n; + + if (*description_ == '[') { + ++description_; + _type = 'V'; + + if (*description_ == '^') { + ++description_; + _indirect = parent_; + d4_assert(*description_ == ']'); + } + + if (*description_ == ']') + ++description_; + else + do { + // 2004-01-20 ignore duplicate property names + // (since there is no good way to report errors at this point) + c4_Field* sf = d4_new c4_Field (description_, this); + for (int i = 0; i < NumSubFields(); ++i) + if (SubField(i).Name().CompareNoCase(sf->Name()) == 0) { + delete sf; + sf = 0; + break; + } + if (sf != 0) + _subFields.Add(sf); + } while (*description_++ == ','); + } +} + +c4_Field::~c4_Field () +{ + if (_indirect == this) { + //better? for (int i = NumSubFields(); --i >= 0 ;) + for (int i = 0; i < NumSubFields(); ++i) { + c4_Field* sf = & SubField(i); + if (sf != this) // careful with recursive subfields + delete sf; + } + } +} + +c4_String c4_Field::Description(bool anonymous_) const +{ + c4_String s = anonymous_ ? "?" : (const char*) Name(); + + if (Type() == 'V') + s += "[" + DescribeSubFields(anonymous_) + "]"; + else { + s += ":"; + s += (c4_String) Type(); + } + + return s; +} + +c4_String c4_Field::DescribeSubFields(bool) const +{ + d4_assert(Type() == 'V'); + + if (_indirect != this) + return "^"; + + c4_String s; + char c = 0; + + for (int i = 0; i < NumSubFields(); ++i) { + if (c != 0) + s += (c4_String) c; + s += SubField(i).Description(); + c = ','; + } + + return s; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/field.h b/akregator/src/mk4storage/metakit/src/field.h new file mode 100644 index 000000000..5dfc25736 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/field.h @@ -0,0 +1,64 @@ +// field.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Core class to represent fields + */ + +#ifndef __FIELD_H__ +#define __FIELD_H__ + +#ifndef __K4CONF_H__ +#error Please include "k4conf.h" before this header file +#endif + +///////////////////////////////////////////////////////////////////////////// + +class c4_Field +{ + c4_PtrArray _subFields; + c4_String _name; + char _type; + c4_Field* _indirect; + +public: +/* Construction / destruction */ + c4_Field (const char*&, c4_Field* =0); + //: Constructs a new field. + ~c4_Field (); + +/* Repeating and compound fields */ + int NumSubFields() const; + //: Returns the number of subfields. + c4_Field& SubField(int) const; + //: Returns the description of each subfield. + bool IsRepeating() const; + //: Returns true if this field contains subtables. + +/* Field name and description */ + const c4_String& Name() const; + //: Returns name of this field. + char Type() const; + //: Returns the type description of this field, if any. + char OrigType() const; + //: Similar, but report types which were originall 'M' as well. + c4_String Description(bool anonymous_ =false) const; + //: Describes the structure, omit names if anonymous. + c4_String DescribeSubFields(bool anonymous_ =false) const; + //: Describes just the subfields, omit names if anonymous. + +private: + c4_Field (const c4_Field&); // not implemented + void operator= (const c4_Field&); // not implemented +}; + +///////////////////////////////////////////////////////////////////////////// + +#if q4_INLINE +#include "field.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/field.inl b/akregator/src/mk4storage/metakit/src/field.inl new file mode 100644 index 000000000..823e626e3 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/field.inl @@ -0,0 +1,37 @@ +// field.inl -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Inlined members of the field class + */ + +d4_inline bool c4_Field::IsRepeating() const +{ + return _type == 'V'; +} + +d4_inline int c4_Field::NumSubFields() const +{ + return _indirect->_subFields.GetSize(); +} + +d4_inline c4_Field& c4_Field::SubField(int index_) const +{ + return *(c4_Field*) _indirect->_subFields.GetAt(index_); +} + +d4_inline const c4_String& c4_Field::Name() const +{ + return _name; +} + +d4_inline char c4_Field::OrigType() const +{ + return _type; +} + +d4_inline char c4_Field::Type() const +{ + return _type == 'M' ? 'B' : _type; +} diff --git a/akregator/src/mk4storage/metakit/src/fileio.cpp b/akregator/src/mk4storage/metakit/src/fileio.cpp new file mode 100644 index 000000000..28ff7dca0 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/fileio.cpp @@ -0,0 +1,434 @@ +// fileio.cpp -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Implementation of c4_FileStrategy and c4_FileStream + */ + +#include "header.h" +#include "mk4io.h" + +#if q4_WIN32 +#if q4_MSVC && !q4_STRICT +#pragma warning(disable: 4201) // nonstandard extension used : ... +#endif +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#if !defined (q4_WINCE) +#include <io.h> +#include <fcntl.h> +#include <sys/stat.h> +#endif +#endif + +#if q4_UNIX && HAVE_MMAP +#include <sys/types.h> +#include <sys/mman.h> +#endif + +#if q4_UNIX +#include <unistd.h> +#include <fcntl.h> +#endif + +#if q4_WINCE +#define _get_osfhandle(x) x +#endif + +#ifndef _O_NOINHERIT +#define _O_NOINHERIT 0 +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// The "Carbon" version of a build on Macintosh supports running under +// either MacOS 7..9 (which has no mmap), or MacOS X (which has mmap). +// The logic below was adapted from a contribution by Paul Snively, it +// decides at run time which case it is, and switches I/O calls to match. + +#if defined (q4_CARBON) && q4_CARBON +//#if q4_MAC && !defined (__MACH__) && (!q4_MWCW || __MWERKS__ >= 0x3000) +#undef HAVE_MMAP +#define HAVE_MMAP 1 + +#include <CFBundle.h> +#include <Folders.h> + +#define PROT_NONE 0x00 +#define PROT_READ 0x01 +#define PROT_WRITE 0x02 +#define PROT_EXEC 0x04 + +#define MAP_SHARED 0x0001 +#define MAP_PRIVATE 0x0002 + +#define MAP_FIXED 0x0010 +#define MAP_RENAME 0x0020 +#define MAP_NORESERVE 0x0040 +#define MAP_INHERIT 0x0080 +#define MAP_NOEXTEND 0x0100 +#define MAP_HASSEMAPHORE 0x0200 + +typedef unsigned long t4_u32; + +static t4_u32 sfwRefCount = 0; +static CFBundleRef systemFramework = NULL; + +static char* fake_mmap(char*, t4_u32, int, int, int, long long) + { return (char*) -1L; } +static int fake_munmap(char*, t4_u32) + { return 0; } + +static FILE* (*my_fopen)(const char*,const char*) = fopen; +static int (*my_fclose)(FILE*) = fclose; +static long (*my_ftell)(FILE*) = ftell; +static int (*my_fseek)(FILE*,long,int) = fseek; +static t4_u32 (*my_fread)(void* ptr,t4_u32,t4_u32,FILE*) = fread; +static t4_u32 (*my_fwrite)(const void* ptr,t4_u32,t4_u32,FILE*) = fwrite; +static int (*my_ferror)(FILE*) = ferror; +static int (*my_fflush)(FILE*) = fflush; +static int (*my_fileno)(FILE*) = fileno; +static char* (*my_mmap)(char*,t4_u32,int,int,int,long long) = fake_mmap; +static int (*my_munmap)(char*,t4_u32) = fake_munmap; + +static void InitializeIO() +{ + if (sfwRefCount++) return; // race condition, infinitesimal risk + + FSRef theRef; + if (FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, + false, &theRef) == noErr) { + CFURLRef fw = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &theRef); + if (fw) { + CFURLRef bd = + CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, + fw, CFSTR("System.framework"), false); + CFRelease(fw); + if (bd) { + systemFramework = CFBundleCreate(kCFAllocatorSystemDefault, bd); + CFRelease(bd); + } + } + if (!systemFramework || !CFBundleLoadExecutable(systemFramework)) + return; +#define F(x) CFBundleGetFunctionPointerForName(systemFramework, CFSTR(#x)) + my_fopen = (FILE* (*)(const char*,const char*)) F(fopen); + my_fclose = (int (*)(FILE*)) F(fclose); + my_ftell = (long (*)(FILE*)) F(ftell); + my_fseek = (int (*)(FILE*,long,int)) F(fseek); + my_fread = (t4_u32 (*)(void* ptr,t4_u32,t4_u32,FILE*)) F(fread); + my_fwrite = (t4_u32 (*)(const void* ptr,t4_u32,t4_u32,FILE*)) F(fwrite); + my_ferror = (int (*)(FILE*)) F(ferror); + my_fflush = (int (*)(FILE*)) F(fflush); + my_fileno = (int (*)(FILE*)) F(fileno); + my_mmap = (char* (*)(char*,t4_u32,int,int,int,long long)) F(mmap); + my_munmap = (int (*)(char*,t4_u32)) F(munmap); +#undef F + d4_assert(my_fopen && my_fclose && my_ftell && my_fseek && + my_fread && my_fwrite && my_ferror && my_fflush && + my_fileno && my_mmap && my_munmap); + } +} + +static void FinalizeIO() +{ + if (--sfwRefCount) return; // race condition, infinitesimal risk + + if (systemFramework) { + CFBundleUnloadExecutable(systemFramework); + CFRelease(systemFramework); + systemFramework = 0; + } +} + +#define fopen my_fopen +#define fclose my_fclose +#define ftell my_ftell +#define fseek my_fseek +#define fread my_fread +#define fwrite my_fwrite +#define ferror my_ferror +#define fflush my_fflush +#define fileno my_fileno +#define mmap my_mmap +#define munmap my_munmap + +#else + +#define InitializeIO() +#define FinalizeIO() + +#endif + +///////////////////////////////////////////////////////////////////////////// + +#if q4_CHECK +#include <stdlib.h> + +void f4_AssertionFailed(const char* cond_, const char* file_, int line_) +{ + fprintf(stderr, "Assertion failed: %s (file %s, line %d)\n", + cond_, file_, line_); + abort(); +} + +#endif //q4_CHECK + +///////////////////////////////////////////////////////////////////////////// +// c4_FileStream + +c4_FileStream::c4_FileStream (FILE* stream_, bool owned_) + : _stream (stream_), _owned (owned_) +{ +} + +c4_FileStream::~c4_FileStream () +{ + if (_owned) + fclose(_stream); +} + +int c4_FileStream::Read(void* buffer_, int length_) +{ + d4_assert(_stream != 0); + + return (int) fread(buffer_, 1, length_, _stream); +} + +bool c4_FileStream::Write(const void* buffer_, int length_) +{ + d4_assert(_stream != 0); + + return (int) fwrite(buffer_, 1, length_, _stream) == length_; +} + +///////////////////////////////////////////////////////////////////////////// +// c4_FileStrategy + +c4_FileStrategy::c4_FileStrategy (FILE* file_) + : _file (file_), _cleanup (0) +{ + InitializeIO(); + ResetFileMapping(); +} + +c4_FileStrategy::~c4_FileStrategy () +{ + _file = 0; + ResetFileMapping(); + + if (_cleanup) + fclose(_cleanup); + + d4_assert(_mapStart == 0); + FinalizeIO(); +} + +bool c4_FileStrategy::IsValid() const +{ + return _file != 0; +} + +t4_i32 c4_FileStrategy::FileSize() +{ + d4_assert(_file != 0); + + long size = -1; + + long old = ftell(_file); + if (old >= 0 && fseek(_file, 0, 2) == 0) { + long pos = ftell(_file); + if (fseek(_file, old, 0) == 0) + size = pos; + } + + if (size < 0) + _failure = ferror(_file); + + return size; +} + +t4_i32 c4_FileStrategy::FreshGeneration() +{ + d4_assert(false); + return 0; +} + +void c4_FileStrategy::ResetFileMapping() +{ +#if q4_WIN32 + if (_mapStart != 0) { + _mapStart -= _baseOffset; + d4_dbgdef(BOOL g =) + ::UnmapViewOfFile((char*) _mapStart); + d4_assert(g); + _mapStart = 0; + _dataSize = 0; + } + + if (_file != 0) { + t4_i32 len = FileSize(); + + if (len > 0) { + FlushFileBuffers((HANDLE) _get_osfhandle(_fileno(_file))); + HANDLE h = ::CreateFileMapping((HANDLE) _get_osfhandle(_fileno(_file)), + 0, PAGE_READONLY, 0, len, 0); + d4_assert(h); // check for errors, but can continue without mapping + + if (h) { + _mapStart = (t4_byte*) ::MapViewOfFile(h, FILE_MAP_READ, 0, 0, len); + d4_assert(_mapStart != 0); + + if (_mapStart != 0) { + _mapStart += _baseOffset; + _dataSize = len - _baseOffset; + } + + d4_dbgdef(BOOL f =) + ::CloseHandle(h); + d4_assert(f); + } + } + } +#elif HAVE_MMAP + if (_mapStart != 0) { + _mapStart -= _baseOffset; + munmap((char*) _mapStart, _baseOffset + _dataSize); // also loses const + _mapStart = 0; + _dataSize = 0; + } + + if (_file != 0) { + t4_i32 len = FileSize(); + + if (len > 0) { + _mapStart = (const t4_byte*) mmap(0, len, PROT_READ, MAP_SHARED, + fileno(_file), 0); + if (_mapStart != (void*) -1L) { + _mapStart += _baseOffset; + _dataSize = len - _baseOffset; + } else + _mapStart = 0; + } + } +#endif +} + +bool c4_FileStrategy::DataOpen(const char* fname_, int mode_) +{ + d4_assert(!_file); + +#if q4_WIN32 && !q4_BORC && !q4_WINCE + int flags = _O_BINARY | _O_NOINHERIT | (mode_ > 0 ? _O_RDWR : _O_RDONLY); + int fd = _open(fname_, flags); + if (fd != -1) + _cleanup = _file = _fdopen(fd, mode_ > 0 ? "r+b" : "rb"); +#else + _cleanup = _file = fopen(fname_, mode_ > 0 ? "r+b" : "rb"); +#if q4_UNIX + if (_file != 0) + fcntl(fileno(_file), F_SETFD, FD_CLOEXEC); +#endif //q4_UNIX +#endif //q4_WIN32 && !q4_BORC && !q4_WINCE + + if (_file != 0) { + ResetFileMapping(); + return true; + } + + if (mode_ > 0) { +#if q4_WIN32 && !q4_BORC && !q4_WINCE + fd = _open(fname_, flags | _O_CREAT, _S_IREAD | _S_IWRITE); + if (fd != -1) + _cleanup = _file = _fdopen(fd, "w+b"); +#else + _cleanup = _file = fopen(fname_, "w+b"); +#if q4_UNIX + if (_file != 0) + fcntl(fileno(_file), F_SETFD, FD_CLOEXEC); +#endif //q4_UNIX +#endif //q4_WIN32 && !q4_BORC && !q4_WINCE + } + + //d4_assert(_file != 0); + return false; +} + +int c4_FileStrategy::DataRead(t4_i32 pos_, void* buf_, int len_) +{ + d4_assert(_baseOffset + pos_ >= 0); + d4_assert(_file != 0); + + //printf("DataRead at %d len %d\n", pos_, len_); + return fseek(_file, _baseOffset + pos_, 0) != 0 ? -1 : + (int) fread(buf_, 1, len_, _file); +} + +void c4_FileStrategy::DataWrite(t4_i32 pos_, const void* buf_, int len_) +{ + d4_assert(_baseOffset + pos_ >= 0); + d4_assert(_file != 0); +#if 0 + if (_mapStart <= buf_ && buf_ < _mapStart + _dataSize) { + printf("DataWrite %08x at %d len %d (map %d)\n", buf_, pos_, len_, + (const t4_byte*) buf_ - _mapStart + _baseOffset); + } else { + printf("DataWrite %08x at %d len %d\n", buf_, pos_, len_); + } + fprintf(stderr, " _mapStart %08x _dataSize %d buf_ %08x len_ %d _baseOffset %d\n", + _mapStart, _dataSize, buf_, len_, _baseOffset); + printf(" _mapStart %08x _dataSize %d buf_ %08x len_ %d _baseOffset %d\n", + _mapStart, _dataSize, buf_, len_, _baseOffset); + fflush(stdout); +#endif + +#if q4_WIN32 || __hpux || __MACH__ +// if (buf_ >= _mapStart && buf_ <= _mapLimit - len_) + + // a horrendous hack to allow file mapping for Win95 on network drive + // must use a temp buf to avoid write from mapped file to same file + // + // 6-Feb-1999 -- this workaround is not thread safe + // 30-Nov-2001 -- changed to use the stack so now it is + // 28-Oct-2002 -- added HP/UX to the mix, to avoid hard lockup + char tempBuf [4096]; + d4_assert(len_ <= sizeof tempBuf); + buf_ = memcpy(tempBuf, buf_, len_); +#endif + + if (fseek(_file, _baseOffset + pos_, 0) != 0 || + (int) fwrite(buf_, 1, len_, _file) != len_) { + _failure = ferror(_file); + d4_assert(_failure != 0); + d4_assert(true); // always force an assertion failure in debug mode + } +} + +void c4_FileStrategy::DataCommit(t4_i32 limit_) +{ + d4_assert(_file != 0); + + if (fflush(_file) < 0) { + _failure = ferror(_file); + d4_assert(_failure != 0); + d4_assert(true); // always force an assertion failure in debug mode + return; + } + + if (limit_ > 0) { +#if 0 // can't truncate file in a portable way! + // unmap the file first, WinNT is more picky about this than Win95 + FILE* save = _file; + + _file = 0; + ResetFileMapping(); + _file = save; + + _file->SetLength(limit_); // now we can resize the file +#endif + ResetFileMapping(); // remap, since file length may have changed + } +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/format.cpp b/akregator/src/mk4storage/metakit/src/format.cpp new file mode 100644 index 000000000..aa23e7391 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/format.cpp @@ -0,0 +1,1341 @@ +// format.cpp -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Format handlers deal with the representation of data + */ + +#include "header.h" +#include "handler.h" +#include "column.h" +#include "format.h" +#include "persist.h" + +///////////////////////////////////////////////////////////////////////////// + +class c4_FormatHandler : public c4_Handler +{ + c4_HandlerSeq& _owner; + +public: + c4_FormatHandler (const c4_Property& prop_, c4_HandlerSeq& owner_); + virtual ~c4_FormatHandler (); + + virtual bool IsPersistent() const; + +protected: + c4_HandlerSeq& Owner() const; +}; + +///////////////////////////////////////////////////////////////////////////// +// c4_FormatHandler + +c4_FormatHandler::c4_FormatHandler (const c4_Property& prop_, c4_HandlerSeq& owner_) + : c4_Handler (prop_), _owner (owner_) +{ +} + +c4_FormatHandler::~c4_FormatHandler () +{ +} + +d4_inline c4_HandlerSeq& c4_FormatHandler::Owner() const +{ + return _owner; +} + +bool c4_FormatHandler::IsPersistent() const +{ + return _owner.Persist() != 0; +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_FormatX : public c4_FormatHandler +{ +public: + c4_FormatX (const c4_Property& prop_, c4_HandlerSeq& seq_, + int width_ =sizeof (t4_i32)); + + virtual void Define(int, const t4_byte**); + virtual void OldDefine(char type_, c4_Persist&); + virtual void FlipBytes(); + + virtual int ItemSize(int index_); + virtual const void* Get(int index_, int& length_); + virtual void Set(int index_, const c4_Bytes& buf_); + + virtual void Insert(int index_, const c4_Bytes& buf_, int count_); + virtual void Remove(int index_, int count_); + + virtual void Commit(c4_SaveContext& ar_); + + virtual void Unmapped(); + + static int DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_); + +protected: + c4_ColOfInts _data; +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_FormatX::c4_FormatX (const c4_Property& p_, c4_HandlerSeq& s_, int w_) + : c4_FormatHandler (p_, s_), _data (s_.Persist(), w_) +{ +} + +int c4_FormatX::DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_) +{ + return c4_ColOfInts::DoCompare(b1_, b2_); +} + +void c4_FormatX::Commit(c4_SaveContext& ar_) +{ + _data.FixSize(true); + ar_.CommitColumn(_data); + //_data.FixSize(false); +} + +void c4_FormatX::Define(int rows_, const t4_byte** ptr_) +{ + if (ptr_ != 0) + _data.PullLocation(*ptr_); + + _data.SetRowCount(rows_); +} + +void c4_FormatX::OldDefine(char, c4_Persist& pers_) +{ + pers_.FetchOldLocation(_data); + _data.SetRowCount(Owner().NumRows()); +} + +void c4_FormatX::FlipBytes() +{ + _data.FlipBytes(); +} + +int c4_FormatX::ItemSize(int index_) +{ + return _data.ItemSize(index_); +} + +const void* c4_FormatX::Get(int index_, int& length_) +{ + return _data.Get(index_, length_); +} + +void c4_FormatX::Set(int index_, const c4_Bytes& buf_) +{ + _data.Set(index_, buf_); +} + +void c4_FormatX::Insert(int index_, const c4_Bytes& buf_, int count_) +{ + _data.Insert(index_, buf_, count_); +} + +void c4_FormatX::Remove(int index_, int count_) +{ + _data.Remove(index_, count_); +} + +void c4_FormatX::Unmapped() +{ + _data.ReleaseAllSegments(); +} + +///////////////////////////////////////////////////////////////////////////// +#if !q4_TINY +///////////////////////////////////////////////////////////////////////////// + +class c4_FormatL : public c4_FormatX +{ +public: + c4_FormatL (const c4_Property& prop_, c4_HandlerSeq& seq_); + + virtual void Define(int, const t4_byte**); + + static int DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_); +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_FormatL::c4_FormatL (const c4_Property& prop_, c4_HandlerSeq& seq_) + : c4_FormatX (prop_, seq_, sizeof (t4_i64)) +{ + // force maximum size, autosizing more than 32 bits won't work + _data.SetAccessWidth(8 * sizeof (t4_i64)); +} + +int c4_FormatL::DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_) +{ + d4_assert(b1_.Size() == sizeof (t4_i64)); + d4_assert(b2_.Size() == sizeof (t4_i64)); + + t4_i64 v1 = *(const t4_i64*) b1_.Contents(); + t4_i64 v2 = *(const t4_i64*) b2_.Contents(); + + return v1 == v2 ? 0 : v1 < v2 ? -1 : +1; +} + +void c4_FormatL::Define(int rows_, const t4_byte** ptr_) +{ + if (ptr_ == 0 && rows_ > 0) { + d4_assert(_data.ColSize() == 0); + _data.InsertData(0, rows_ * sizeof (t4_i64), true); + } + + c4_FormatX::Define(rows_, ptr_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_FormatF : public c4_FormatX +{ +public: + c4_FormatF (const c4_Property& prop_, c4_HandlerSeq& seq_); + + static int DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_); +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_FormatF::c4_FormatF (const c4_Property& prop_, c4_HandlerSeq& seq_) + : c4_FormatX (prop_, seq_, sizeof (float)) +{ +} + +int c4_FormatF::DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_) +{ + d4_assert(b1_.Size() == sizeof (float)); + d4_assert(b2_.Size() == sizeof (float)); + + float v1 = *(const float*) b1_.Contents(); + float v2 = *(const float*) b2_.Contents(); + + return v1 == v2 ? 0 : v1 < v2 ? -1 : +1; +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_FormatD : public c4_FormatX +{ +public: + c4_FormatD (const c4_Property& prop_, c4_HandlerSeq& seq_); + + virtual void Define(int, const t4_byte**); + + static int DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_); +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_FormatD::c4_FormatD (const c4_Property& prop_, c4_HandlerSeq& seq_) + : c4_FormatX (prop_, seq_, sizeof (double)) +{ + // force maximum size, autosizing more than 32 bits won't work + _data.SetAccessWidth(8 * sizeof (double)); +} + +int c4_FormatD::DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_) +{ + d4_assert(b1_.Size() == sizeof (double)); + d4_assert(b2_.Size() == sizeof (double)); + + double v1 = *(const double*) b1_.Contents(); + double v2 = *(const double*) b2_.Contents(); + + return v1 == v2 ? 0 : v1 < v2 ? -1 : +1; +} + +void c4_FormatD::Define(int rows_, const t4_byte** ptr_) +{ + if (ptr_ == 0 && rows_ > 0) { + d4_assert(_data.ColSize() == 0); + _data.InsertData(0, rows_ * sizeof (double), true); + } + + c4_FormatX::Define(rows_, ptr_); +} + +///////////////////////////////////////////////////////////////////////////// +#endif // !q4_TINY +///////////////////////////////////////////////////////////////////////////// + +/* + Byte properties are used for raw bytes and for indirect (memo) data. + + There are two columns: the actual data and the item sizes. If the data + is indirect, then the size is stored as a negative value. + + In addition, there is an in-memory-only vector of columns (_memos). + Columns are created when asked for, and stay around until released with + a commit call. If the column object exists and is not dirty, then it + is either a real column (size < 0), or simply a duplicate of the data + stored inline as bytes. +*/ + +class c4_FormatB : public c4_FormatHandler +{ +public: + c4_FormatB (const c4_Property& prop_, c4_HandlerSeq& seq_); + virtual ~c4_FormatB (); + + virtual void Define(int, const t4_byte**); + virtual void OldDefine(char type_, c4_Persist&); + virtual void Commit(c4_SaveContext& ar_); + + virtual int ItemSize(int index_); + virtual const void* Get(int index_, int& length_); + virtual void Set(int index_, const c4_Bytes& buf_); + + virtual void Insert(int index_, const c4_Bytes& buf_, int count_); + virtual void Remove(int index_, int count_); + + virtual c4_Column* GetNthMemoCol(int index_, bool alloc_); + + virtual void Unmapped(); + + static int DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_); + +protected: + const void* GetOne(int index_, int& length_); + void SetOne(int index_, const c4_Bytes& buf_, bool ignoreMemos_ =false); + +private: + t4_i32 Offset(int index_) const; + bool ShouldBeMemo(int length_) const; + int ItemLenOffCol(int index_, t4_i32& off_, c4_Column*& col_); + bool CommitItem(c4_SaveContext& ar_, int index_); + void InitOffsets(c4_ColOfInts& sizes_); + + c4_Column _data; + c4_ColOfInts _sizeCol; // 2001-11-27: keep, to track position on disk + c4_Column _memoCol; // 2001-11-27: keep, to track position on disk + c4_DWordArray _offsets; + c4_PtrArray _memos; + bool _recalc; // 2001-11-27: remember when to redo _{size,memo}Col +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_FormatB::c4_FormatB (const c4_Property& prop_, c4_HandlerSeq& seq_) + : c4_FormatHandler (prop_, seq_), _data (seq_.Persist()), + _sizeCol (seq_.Persist()), _memoCol (seq_.Persist()), _recalc (false) +{ + _offsets.SetSize(1, 100); + _offsets.SetAt(0, 0); +} + +c4_FormatB::~c4_FormatB () +{ + // cleanup allocated columns + //better? for (int i = _memos.GetSize(); --i >= 0 ;) + for (int i = 0; i < _memos.GetSize(); ++i) + delete (c4_Column*) _memos.GetAt(i); +} + +d4_inline t4_i32 c4_FormatB::Offset(int index_) const +{ + d4_assert((t4_i32) _offsets.GetAt(_offsets.GetSize() - 1) == _data.ColSize()); + d4_assert(_offsets.GetSize() == _memos.GetSize() + 1); + d4_assert(index_ < _offsets.GetSize()); + + // extend offset vectors for missing empty entries at end + int n = _offsets.GetSize(); + d4_assert(n > 0); + + if (index_ >= n) + index_ = n - 1; + + return _offsets.GetAt(index_); +} + +d4_inline bool c4_FormatB::ShouldBeMemo(int length_) const +{ + // items over 10000 bytes are always memos + // items up to 100 bytes are never memos + // + // else, memo only if the column would be under 1 Mb + // (assuming all items had the same size as this one) + // + // the effect is that as the number of rows increases, + // smaller and smaller items get turned into memos + // + // note that items which are no memo right now stay + // as is, and so do memos which have not been modified + + int rows = _memos.GetSize() + 1; // avoids divide by zero + return length_ > 10000 || length_ > 100 && length_ > 1000000 / rows; +} + +int c4_FormatB::ItemLenOffCol(int index_, t4_i32& off_, c4_Column*& col_) +{ + col_ = (c4_Column*) _memos.GetAt(index_); + if (col_ != 0) { + off_ = 0; + return col_->ColSize(); + } + + col_ = &_data; + off_ = Offset(index_); + return Offset(index_ + 1) - off_; +} + +c4_Column* c4_FormatB::GetNthMemoCol(int index_, bool alloc_) +{ + t4_i32 start; + c4_Column* col; + int n = ItemLenOffCol(index_, start, col); + + if (col == &_data && alloc_) { + col = d4_new c4_Column (_data.Persist()); + _memos.SetAt(index_, col); + + if (n > 0) + if (_data.IsDirty()) { + c4_Bytes temp; + _data.FetchBytes(start, n, temp, true); + col->SetBuffer(n); + col->StoreBytes(0, temp); + } + else + col->SetLocation(_data.Position() + start, n); + } + + return col; +} + +void c4_FormatB::Unmapped() +{ + _data.ReleaseAllSegments(); + _sizeCol.ReleaseAllSegments(); + _memoCol.ReleaseAllSegments(); + + for (int i = 0; i < _memos.GetSize(); ++i) { + c4_Column* cp = (c4_Column*) _memos.GetAt(i); + if (cp != 0) + cp->ReleaseAllSegments(); + } +} + +void c4_FormatB::Define(int, const t4_byte** ptr_) +{ + d4_assert(_memos.GetSize() == 0); + + if (ptr_ != 0) { + _data.PullLocation(*ptr_); + if (_data.ColSize() > 0) + _sizeCol.PullLocation(*ptr_); + _memoCol.PullLocation(*ptr_); + } + + // everything below this point could be delayed until use + // in that case, watch out that column space use is properly tracked + + InitOffsets(_sizeCol); + + if (_memoCol.ColSize() > 0) { + c4_Bytes walk; + _memoCol.FetchBytes(0, _memoCol.ColSize(), walk, true); + + const t4_byte* p = walk.Contents(); + + for (int row = 0; p < walk.Contents() + walk.Size(); ++row) { + row += c4_Column::PullValue(p); + d4_assert(row < _memos.GetSize()); + + c4_Column* mc = d4_new c4_Column (_data.Persist()); + d4_assert(mc != 0); + _memos.SetAt(row, mc); + + mc->PullLocation(p); + } + + d4_assert(p == walk.Contents() + walk.Size()); + } +} + +void c4_FormatB::OldDefine(char type_, c4_Persist& pers_) +{ + int rows = Owner().NumRows(); + + c4_ColOfInts sizes (_data.Persist()); + + if (type_ == 'M') { + InitOffsets(sizes); + + c4_ColOfInts szVec (_data.Persist()); + pers_.FetchOldLocation(szVec); + szVec.SetRowCount(rows); + + c4_ColOfInts posVec (_data.Persist()); + pers_.FetchOldLocation(posVec); + posVec.SetRowCount(rows); + + for (int r = 0; r < rows; ++r) { + t4_i32 sz = szVec.GetInt(r); + if (sz > 0) { + c4_Column* mc = d4_new c4_Column (_data.Persist()); + d4_assert(mc != 0); + _memos.SetAt(r, mc); + + mc->SetLocation(posVec.GetInt(r), sz); + } + } + } else { + pers_.FetchOldLocation(_data); + + if (type_ == 'B') { + pers_.FetchOldLocation(sizes); + +#if !q4_OLD_IS_ALWAYS_V2 + + // WARNING - HUGE HACK AHEAD - THIS IS NOT 100% FULLPROOF! + // + // The above is correct for MK versions 2.0 and up, but *NOT* + // for MK 1.8.6 datafiles, which store sizes first (OUCH!!!). + // This means that there is not a 100% safe way to auto-convert + // both 1.8.6 and 2.0 files - since there is no way to detect + // unambiguously which version a datafile is. All we can do, + // is to carefully check both vectors, and *hope* that only one + // of them is valid as sizes vector. This problem applies to + // the 'B' (bytes) property type only, and only pre 2.0 files. + // + // To build a version which *always* converts assuming 1.8.6, + // add flag "-Dq4_OLD_IS_PRE_V2" to the compiler command line. + // Conversely, "-Dq4_OLD_IS_ALWAYS_V2" forces 2.0 conversion. + + if (rows > 0) { + t4_i32 s1 = sizes.ColSize(); + t4_i32 s2 = _data.ColSize(); + +#if !q4_OLD_IS_PRE_V2 + // if the size vector is clearly impossible, swap vectors + bool fix = c4_ColOfInts::CalcAccessWidth(rows, s1) < 0; + + // if the other vector might be valid as well, check further + if (!fix && c4_ColOfInts::CalcAccessWidth(rows, s2) >= 0) { + sizes.SetRowCount(rows); + t4_i32 total = 0; + for (int i = 0; i < rows; ++i) { + t4_i32 w = sizes.GetInt(i); + if (w < 0 || total > s2) { + total = -1; + break; + } + total += w; + } + + // if the sizes don't add up, swap vectors + fix = total != s2; + } + + if (fix) +#endif + { + t4_i32 p1 = sizes.Position(); + t4_i32 p2 = _data.Position(); + _data.SetLocation(p1, s1); + sizes.SetLocation(p2, s2); + } + } +#endif + InitOffsets(sizes); + } else { + d4_assert(type_ == 'S'); + + sizes.SetRowCount(rows); + + t4_i32 pos = 0; + t4_i32 lastEnd = 0; + int k = 0; + + c4_ColIter iter (_data, 0, _data.ColSize()); + while (iter.Next()) { + const t4_byte* p = iter.BufLoad(); + for (int j = 0; j < iter.BufLen(); ++j) + if (!p[j]) { + sizes.SetInt(k++, pos + j + 1 - lastEnd); + lastEnd = pos + j + 1; + } + + pos += iter.BufLen(); + } + + d4_assert(pos == _data.ColSize()); + + if (lastEnd < pos) { // last entry had no zero byte + _data.InsertData(pos++, 1, true); + sizes.SetInt(k, pos - lastEnd); + } + + InitOffsets(sizes); + + // get rid of entries with just a null byte + for (int r = 0; r < rows; ++r) + if (c4_FormatB::ItemSize(r) == 1) + SetOne(r, c4_Bytes ()); + } + } +} + +void c4_FormatB::InitOffsets(c4_ColOfInts& sizes_) +{ + int rows = Owner().NumRows(); + + if (sizes_.RowCount() != rows) { + sizes_.SetRowCount(rows); + } + + _memos.SetSize(rows); + _offsets.SetSize(rows + 1); + + if (_data.ColSize() > 0) { + t4_i32 total = 0; + + for (int r = 0; r < rows; ++r) { + int n = sizes_.GetInt(r); + d4_assert(n >= 0); + total += n; + _offsets.SetAt(r + 1, total); + } + + d4_assert(total == _data.ColSize()); + } + +} + +int c4_FormatB::ItemSize(int index_) +{ + t4_i32 start; + c4_Column* col; + return ItemLenOffCol(index_, start, col); +} + +const void* c4_FormatB::GetOne(int index_, int& length_) +{ + t4_i32 start; + c4_Column* cp; + length_ = ItemLenOffCol(index_, start, cp); + d4_assert(length_ >= 0); + + if (length_ == 0) + return ""; + + return cp->FetchBytes(start, length_, Owner().Buffer(), false); +} + +const void* c4_FormatB::Get(int index_, int& length_) +{ + return GetOne(index_, length_); +} + +void c4_FormatB::SetOne(int index_, const c4_Bytes& xbuf_, bool ignoreMemos_) +{ + // this fixes bug in 2.4.0 when copying string from higher row + // TODO: this fix is very conservative, figure out when to copy + // (can probably look at pointer to see whether it's from us) + int sz = xbuf_.Size(); + c4_Bytes buf_ (xbuf_.Contents(), sz, 0 < sz && sz <= c4_Column::kSegMax); + + c4_Column* cp = &_data; + t4_i32 start = Offset(index_); + int len = Offset(index_ + 1) - start; + + if (!ignoreMemos_ && _memos.GetAt(index_) != 0) + len = ItemLenOffCol(index_, start, cp); + + int m = buf_.Size(); + int n = m - len; + + if (n > 0) + cp->Grow(start, n); + else if (n < 0) + cp->Shrink(start, - n); + else if (m == 0) + return; // no size change and no contents + + _recalc = true; + + cp->StoreBytes(start, buf_); + + if (n && cp == &_data) { // if size has changed + int k = _offsets.GetSize() - 1; + + // if filling in an empty entry at end: extend offsets first + if (m > 0 && index_ >= k) { + _offsets.InsertAt(k, _offsets.GetAt(k), index_ - k + 1); + + k = index_ + 1; + d4_assert(k == _offsets.GetSize() - 1); + } + + // adjust following entry offsets + while (++index_ <= k) + _offsets.ElementAt(index_) += n; + } + + d4_assert((t4_i32) _offsets.GetAt(_offsets.GetSize() - 1) == _data.ColSize()); +} + +void c4_FormatB::Set(int index_, const c4_Bytes& buf_) +{ + SetOne(index_, buf_); +} + +int c4_FormatB::DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_) +{ + int n = b1_.Size(); + if (n > b2_.Size()) + n = b2_.Size(); + + int f = memcmp(b1_.Contents(), b2_.Contents(), n); + return f ? f : b1_.Size() - b2_.Size(); +} + +void c4_FormatB::Insert(int index_, const c4_Bytes& buf_, int count_) +{ + d4_assert(count_ > 0); + + _recalc = true; + + int m = buf_.Size(); + t4_i32 off = Offset(index_); + + _memos.InsertAt(index_, 0, count_); + + // insert the appropriate number of bytes + t4_i32 n = count_ * (t4_i32) m; + if (n > 0) { + _data.Grow(off, n); + + // store as many copies as needed, but may have to do it in chunks + int spos = 0; + + c4_ColIter iter (_data, off, off + n); + while (iter.Next(m - spos)) { + memcpy(iter.BufSave(), buf_.Contents() + spos, iter.BufLen()); + + spos += iter.BufLen(); + if (spos >= m) + spos = 0; + } + + d4_assert(spos == 0); // must have copied an exact multiple of the data + } + + // define offsets of the new entries + _offsets.InsertAt(index_, 0, count_); + d4_assert(_offsets.GetSize() <= _memos.GetSize() + 1); + + while (--count_ >= 0) { + _offsets.SetAt(index_++, off); + off += m; + } + + d4_assert(index_ < _offsets.GetSize()); + + // adjust all following entries + while (index_ < _offsets.GetSize()) + _offsets.ElementAt(index_++) += n; + + d4_assert((t4_i32) _offsets.GetAt(index_ - 1) == _data.ColSize()); + d4_assert(index_ <= _memos.GetSize() + 1); +} + +void c4_FormatB::Remove(int index_, int count_) +{ + _recalc = true; + + t4_i32 off = Offset(index_); + t4_i32 n = Offset(index_ + count_) - off; + d4_assert(n >= 0); + + // remove the columns, if present + for (int i = 0; i < count_; ++i) + delete (c4_Column*) _memos.GetAt(index_ + i); + _memos.RemoveAt(index_, count_); + + if (n > 0) + _data.Shrink(off, n); + + _offsets.RemoveAt(index_, count_); + + d4_assert(index_ < _offsets.GetSize()); + + // adjust all following entries + while (index_ < _offsets.GetSize()) + _offsets.ElementAt(index_++) -= n; + + d4_assert((t4_i32) _offsets.GetAt(index_ - 1) == _data.ColSize()); + d4_assert(index_ <= _memos.GetSize() + 1); +} + +void c4_FormatB::Commit(c4_SaveContext& ar_) +{ + int rows = _memos.GetSize(); + d4_assert(rows > 0); + + bool full = _recalc || ar_.Serializing(); + + if (!full) + for (int i = 0; i < rows; ++i) { + c4_Column* col = (c4_Column*) _memos.GetAt(i); + if (col != 0) { + full = true; + break; + } + } + d4_assert(_recalc || _sizeCol.RowCount() == rows); + + if (full) { + _memoCol.SetBuffer(0); + _sizeCol.SetBuffer(0); + _sizeCol.SetAccessWidth(0); + _sizeCol.SetRowCount(rows); + + int skip = 0; + + c4_Column* saved = ar_.SetWalkBuffer(&_memoCol); + + for (int r = 0; r < rows; ++r) { + ++skip; + + t4_i32 start; + c4_Column* col; + int len = ItemLenOffCol(r, start, col); + + bool oldMemo = col != &_data; + bool newMemo = ShouldBeMemo(len); + + if (!oldMemo && newMemo) { + col = GetNthMemoCol(r, true); + d4_assert(col != &_data); + //? start = 0; + } + + c4_Bytes temp; + + if (newMemo) { // it now is a memo, inlined data will be empty + ar_.StoreValue(skip - 1); + skip = 0; + ar_.CommitColumn(*col); + } else if (!oldMemo) { // it was no memo, done if it hasn't become one + _sizeCol.SetInt(r, len); + continue; + } else { // it was a memo, but it no longer is + d4_assert(start == 0); + if (len > 0) + { + _sizeCol.SetInt(r, len); + col->FetchBytes(start, len, temp, true); + delete (c4_Column*) _memos.GetAt(r); // 28-11-2001: fix mem leak + _memos.SetAt(r, 0); // 02-11-2001: fix for use after commit + } + } + + SetOne(r, temp, true); // bypass current memo pointer + } + + ar_.SetWalkBuffer(saved); + } + + ar_.CommitColumn(_data); + + if (_data.ColSize() > 0) { + _sizeCol.FixSize(true); + ar_.CommitColumn(_sizeCol); + //_sizeCol.FixSize(false); + } + + ar_.CommitColumn(_memoCol); + + // need a way to find out when the data has been committed (on 2nd pass) + // both _sizeCol and _memoCol will be clean again when it has + // but be careful because dirty flag is only useful if size is nonzero + if (_recalc && !ar_.Serializing()) + _recalc = _sizeCol.ColSize() > 0 && _sizeCol.IsDirty() || + _memoCol.ColSize() > 0 && _memoCol.IsDirty(); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_FormatS : public c4_FormatB +{ +public: + c4_FormatS (const c4_Property& prop_, c4_HandlerSeq& seq_); + + virtual int ItemSize(int index_); + virtual const void* Get(int index_, int& length_); + virtual void Set(int index_, const c4_Bytes& buf_); + + virtual void Insert(int index_, const c4_Bytes& buf_, int count_); + + static int DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_); +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_FormatS::c4_FormatS (const c4_Property& prop_, c4_HandlerSeq& seq_) + : c4_FormatB (prop_, seq_) +{ +} + +int c4_FormatS::ItemSize(int index_) +{ + int n = c4_FormatB::ItemSize(index_) - 1; + return n >= 0 ? n : 0; +} + +const void* c4_FormatS::Get(int index_, int& length_) +{ + const void* ptr = GetOne(index_, length_); + + if (length_ == 0) { + length_ = 1; + ptr = ""; + } + + d4_assert(((const char*) ptr)[length_-1] == 0); + return ptr; +} + +void c4_FormatS::Set(int index_, const c4_Bytes& buf_) +{ + int m = buf_.Size(); + if (--m >= 0) { + d4_assert(buf_.Contents()[m] == 0); + if (m == 0) { + SetOne(index_, c4_Bytes ()); // don't store data for empty strings + return; + } + } + + SetOne(index_, buf_); +} + +int c4_FormatS::DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_) +{ + c4_String v1 ((const char*) b1_.Contents(), b1_.Size()); + c4_String v2 ((const char*) b2_.Contents(), b2_.Size()); + + return v1.CompareNoCase(v2); +} + +void c4_FormatS::Insert(int index_, const c4_Bytes& buf_, int count_) +{ + d4_assert(count_ > 0); + + int m = buf_.Size(); + if (--m >= 0) { + d4_assert(buf_.Contents()[m] == 0); + if (m == 0) { + c4_FormatB::Insert(index_, c4_Bytes (), count_); + return; + } + } + + c4_FormatB::Insert(index_, buf_, count_); +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_FormatV : public c4_FormatHandler +{ +public: + c4_FormatV (const c4_Property& prop_, c4_HandlerSeq& seq_); + virtual ~c4_FormatV (); + + virtual void Define(int rows_, const t4_byte** ptr_); + virtual void OldDefine(char type_, c4_Persist&); + virtual void Commit(c4_SaveContext& ar_); + + virtual void FlipBytes(); + + virtual int ItemSize(int index_); + virtual const void* Get(int index_, int& length_); + virtual void Set(int index_, const c4_Bytes& buf_); + + virtual void Insert(int index_, const c4_Bytes& buf_, int count_); + virtual void Remove(int index_, int count_); + + virtual void Unmapped(); + virtual bool HasSubview(int index_); + + static int DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_); + +private: + c4_HandlerSeq& At(int index_); + void Replace(int index_, c4_HandlerSeq* seq_); + void SetupAllSubviews(); + void ForgetSubview(int index_); + + c4_Column _data; + c4_PtrArray _subSeqs; + bool _inited; +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_FormatV::c4_FormatV (const c4_Property& prop_, c4_HandlerSeq& seq_) + : c4_FormatHandler (prop_, seq_), _data (seq_.Persist()), _inited (false) +{ +} + +c4_FormatV::~c4_FormatV () +{ + for (int i = 0; i < _subSeqs.GetSize(); ++i) + ForgetSubview(i); +} + +c4_HandlerSeq& c4_FormatV::At(int index_) +{ + d4_assert(_inited); + + c4_HandlerSeq*& hs = (c4_HandlerSeq*&) _subSeqs.ElementAt(index_); + if (hs == 0) { + hs = d4_new c4_HandlerSeq (Owner(), this); + hs->IncRef(); + } + + return *hs; +} + +void c4_FormatV::SetupAllSubviews() +{ + d4_assert(!_inited); + _inited = true; + + if (_data.ColSize() > 0) { + c4_Bytes temp; + _data.FetchBytes(0, _data.ColSize(), temp, true); + const t4_byte* ptr = temp.Contents(); + + for (int r = 0; r < _subSeqs.GetSize(); ++r) { + // don't materialize subview if it is empty + // duplicates code which is in c4_HandlerSeq::Prepare + const t4_byte* p2 = ptr; + d4_dbgdef(t4_i32 sias =) + c4_Column::PullValue(p2); + d4_assert(sias == 0); // not yet + + if (c4_Column::PullValue(p2) > 0) + At(r).Prepare(&ptr, false); + else + ptr = p2; + } + + d4_assert(ptr == temp.Contents() + temp.Size()); + } +} + +void c4_FormatV::Define(int rows_, const t4_byte** ptr_) +{ + if (_inited) { + // big oops: a root handler already contains data + + for (int i = 0; i < _subSeqs.GetSize(); ++i) + ForgetSubview(i); + + _inited = false; + } + + _subSeqs.SetSize(rows_); + if (ptr_ != 0) + _data.PullLocation(*ptr_); +} + +void c4_FormatV::OldDefine(char, c4_Persist& pers_) +{ + int rows = Owner().NumRows(); + _subSeqs.SetSize(rows); + + for (int i = 0; i < rows; ++i) { + int n = pers_.FetchOldValue(); + if (n) { + // 14-11-2000: do not create again (this causes a mem leak) + // 04-12-2000: but do create if absent (fixes occasional crash) + c4_HandlerSeq* hs = (c4_HandlerSeq*) _subSeqs.GetAt(i); + if (hs == 0) { + hs = d4_new c4_HandlerSeq (Owner(), this); + _subSeqs.SetAt(i, hs); + hs->IncRef(); + } + hs->SetNumRows(n); + hs->OldPrepare(); + } + } +} + +void c4_FormatV::FlipBytes() +{ + if (!_inited) + SetupAllSubviews(); + + for (int i = 0; i < _subSeqs.GetSize(); ++i) + At(i).FlipAllBytes(); +} + +int c4_FormatV::ItemSize(int index_) +{ + if (!_inited) + SetupAllSubviews(); + + // 06-02-2002: avoid creating empty subview + c4_HandlerSeq* hs = (c4_HandlerSeq*&) _subSeqs.ElementAt(index_); + return hs == 0 ? 0 : hs->NumRows(); +} + +const void* c4_FormatV::Get(int index_, int& length_) +{ + if (!_inited) + SetupAllSubviews(); + + At(index_); // forces existence of a real entry + c4_HandlerSeq*& e = (c4_HandlerSeq*&) _subSeqs.ElementAt(index_); + + length_ = sizeof (c4_HandlerSeq**); + return &e; +} + +void c4_FormatV::Set(int index_, const c4_Bytes& buf_) +{ + d4_assert(buf_.Size() == sizeof (c4_Sequence*)); + + if (!_inited) + SetupAllSubviews(); + + c4_HandlerSeq* value = *(c4_HandlerSeq* const*) buf_.Contents(); + + if (value != & At(index_)) + Replace(index_, value); +} + +void c4_FormatV::Replace(int index_, c4_HandlerSeq* seq_) +{ + if (!_inited) + SetupAllSubviews(); + + c4_HandlerSeq*& curr = (c4_HandlerSeq*&) _subSeqs.ElementAt(index_); + if (seq_ == curr) + return; + + if (curr != 0) { + d4_assert(&curr->Parent() == &Owner()); + curr->DetachFromParent(); + curr->DetachFromStorage(true); + + curr->DecRef(); + curr = 0; + } + + if (seq_) { + int n = seq_->NumRows(); + + c4_HandlerSeq& t = At(index_); + d4_assert(t.NumRows() == 0); + + t.Resize(n); + + c4_Bytes data; + + // this dest seq has only the persistent handlers + // and maybe in a different order + // create any others we need as temporary properties + for (int i = 0; i < seq_->NumHandlers(); ++i) { + c4_Handler& h1 = seq_->NthHandler(i); + + int j = t.PropIndex(h1.Property()); + d4_assert(j >= 0); + + c4_Handler& h2 = t.NthHandler(j); + + for (int k = 0; k < n; ++k) + if (seq_->Get(k, h1.PropId(), data)) + h2.Set(k, data); + } + } +} + +int c4_FormatV::DoCompare(const c4_Bytes& b1_, const c4_Bytes& b2_) +{ + d4_assert(b1_.Size() == sizeof (c4_Sequence*)); + d4_assert(b2_.Size() == sizeof (c4_Sequence*)); + + c4_View v1 = *(c4_Sequence* const*) b1_.Contents(); + c4_View v2 = *(c4_Sequence* const*) b2_.Contents(); + + return v1.Compare(v2); +} + +void c4_FormatV::Insert(int index_, const c4_Bytes& buf_, int count_) +{ + d4_assert(buf_.Size() == sizeof (c4_Sequence*)); + d4_assert(count_ > 0); + + // can only insert an empty entry! + d4_assert(*(c4_Sequence* const*) buf_.Contents() == 0); + + if (!_inited) + SetupAllSubviews(); + + _subSeqs.InsertAt(index_, 0, count_); + _data.SetBuffer(0); // 2004-01-18 force dirty +} + +void c4_FormatV::Remove(int index_, int count_) +{ + d4_assert(count_ > 0); + + if (!_inited) + SetupAllSubviews(); + + for (int i = 0; i < count_; ++i) + ForgetSubview(index_ + i); + + _subSeqs.RemoveAt(index_, count_); + _data.SetBuffer(0); // 2004-01-18 force dirty +} + +void c4_FormatV::Unmapped() +{ + if (_inited) + for (int i = 0; i < _subSeqs.GetSize(); ++i) + if (HasSubview(i)) { + c4_HandlerSeq& hs = At(i); + hs.UnmappedAll(); + if (hs.NumRefs() == 1 && hs.NumRows() == 0) + ForgetSubview(i); + } + + _data.ReleaseAllSegments(); +} + +bool c4_FormatV::HasSubview(int index_) +{ + if (!_inited) + SetupAllSubviews(); + + return _subSeqs.ElementAt(index_) != 0; +} + +void c4_FormatV::ForgetSubview(int index_) +{ + c4_HandlerSeq*& seq = (c4_HandlerSeq*&) _subSeqs.ElementAt(index_); + if (seq != 0) { + d4_assert(&seq->Parent() == &Owner()); + seq->DetachFromParent(); + seq->DetachFromStorage(true); + seq->UnmappedAll(); + seq->DecRef(); + seq = 0; + } +} + +void c4_FormatV::Commit(c4_SaveContext& ar_) +{ + if (!_inited) + SetupAllSubviews(); + + int rows = _subSeqs.GetSize(); + d4_assert(rows > 0); + + c4_Column temp (0); + c4_Column* saved = ar_.SetWalkBuffer(&temp); + + for (int r = 0; r < rows; ++r) + if (HasSubview(r)) { + c4_HandlerSeq& hs = At(r); + ar_.CommitSequence(hs, false); + if (hs.NumRefs() == 1 && hs.NumRows() == 0) + ForgetSubview(r); + } else { + ar_.StoreValue(0); // sias + ar_.StoreValue(0); // row count + } + + ar_.SetWalkBuffer(saved); + + c4_Bytes buf; + temp.FetchBytes(0, temp.ColSize(), buf, true); + + bool changed = temp.ColSize() != _data.ColSize(); + + if (!changed) { + c4_Bytes buf2; + _data.FetchBytes(0, _data.ColSize(), buf2, true); + changed = buf != buf2; + } + + if (changed) { + _data.SetBuffer(buf.Size()); + _data.StoreBytes(0, buf); + } + + ar_.CommitColumn(_data); +} + +///////////////////////////////////////////////////////////////////////////// + +c4_Handler* f4_CreateFormat(const c4_Property& prop_, c4_HandlerSeq& seq_) +{ + switch (prop_.Type()) { + case 'I': return d4_new c4_FormatX (prop_, seq_); +#if !q4_TINY + case 'L': return d4_new c4_FormatL (prop_, seq_); + case 'F': return d4_new c4_FormatF (prop_, seq_); + case 'D': return d4_new c4_FormatD (prop_, seq_); +#endif + case 'B': return d4_new c4_FormatB (prop_, seq_); + case 'S': return d4_new c4_FormatS (prop_, seq_); + case 'V': return d4_new c4_FormatV (prop_, seq_); + } + + d4_assert(0); + // 2004-01-16 turn bad definition type into an int property to avoid crash + return d4_new c4_FormatX (c4_IntProp (prop_.Name()), seq_); +} + +///////////////////////////////////////////////////////////////////////////// + +int f4_ClearFormat(char type_) +{ + switch (type_) { + case 'I': return sizeof (t4_i32); +#if !q4_TINY + case 'L': return sizeof (t4_i64); + case 'F': return sizeof (float); + case 'D': return sizeof (double); +#endif + case 'S': return 1; + case 'V': return sizeof (c4_Sequence*); + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////// + +int f4_CompareFormat(char type_, const c4_Bytes& b1_, const c4_Bytes& b2_) +{ + switch (type_) { + case 'I': return c4_FormatX::DoCompare(b1_, b2_); +#if !q4_TINY + case 'L': return c4_FormatL::DoCompare(b1_, b2_); + case 'F': return c4_FormatF::DoCompare(b1_, b2_); + case 'D': return c4_FormatD::DoCompare(b1_, b2_); +#endif + case 'B': return c4_FormatB::DoCompare(b1_, b2_); + case 'S': return c4_FormatS::DoCompare(b1_, b2_); + case 'V': return c4_FormatV::DoCompare(b1_, b2_); + } + + d4_assert(0); + return 0; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/format.h b/akregator/src/mk4storage/metakit/src/format.h new file mode 100644 index 000000000..721e55484 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/format.h @@ -0,0 +1,23 @@ +// format.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Encapsulation of all format handlers + */ + +#ifndef __FORMAT_H__ +#define __FORMAT_H__ + +///////////////////////////////////////////////////////////////////////////// +// Declarations in this file + + class c4_Handler; // not defined here + + extern c4_Handler* f4_CreateFormat(const c4_Property&, c4_HandlerSeq&); + extern int f4_ClearFormat(char); + extern int f4_CompareFormat(char, const c4_Bytes&, const c4_Bytes&); + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/gnuc.h b/akregator/src/mk4storage/metakit/src/gnuc.h new file mode 100644 index 000000000..da112ac6a --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/gnuc.h @@ -0,0 +1,13 @@ +// gnuc.h -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Configuration header for GNU C++ + */ + +#define q4_GNUC 1 + +#if !defined (q4_BOOL) +#define q4_BOOL 1 +#endif diff --git a/akregator/src/mk4storage/metakit/src/handler.cpp b/akregator/src/mk4storage/metakit/src/handler.cpp new file mode 100644 index 000000000..6c68c5c3f --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/handler.cpp @@ -0,0 +1,500 @@ +// handler.cpp -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Handlers store data in column-wise format + */ + +#include "header.h" +#include "handler.h" +#include "format.h" +#include "field.h" +#include "column.h" +#include "persist.h" + +#if !q4_INLINE +#include "handler.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// +// c4_Handler + +void c4_Handler::ClearBytes(c4_Bytes& buf_) const +{ + static char zeros[8]; + + int n = f4_ClearFormat(Property().Type()); + d4_assert(n <= sizeof zeros); + + buf_ = c4_Bytes (zeros, n); +} + +int c4_Handler::Compare(int index_, const c4_Bytes& buf_) +{ + // create a copy for small data, since ints use a common _item buffer + c4_Bytes copy (buf_.Contents(), buf_.Size(), buf_.Size() <= 8); + + c4_Bytes data; + GetBytes(index_, data); + + return f4_CompareFormat(Property().Type(), data, copy); +} + +void c4_Handler::Commit(c4_SaveContext&) +{ + d4_assert(0); +} + +void c4_Handler::OldDefine(char, c4_Persist&) +{ + d4_assert(0); +} + + // this is how the old "Get" was, keep it until no longer needed +void c4_Handler::GetBytes(int index_, c4_Bytes& buf_, bool copySmall_) +{ + int n; + const void* p = Get(index_, n); + buf_ = c4_Bytes (p, n, copySmall_ && n <= 8); +} + +void c4_Handler::Move(int from_, int to_) +{ + if (from_ != to_) { + c4_Bytes data; + GetBytes(from_, data); + + Remove(from_, 1); + + if (to_ > from_) + --to_; + + Insert(to_, data, 1); + } +} + +///////////////////////////////////////////////////////////////////////////// +// c4_HandlerSeq + +c4_HandlerSeq::c4_HandlerSeq (c4_Persist* persist_) + : _persist (persist_), _field (0), _parent (0), _numRows (0) +{ +} + +c4_HandlerSeq::c4_HandlerSeq (c4_HandlerSeq& owner_, c4_Handler* handler_) + : _persist (owner_.Persist()), _field (owner_.FindField(handler_)), + _parent (&owner_), _numRows (0) +{ + for (int i = 0; i < NumFields(); ++i) { + c4_Field& field = Field(i); + c4_Property prop (field.Type(), field.Name()); + + d4_dbgdef(int n =) + AddHandler(f4_CreateFormat(prop, *this)); + d4_assert(n == i); + } +} + +c4_HandlerSeq::~c4_HandlerSeq () +{ + const bool rootLevel = _parent == this; + c4_Persist* pers = _persist; + + if (rootLevel && pers != 0) + pers->DoAutoCommit(); + + DetachFromParent(); + DetachFromStorage(true); + + for (int i = 0; i < NumHandlers(); ++i) + delete & NthHandler(i); + _handlers.SetSize(0); + + ClearCache(); + + if (rootLevel) { + delete _field; + + d4_assert(pers != 0); + delete pers; + } +} + +c4_Persist* c4_HandlerSeq::Persist() const +{ + return _persist; +} + +void c4_HandlerSeq::DefineRoot() +{ + d4_assert(_field == 0); + d4_assert(_parent == 0); + + SetNumRows(1); + + const char* desc = "[]"; + _field = d4_new c4_Field (desc); + d4_assert(!*desc); + + _parent = this; +} + +c4_Handler* c4_HandlerSeq::CreateHandler(const c4_Property& prop_) +{ + return f4_CreateFormat(prop_, *this); +} + +c4_Field& c4_HandlerSeq::Definition() const +{ + d4_assert(_field != 0); + + return *_field; +} + +void c4_HandlerSeq::DetachFromParent() +{ + if (_field != 0) { + const char* desc = "[]"; + c4_Field f (desc); + d4_assert(!*desc); + Restructure(f, false); + _field = 0; + } + + _parent = 0; +} + +void c4_HandlerSeq::DetachFromStorage(bool full_) +{ + if (_persist != 0) { + int limit = full_ ? 0 : NumFields(); + + // get rid of all handlers which might do I/O + for (int c = NumHandlers(); --c >= 0; ) { + c4_Handler& h = NthHandler(c); + + // all nested fields are detached recursively + if (IsNested(c)) + for (int r = 0; r < NumRows(); ++r) + if (h.HasSubview(r)) + SubEntry(c, r).DetachFromStorage(full_); + + if (c >= limit) { + if (h.IsPersistent()) { + delete &h; + _handlers.RemoveAt(c); + ClearCache(); + } + } + } + + if (full_) { + //UnmappedAll(); + _persist = 0; + } + } +} + +void c4_HandlerSeq::DetermineSpaceUsage() +{ + for (int c = 0; c < NumFields(); ++c) + if (IsNested(c)) { + c4_Handler& h = NthHandler(c); + for (int r = 0; r < NumRows(); ++r) + if (h.HasSubview(r)) + SubEntry(c, r).DetermineSpaceUsage(); + } +} + +void c4_HandlerSeq::SetNumRows(int numRows_) +{ + d4_assert(_numRows >= 0); + + _numRows = numRows_; +} + +int c4_HandlerSeq::AddHandler(c4_Handler* handler_) +{ + d4_assert(handler_ != 0); + + return _handlers.Add(handler_); +} + +const char* c4_HandlerSeq::Description() +{ + // 19-01-2003: avoid too dense code, since Sun CC seems to choke on it + //return _field != 0 ? UseTempBuffer(Definition().DescribeSubFields()) : 0; + if (_field == 0) + return 0; + c4_String s = _field->DescribeSubFields(); + return UseTempBuffer(s); +} + +void c4_HandlerSeq::Restructure(c4_Field& field_, bool remove_) +{ + //d4_assert(_field != 0); + + // all nested fields must be set up, before we shuffle them around + for (int k = 0; k < NumHandlers(); ++k) + if (IsNested(k)) { + c4_Handler& h = NthHandler(k); + for (int n = 0; n < NumRows(); ++n) + if (h.HasSubview(n)) + SubEntry(k, n); + } + + for (int i = 0; i < field_.NumSubFields(); ++i) { + c4_Field& nf = field_.SubField(i); + c4_Property prop (nf.Type(), nf.Name()); + + int n = PropIndex(prop.GetId()); + if (n == i) + continue; + + if (n < 0) { + _handlers.InsertAt(i, f4_CreateFormat(prop, *this)); + NthHandler(i).Define(NumRows(), 0); + } else { + // move the handler to the front + d4_assert(n > i); + _handlers.InsertAt(i, _handlers.GetAt(n)); + _handlers.RemoveAt(++n); + } + + ClearCache(); // we mess with the order of handler, keep clearing it + + d4_assert(PropIndex(prop.GetId()) == i); + } + + c4_Field* ofld = _field; + // special case if we're "restructuring a view out of persistence", see below + + _field = remove_ ? 0 : &field_; + + // let handler do additional init once all have been prepared + //for (int n = 0; n < NumHandlers(); ++n) + // NthHandler(n).Define(NumRows(), 0); + + const char* desc = "[]"; + c4_Field temp (desc); + + // all nested fields are restructured recursively + for (int j = 0; j < NumHandlers(); ++j) + if (IsNested(j)) { + c4_Handler& h = NthHandler(j); + for (int n = 0; n < NumRows(); ++n) + if (h.HasSubview(n)) { + c4_HandlerSeq& seq = SubEntry(j, n); + if (j < NumFields()) + seq.Restructure(field_.SubField(j), false); + else if (seq._field != 0) + seq.Restructure(temp, true); + } + } + + if (_parent == this) + delete ofld; // the root table owns its field structure tree +} + +int c4_HandlerSeq::NumFields() const +{ + return _field != 0 ? _field->NumSubFields() : 0; +} + +char c4_HandlerSeq::ColumnType(int index_) const +{ + return NthHandler(index_).Property().Type(); +} + +bool c4_HandlerSeq::IsNested(int index_) const +{ + return ColumnType(index_) == 'V'; +} + +c4_Field& c4_HandlerSeq::Field(int index_) const +{ + d4_assert(_field != 0); + + return _field->SubField(index_); +} + +void c4_HandlerSeq::Prepare(const t4_byte** ptr_, bool selfDesc_) +{ + if (ptr_ != 0) { + d4_dbgdef(t4_i32 sias =) + c4_Column::PullValue(*ptr_); + d4_assert(sias == 0); // not yet + + if (selfDesc_) { + t4_i32 n = c4_Column::PullValue(*ptr_); + if (n > 0) { + c4_String s = "[" + c4_String ((const char*) *ptr_, n) + "]"; + const char* desc = s; + + c4_Field* f = d4_new c4_Field (desc); + d4_assert(!*desc); + + Restructure(*f, false); + *ptr_ += n; + } + } + + int rows = (int) c4_Column::PullValue(*ptr_); + if (rows > 0) { + SetNumRows(rows); + + for (int i = 0; i < NumFields(); ++i) + NthHandler(i).Define(rows, ptr_); + } + } +} + +void c4_HandlerSeq::OldPrepare() +{ + d4_assert(_persist != 0); + + for (int i = 0; i < NumFields(); ++i) { + char origType = _field->SubField(i).OrigType(); + NthHandler(i).OldDefine(origType, *_persist); + } +} + +void c4_HandlerSeq::FlipAllBytes() +{ + for (int i = 0; i < NumHandlers(); ++i) { + c4_Handler& h = NthHandler(i); + h.FlipBytes(); + } +} + + // New 19990903: swap rows in tables without touching the memo fields + // or subviews on disk. This is used by the new c4_View::RelocateRows. + +void c4_HandlerSeq::ExchangeEntries(int srcPos_, c4_HandlerSeq& dst_, int dstPos_) +{ + d4_assert(NumHandlers() == dst_.NumHandlers()); + + c4_Bytes t1, t2; + + for (int col = 0; col < NumHandlers(); ++col) + { + if (IsNested(col)) + { + d4_assert(dst_.IsNested(col)); + + int n; + c4_HandlerSeq** e1 = (c4_HandlerSeq**) NthHandler(col).Get(srcPos_, n); + c4_HandlerSeq** e2 = (c4_HandlerSeq**) dst_.NthHandler(col).Get(dstPos_, n); + d4_assert(*e1 != 0 && *e2 != 0); + + // swap the two entries + c4_HandlerSeq* e = *e1; + *e1 = *e2; + *e2 = e; + + // shorthand, *after* the swap + c4_HandlerSeq& t1 = SubEntry(col, srcPos_); + c4_HandlerSeq& t2 = dst_.SubEntry(col, dstPos_); + + // adjust the parents + t1._parent = this; + t2._parent = &dst_; + + // reattach the proper field structures + t1.Restructure(Field(col), false); + t2.Restructure(dst_.Field(col), false); + } + else + { + d4_assert(ColumnType(col) == dst_.ColumnType(col)); + + c4_Handler& h1 = NthHandler(col); + c4_Handler& h2 = dst_.NthHandler(col); + +#if 0 // memo's are 'B' now, but tricky to deal with, so copy them for now + if (ColumnType(col) == 'M') + { + c4_Column* c1 = h1.GetNthMemoCol(srcPos_, true); + c4_Column* c2 = h2.GetNthMemoCol(dstPos_, true); + + t4_i32 p1 = c1 ? c1->Position() : 0; + t4_i32 p2 = c2 ? c2->Position() : 0; + + t4_i32 s1 = c1 ? c1->ColSize() : 0; + t4_i32 s2 = c2 ? c2->ColSize() : 0; + + d4_assert(false); // broken + //!h1.SetNthMemoPos(srcPos_, p2, s2, c2); + //!h2.SetNthMemoPos(dstPos_, p1, s1, c1); + } +#endif + // 10-4-2002: Need to use copies in case either item points into + // memory that could move, or if access re-uses a shared buffer. + // The special cases are sufficiently tricky that it's NOT being + // optimized for now (temp bufs, mmap ptrs, c4_Bytes buffering). + + int n1, n2; + const void* p1 = h1.Get(srcPos_, n1); + const void* p2 = h2.Get(dstPos_, n2); + + c4_Bytes t1 (p1, n1, true); + c4_Bytes t2 (p2, n2, true); + + h1.Set(srcPos_, t2); + h2.Set(dstPos_, t1); + } + } +} + +c4_HandlerSeq& c4_HandlerSeq::SubEntry(int col_, int row_) const +{ + d4_assert(IsNested(col_)); + + c4_Bytes temp; + NthHandler(col_).GetBytes(row_, temp); + + d4_assert(temp.Size() == sizeof (c4_HandlerSeq**)); + c4_HandlerSeq** p = (c4_HandlerSeq**) temp.Contents(); // loses const + + d4_assert(p != 0 && *p != 0); + + return **p; +} + +c4_Field* c4_HandlerSeq::FindField(const c4_Handler* handler_) +{ + for (int i = 0; i < NumFields(); ++i) + if (handler_ == &NthHandler(i)) + return &Field(i); + return 0; +} + +void c4_HandlerSeq::UnmappedAll() +{ + for (int i = 0; i < NumFields(); ++i) + NthHandler(i).Unmapped(); +} + + // construct meta view from a pre-parsed field tree structure + // this will one day be converted to directly parse the description string +void c4_HandlerSeq::BuildMeta(int parent_, int colnum_, c4_View& meta_, + const c4_Field& field_) +{ + c4_IntProp pP ("P"), pC ("C"); + c4_ViewProp pF ("F"); + c4_StringProp pN ("N"), pT ("T"); + + int n = meta_.Add(pP [parent_] + pC [colnum_]); + c4_View fields = pF (meta_[n]); + + for (int i = 0; i < field_.NumSubFields(); ++i) { + const c4_Field& f = field_.SubField(i); + char type = f.Type(); + fields.Add(pN [f.Name()] + pT [c4_String (&type, 1)]); + if (type == 'V') + BuildMeta(n, i, meta_, f); + } +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/handler.h b/akregator/src/mk4storage/metakit/src/handler.h new file mode 100644 index 000000000..6003f625d --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/handler.h @@ -0,0 +1,150 @@ +// handler.h -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Definition of the main handler classes + */ + +#ifndef __HANDLER_H__ +#define __HANDLER_H__ + +///////////////////////////////////////////////////////////////////////////// +// Declarations in this file + + class c4_Handler; // data representation handler + +// class c4_Sequence; + class c4_HandlerSeq; // a sequence built from handlers + + class c4_Column; // not defined here + class c4_Field; // not defined here + class c4_Persist; // not defined here + class c4_SaveContext; // not defined here + +///////////////////////////////////////////////////////////////////////////// + +class c4_Handler +{ + c4_Property _property; + +public: + c4_Handler (const c4_Property& _prop); + //: Constructor (this is an abstract base class). + virtual ~c4_Handler (); + + virtual void Define(int, const t4_byte**); + //: Called when the corresponding table has been fully defined. + virtual void FlipBytes(); + //: Called to reverse the internal byte order of foreign data. + virtual void Commit(c4_SaveContext& ar_); + //: Commit the associated column(s) to file. + virtual void OldDefine(char, c4_Persist&); + + const c4_Property& Property() const; + //: Returns the property associated with this handler. + int PropId() const; + //: Returns the id of the property associated with this handler. + + void ClearBytes(c4_Bytes& buf_) const; + //: Returns the default value for items of this type. + + virtual int ItemSize(int index_) = 0; + //: Return width of specified data item. + void GetBytes(int index_, c4_Bytes& buf_, bool copySmall_ =false); + //: Used for backward compatibility, should probably be replaced. + virtual const void* Get(int index_, int& length_) = 0; + //: Retrieves the data item at the specified index. + virtual void Set(int index_, const c4_Bytes& buf_) = 0; + //: Stores a new data item at the specified index. + + int Compare(int index_, const c4_Bytes& buf_); + //: Compares an entry with a specified data item. + + virtual void Insert(int index_, const c4_Bytes& buf_, int count_) = 0; + //: Inserts 1 or more data items at the specified index. + virtual void Remove(int index_, int count_) = 0; + //: Removes 1 or more data items at the specified index. + void Move(int from_, int to_); + //: Move a data item to another position. + + virtual c4_Column* GetNthMemoCol(int index_, bool alloc_ =false); + //: Special access to underlying data of memo entries + + virtual bool IsPersistent() const; + //: True if this handler might do I/O to satisfy fetches + + virtual void Unmapped(); + //: Make sure this handler stops using file mappings + + virtual bool HasSubview(int index_); + //: True if this subview has materialized into an object +}; + +///////////////////////////////////////////////////////////////////////////// + +class c4_HandlerSeq : public c4_Sequence +{ + c4_PtrArray _handlers; + c4_Persist* _persist; + c4_Field* _field; + c4_HandlerSeq* _parent; + int _numRows; + +public: + c4_HandlerSeq (c4_Persist*); + c4_HandlerSeq (c4_HandlerSeq& owner_, c4_Handler* handler_); + + virtual int NumRows() const; + virtual void SetNumRows(int); + + virtual int NumHandlers() const; + virtual c4_Handler& NthHandler(int) const; + virtual const c4_Sequence* HandlerContext(int) const; + virtual int AddHandler(c4_Handler*); + + void DefineRoot(); + void Restructure(c4_Field&, bool remove_); + void DetachFromParent(); + void DetachFromStorage(bool full_); + void DetermineSpaceUsage(); + + c4_Field& Definition() const; + const char* Description(); + c4_HandlerSeq& Parent() const; + virtual c4_Persist* Persist() const; + + c4_Field& Field(int) const; + int NumFields() const; + char ColumnType(int index_) const; + bool IsNested(int) const; + + void Prepare(const t4_byte** ptr_, bool selfDesc_); + void OldPrepare(); + + void FlipAllBytes(); + void ExchangeEntries(int srcPos_, c4_HandlerSeq& dst_, int dstPos_); + + c4_HandlerSeq& SubEntry(int, int) const; + + c4_Field* FindField(const c4_Handler* handler_); + + void UnmappedAll(); + + static void BuildMeta(int, int, c4_View&, const c4_Field&); + +protected: + virtual c4_Handler* CreateHandler(const c4_Property&); + + virtual ~c4_HandlerSeq (); +}; + +///////////////////////////////////////////////////////////////////////////// + +#if q4_INLINE +#include "handler.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/handler.inl b/akregator/src/mk4storage/metakit/src/handler.inl new file mode 100644 index 000000000..75321f9c7 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/handler.inl @@ -0,0 +1,90 @@ +// handler.inl -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Inlined members of the handler classes + */ + +///////////////////////////////////////////////////////////////////////////// +// c4_Handler + +d4_inline c4_Handler::c4_Handler (const c4_Property& prop_) + : _property (prop_) +{ +} + +d4_inline c4_Handler::~c4_Handler () +{ +} + +d4_inline void c4_Handler::Define(int, const t4_byte**) +{ +} + +d4_inline void c4_Handler::FlipBytes() +{ +} + +d4_inline const c4_Property& c4_Handler::Property() const +{ + return _property; +} + +d4_inline int c4_Handler::PropId() const +{ + return _property.GetId(); +} + +d4_inline c4_Column* c4_Handler::GetNthMemoCol(int, bool alloc_) +{ + return 0; +} + +d4_inline bool c4_Handler::IsPersistent() const +{ + return false; +} + +d4_inline void c4_Handler::Unmapped() +{ +} + +d4_inline bool c4_Handler::HasSubview(int) +{ + return false; +} + +///////////////////////////////////////////////////////////////////////////// +// c4_HandlerSeq + +d4_inline int c4_HandlerSeq::NumRows() const +{ + d4_assert(_numRows >= 0); + + return _numRows; +} + +d4_inline int c4_HandlerSeq::NumHandlers() const +{ + return _handlers.GetSize(); +} + +d4_inline c4_Handler& c4_HandlerSeq::NthHandler(int index_) const +{ + d4_assert(_handlers.GetAt(index_) != 0); + + return *(c4_Handler*) _handlers.GetAt(index_); +} + +d4_inline const c4_Sequence* c4_HandlerSeq::HandlerContext(int) const +{ + return this; +} + +d4_inline c4_HandlerSeq& c4_HandlerSeq::Parent() const +{ + return *_parent; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/header.h b/akregator/src/mk4storage/metakit/src/header.h new file mode 100644 index 000000000..2f8648b8f --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/header.h @@ -0,0 +1,215 @@ +// header.h -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * The internal header included in all source files + */ + +#ifndef __HEADER_H__ +#define __HEADER_H__ + +///////////////////////////////////////////////////////////////////////////// + +#include "config.h" + +///////////////////////////////////////////////////////////////////////////// +// A number of preprocessor options are used in the source code +// +// q4_DOS MS-DOS real-mode OS +// q4_MAC Apple Macintosh OS +// q4_UNIX Unix, any flavor +// q4_VMS DEC OpenVMS OS +// q4_WIN Microsoft Windows OS, any flavor +// q4_WIN32 Microsoft Windows OS, 32-bit +// q4_WINCE Microsoft Windows OS, embedded +// +// q4_MFC Microsoft MFC framework +// q4_STD Standard STL version +// q4_UNIV Universal version +// +// q4_BOOL compiler supports bool datatype +// q4_CHECK enable assertion checks +// q4_FIX manual header fix (see above) +// q4_INLINE enable inline expansion +// q4_KITDLL compile as DLL (shared library) +// q4_MULTI compile for multi-threading +// q4_NOLIB do not add automatic lib linkage (MSVC5) +// q4_NO_NS don't use namespaces for STL +// q4_OK assume all software is perfect +// q4_STRICT do not disable any compiler warnings +// q4_TINY small version, no floating point +// +///////////////////////////////////////////////////////////////////////////// + +#define __K4CONF_H__ // skip section in "mk4.h", since we use "header.h" + + // if neither MFC nor STD are specified, default to Universal version +#if !q4_MFC && !q4_STD && !defined (q4_UNIV) +#define q4_UNIV 1 +#endif + +///////////////////////////////////////////////////////////////////////////// +// You can either use '#define q4_xxx 1' to flag the choice of an OS, or +// use a '#define d4_OS_H "file.h"' to force inclusion of a header later. + +#if defined (__MINGW32__) +#define d4_OS_H "win.h" +#elif defined (MSDOS) && defined (__GNUC__) +#define q4_DOS 1 +#elif defined(unix) || defined(__unix__) || defined(__GNUC__) || \ + defined(_AIX) || defined(__hpux) +#define q4_UNIX 1 +#elif defined (__VMS) +#define q4_VMS 1 +#elif defined (macintosh) +#define q4_MAC 1 +#elif !defined (d4_OS_H) +#define d4_OS_H "win.h" +#endif + +///////////////////////////////////////////////////////////////////////////// +// Use '#define q4_xxx 1' to flag the choice of a CPU. + +#if defined (_M_I86) || defined (_M_IX86) || defined (i386) +#define q4_I86 1 +#if defined (_M_I86SM) +#define q4_TINY 1 +#endif +#elif defined (__powerc) +#define q4_PPC 1 +#elif defined (__alpha) +#define q4_AXP 1 +#define q4_LONG64 1 +#elif defined (__VMS) +#define q4_VAX 1 +#else +#define q4_M68K 1 +#endif + +///////////////////////////////////////////////////////////////////////////// +// Use '#define q4_xxx 1' to flag the choice of an IDE, and optionally also +// add '#include "file.h"' to force inclusion of a header file right here. + +#if defined (__BORLANDC__) // Borland C++ +#include "borc.h" +#elif defined (__DECCXX) // DEC C++ +#define q4_DECC 1 +#elif defined (__GNUC__) // GNU C++ +#include "gnuc.h" +#elif defined (__MWERKS__) // Metrowerks CodeWarrior C++ +#include "mwcw.h" +#elif defined (_MSC_VER) // Microsoft Visual C++ +#include "msvc.h" +#elif defined (__SC__) // Symantec C++ +#define q4_SYMC 1 +#elif defined (__WATCOMC__) // Watcom C++ +#define q4_WATC 1 +#endif + +///////////////////////////////////////////////////////////////////////////// +// Some of the options take precedence over others + +#if !q4_BOOL && !q4_STD // define a bool datatype +#define false 0 +#define true 1 +#define bool int +#endif + +#if !q4_CHECK // disable assertions +#undef d4_assert +#define d4_dbgdef(x) +#define d4_assert(x) +#endif + +#if q4_NO_NS // don't use namespaces +#define d4_std +#else +#define d4_std std +#endif + +#if HAVE_MEMMOVE +#define d4_memmove(d,s,n) memmove(d,s,n) +#elif HAVE_BCOPY +#define d4_memmove(d,s,n) bcopy(s,d,n) +#else +#define d4_memmove f4_memmove +extern void f4_memmove(void* d, const void* s, int n); +#endif + +typedef unsigned char t4_byte; // create typedefs for t4_byte, etc. + +///////////////////////////////////////////////////////////////////////////// +// Include header files which contain additional os/cpu/ide/fw specifics + +#ifdef d4_OS_H // operating system dependencies +#include d4_OS_H +#endif + +///////////////////////////////////////////////////////////////////////////// +// Several defines should always be set + +#ifndef d4_assert // assertion macro +#include <assert.h> +#define d4_assert assert +#endif + +#ifndef d4_dbgdef // conditionally compiled +#ifdef NDEBUG +#define d4_dbgdef(x) +#else +#define d4_dbgdef(x) x +#endif +#endif + +#ifndef d4_new // heap allocator +#define d4_new new +#endif + +#ifndef d4_reentrant // thread-local storage +#define d4_reentrant +#endif + +///////////////////////////////////////////////////////////////////////////// +// Debug logging option, called internally where properties are modified + +#if q4_LOGPROPMODS +void f4_DoLogProp(const c4_Handler*, int, const char*, int); +#else +#define f4_LogPropMods(a,b) 0 +#endif + +///////////////////////////////////////////////////////////////////////////// +// Public definitions, plus a few more framework-specific ones + +#include "mk4.h" + +#if q4_MFC +#include "mfc.h" +#elif q4_STD +#include "std.h" +#elif q4_UNIV +#include "univ.h" +#endif + +#ifdef _MSC_VER +#pragma warning(disable: 4100 4127 4135 4244 4511 4512 4514) +#endif + +#include <string.h> + +///////////////////////////////////////////////////////////////////////////// +// Report unexpected combinations of settings + +#if !q4_FIX +#if (q4_DOS+q4_MAC+q4_UNIX+q4_VMS+q4_WIN) != 1 +#error Exactly one operating system should have been defined +#endif +#if (q4_MFC+q4_STD+q4_UNIV) != 1 +#error Exactly one container library should have been defined +#endif +#endif + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/mfc.h b/akregator/src/mk4storage/metakit/src/mfc.h new file mode 100644 index 000000000..6e6d3e248 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/mfc.h @@ -0,0 +1,34 @@ +// mfc.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Configuration header for MFC-based builds + */ + +#define q4_MFC 1 + +#if q4_WIN && !q4_WIN32 +#include <afxwin.h> +#else +#include <afxcoll.h> +#endif + +#undef d4_assert +#define d4_assert ASSERT + +#undef d4_assertThis +#define d4_assertThis d4_assert(AfxIsValidAddress(this, sizeof *this, FALSE)) + +#undef d4_new +#define d4_new DEBUG_NEW + +typedef class CString c4_String; +typedef class CPtrArray c4_PtrArray; +typedef class CDWordArray c4_DWordArray; +typedef class CStringArray c4_StringArray; + + // MSVC 1.52 thinks a typedef has no constructor, so use a define instead +#if !q4_OK && q4_MSVC && _MSC_VER == 800 +#define c4_String CString +#endif diff --git a/akregator/src/mk4storage/metakit/src/msvc.h b/akregator/src/mk4storage/metakit/src/msvc.h new file mode 100644 index 000000000..a53e8b6dc --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/msvc.h @@ -0,0 +1,39 @@ +// msvc.h -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Configuration header for Microsoft Visual C++ + */ + +#define q4_MSVC 1 + + // get rid of several common warning messages +#if !q4_STRICT +//#pragma warning(disable: 4244) // conversion ..., possible loss of data +//#pragma warning(disable: 4135) // conversion between diff. integral types +//#pragma warning(disable: 4511) // copy constructor could not be generated +//#pragma warning(disable: 4512) // assignment op could not be generated +//#pragma warning(disable: 4514) // unreferenced inline removed +#pragma warning(disable: 4710) // function ... not inlined +#pragma warning(disable: 4711) // ... selected for automatic inline expansion +#pragma warning(disable: 4100) // unreferenced formal parameter +#endif + +#if _MSC_VER >= 1100 +#define q4_BOOL 1 // 5.0 supports the bool datatype +#else +#define q4_NO_NS 1 // 4.x doesn't use namespaces for STL +#endif + +#if defined (_MT) +#define q4_MULTI 1 // uses multi-threading +#endif + +#if defined (_DEBUG) && !defined (q4_CHECK) // use assertions in debug build +#define q4_CHECK 1 +#endif + +#if !q4_STD && !q4_UNIV && !defined (q4_MFC) +#define d4_FW_H "mfc.h" // default for MSVC is to use MFC +#endif diff --git a/akregator/src/mk4storage/metakit/src/mwcw.h b/akregator/src/mk4storage/metakit/src/mwcw.h new file mode 100644 index 000000000..1c863b967 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/mwcw.h @@ -0,0 +1,31 @@ +// mwcw.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Configuration header for Metrowerks CodeWarrior + */ + +#define q4_MWCW 1 + +///////////////////////////////////////////////////////////////////////////// + +#if q4_68K +#if !__option(IEEEdoubles) +#error Cannot build Metakit with 10-byte doubles +#endif +#endif + +#if __option(bool) +#define q4_BOOL 1 + // undo previous defaults, because q4_BOOL is not set early enough +#undef false +#undef true +#undef bool +#endif + +#undef _MSC_VER + +#pragma export on + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/persist.cpp b/akregator/src/mk4storage/metakit/src/persist.cpp new file mode 100644 index 000000000..65a9e94eb --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/persist.cpp @@ -0,0 +1,1185 @@ +// persist.cpp -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Implementation of the main file management classes + */ + +#include "header.h" +#include "column.h" +#include "persist.h" +#include "handler.h" +#include "store.h" +#include "field.h" + +///////////////////////////////////////////////////////////////////////////// + +class c4_FileMark +{ + enum { + kStorageFormat = 0x4C4A, // b0 = 'J', b1 = <4C> (on Intel) + kReverseFormat = 0x4A4C // b0 = <4C>, b1 = 'J' + }; + + t4_byte _data [8]; + +public: + c4_FileMark (); + c4_FileMark (t4_i32 pos_, bool flipped_, bool extend_); + c4_FileMark (t4_i32 pos_, int len_); + + t4_i32 Offset() const; + t4_i32 OldOffset() const; + + bool IsHeader() const; + bool IsOldHeader() const; + bool IsFlipped() const; +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_FileMark::c4_FileMark () +{ + d4_assert(sizeof *this == 8); +} + +c4_FileMark::c4_FileMark (t4_i32 pos_, bool flipped_, bool extend_) +{ + d4_assert(sizeof *this == 8); + *(short*) _data = flipped_ ? kReverseFormat : kStorageFormat; + _data[2] = extend_ ? 0x0A : 0x1A; + _data[3] = 0; + t4_byte* p = _data + 4; + for (int i = 24; i >= 0; i -= 8) + *p++ = (t4_byte) (pos_ >> i); + d4_assert(p == _data + sizeof _data); +} + +c4_FileMark::c4_FileMark (t4_i32 pos_, int len_) +{ + d4_assert(sizeof *this == 8); + t4_byte* p = _data; + *p++ = 0x80; + for (int j = 16; j >= 0; j -= 8) + *p++ = (t4_byte) (len_ >> j); + for (int i = 24; i >= 0; i -= 8) + *p++ = (t4_byte) (pos_ >> i); + d4_assert(p == _data + sizeof _data); +} + +t4_i32 c4_FileMark::Offset() const +{ + t4_i32 v = 0; + for (int i = 4; i < 8; ++i) + v = (v << 8) + _data[i]; + return v; +} + +t4_i32 c4_FileMark::OldOffset() const +{ + t4_i32 v = 0; + for (int i = 8; --i >= 4; ) + v = (v << 8) + _data[i]; + return v; +} + +bool c4_FileMark::IsHeader() const +{ + return (_data[0] == 'J' || _data[0] == 'L') && + (_data[0] ^ _data[1]) == ('J' ^ 'L') && _data[2] == 0x1A; +} + +bool c4_FileMark::IsOldHeader() const +{ + return IsHeader() && _data[3] == 0x80; +} + +bool c4_FileMark::IsFlipped() const +{ + return *(short*) _data == kReverseFormat; + +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_Allocator : public c4_DWordArray +{ +public: + c4_Allocator (); + + void Initialize(t4_i32 first_ =1); + + t4_i32 AllocationLimit() const; + + t4_i32 Allocate(t4_i32 len_); + void Occupy(t4_i32 pos_, t4_i32 len_); + void Release(t4_i32 pos_, t4_i32 len_); + void Dump(const char* str_); + +private: + int Locate(t4_i32 pos_) const; + void InsertPair(int i_, t4_i32 from_, t4_i32 to_); + t4_i32 ReduceFrags(int goal_, int sHi_, int sLo_); +}; + +///////////////////////////////////////////////////////////////////////////// +// +// Allocation of blocks is maintained in a separate data structure. +// There is no allocation overhead in the allocation arena itself. +// +// A single vector of "walls" is maintained, sorted by position: +// +// * Each transition between free and allocated is a single entry. +// The number of entries is <num-free-ranges> + <num-used-ranges>. +// * By definition, free areas start at the positions indicated +// by the entries on even indices. Allocated ones use odd entries. +// * There is an extra <0,0> free slot at the very beginning. This +// simplifies boundary conditions at the start of the arena. +// * Position zero cannot be allocated, first slot starts at 1. +// +// Properties of this approach: +// +// * No allocation overhead for adjacent allocated areas. On the +// other hand, the allocator does not know the size of used slots. +// * Alternate function allows marking a specific range as occupied. +// * Allocator can be initialized as either all free or all in-use. +// * Allocation info contains only integers, it could be stored. +// * To extend allocated slots: "occupy" extra bytes at the end. +// * Generic: can be used for memory, disk files, and array entries. + +c4_Allocator::c4_Allocator () +{ + Initialize(); +} + +void c4_Allocator::Initialize(t4_i32 first_) +{ + SetSize(0, 1000); // empty, and growing in large chunks + Add(0); // fake block at start + Add(0); // ... only used to avoid merging + + // if occupied, add a tiny free slot at the end, else add entire range + const t4_i32 kMaxInt = 0x7fffffff; + if (first_ == 0) + first_ = kMaxInt; + + Add(first_); // start at a nicely aligned position + Add(kMaxInt); // ... there is no limit on file size +} + +t4_i32 c4_Allocator::Allocate(t4_i32 len_) +{ + // zero arg is ok, it simply returns first allocatable position + for (int i = 2; i < GetSize(); i += 2) + if (GetAt(i+1) >= GetAt(i) + len_) { + t4_i32 pos = GetAt(i); + if ((t4_i32) GetAt(i+1) > pos + len_) + ElementAt(i) += len_; + else + RemoveAt(i, 2); + return pos; + } + + d4_assert(0); + return 0; // not reached +} + +void c4_Allocator::Occupy(t4_i32 pos_, t4_i32 len_) +{ + d4_assert(pos_ > 0); + // note that zero size simply checks if there is any space to extend + + int i = Locate(pos_); + d4_assert(0 < i && i < GetSize()); + + if (i % 2) { // allocation is not at start of free block + d4_assert((t4_i32) GetAt(i-1) < pos_); + + if ((t4_i32) GetAt(i) == pos_ + len_) // allocate from end of free block + SetAt(i, pos_); + else // split free block in two + InsertPair(i, pos_, pos_ + len_); + } + else if ((t4_i32) GetAt(i) == pos_) +/* + This side of the if used to be unconditional, but that was + incorrect if ReduceFrags gets called (which only happens with + severely fragmented files) - there are cases when allocation + leads to an occupy request of which the free space list knows + nothing about because it dropped small segments. The solution + is to silently "allow" such allocations - fixed 29-02-2000 + Thanks to Andrew Kuchling for his help in chasing this bug. +*/ + { // else extend tail of allocated area + if ((t4_i32) GetAt(i+1) > pos_ + len_) + ElementAt(i) += len_; // move start of next free up + else + RemoveAt(i, 2); // remove this slot + } +} + +void c4_Allocator::Release(t4_i32 pos, t4_i32 len) +{ + int i = Locate(pos + len); + d4_assert(0 < i && i < GetSize()); + d4_assert(i % 2 == 0); // don't release inside a free block + + if ((t4_i32) GetAt(i) == pos) // move start of next free down + ElementAt(i) -= len; + else if ((t4_i32) GetAt(i-1) == pos) // move end of previous free up + ElementAt(i-1) += len; + else // insert a new entry + InsertPair(i, pos, pos + len); + + if (GetAt(i-1) == GetAt(i)) // merge if adjacent free + RemoveAt(i-1, 2); +} + +t4_i32 c4_Allocator::AllocationLimit() const +{ + d4_assert(GetSize() >= 2); + + return GetAt(GetSize() - 2); +} + +int c4_Allocator::Locate(t4_i32 pos) const +{ + int lo = 0, hi = GetSize() - 1; + + while (lo < hi) { + int i = (lo + hi) / 2; + if (pos < (t4_i32) GetAt(i)) + hi = i - 1; + else if (pos > (t4_i32) GetAt(i)) + lo = i + 1; + else + return i; + } + + return lo < GetSize() && pos > (t4_i32) GetAt(lo) ? lo + 1 : lo; +} + +void c4_Allocator::InsertPair(int i_, t4_i32 from_, t4_i32 to_) +{ + d4_assert(0 < i_); + d4_assert(i_ < GetSize()); + + d4_assert(from_ < to_); + d4_assert((t4_i32) GetAt(i_-1) < from_); + //!d4_assert(to_ < GetAt(i_)); + + if (to_ >= (t4_i32) GetAt(i_)) + return; // ignore 2nd allocation of used area + + InsertAt(i_, from_, 2); + SetAt(i_+1, to_); + + // it's ok to have arrays up to some 30000 bytes + if (GetSize() > 7500) + ReduceFrags(5000, 12, 6); +} + +t4_i32 c4_Allocator::ReduceFrags(int goal_, int sHi_, int sLo_) +{ + // drastic fail-safe measure: remove small gaps if vec gets too long + // this will cause some lost free space but avoids array overflow + // the lost space will most probably be re-used after the next commit + + int limit = GetSize() - 2; + t4_i32 loss = 0; + + // go through all entries and remove gaps under the given threshold + for (int shift = sHi_; shift >= sLo_; --shift) { + // the threshold is a fraction of the current size of the arena + t4_i32 threshold = AllocationLimit() >> shift; + if (threshold == 0) + continue; + + int n = 2; + for (int i = n; i < limit; i += 2) + if ((t4_i32) GetAt(i+1) - (t4_i32) GetAt(i) > threshold) { + SetAt(n++, GetAt(i)); + SetAt(n++, GetAt(i+1)); + } + else + loss += GetAt(i+1) - GetAt(i); + + limit = n; + + // if (GetSize() < goal_) - suboptimal, fixed 29-02-2000 + if (limit < goal_) + break; // got rid of enough entries, that's enough + } + + int n = GetSize() - 2; + SetAt(limit++, GetAt(n++)); + SetAt(limit++, GetAt(n)); + SetSize(limit); + + return loss; +} + +#if q4_CHECK +#include <stdio.h> + +void c4_Allocator::Dump(const char* str_) +{ + fprintf(stderr, "c4_Allocator::Dump, %d entries <%s>\n", GetSize(), str_); + for (int i = 2; i < GetSize(); i += 2) + fprintf(stderr, " %10ld .. %ld\n", GetAt(i-1), GetAt(i)); + fprintf(stderr, "END\n"); +} + +#else + +void c4_Allocator::Dump(const char* str_) { } + +#endif + +///////////////////////////////////////////////////////////////////////////// + +class c4_Differ +{ +public: + c4_Differ (c4_Storage& storage_); + ~c4_Differ (); + + int NewDiffID(); + void CreateDiff(int id_, c4_Column& col_); + t4_i32 BaseOfDiff(int id_); + void ApplyDiff(int id_, c4_Column& col_) const; + + void GetRoot(c4_Bytes& buffer_); + + c4_Storage _storage; + c4_View _diffs; + c4_View _temp; + +private: + void AddEntry(t4_i32, t4_i32, const c4_Bytes&); + + c4_ViewProp pCols; // column info: + c4_IntProp pOrig; // original position + c4_ViewProp pDiff; // difference chunks: + c4_IntProp pKeep; // offset + c4_IntProp pResize; // length + c4_BytesProp pBytes; // data +}; + +c4_Differ::c4_Differ (c4_Storage& storage_) + : _storage (storage_), pCols ("_C"), pOrig ("_O"), + pDiff ("_D"), pKeep ("_K"), pResize ("_R"), pBytes ("_B") +{ + // weird names, to avoid clashing with existing ones (capitalization!) + _diffs = _storage.GetAs("_C[_O:I,_D[_K:I,_R:I,_B:B]]"); +} + +c4_Differ::~c4_Differ () +{ + _diffs = c4_View (); +} + +void c4_Differ::AddEntry(t4_i32 off_, t4_i32 len_, const c4_Bytes& data_) +{ + int n = _temp.GetSize(); + _temp.SetSize(n + 1); + c4_RowRef r = _temp[n]; + + pKeep (r) = (t4_i32) off_; + pResize (r) = (t4_i32) len_; + pBytes (r).SetData(data_); +} + +int c4_Differ::NewDiffID() +{ + int n = _diffs.GetSize(); + _diffs.SetSize(n + 1); + return n; +} + +void c4_Differ::CreateDiff(int id_, c4_Column& col_) +{ + _temp.SetSize(0); +#if 0 + t4_i32 offset = 0; + t4_i32 savedOff = 0; + t4_i32 savedLen = 0; + + c4_Strategy* strat = col_.Persist() != 0 ? &col_.Strategy() : 0; + + c4_ColIter iter (col_, 0, col_.ColSize()); + while (iter.Next()) { + const t4_byte* p = iter.BufLoad(); + if (strat != 0 && strat->_mapStart != 0 && p >= strat->_mapStart && + p - strat->_mapStart < strat->_dataSize) + { + t4_i32 nextOff = p - strat->_mapStart; + if (savedLen == 0) + savedOff = nextOff; + if (nextOff == savedOff + savedLen) { + savedLen += iter.BufLen(); + continue; + } + + if (savedLen > 0) + AddEntry(savedOff, savedLen, c4_Bytes ()); + + savedOff = nextOff; + savedLen = iter.BufLen(); + } else { + AddEntry(savedOff, savedLen, c4_Bytes (p, iter.BufLen())); + savedLen = 0; + } + + offset += iter.BufLen(); + } + + c4_View diff = pDiff (_diffs[id_]); + if (_temp.GetSize() != diff.GetSize() || _temp != diff) +#else + c4_Bytes t1; + const t4_byte* p = col_.FetchBytes(0, col_.ColSize(), t1, false); + AddEntry(0, 0, c4_Bytes (p, col_.ColSize())); +#endif + pDiff (_diffs[id_]) = _temp; + + pOrig (_diffs[id_]) = col_.Position(); +} + +t4_i32 c4_Differ::BaseOfDiff(int id_) +{ + d4_assert(0 <= id_ && id_ < _diffs.GetSize()); + + return pOrig (_diffs[id_]); +} + +void c4_Differ::ApplyDiff(int id_, c4_Column& col_) const +{ + d4_assert(0 <= id_ && id_ < _diffs.GetSize()); + + c4_View diff = pDiff (_diffs[id_]); + t4_i32 offset = 0; + + for (int n = 0; n < diff.GetSize(); ++n) { + c4_RowRef row (diff[n]); + offset += pKeep (row); + + c4_Bytes data; + pBytes(row).GetData(data); + + // the following code is a lot like c4_MemoRef::Modify + const t4_i32 change = pResize (row); + if (change < 0) + col_.Shrink(offset, -change); + else if (change > 0) + col_.Grow(offset, change); + + col_.StoreBytes(offset, data); + offset += data.Size(); + } + + if (offset > col_.ColSize()) + col_.Shrink(offset, offset - col_.ColSize()); +} + +void c4_Differ::GetRoot(c4_Bytes& buffer_) +{ + int last = _diffs.GetSize() - 1; + if (last >= 0) { + c4_Bytes temp; + c4_View diff = pDiff (_diffs[last]); + if (diff.GetSize() > 0) + pBytes (diff[0]).GetData(buffer_); + } +} + +///////////////////////////////////////////////////////////////////////////// + +c4_SaveContext::c4_SaveContext (c4_Strategy& strategy_, bool fullScan_, + int mode_, c4_Differ* differ_, c4_Allocator* space_) + : _strategy (strategy_), _walk (0), _differ (differ_), _space (space_), + _cleanup (0), _nextSpace (0), _preflight (true), _fullScan (fullScan_), + _mode (mode_), _nextPosIndex (0), _bufPtr (_buffer), _curr (_buffer), + _limit (_buffer) +{ + if (_space == 0) + _space = _cleanup = d4_new c4_Allocator; + + _nextSpace = _mode == 1 ? d4_new c4_Allocator : _space; +} + +c4_SaveContext::~c4_SaveContext () +{ + delete _cleanup; + if (_nextSpace != _space) + delete _nextSpace; +} + +bool c4_SaveContext::IsFlipped() const +{ + return _strategy._bytesFlipped; +} + +bool c4_SaveContext::Serializing() const +{ + return _fullScan; +} + +void c4_SaveContext::AllocDump(const char* str_, bool next_) +{ + c4_Allocator* ap = next_ ? _nextSpace : _space; + if (ap != 0) + ap->Dump(str_); +} + +void c4_SaveContext::FlushBuffer() +{ + int n = _curr - _bufPtr; + if (_walk != 0 && n > 0) { + t4_i32 end = _walk->ColSize(); + _walk->Grow(end, n); + _walk->StoreBytes(end, c4_Bytes (_bufPtr, n)); + } + + _curr = _bufPtr = _buffer; + _limit = _buffer + sizeof _buffer; +} + +c4_Column* c4_SaveContext::SetWalkBuffer(c4_Column* col_) +{ + FlushBuffer(); + + c4_Column* prev = _walk; + _walk = col_; + return prev; +} + +void c4_SaveContext::Write(const void* buf_, int len_) +{ + // use buffering if possible + if (_curr + len_ <= _limit) { + memcpy(_curr, buf_, len_); + _curr += len_; + } else { + FlushBuffer(); + _bufPtr = (t4_byte*) buf_; // also loses const + _curr = _limit = _bufPtr + len_; + FlushBuffer(); + } +} + +void c4_SaveContext::StoreValue(t4_i32 v_) +{ + if (_walk == 0) + return; + + if (_curr + 10 >= _limit) + FlushBuffer(); + + d4_assert(_curr + 10 < _limit); + c4_Column::PushValue(_curr, v_); +} + +void c4_SaveContext::SaveIt(c4_HandlerSeq& root_, c4_Allocator** spacePtr_, + c4_Bytes& rootWalk_) +{ + d4_assert(_space != 0); + + const t4_i32 size = _strategy.FileSize(); + if (_strategy._failure != 0) + return; + + const t4_i32 end = _fullScan ? 0 : size - _strategy._baseOffset; + + if (_differ == 0) { + if (_mode != 1) + _space->Initialize(); + + // don't allocate anything inside the file in extend mode + if (_mode == 2 && end > 0) { + _space->Occupy(1, end - 1); + _nextSpace->Occupy(1, end - 1); + } + + // the header is always reserved + _space->Occupy(1, 7); + _nextSpace->Occupy(1, 7); + + if (end > 0) { + d4_assert(end >= 16); + _space->Occupy(end - 16, 16); + _nextSpace->Occupy(end - 16, 16); + _space->Occupy(end, 8); + _nextSpace->Occupy(end, 8); + } + } + + //AllocDump("a1", false); + //AllocDump("a2", true); + + // first pass allocates columns and constructs shallow walks + c4_Column walk (root_.Persist()); + SetWalkBuffer(&walk); + CommitSequence(root_, true); + SetWalkBuffer(0); + CommitColumn(walk); + + c4_Bytes tempWalk; + walk.FetchBytes(0, walk.ColSize(), tempWalk, true); + + t4_i32 limit = _nextSpace->AllocationLimit(); + d4_assert(limit >= 8 || _differ != 0); + + bool changed = _fullScan || tempWalk != rootWalk_; + + rootWalk_ = c4_Bytes (tempWalk.Contents(), tempWalk.Size(), true); + + _preflight = false; + + // special-case to avoid saving data if file is logically empty + // in that case, the data is 0x80 0x81 0x80 (plus the header) + if (!_fullScan && limit <= 11 && _differ == 0) { + _space->Initialize(); + _nextSpace->Initialize(); + changed = false; + } + + if (!changed) + return; + + //AllocDump("b1", false); + //AllocDump("b2", true); + + if (_differ != 0) { + int n = _differ->NewDiffID(); + _differ->CreateDiff(n, walk); + return; + } + + d4_assert(_mode != 0 || _fullScan); + + // this is the place where writing may start + + // figure out where the new file ends and write a skip tail there + t4_i32 end0 = end; + + // true if the file need not be extended due to internal free space + bool inPlace = end0 == limit - 8; + if (inPlace) { + d4_assert(!_fullScan); + _space->Release(end0, 8); + _nextSpace->Release(end0, 8); + end0 -= 16; // overwrite existing tail markers + } else { + c4_FileMark head (limit + 16 - end, _strategy._bytesFlipped, end > 0); + _strategy.DataWrite(end, &head, sizeof head); + + if (end0 < limit) + end0 = limit; // create a gap + } + + t4_i32 end1 = end0 + 8; + t4_i32 end2 = end1 + 8; + + if (!_fullScan && !inPlace) { + c4_FileMark mark1 (end0, 0); + _strategy.DataWrite(end0, &mark1, sizeof mark1); +#if q4_WIN32 + /* March 8, 2002 + * On at least NT4 with NTFS, extending a file can cause it to be + * rounded up further than expected. To prevent creating a bad + * file (since the file does then not end with a marker), the + * workaround it so simply accept the new end instead and rewrite. + * Note that between these two writes, the file is in a bad state. + */ + t4_i32 realend = _strategy.FileSize() - _strategy._baseOffset; + if (realend > end1) { + end0 = limit = realend - 8; + end1 = realend; + end2 = realend + 8; + c4_FileMark mark1a (end0, 0); + _strategy.DataWrite(end0, &mark1a, sizeof mark1a); + } +#endif + d4_assert(_strategy.FileSize() == _strategy._baseOffset + end1); + } + + _space->Occupy(end0, 16); + _nextSpace->Occupy(end0, 16); + + // strategy.DataCommit(0); // may be needed, need more info on how FS's work + // but this would need more work, since we can't adjust file-mapping here + + // second pass saves the columns and structure to disk + CommitSequence(root_, true); // writes changed columns + CommitColumn(walk); + + //! d4_assert(_curr == 0); + d4_assert(_nextPosIndex == _newPositions.GetSize()); + + if (_fullScan) { + c4_FileMark mark1 (limit, 0); + _strategy.DataWrite(_strategy.FileSize() - _strategy._baseOffset, + &mark1, sizeof mark1); + + c4_FileMark mark2 (limit - walk.ColSize(), walk.ColSize()); + _strategy.DataWrite(_strategy.FileSize() - _strategy._baseOffset, + &mark2, sizeof mark2); + + return; + } + + if (inPlace) + d4_assert(_strategy.FileSize() == _strategy._baseOffset + end2); + else { + // make sure the allocated size hasn't changed + d4_assert(_nextSpace->AllocationLimit() == limit + 16); + d4_assert(end0 >= limit); + d4_assert(_strategy.FileSize() - _strategy._baseOffset == end1); + } + + if (walk.Position() == 0 || _strategy._failure != 0) + return; + + _strategy.DataCommit(0); + + c4_FileMark mark2 (walk.Position(), walk.ColSize()); + _strategy.DataWrite(end1, &mark2, sizeof mark2); + d4_assert(_strategy.FileSize() - _strategy._baseOffset == end2); + + // do not alter the file header in extend mode, unless it is new + if (!_fullScan && (_mode == 1 || end == 0)) { + _strategy.DataCommit(0); + + c4_FileMark head (end2, _strategy._bytesFlipped, false); + d4_assert(head.IsHeader()); + _strategy.DataWrite(0, &head, sizeof head); + + // if the file became smaller, we could shrink it + if (limit + 16 < end0) { +/* + Not yet, this depends on the strategy class being able to truncate, but + there is no way to find out whether it does (the solution is to write tail + markers in such a way that the file won't grow unnecessarily if it doesn't). + + The logic will probably be: + + * write new skip + commit "tails" at limit (no visible effect on file) + * overwrite commit tail at end with a skip to this new one (equivalent) + * replace header with one pointing to that internal new one (equivalent) + * flush (now the file is valid both truncated and not-yet-truncated + + end = limit; +*/ + } + } + + // if using memory mapped files, make sure the map is no longer in use + if (_strategy._mapStart != 0) + root_.UnmappedAll(); + + // commit and tell strategy object what the new file size is, this + // may be smaller now, if old data at the end is no longer referenced + _strategy.DataCommit(end2); + + d4_assert(_strategy.FileSize() - _strategy._baseOffset == end2); + + if (spacePtr_ != 0 && _space != _nextSpace) { + d4_assert(*spacePtr_ == _space); + delete *spacePtr_; + *spacePtr_ = _nextSpace; + _nextSpace = 0; + } +} + +bool c4_SaveContext::CommitColumn(c4_Column& col_) +{ + bool changed = col_.IsDirty() || _fullScan; + + t4_i32 sz = col_.ColSize(); + StoreValue(sz); + if (sz > 0) { + t4_i32 pos = col_.Position(); + + if (_differ) { + if (changed) { + int n = pos < 0 ? ~pos : _differ->NewDiffID(); + _differ->CreateDiff(n, col_); + + d4_assert(n >= 0); + pos = ~n; + } + } else if (_preflight) { + if (changed) + pos = _space->Allocate(sz); + + _nextSpace->Occupy(pos, sz); + _newPositions.Add(pos); + } else { + pos = _newPositions.GetAt(_nextPosIndex++); + + if (changed) + col_.SaveNow(_strategy, pos); + + if (!_fullScan) + col_.SetLocation(pos, sz); + } + + StoreValue(pos); + } + + return changed; +} + +void c4_SaveContext::CommitSequence(c4_HandlerSeq& seq_, bool selfDesc_) +{ + StoreValue(0); // sias prefix + + if (selfDesc_) { + c4_String desc = seq_.Description(); + int k = desc.GetLength(); + StoreValue(k); + Write((const char*) desc, k); + } + + StoreValue(seq_.NumRows()); + if (seq_.NumRows() > 0) + for (int i = 0; i < seq_.NumFields(); ++i) + seq_.NthHandler(i).Commit(*this); +} + +///////////////////////////////////////////////////////////////////////////// + + // used for on-the-fly conversion of old-format datafiles + t4_byte* _oldBuf; + const t4_byte* _oldCurr; + const t4_byte* _oldLimit; + t4_i32 _oldSeek; + + +c4_Persist::c4_Persist (c4_Strategy& strategy_, bool owned_, int mode_) + : _space (0), _strategy (strategy_), _root (0), _differ (0), + _fCommit (0), _mode (mode_), _owned (owned_), _oldBuf (0), + _oldCurr (0), _oldLimit (0), _oldSeek (-1) +{ + if (_mode == 1) + _space = d4_new c4_Allocator; +} + +c4_Persist::~c4_Persist () +{ + delete _differ; + + if (_owned) { + if (_root != 0) + _root->UnmappedAll(); + delete &_strategy; + } + + delete _space; + + if (_oldBuf != 0) + delete [] _oldBuf; +} + +c4_HandlerSeq& c4_Persist::Root() const +{ + d4_assert(_root != 0); + return *_root; +} + +void c4_Persist::SetRoot(c4_HandlerSeq* root_) +{ + d4_assert(_root == 0); + _root = root_; +} + +c4_Strategy& c4_Persist::Strategy() const +{ + return _strategy; +} + +bool c4_Persist::AutoCommit(bool flag_) +{ + bool prev = _fCommit != 0; + if (flag_) + _fCommit = &c4_Persist::Commit; + else + _fCommit = 0; + return prev; +} + +void c4_Persist::DoAutoCommit() +{ + if (_fCommit != 0) + (this->*_fCommit)(false); +} + +bool c4_Persist::SetAside(c4_Storage& aside_) +{ + delete _differ; + _differ = d4_new c4_Differ (aside_); + Rollback(false); + return true; //! true if the generation matches +} + +c4_Storage* c4_Persist::GetAside() const +{ + return _differ != 0 ? &_differ->_storage : 0; +} + +bool c4_Persist::Commit(bool full_) +{ + // 1-Mar-1999, new semantics! return success status of commits + _strategy._failure = 0; + + if (!_strategy.IsValid()) + return false; + + if (_mode == 0 && (_differ == 0 || full_)) // can't commit to r/o file + return false; // note that _strategy._failure is *zero* in this case + + c4_SaveContext ar (_strategy, false, _mode, full_ ? 0 : _differ, _space); + + // get rid of temp properties which still use the datafile + if (_mode == 1) + _root->DetachFromStorage(false); + + // 30-3-2001: moved down, fixes "crash every 2nd call of mkdemo/dbg" + ar.SaveIt(*_root, &_space, _rootWalk); + return _strategy._failure == 0; +} + +bool c4_Persist::Rollback(bool full_) +{ + _root->DetachFromParent(); + _root->DetachFromStorage(true); + _root = 0; + + if (_space != 0) + _space->Initialize(); + + c4_HandlerSeq* seq = d4_new c4_HandlerSeq (this); + seq->DefineRoot(); + SetRoot(seq); + + if (full_) { + delete _differ; + _differ = 0; + } + + LoadAll(); + + return _strategy._failure == 0; +} + +bool c4_Persist::LoadIt(c4_Column& walk_) +{ + t4_i32 limit = _strategy.FileSize(); + if (_strategy._failure != 0) + return false; + + if (_strategy.EndOfData(limit) < 0) { + _strategy.SetBase(limit); + d4_assert(_strategy._failure == 0); // file is ok, but empty + return false; + } + + if (_strategy._rootLen > 0) + walk_.SetLocation(_strategy._rootPos, _strategy._rootLen); + + // if the file size has increased, we must remap + if (_strategy._mapStart != 0 && + _strategy.FileSize() > _strategy._baseOffset + _strategy._dataSize) + _strategy.ResetFileMapping(); + + return true; +} + +void c4_Persist::LoadAll() +{ + c4_Column walk (this); + if (!LoadIt(walk)) + return; + + if (_strategy._rootLen < 0) { + _oldSeek = _strategy._rootPos; + _oldBuf = d4_new t4_byte [512]; + _oldCurr = _oldLimit = _oldBuf; + + t4_i32 n = FetchOldValue(); + d4_assert(n == 0); + n = FetchOldValue(); + d4_assert(n > 0); + + c4_Bytes temp; + t4_byte* buf = temp.SetBuffer(n); + d4_dbgdef(int n2 =) + OldRead(buf, n); + d4_assert(n2 == n); + + c4_String s = "[" + c4_String ((const char*) buf, n) + "]"; + const char* desc = s; + + c4_Field* f = d4_new c4_Field (desc); + d4_assert(!*desc); + + //?_root->DefineRoot(); + _root->Restructure(*f, false); + + _root->OldPrepare(); + + // don't touch data inside while converting the file + if (_strategy.FileSize() >= 0) + OccupySpace(1, _strategy.FileSize()); + } else { + walk.FetchBytes(0, walk.ColSize(), _rootWalk, true); + if (_differ) + _differ->GetRoot(_rootWalk); + + // define and fill the root table + const t4_byte* ptr = _rootWalk.Contents(); + _root->Prepare(&ptr, true); + d4_assert(ptr == _rootWalk.Contents() + _rootWalk.Size()); + } +} + +t4_i32 c4_Persist::FetchOldValue() +{ + d4_assert(_oldSeek >= 0); + + if (_oldCurr == _oldLimit) { + int n = OldRead(_oldBuf, 500); + _oldLimit = _oldCurr + n; + _oldBuf[n] = 0x80; // to force end + } + + const t4_byte* p = _oldCurr; + t4_i32 value = c4_Column::PullValue(p); + + if (p > _oldLimit) { + int k = _oldLimit - _oldCurr; + d4_assert(0 < k && k < 10); + memcpy(_oldBuf, _oldCurr, k); + + int n = OldRead(_oldBuf + k, 500); + _oldCurr = _oldBuf + k; + _oldLimit = _oldCurr + n; + _oldBuf[n+k] = 0x80; // to force end + + p = _oldCurr; + value = c4_Column::PullValue(p); + d4_assert(p <= _oldLimit); + } + + _oldCurr = p; + return value; +} + +void c4_Persist::FetchOldLocation(c4_Column& col_) +{ + d4_assert(_oldSeek >= 0); + + t4_i32 sz = FetchOldValue(); + if (sz > 0) + col_.SetLocation(FetchOldValue(), sz); +} + +int c4_Persist::OldRead(t4_byte* buf_, int len_) +{ + d4_assert(_oldSeek >= 0); + + t4_i32 newSeek = _oldSeek + _oldCurr - _oldLimit; + int n = _strategy.DataRead(newSeek, buf_, len_); + d4_assert(n > 0); + _oldSeek = newSeek + n; + _oldCurr = _oldLimit = _oldBuf; + return n; +} + +c4_HandlerSeq* c4_Persist::Load(c4_Stream* stream_) +{ + d4_assert(stream_ != 0); + + c4_FileMark head; + if (stream_->Read(&head, sizeof head) != sizeof head || !head.IsHeader()) + return 0; // no data in file + + //_oldStyle = head._data[3] == 0x80; + d4_assert(!head.IsOldHeader()); + + t4_i32 limit = head.Offset(); + + c4_StreamStrategy* strat = d4_new c4_StreamStrategy (limit); + strat->_bytesFlipped = head.IsFlipped(); + strat->DataWrite(strat->FileSize() - strat->_baseOffset, &head, sizeof head); + + while (strat->FileSize() - strat->_baseOffset < limit) { + char buffer [4096]; + int n = stream_->Read(buffer, sizeof buffer); + d4_assert(n > 0); + strat->DataWrite(strat->FileSize() - strat->_baseOffset, buffer, n); + } + + c4_Persist* pers = d4_new c4_Persist (*strat, true, 0); + c4_HandlerSeq* seq = d4_new c4_HandlerSeq (pers); + seq->DefineRoot(); + pers->SetRoot(seq); + + c4_Column walk (pers); + if (!pers->LoadIt(walk)) { + seq->IncRef(); + seq->DecRef(); // a funny way to delete + return 0; + } + + c4_Bytes tempWalk; + walk.FetchBytes(0, walk.ColSize(), tempWalk, true); + + const t4_byte* ptr = tempWalk.Contents(); + seq->Prepare(&ptr, true); + d4_assert(ptr == tempWalk.Contents() + tempWalk.Size()); + + return seq; +} + +void c4_Persist::Save(c4_Stream* stream_, c4_HandlerSeq& root_) +{ + d4_assert(stream_ != 0); + + c4_StreamStrategy strat (stream_); + + // 31-01-2002: streaming must adopt byte order of origin datafile + c4_Persist* p = root_.Persist(); + if (p != 0) + strat._bytesFlipped = p->Strategy()._bytesFlipped; + + c4_SaveContext ar (strat, true, 0, 0, 0); + c4_Bytes tempWalk; + ar.SaveIt(root_, 0, tempWalk); +} + +t4_i32 c4_Persist::LookupAside(int id_) +{ + d4_assert(_differ != 0); + + return _differ->BaseOfDiff(id_); +} + +void c4_Persist::ApplyAside(int id_, c4_Column& col_) +{ + d4_assert(_differ != 0); + + _differ->ApplyDiff(id_, col_); +} + +void c4_Persist::OccupySpace(t4_i32 pos_, t4_i32 len_) +{ + d4_assert(_mode != 1 || _space != 0); + + if (_space != 0) + _space->Occupy(pos_, len_); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/persist.h b/akregator/src/mk4storage/metakit/src/persist.h new file mode 100644 index 000000000..61ef261ee --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/persist.h @@ -0,0 +1,127 @@ +// persist.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Definition of the core file management classes + */ + +#ifndef __PERSIST_H__ +#define __PERSIST_H__ + +///////////////////////////////////////////////////////////////////////////// +// Declarations in this file + + class c4_SaveContext; // wraps file commits + class c4_Persist; // persistent table storage + + class c4_Allocator; // not defined here + class c4_Column; // not defined here + class c4_Differ; // not defined here + class c4_FileMark; // not defined here + class c4_Strategy; // not defined here + class c4_HandlerSeq; // not defined here + +///////////////////////////////////////////////////////////////////////////// + +class c4_SaveContext +{ + c4_Strategy& _strategy; + c4_Column* _walk; + c4_Differ* _differ; + + c4_Allocator* _space; + c4_Allocator* _cleanup; + c4_Allocator* _nextSpace; + + bool _preflight; + bool _fullScan; + int _mode; + + c4_DWordArray _newPositions; + int _nextPosIndex; + + t4_byte* _bufPtr; + t4_byte* _curr; + t4_byte* _limit; + t4_byte _buffer [512]; + +public: + c4_SaveContext (c4_Strategy& strategy_, bool fullScan_, int mode_, + c4_Differ* differ_, c4_Allocator* space_); + ~c4_SaveContext (); + + void SaveIt(c4_HandlerSeq& root_, c4_Allocator** spacePtr_, + c4_Bytes& rootWalk_); + + void StoreValue(t4_i32 v_); + bool CommitColumn(c4_Column& col_); + void CommitSequence(c4_HandlerSeq& seq_, bool selfDesc_); + + c4_Column* SetWalkBuffer(c4_Column* walk_); + bool IsFlipped() const; + + bool Serializing() const; + void AllocDump(const char*, bool =false); + +private: + void FlushBuffer(); + void Write(const void* buf_, int len_); +}; + +///////////////////////////////////////////////////////////////////////////// + +class c4_Persist +{ + c4_Allocator* _space; + c4_Strategy& _strategy; + c4_HandlerSeq* _root; + c4_Differ* _differ; + c4_Bytes _rootWalk; + bool (c4_Persist::*_fCommit) (bool); + int _mode; + bool _owned; + + // used for on-the-fly conversion of old-format datafiles + t4_byte* _oldBuf; + const t4_byte* _oldCurr; + const t4_byte* _oldLimit; + t4_i32 _oldSeek; + + int OldRead(t4_byte* buf_, int len_); + +public: + c4_Persist (c4_Strategy&, bool owned_, int mode_); + ~c4_Persist (); + + c4_HandlerSeq& Root() const; + void SetRoot(c4_HandlerSeq* root_); + c4_Strategy& Strategy() const; + + bool AutoCommit(bool =true); + void DoAutoCommit(); + + bool SetAside(c4_Storage& aside_); + c4_Storage* GetAside() const; + + bool Commit(bool full_); + bool Rollback(bool full_); + + bool LoadIt(c4_Column& walk_); + void LoadAll(); + + t4_i32 LookupAside(int id_); + void ApplyAside(int id_, c4_Column& col_); + + void OccupySpace(t4_i32 pos_, t4_i32 len_); + + t4_i32 FetchOldValue(); + void FetchOldLocation(c4_Column& col_); + + static c4_HandlerSeq* Load(c4_Stream*); + static void Save(c4_Stream*, c4_HandlerSeq& root_); +}; + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/remap.cpp b/akregator/src/mk4storage/metakit/src/remap.cpp new file mode 100644 index 000000000..cc8175df2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/remap.cpp @@ -0,0 +1,1154 @@ +// remap.cpp -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file +* Mapping and remapping custom viewers +*/ + +#include "header.h" +#include "remap.h" +#include "handler.h" + +///////////////////////////////////////////////////////////////////////////// + +class c4_ReadOnlyViewer : public c4_CustomViewer +{ + c4_View _base; + +public: + c4_ReadOnlyViewer (c4_Sequence& seq_) : _base (&seq_) { } + virtual ~c4_ReadOnlyViewer () { } + + virtual c4_View GetTemplate() { return _base.Clone(); } + virtual int GetSize() { return _base.GetSize(); } + + virtual int Lookup(c4_Cursor key_, int& count_) + { int pos = 0; count_ = _base.GetSize(); + return _base.RestrictSearch(*key_, pos, count_); } + + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_) + { return _base.GetItem(row_, col_, buf_); } +}; + +///////////////////////////////////////////////////////////////////////////// + +class c4_HashViewer : public c4_CustomViewer +{ + c4_View _base; + c4_View _map; + int _numKeys; + + c4_IntProp _pHash; + c4_IntProp _pRow; + + bool KeySame(int row_, c4_Cursor cursor_) const; + t4_i32 CalcHash(c4_Cursor cursor_) const; + int LookDict(t4_i32 hash_, c4_Cursor cursor_) const; + void InsertDict(int row_); + void RemoveDict(int pos_); + bool DictResize(int minused); + + int Row(int i_) const { return _pRow (_map[i_]); } + int Hash(int i_) const { return _pHash (_map[i_]); } + + void SetRow(int i_, int v_) { _pRow (_map[i_]) = v_; } + void SetHash(int i_, int v_) { _pHash (_map[i_]) = v_; } + + bool IsUnused(int) const; + bool IsDummy(int) const; + bool IsActive(int i_) const { return Row(i_) >= 0; } + + int GetPoly() const; + void SetPoly(int v_); + int GetSpare() const; + void SetSpare(int v_); + +public: + c4_HashViewer (c4_Sequence& seq_, int numKeys_, + c4_Sequence* map_=0); + virtual ~c4_HashViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual int Lookup(c4_Cursor key_, int& count_); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); + virtual bool SetItem(int row_, int col_, const c4_Bytes& buf_); + virtual bool InsertRows(int pos_, c4_Cursor value_, int count_=1); + virtual bool RemoveRows(int pos_, int count_=1); +}; + +///////////////////////////////////////////////////////////////////////////// +// The following contains code derived froms Python's dictionaries, hence: +// Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, +// The Netherlands. +// Reduced and turned into a fast C++ class by Christian Tismer, hence: +// Copyright 1999 by Christian Tismer. +// Vectorized and reorganized further by Jean-Claude Wippler. +///////////////////////////////////////////////////////////////////////////// + +// Table of irreducible polynomials to efficiently cycle through +// GF(2^n)-{0}, 2<=n<=30. + +static long s_polys[] = { + 4 + 3, + 8 + 3, + 16 + 3, + 32 + 5, + 64 + 3, + 128 + 3, + 256 + 29, + 512 + 17, + 1024 + 9, + 2048 + 5, + 4096 + 83, + 8192 + 27, + 16384 + 43, + 32768 + 3, + 65536 + 45, + 131072 + 9, + 262144 + 39, + 524288 + 39, + 1048576 + 9, + 2097152 + 5, + 4194304 + 3, + 8388608 + 33, + 16777216 + 27, + 33554432 + 9, + 67108864 + 71, + 134217728 + 39, + 268435456 + 9, + 536870912 + 5, + 1073741824 + 83, + 0 +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_HashViewer::c4_HashViewer (c4_Sequence& seq_, int numKeys_, + c4_Sequence* map_) + : _base (&seq_), _map (map_), _numKeys (numKeys_), + _pHash ("_H"), _pRow ("_R") +{ + if (_map.GetSize() == 0) + _map.SetSize(1); + + int poly = GetPoly(); + if (poly == 0 || _map.GetSize() <= _base.GetSize()) + DictResize(_base.GetSize()); +} + +c4_HashViewer::~c4_HashViewer () +{ +} + +bool c4_HashViewer::IsUnused(int row_) const +{ + c4_RowRef r = _map[row_]; + return _pRow (r) < 0 && _pHash (r) == 0; +} + +bool c4_HashViewer::IsDummy(int row_) const +{ + c4_RowRef r = _map[row_]; + return _pRow (r) < 0 && _pHash (r) < 0; +} + +int c4_HashViewer::GetPoly() const +{ + return Hash(_map.GetSize()-1); +} + +void c4_HashViewer::SetPoly(int v_) +{ + SetHash(_map.GetSize()-1, v_); +} + +int c4_HashViewer::GetSpare() const +{ + return Row(_map.GetSize()-1); +} + +void c4_HashViewer::SetSpare(int v_) +{ + SetRow(_map.GetSize()-1, v_); +} + +bool c4_HashViewer::KeySame(int row_, c4_Cursor cursor_) const +{ + for (int i = 0; i < _numKeys; ++i) + { + c4_Bytes buffer; + _base.GetItem(row_, i, buffer); + + c4_Handler& h = cursor_._seq->NthHandler(i); + if (h.Compare(cursor_._index, buffer) != 0) + return false; + } + + return true; +} + +/// Create mapped view which is uses a second view for hashing +t4_i32 c4_HashViewer::CalcHash(c4_Cursor cursor_) const +{ + c4_Bytes buffer, buf2; + const t4_i32 endian = 0x03020100; + t4_i32 hash = 0; + + for (int i = 0; i < _numKeys; ++i) + { + c4_Handler& h = cursor_._seq->NthHandler(i); + cursor_._seq->Get(cursor_._index, h.PropId(), buffer); + + // this code borrows from Python's stringobject.c/string_hash() + int len = buffer.Size(); + if (len > 0) + { + const t4_byte* p = buffer.Contents(); + + // 20030218: careful to avoid endian-ness sensitivity + if (*(const t4_byte*) &endian) // true on big-endian systems + switch (h.Property().Type()) + { + case 'I': case 'L': case 'F': case 'D': + { + t4_byte* q = buf2.SetBuffer(len); + for (int j = 0; j < len; ++j) + q[len-j-1] = p[j]; + p = q; + } + } + + long x = *p << 7; + + // modifications are risky, this code avoid scanning huge blobs + if (len > 200) + len = 100; + + while (--len >= 0) + x = (1000003 * x) ^ *p++; + + if (buffer.Size() > 200) + { + len = 100; + p += buffer.Size() - 200; + while (--len >= 0) + x = (1000003 * x) ^ *p++; + } + + x ^= buffer.Size(); + hash ^= x ^ i; + } + } + + if (hash == 0) + hash = -1; + + return hash; +} + +/* + * Types of slots: + * Unused: row = -1, hash = 0 + * Dummy: row = -1, hash = -1 + * Active: row >= 0 + * There must be at least one Unused slot at all times. + */ + +int c4_HashViewer::LookDict(t4_i32 hash_, c4_Cursor cursor_) const +{ + const unsigned int mask = _map.GetSize() - 2; + /* We must come up with (i, incr) such that 0 <= i < _size + and 0 < incr < _size and both are a function of hash */ + int i = mask & ~hash_; + /* We use ~hash_ instead of hash_, as degenerate hash functions, such + as for ints <sigh>, can have lots of leading zeros. It's not + really a performance risk, but better safe than sorry. */ + if (IsUnused(i) || Hash(i) == hash_ && KeySame(Row(i), cursor_)) + return i; + + int freeslot = IsDummy(i) ? i : -1; + + /* Derive incr from hash_, just to make it more arbitrary. Note that + incr must not be 0, or we will get into an infinite loop.*/ + unsigned incr = (hash_ ^ ((unsigned long) hash_ >> 3)) & mask; + if (!incr) + incr = mask; + + int poly = GetPoly(); + for (;;) + { + i = (i+incr) & mask; + if (IsUnused(i)) + break; + if (Hash(i) == hash_ && KeySame(Row(i), cursor_)) + return i; + if (freeslot == -1 && IsDummy(i)) + freeslot = i; + /* Cycle through GF(2^n)-{0} */ + incr = incr << 1; + if (incr > mask) + incr ^= poly; /* This will implicitely clear the highest bit */ + } + + return freeslot != -1 ? freeslot : i; +} + +void c4_HashViewer::InsertDict(int row_) +{ + c4_Cursor cursor = &_base[row_]; + + t4_i32 hash = CalcHash(cursor); + int i = LookDict(hash, cursor); + + if (IsDummy(i)) + { + int n = GetSpare(); + d4_assert(n > 0); + SetSpare(n - 1); + } + + SetHash(i, hash); + SetRow(i, row_); +} + +void c4_HashViewer::RemoveDict(int pos_) +{ + c4_Cursor key = &_base[pos_]; + t4_i32 hash = CalcHash(key); + int i = LookDict(hash, key); + d4_assert(i >= 0); + + d4_assert(Row(i) == pos_); + + SetHash(i, -1); + SetRow(i, -1); + + SetSpare(GetSpare() + 1); +} + +bool c4_HashViewer::DictResize(int minused) +{ + int i, newsize, newpoly; + for (i = 0, newsize = 4; ; i++, newsize <<= 1) { + if (s_polys[i] == 0) + return false; + else if (newsize > minused) { + newpoly = s_polys[i]; + break; + } + } + + _map.SetSize(0); + + c4_Row empty; + _pRow (empty) = -1; + _map.InsertAt(0, empty, newsize + 1); + + SetPoly(newpoly); + SetSpare(0); + + for (int j = 0; j < _base.GetSize(); ++j) + InsertDict(j); + + return true; +} + +c4_View c4_HashViewer::GetTemplate() +{ + return _base.Clone(); +} + +int c4_HashViewer::GetSize() +{ + return _base.GetSize(); +} + +int c4_HashViewer::Lookup(c4_Cursor key_, int& count_) +{ + // can only use hashing if the properties match the query + // XXX it appears that this loop takes some 300 uS! + c4_View kv = (*key_).Container(); + for (int k = 0; k < _numKeys; ++k) + if (kv.FindProperty(_base.NthProperty(k).GetId()) < 0) + return -1; + + t4_i32 hash = CalcHash(key_); // TODO should combine with above loop + int i = LookDict(hash, key_); + + int row = Row(i); + count_ = row >= 0 && KeySame(row, key_) ? 1 : 0; + return count_ ? row : 0; // don't return -1, we *know* it's not there +} + +bool c4_HashViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + return _base.GetItem(row_, col_, buf_); +} + +bool c4_HashViewer::SetItem(int row_, int col_, const c4_Bytes& buf_) +{ + if (col_ < _numKeys) + { + c4_Bytes temp; + _base.GetItem(row_, col_, temp); + if (buf_ == temp) + return true; // this call will have no effect, just ignore it + + RemoveDict(row_); + } + + _base.SetItem(row_, col_, buf_); + + if (col_ < _numKeys) + { + // careful if changing a key to one which is already present: + // in that case, delete the other row to preserve uniqueness + // + // Note: this is a tricky and confusing issue, because now the + // mere act of *setting* a property value can *delete* a row! + // + // The big problem here is that setting the rest of the values + // in a loop can end up *wrong*, if the row has moved down!!! + int n; + int i = Lookup(&_base[row_], n); + if (i >= 0 && n > 0) + { + RemoveRows(i, 1); + if (i < row_) + --row_; + } + + InsertDict(row_); + } + + return true; +} + +bool c4_HashViewer::InsertRows(int pos_, c4_Cursor value_, int count_) +{ + d4_assert(count_ > 0); + + int n; + int i = Lookup(value_, n); + if (i >= 0 && n > 0) + { + _base.SetAt(i, *value_); // replace existing + return true; + } + + // adjust row numbers if the insertion is not at the end + // + // TODO this could be optimized to go through the rows which + // were moved up, and then adjusting the map through a lookup + // (probably better than full scan if pos_ is relatively high) + if (pos_ < _base.GetSize()) + { + for (int r = 0; r < _map.GetSize() - 1; ++r) + { + int n2 = Row(r); + if (n2 >= pos_) + SetRow(r, n2 + 1); + } + } + + _base.InsertAt(pos_, *value_); + InsertDict(pos_); + + int used = _base.GetSize(); + int fill = used + GetSpare(); + if (fill * 3 >= (_map.GetSize() - 1) * 2 && !DictResize(used * 2)) + return false; // bail out + + d4_assert(_base.GetSize() + GetSpare() < _map.GetSize() - 1); + return true; +} + +bool c4_HashViewer::RemoveRows(int pos_, int count_) +{ + while (--count_ >= 0) + { + // since the map persists, be somewhat more aggressive than the + // original code in resizing down when the map is getting empty + if (_base.GetSize() * 3 < _map.GetSize() - 1 && + !DictResize(_base.GetSize())) + return false; // bail out + + RemoveDict(pos_); + + // move rows down for now + // + // optionally: consider replacing with last entry (much faster) + for (int r = 0; r < _map.GetSize() - 1; ++r) + { + int n = Row(r); + if (n > pos_) + SetRow(r, n - 1); + } + + _base.RemoveAt(pos_, 1); + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_BlockedViewer : public c4_CustomViewer +{ + enum { kLimit = 1000 }; + + c4_View _base; + + c4_ViewProp _pBlock; + c4_DWordArray _offsets; + + int Slot(int& pos_); + void Split(int block_, int row_); + void Merge(int block_); + void Validate() const; + +public: + c4_BlockedViewer (c4_Sequence& seq_); + virtual ~c4_BlockedViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); + virtual bool SetItem(int row_, int col_, const c4_Bytes& buf_); + virtual bool InsertRows(int pos_, c4_Cursor value_, int count_=1); + virtual bool RemoveRows(int pos_, int count_=1); +}; + +///////////////////////////////////////////////////////////////////////////// + +#if q4_CHECK + + // debugging version to verify that the internal data is consistent + void c4_BlockedViewer::Validate() const + { + d4_assert(_base.GetSize() >= 2); + + int n = _base.GetSize() - 1; + d4_assert(_offsets.GetSize() == n); + + int total = 0; + for (int i = 0; i < n; i++) + { + c4_View bv = _pBlock (_base[i]); + d4_assert(bv.GetSize() > 0 || i == 0); + total += bv.GetSize(); + d4_assert((int) _offsets.GetAt(i) == total++); + } + + c4_View be = _pBlock (_base[n]); + d4_assert(be.GetSize() == n - 1); + } + +#else + + // nothing, so inline this thing to avoid even the calling overhead + d4_inline void c4_BlockedViewer::Validate() const + { + } + +#endif + +c4_BlockedViewer::c4_BlockedViewer (c4_Sequence& seq_) + : _base (&seq_), _pBlock ("_B") +{ + if (_base.GetSize() < 2) + _base.SetSize(2); + + int n = _base.GetSize() - 1; + _offsets.SetSize(n); + + int total = 0; + for (int i = 0; i < n; i++) + { + c4_View bv = _pBlock (_base[i]); + total += bv.GetSize(); + _offsets.SetAt(i, total++); + } + Validate(); +} + +c4_BlockedViewer::~c4_BlockedViewer () +{ +} + +int c4_BlockedViewer::Slot(int& pos_) +{ + d4_assert(_offsets.GetSize() > 0); + d4_assert(pos_ <= (int) _offsets.GetAt(_offsets.GetSize() - 1)); + +#if 0 + const int n = _offsets.GetSize(); + + int h; + for (h = 0; h < n; ++h) + if (pos_ <= (t4_i32) _offsets.GetAt(h)) + break; +#else + // switch to binary search, adapted from code by Zhang Dehua, 28-3-2002 + // slows down some 5%, but said to be much better with 5 million rows + int l = 0, h = _offsets.GetSize() - 1; + while (l < h) { + int m = l + (h - l) / 2; + if ((t4_i32) _offsets.GetAt(m) < pos_) + l = m + 1; + else + h = m; + } +#endif + + if (h > 0) + pos_ -= _offsets.GetAt(h-1) + 1; + + return h; +} + +void c4_BlockedViewer::Split(int bno_, int row_) +{ + int z = _base.GetSize() - 1; + d4_assert(bno_ < z); + c4_View bz = _pBlock (_base[z]); + c4_View bv = _pBlock (_base[bno_]); + d4_assert(row_ < bv.GetSize()); + + _offsets.InsertAt(bno_, _offsets.GetAt(bno_) - bv.GetSize() + row_); + + _base.InsertAt(bno_+1, c4_Row ()); + c4_View bn = _pBlock (_base[bno_+1]); + + bv.RelocateRows(row_ + 1, -1, bn, 0); + bv.RelocateRows(row_, 1, bz, bno_); + + Validate(); +} + +void c4_BlockedViewer::Merge(int bno_) +{ + int z = _base.GetSize() - 1; + c4_View bz = _pBlock (_base[z]); + c4_View bv1 = _pBlock (_base[bno_]); + c4_View bv2 = _pBlock (_base[bno_+1]); + + _offsets.RemoveAt(bno_); + + bz.RelocateRows(bno_, 1, bv1, -1); + bv2.RelocateRows(0, -1, bv1, -1); + + _base.RemoveAt(bno_+1); + + Validate(); +} + +c4_View c4_BlockedViewer::GetTemplate() +{ + c4_View bv = _pBlock (_base[0]); + return bv.Clone(); +} + +int c4_BlockedViewer::GetSize() +{ + int n = _offsets.GetAt(_offsets.GetSize() - 1); + d4_assert(n >= 0); + return n; +} + +bool c4_BlockedViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + int orig = row_; + + int i = Slot(row_); + d4_assert(0 <= i && i < _base.GetSize() - 1); + + if ((t4_i32) _offsets.GetAt(i) == orig) + { + row_ = i; + i = _base.GetSize() - 1; + } + + c4_View bv = _pBlock (_base[i]); + return bv.GetItem(row_, col_, buf_); +} + +bool c4_BlockedViewer::SetItem(int row_, int col_, const c4_Bytes& buf_) +{ + int orig = row_; + + int i = Slot(row_); + d4_assert(0 <= i && i < _base.GetSize() - 1); + + if ((t4_i32) _offsets.GetAt(i) == orig) + { + row_ = i; + i = _base.GetSize() - 1; + } + + c4_View bv = _pBlock (_base[i]); + bv.SetItem(row_, col_, buf_); + return true; +} + +bool c4_BlockedViewer::InsertRows(int pos_, c4_Cursor value_, int count_) +{ + d4_assert(count_ > 0); + + bool atEnd = pos_ == GetSize(); + + int z = _base.GetSize() - 1; + int i = Slot(pos_); + d4_assert(0 <= i && i < z); + + c4_View bv = _pBlock (_base[i]); + d4_assert(0 <= pos_ && pos_ <= bv.GetSize()); + + bv.InsertAt(pos_, *value_, count_); + for (int j = i; j < z; ++j) + _offsets.SetAt(j, _offsets.GetAt(j) + count_); + + // massive insertions are first split off + while (bv.GetSize() >= 2 * kLimit) + Split(i, bv.GetSize() - kLimit - 2); + + if (bv.GetSize() > kLimit ) + Split(i, atEnd ? kLimit - 1 : bv.GetSize() / 2); // 23-3-2002, from MB + + Validate(); + + return true; +} + +bool c4_BlockedViewer::RemoveRows(int pos_, int count_) +{ + d4_assert(count_ > 0); + d4_assert(pos_ + count_ <= GetSize()); + + int z = _base.GetSize() - 1; + int i = Slot(pos_); + d4_assert(0 <= i && i < z); + + c4_View bv = _pBlock (_base[i]); + d4_assert(0 <= pos_ && pos_ <= bv.GetSize()); + + int todo = count_; + + // optimize if the deletion goes past the end of this block... + int overshoot = pos_ + count_ - bv.GetSize(); + if (overshoot > 0) { + + // first, delete blocks which are going away completely + while (i+1 < _offsets.GetSize()) { + int nextsize = _offsets.GetAt(i+1) - _offsets.GetAt(i); + if (overshoot < nextsize) + break; + todo -= nextsize; + overshoot -= nextsize; + + // drop the block and forget it ever existed + for (int j = i+1; j < z; ++j) + _offsets.SetAt(j, _offsets.GetAt(j) - nextsize); + _offsets.RemoveAt(i+1); + + _base.RemoveAt(i+1); + --z; + c4_View bz = _pBlock (_base[z]); + bz.RemoveAt(i); + + Validate(); + } + + // delete before merging, to avoid useless copying + if (overshoot > 1) { + c4_View bv2 = _pBlock (_base[i+1]); + bv2.RemoveAt(0, overshoot - 1); + todo -= overshoot - 1; + + for (int j = i+1; j < z; ++j) + _offsets.SetAt(j, _offsets.GetAt(j) - (overshoot - 1)); + + // if the next block is filled enough, rotate the separator + // this avoids an expensive and unnecessary merge + split + if (bv2.GetSize() > kLimit / 2) { + c4_View bz = _pBlock (_base[z]); + bz[i] = bv2[0]; + bv2.RemoveAt(0); + --todo; + d4_assert(pos_ + todo <= bv.GetSize()); + d4_assert(i < _offsets.GetSize()); + + for (int j = i+1; j < z; ++j) + _offsets.SetAt(j, _offsets.GetAt(j) - 1); + } + } + + // merge into one block + if (pos_ + todo > bv.GetSize()) { + d4_assert(i < z - 1); + Merge(i); + --z; + } + } + d4_assert(pos_ + todo <= bv.GetSize()); + + // now remove the rows and adjust offsets + if (todo > 0) + bv.RemoveAt(pos_, todo); + + for (int j = i; j < z; ++j) + _offsets.SetAt(j, _offsets.GetAt(j) - todo); + + // if the block underflows, merge it + if (bv.GetSize() < kLimit / 2) { + if (i > 0) // merge with predecessor, preferably + bv = _pBlock (_base[--i]); + if (i >= z - 1) // unless there is no successor to merge with + return true; + Merge(i); + } + + // if the block overflows, split it + if (bv.GetSize() > kLimit ) + Split(i, bv.GetSize() / 2); + + Validate(); + + return true; +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_OrderedViewer : public c4_CustomViewer +{ + c4_View _base; + int _numKeys; + + int KeyCompare(int row_, c4_Cursor cursor_) const; + +public: + c4_OrderedViewer (c4_Sequence& seq_, int numKeys_); + virtual ~c4_OrderedViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual int Lookup(c4_Cursor key_, int& count_); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); + virtual bool SetItem(int row_, int col_, const c4_Bytes& buf_); + virtual bool InsertRows(int pos_, c4_Cursor value_, int count_=1); + virtual bool RemoveRows(int pos_, int count_=1); +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_OrderedViewer::c4_OrderedViewer (c4_Sequence& seq_, int numKeys_) + : _base (&seq_), _numKeys (numKeys_) +{ +} + +c4_OrderedViewer::~c4_OrderedViewer () +{ +} + +int c4_OrderedViewer::KeyCompare(int row_, c4_Cursor cursor_) const +{ + for (int i = 0; i < _numKeys; ++i) + { + c4_Bytes buffer; + _base.GetItem(row_, i, buffer); + + c4_Handler& h = cursor_._seq->NthHandler(i); + int f = h.Compare(cursor_._index, buffer); + if (f != 0) + return f; + } + + return 0; +} + +c4_View c4_OrderedViewer::GetTemplate() +{ + return _base.Clone(); +} + +int c4_OrderedViewer::GetSize() +{ + return _base.GetSize(); +} + +int c4_OrderedViewer::Lookup(c4_Cursor key_, int& count_) +{ + // can only use bsearch if the properties match the query + // XXX with ord1.tcl (dict words), this loop takes 300 uS! + c4_View kv = (*key_).Container(); + for (int k = 0; k < _numKeys; ++k) + if (kv.FindProperty(_base.NthProperty(k).GetId()) < 0) + return -1; + +#if 0 // Locate gets the count wrong, it seems 2000-06-15 + int pos; + count_ = _base.Locate(*key_, &pos); +#else + int pos = _base.Search(*key_); + count_ = pos < _base.GetSize() && KeyCompare(pos, key_) == 0 ? 1 : 0; +#endif + return pos; +} + +bool c4_OrderedViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + return _base.GetItem(row_, col_, buf_); +} + +bool c4_OrderedViewer::SetItem(int row_, int col_, const c4_Bytes& buf_) +{ + if (col_ < _numKeys) + { + c4_Bytes temp; + _base.GetItem(row_, col_, temp); + if (buf_ == temp) + return true; // this call will have no effect, just ignore it + } + + _base.SetItem(row_, col_, buf_); + + if (col_ < _numKeys) + { + c4_Row copy = _base[row_]; + // have to remove the row because it messes up searching + // it would be more efficient to search *around* this row + // or perhaps figure out new pos before changing any data + RemoveRows(row_); + InsertRows(0, ©); // position is ignored + } + + return true; +} + +bool c4_OrderedViewer::InsertRows(int, c4_Cursor value_, int count_) +{ + d4_assert(count_ > 0); + + int n; + int i = Lookup(value_, n); + + // XXX if the lookup does not work, then insert as first element (!?) + d4_assert(i >= 0); + if (i < 0) + i = 0; + + if (n == 0) + _base.InsertAt(i, *value_); + else + { + d4_assert(i < _base.GetSize()); + _base.SetAt(i, *value_); // replace existing + } + + return true; +} + +bool c4_OrderedViewer::RemoveRows(int pos_, int count_) +{ + _base.RemoveAt(pos_, count_); + return true; +} + +///////////////////////////////////////////////////////////////////////////// + +class c4_IndexedViewer : public c4_CustomViewer +{ + c4_View _base; + c4_View _map; + c4_View _props; + bool _unique; + c4_IntProp _mapProp; + + int KeyCompare(int row_, c4_Cursor cursor_) const; + +public: + c4_IndexedViewer (c4_Sequence& seq_, c4_Sequence& map_, + const c4_View& props_, bool unique_); + virtual ~c4_IndexedViewer (); + + virtual c4_View GetTemplate(); + virtual int GetSize(); + virtual int Lookup(c4_Cursor key_, int& count_); + virtual bool GetItem(int row_, int col_, c4_Bytes& buf_); + virtual bool SetItem(int row_, int col_, const c4_Bytes& buf_); + virtual bool InsertRows(int pos_, c4_Cursor value_, int count_=1); + virtual bool RemoveRows(int pos_, int count_=1); +}; + +///////////////////////////////////////////////////////////////////////////// + +c4_IndexedViewer::c4_IndexedViewer (c4_Sequence& seq_, c4_Sequence& map_, + const c4_View& props_, bool unique_) + : _base (&seq_), _map (&map_), _props (props_), _unique (unique_), + _mapProp ((const c4_IntProp&) _map.NthProperty(0)) +{ + int n = _base.GetSize(); + if (_map.GetSize() != n) + { + c4_View sorted = _base.SortOn(_props); + + _map.SetSize(n); + for (int i = 0; i < n; ++i) + _mapProp (_map[i]) = _base.GetIndexOf(sorted[i]); + } +} + +c4_IndexedViewer::~c4_IndexedViewer () +{ +} + +int c4_IndexedViewer::KeyCompare(int row_, c4_Cursor cursor_) const +{ + int n = _props.NumProperties(); + for (int i = 0; i < n; ++i) + { + c4_Bytes buffer; + _base.GetItem(row_, i, buffer); + + c4_Handler& h = cursor_._seq->NthHandler(i); + int f = h.Compare(cursor_._index, buffer); + if (f != 0) + return f; + } + + return 0; +} + +c4_View c4_IndexedViewer::GetTemplate() +{ + return _base.Clone(); +} + +int c4_IndexedViewer::GetSize() +{ + return _base.GetSize(); +} + +int c4_IndexedViewer::Lookup(c4_Cursor key_, int& count_) +{ + // can only use bsearch if the properties match the query + // XXX with ord1.tcl (dict words), this loop takes 300 uS! + c4_View kv = (*key_).Container(); + int n = _props.NumProperties(); + for (int k = 0; k < n; ++k) + if (kv.FindProperty(_props.NthProperty(k).GetId()) < 0) + return -1; + +#if 0 // Locate gets the count wrong, it seems 2000-06-15 + int pos; + count_ = _base.Locate(*key_, &pos); +#else + int pos = _base.Search(*key_); + count_ = pos < _base.GetSize() && KeyCompare(pos, key_) == 0 ? 1 : 0; +#endif + return pos; +} + +bool c4_IndexedViewer::GetItem(int row_, int col_, c4_Bytes& buf_) +{ + return _base.GetItem(row_, col_, buf_); +} + +bool c4_IndexedViewer::SetItem(int row_, int col_, const c4_Bytes& buf_) +{ + const int id = _base.NthProperty(col_).GetId(); + const bool keyMod = _props.FindProperty(id) >= 0; + + if (keyMod) + { + c4_Bytes temp; + _base.GetItem(row_, col_, temp); + if (buf_ == temp) + return true; // this call will have no effect, just ignore it + } + + _base.SetItem(row_, col_, buf_); + + if (keyMod) + { + // TODO adjust index + } + + return true; +} + +bool c4_IndexedViewer::InsertRows(int, c4_Cursor value_, int count_) +{ + d4_assert(count_ > 0); + + if (_unique) + count_ = 1; + + int n; + int i = Lookup(value_, n); + + // XXX if the lookup does not work, then insert as first element (!?) + d4_assert(i >= 0); + if (i < 0) + i = 0; + + if (n == 0) + _base.InsertAt(i, *value_); + else + { + d4_assert(i < _base.GetSize()); + _base.SetAt(i, *value_); // replace existing + } + + return true; +} + +bool c4_IndexedViewer::RemoveRows(int pos_, int count_) +{ + _base.RemoveAt(pos_, count_); + + int n = _map.GetSize(); + while (--n >= 0) + { + int v = _mapProp (_map[n]); + if (v >= pos_) + if (v < pos_ + count_) + _map.RemoveAt(n); + else + _mapProp (_map[n]) = v - count_; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_CustomViewer* f4_CreateReadOnly(c4_Sequence& seq_) +{ + return d4_new c4_ReadOnlyViewer (seq_); +} + +c4_CustomViewer* f4_CreateHash(c4_Sequence& seq_, int nk_, c4_Sequence* map_) +{ + return d4_new c4_HashViewer (seq_, nk_, map_); +} + +c4_CustomViewer* f4_CreateBlocked(c4_Sequence& seq_) +{ + return d4_new c4_BlockedViewer (seq_); +} + +c4_CustomViewer* f4_CreateOrdered(c4_Sequence& seq_, int nk_) +{ + return d4_new c4_OrderedViewer (seq_, nk_); +} + +c4_CustomViewer* f4_CreateIndexed(c4_Sequence& seq_, c4_Sequence& map_, + const c4_View& props_, bool unique_) +{ + return d4_new c4_IndexedViewer (seq_, map_, props_, unique_); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/remap.h b/akregator/src/mk4storage/metakit/src/remap.h new file mode 100644 index 000000000..a435f853b --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/remap.h @@ -0,0 +1,26 @@ +// remap.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Encapsulation of the (re)mapping viewers + */ + +#ifndef __REMAP_H__ +#define __REMAP_H__ + +///////////////////////////////////////////////////////////////////////////// +// Declarations in this file + + class c4_Sequence; // not defined here + + extern c4_CustomViewer* f4_CreateReadOnly(c4_Sequence&); + extern c4_CustomViewer* f4_CreateHash(c4_Sequence&, int, c4_Sequence* =0); + extern c4_CustomViewer* f4_CreateBlocked(c4_Sequence&); + extern c4_CustomViewer* f4_CreateOrdered(c4_Sequence&, int); + extern c4_CustomViewer* f4_CreateIndexed(c4_Sequence&, c4_Sequence&, + const c4_View&, bool =false); + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/std.cpp b/akregator/src/mk4storage/metakit/src/std.cpp new file mode 100644 index 000000000..135fe7766 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/std.cpp @@ -0,0 +1,84 @@ +// std.cpp -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Implementation of STL-based strings and containers + */ + +#include "header.h" + +#if q4_STD // until end of source +///////////////////////////////////////////////////////////////////////////// + +#include "column.h" // c4_ColCache + +#if !q4_INLINE +static char _mk4stdInl[] = "mk4str.inl"; +#include "mk4str.inl" +#endif + +#if !q4_NO_NS +using namespace std; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Implemented in this file + + class c4_String; + +///////////////////////////////////////////////////////////////////////////// + +#if !q4_MSVC && !q4_WATC + + // MS C/C++ has this handy stricmp: a case-insensitive version of strcmp + // This version only works with 7-bit ASCII characters 0x00 through 0x7F + + static int stricmp(const char* p1, const char* p2) + { + int c1, c2; + +#ifdef d4_USE_UNOPTIMIZED_CODE + do + { + c1 = tolower(*p1++); + c2 = tolower(*p2++); + } while (c1 != 0 && c1 == c2); +#else + do + { + c1 = *p1++; + c2 = *p2++; + } while (c1 != 0 && (c1 == c2 || tolower(c1) == tolower(c2))); + + c1 = tolower(c1); + c2 = tolower(c2); +#endif + + return c1 - c2; + } + +#endif + +///////////////////////////////////////////////////////////////////////////// +// c4_String + +c4_String c4_String::Mid(int nFirst_, int nCount_) const +{ + int n = length(); + if (nFirst_ > n) + nFirst_ = n; + if (nFirst_ + nCount_ > n) + nCount_ = n - nFirst_; + + return substr(nFirst_, nCount_); +} + +int c4_String::CompareNoCase(const char* str_) const +{ + // this is not very "standard library-ish" ... + return *(const string*) this == str_ ? 0 : stricmp(c_str(), str_); +} + +///////////////////////////////////////////////////////////////////////////// +#endif // q4_STD diff --git a/akregator/src/mk4storage/metakit/src/std.h b/akregator/src/mk4storage/metakit/src/std.h new file mode 100644 index 000000000..1d1937be3 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/std.h @@ -0,0 +1,63 @@ +// std.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Configuration header for STL-based builds + */ + +#define q4_STD 1 + +#include "mk4str.h" + +#include <vector> + +///////////////////////////////////////////////////////////////////////////// + +template<class T> +class c4_ArrayT +{ +#ifdef _MSC_VER + d4_std::vector< T, d4_std::allocator<T> > _vector; +#else + d4_std::vector< T, d4_std::alloc > _vector; +#endif + +public: + c4_ArrayT () { } + ~c4_ArrayT () { } + + int GetSize() const { return _vector.size(); } + void SetSize(int nNewSize, int =-1) { _vector.resize(nNewSize); } + + T GetAt(int nIndex) const { return _vector[nIndex]; } + T& ElementAt(int nIndex) { return _vector[nIndex]; } + + void SetAt(int nIndex, const T& newElement) + { + _vector[nIndex] = newElement; + } + + int Add(const T& newElement) + { + int n = _vector.size(); + _vector.push_back(newElement); + return n; + } + + void InsertAt(int nIndex, const T& newElement, int nCount =1) + { + _vector.insert(&_vector[nIndex], nCount, newElement); + } + + void RemoveAt(int nIndex, int nCount =1) + { + _vector.erase(&_vector[nIndex], &_vector[nIndex+nCount]); + } +}; + +typedef c4_ArrayT<t4_i32> c4_DWordArray; +typedef c4_ArrayT<void*> c4_PtrArray; +typedef c4_ArrayT<c4_String> c4_StringArray; + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/store.cpp b/akregator/src/mk4storage/metakit/src/store.cpp new file mode 100644 index 000000000..a32de665c --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/store.cpp @@ -0,0 +1,587 @@ +// store.cpp -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Storage management and several other loose ends + */ + +#include "header.h" +#include "handler.h" // 19990906 +#include "store.h" +#include "field.h" +#include "persist.h" +#include "format.h" // 19990906 + +#include "mk4io.h" // 19991104 + +#if !q4_INLINE +#include "store.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + +c4_Dependencies::c4_Dependencies () +{ + _refs.SetSize(0, 3); // a little optimization +} + +c4_Dependencies::~c4_Dependencies () +{ +} + +void c4_Dependencies::Add(c4_Sequence* seq_) +{ + for (int i = 0; i < _refs.GetSize(); ++i) + d4_assert(_refs.GetAt(i) != seq_); + + _refs.Add(seq_); +} + +bool c4_Dependencies::Remove(c4_Sequence* seq_) +{ + int n = _refs.GetSize() - 1; + d4_assert(n >= 0); + + for (int i = 0; i <= n; ++i) + if (_refs.GetAt(i) == seq_) { + _refs.SetAt(i, _refs.GetAt(n)); + _refs.SetSize(n); + return n > 0; + } + + d4_assert(0); // dependency not found + return true; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_Notifier::~c4_Notifier () +{ + if (_type > kNone && _origin->GetDependencies()) { + c4_PtrArray& refs = _origin->GetDependencies()->_refs; + + for (int i = 0; i < refs.GetSize(); ++i) { + c4_Sequence* seq = (c4_Sequence*) refs.GetAt(i); + d4_assert(seq != 0); + + seq->PostChange(*this); + + if (_chain && _chain->_origin == seq) { + c4_Notifier* next = _chain->_next; + _chain->_next = 0; + + delete _chain; + + _chain = next; + } + } + } + + d4_assert(!_chain); + d4_assert(!_next); +} + +void c4_Notifier::StartSetAt(int index_, c4_Cursor& cursor_) +{ + _type = kSetAt; + _index = index_; + _cursor = &cursor_; + + Notify(); +} + +void c4_Notifier::StartInsertAt(int i_, c4_Cursor& cursor_, int n_) +{ + _type = kInsertAt; + _index = i_; + _cursor = &cursor_; + _count = n_; + + Notify(); +} + +void c4_Notifier::StartRemoveAt(int index_, int count_) +{ + _type = kRemoveAt; + _index = index_; + _count = count_; + + Notify(); +} + +void c4_Notifier::StartMove(int from_, int to_) +{ + _type = kMove; + _index = from_; + _count = to_; + + Notify(); +} + +void c4_Notifier::StartSet(int i_, int propId_, const c4_Bytes& buf_) +{ + _type = kSet; + _index = i_; + _propId = propId_; + _bytes = &buf_; + + Notify(); +} + +void c4_Notifier::Notify() +{ + d4_assert(_origin->GetDependencies() != 0); + c4_PtrArray& refs = _origin->GetDependencies()->_refs; + + int n = refs.GetSize(); + d4_assert(n > 0); + + c4_Notifier** rover = &_chain; + + for (int i = 0; i < n; ++i) { + c4_Sequence* seq = (c4_Sequence*) refs.GetAt(i); + d4_assert(seq != 0); + + c4_Notifier* ptr = seq->PreChange(*this); + if (ptr) { + d4_assert(ptr->_origin == seq); + + d4_assert(!*rover); + *rover = ptr; + rover = &ptr->_next; + } + } +} + +///////////////////////////////////////////////////////////////////////////// + +/** @class c4_Storage + * + * Manager for persistent storage of view structures. + * + * The storage class uses a view, with additional functionality to be able + * to store and reload the data it contains (including nested subviews). + * + * By default, data is loaded on demand, i.e. whenever data which has + * not yet been referenced is used for the first time. Loading is limited + * to the lifetime of this storage object, since the storage object carries + * the file descriptor with it that is needed to access the data file. + * + * To save changes, call the Commit member. This is the only time + * that data is written to file - when using a read-only file simply avoid + * calling Commit. + * + * The LoadFromStream and SaveToStream members can be used to + * serialize the contents of this storage row using only sequential I/O + * (no seeking, only read or write calls). + * + * The data storage mechanism implementation provides fail-safe operation: + * if anything prevents Commit from completing its task, the last + * succesfully committed version of the saved data will be recovered on + * the next open. This also includes changes made to the table structure. + * + * The following code creates a view with 1 row and stores it on file: + * @code + * c4_StringProp pName ("Name"); + * c4_IntProp pAge ("Age"); + * + * c4_Storage storage ("myfile.dat", true); + * c4_View myView = storage.GetAs("Musicians[Name:S,Age:I]"); + * + * myView.Add(pName ["John Williams"] + pAge [43]); + * + * storage.Commit(); + * @endcode + */ + +c4_Storage::c4_Storage () +{ + // changed to r/o, now that commits don't crash on it anymore + Initialize(*d4_new c4_Strategy, true, 0); +} + +c4_Storage::c4_Storage (c4_Strategy& strategy_, bool owned_, int mode_) +{ + Initialize(strategy_, owned_, mode_); + Persist()->LoadAll(); +} + +c4_Storage::c4_Storage (const char* fname_, int mode_) +{ + c4_FileStrategy* strat = d4_new c4_FileStrategy; + strat->DataOpen(fname_, mode_); + + Initialize(*strat, true, mode_); + if (strat->IsValid()) + Persist()->LoadAll(); +} + +c4_Storage::c4_Storage (const c4_View& root_) +{ + if (root_.Persist() != 0) // only restore if view was indeed persistent + *(c4_View*) this = root_; + else // if this was not possible, start with a fresh empty storage + Initialize(*d4_new c4_Strategy, true, 0); +} + +c4_Storage::~c4_Storage () +{ + // cannot unmap here, because there may still be an autocommit pending + //((c4_HandlerSeq*) _seq)->UnmapAll(); +} + +void c4_Storage::Initialize(c4_Strategy& strategy_, bool owned_, int mode_) +{ + c4_Persist* pers = d4_new c4_Persist (strategy_, owned_, mode_); + c4_HandlerSeq* seq = d4_new c4_HandlerSeq (pers); + seq->DefineRoot(); + *(c4_View*) this = seq; + pers->SetRoot(seq); +} + + /// Get or set a named view in this storage object +c4_ViewRef c4_Storage::View(const char* name_) +{ + /* + The easy solution would seem to be: + + c4_ViewProp prop (name_); + return prop (Contents()); + + But this does not work, because the return value would point to + an object allocated on the stack. + + Instead, make sure the view *has* such a property, and use the + one inside the c4_Handler for it (since this will stay around). + */ + +// int n = _root->PropIndex(c4_ViewProp (name_)); + + c4_ViewProp prop (name_); + int n = AddProperty(prop); + d4_assert(n >= 0); + + // the following is an expression of the form "property (rowref)" + return NthProperty(n) (GetAt(0)); +} + + /// Get a named view, redefining it to match the given structure +c4_View c4_Storage::GetAs(const char* description_) +{ + d4_assert(description_ != 0); + + // Dec 2001: now that GetAs is being used so much more frequently, + // add a quick check to see whether restructuring is needed at all + const char* q = strchr(description_, '['); + if (q != 0) { + c4_String vname (description_, q - description_); + const char* d = Description(vname); + if (d != 0) { + c4_String desc (d); + if (("[" + desc + "]").CompareNoCase(q) == 0) + return View(vname); + } + } + + c4_Field* field = d4_new c4_Field (description_); + d4_assert(field != 0); + + d4_assert(!*description_); + + c4_String name = field->Name(); + d4_assert(!name.IsEmpty()); + + c4_Field& curr = Persist()->Root().Definition(); + + c4_String newField = "," + field->Description(); + bool keep = newField.Find('[') >= 0; + + c4_String newDef; + + // go through all subfields + for (int i = 0; i < curr.NumSubFields(); ++i) { + c4_Field& of = curr.SubField(i); + if (of.Name().CompareNoCase(name) == 0) { + if (field->IsRepeating()) + newDef += newField; + // else new is not a repeating entry, so drop this entire field + + newField.Empty(); // don't append it later on + continue; + } + + newDef += "," + of.Description(); // keep original field + } + + if (keep) // added 19990824 ignore if deletion + newDef += newField; // appends new definition if not found earlier + + delete field; + + const char* p = newDef; + SetStructure(*p ? ++p : p); // skip the leading comma + + if (!keep) // 19990916: avoid adding an empty view again + return c4_View (); + + return View(name); +} + + /// Define the complete view structure of the storage +void c4_Storage::SetStructure(const char* description_) +{ + d4_assert(description_ != 0); + + if (description_ != Description()) { + c4_String s = "[" + c4_String (description_) + "]"; + description_ = s; + + c4_Field* field = d4_new c4_Field (description_); + d4_assert(!*description_); + + d4_assert(field != 0); + Persist()->Root().Restructure(*field, false); + } +} + + /// Return the strategy object associated with this storage +c4_Strategy& c4_Storage::Strategy() const +{ + return Persist()->Strategy(); +} + + /// Return a description of the view structure (default is all) +const char* c4_Storage::Description(const char* name_) +{ + if (name_ == 0 || *name_ == 0) + return c4_View::Description(); + + c4_View v = View(name_); + return v.Description(); +} + + /// Define the storage to use for differential commits +bool c4_Storage::SetAside(c4_Storage& aside_) +{ + c4_Persist* pers = Persist(); + bool f = pers->SetAside(aside_); + // adjust our copy when the root view has been replaced + *(c4_View*) this = &pers->Root(); + return f; +} + + /// Return storage used for differential commits, or null +c4_Storage* c4_Storage::GetAside() const +{ + return Persist()->GetAside(); +} + + /// Flush pending changes to file right now +bool c4_Storage::Commit(bool full_) +{ + return Strategy().IsValid() && Persist()->Commit(full_); +} + +/** (Re)initialize for on-demand loading + * + * Calling Rollback will cancel all uncommitted changes. + */ +bool c4_Storage::Rollback(bool full_) +{ + c4_Persist* pers = Persist(); + bool f = Strategy().IsValid() && pers->Rollback(full_); + // adjust our copy when the root view has been replaced + *(c4_View*) this = &pers->Root(); + return f; +} + + /// Set storage up to always call Commit in the destructor +bool c4_Storage::AutoCommit(bool flag_) +{ + return Persist()->AutoCommit(flag_); +} + + /// Load contents from the specified input stream +bool c4_Storage::LoadFrom(c4_Stream& stream_) +{ + c4_HandlerSeq* newRoot = c4_Persist::Load(&stream_); + if (newRoot == 0) + return false; + + // fix commit-after-load bug, by using a full view copy + // this is inefficient, but avoids mapping/strategy problems + c4_View temp (newRoot); + + SetSize(0); + SetStructure(temp.Description()); + InsertAt(0, temp); + + return true; +} + + /// Save contents to the specified output stream +void c4_Storage::SaveTo(c4_Stream& stream_) +{ + c4_Persist::Save(&stream_, Persist()->Root()); +} + +///////////////////////////////////////////////////////////////////////////// + +c4_DerivedSeq::c4_DerivedSeq (c4_Sequence& seq_) + : _seq (seq_) +{ + _seq.Attach(this); +} + +c4_DerivedSeq::~c4_DerivedSeq () +{ + _seq.Detach(this); +} + +int c4_DerivedSeq::RemapIndex(int index_, const c4_Sequence* seq_) const +{ + return seq_ == this ? index_ : _seq.RemapIndex(index_, seq_); +} + +int c4_DerivedSeq::NumRows() const +{ + return _seq.NumRows(); +} + +int c4_DerivedSeq::NumHandlers() const +{ + return _seq.NumHandlers(); +} + +c4_Handler& c4_DerivedSeq::NthHandler(int colNum_) const +{ + return _seq.NthHandler(colNum_); +} + +const c4_Sequence* c4_DerivedSeq::HandlerContext(int colNum_) const +{ + return _seq.HandlerContext(colNum_); +} + +int c4_DerivedSeq::AddHandler(c4_Handler* handler_) +{ + return _seq.AddHandler(handler_); +} + +c4_Handler* c4_DerivedSeq::CreateHandler(const c4_Property& prop_) +{ + return _seq.CreateHandler(prop_); +} + +void c4_DerivedSeq::SetNumRows(int size_) +{ + _seq.SetNumRows(size_); +} + +c4_Notifier* c4_DerivedSeq::PreChange(c4_Notifier& nf_) +{ + if (!GetDependencies()) + return 0; + + c4_Notifier* chg = d4_new c4_Notifier (this); + + switch (nf_._type) + { + case c4_Notifier::kSetAt: + chg->StartSetAt(nf_._index, *nf_._cursor); + break; + + case c4_Notifier::kSet: + chg->StartSet(nf_._index, nf_._propId, *nf_._bytes); + break; + + case c4_Notifier::kInsertAt: + chg->StartInsertAt(nf_._index, *nf_._cursor, nf_._count); + break; + + case c4_Notifier::kRemoveAt: + chg->StartRemoveAt(nf_._index, nf_._count); + break; + + case c4_Notifier::kMove: + chg->StartMove(nf_._index, nf_._count); + break; + } + + return chg; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_StreamStrategy::c4_StreamStrategy (t4_i32 buflen_) + : _stream (0), _buffer (d4_new t4_byte [buflen_]), _buflen (buflen_), _position (0) +{ + _mapStart = _buffer; + _dataSize = buflen_; +} + +c4_StreamStrategy::c4_StreamStrategy (c4_Stream* stream_) + : _stream (stream_), _buffer (0), _buflen (0), _position (0) +{ +} + +c4_StreamStrategy::~c4_StreamStrategy () +{ + _mapStart = 0; + _dataSize = 0; + + if (_buffer != 0) + delete [] _buffer; +} + +bool c4_StreamStrategy::IsValid() const +{ + return true; +} + +int c4_StreamStrategy::DataRead(t4_i32 pos_, void* buffer_, int length_) +{ + if (_buffer != 0) { + d4_assert(pos_ <= _buflen); + _position = pos_ + _baseOffset; + + if (length_ > _buflen - _position) + length_ = _buflen - _position; + if (length_ > 0) + memcpy(buffer_, _buffer + _position, length_); + } else { + d4_assert(_position == pos_ + _baseOffset); + length_ = _stream != 0 ? _stream->Read(buffer_, length_) : 0; + } + + _position += length_; + return length_; +} + +void c4_StreamStrategy::DataWrite(t4_i32 pos_, const void* buffer_, int length_) +{ + if (_buffer != 0) { + d4_assert(pos_ <= _buflen); + _position = pos_ + _baseOffset; + + int n = length_; + if (n > _buflen - _position) + n = _buflen - _position; + if (n > 0) + memcpy(_buffer + _position, buffer_, n); + } else { + d4_assert(_position == pos_ + _baseOffset); + if (_stream != 0 && !_stream->Write(buffer_, length_)) + ++_failure; + } + + _position += length_; +} + +t4_i32 c4_StreamStrategy::FileSize() +{ + return _position; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/store.h b/akregator/src/mk4storage/metakit/src/store.h new file mode 100644 index 000000000..c45d258ea --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/store.h @@ -0,0 +1,114 @@ +// store.h -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Definition of auxiliary storage management classes + */ + +#ifndef __STORE_H__ +#define __STORE_H__ + +///////////////////////////////////////////////////////////////////////////// + +class c4_Dependencies +{ + c4_PtrArray _refs; + +public: + c4_Dependencies (); + ~c4_Dependencies (); + + void Add(c4_Sequence* seq_); + bool Remove(c4_Sequence* seq_); + + friend class c4_Notifier; +}; + +///////////////////////////////////////////////////////////////////////////// + +class c4_Notifier +{ + c4_Sequence* _origin; + c4_Notifier* _chain; + c4_Notifier* _next; + +public: + enum { kNone, kSetAt, kInsertAt, kRemoveAt, kMove, kSet, kLimit }; + + c4_Notifier (c4_Sequence* origin_); + ~c4_Notifier (); + + bool HasDependents() const; + + void StartSetAt(int index_, c4_Cursor& cursor_); + void StartInsertAt(int index_, c4_Cursor& cursor_, int count_); + void StartRemoveAt(int index_, int count_); + void StartMove(int from_, int to_); + void StartSet(int index_, int propId_, const c4_Bytes& buf_); + + int _type; + int _index; + int _propId; + int _count; + c4_Cursor* _cursor; + const c4_Bytes* _bytes; + +private: + void Notify(); +}; + +///////////////////////////////////////////////////////////////////////////// + +class c4_DerivedSeq : public c4_Sequence +{ +protected: + c4_Sequence& _seq; + +protected: + c4_DerivedSeq (c4_Sequence& seq_); + virtual ~c4_DerivedSeq (); + +public: + virtual int RemapIndex(int, const c4_Sequence*) const; + + virtual int NumRows() const; + virtual void SetNumRows(int size_); + + virtual int NumHandlers() const; + virtual c4_Handler& NthHandler(int) const; + virtual const c4_Sequence* HandlerContext(int) const; + virtual int AddHandler(c4_Handler*); + virtual c4_Handler* CreateHandler(const c4_Property&); + + virtual c4_Notifier* PreChange(c4_Notifier& nf_); +}; + +///////////////////////////////////////////////////////////////////////////// + +class c4_StreamStrategy : public c4_Strategy +{ + c4_Stream* _stream; + t4_byte* _buffer; + t4_i32 _buflen; + t4_i32 _position; +public: + c4_StreamStrategy (t4_i32 buflen_); + c4_StreamStrategy (c4_Stream* stream_); + virtual ~c4_StreamStrategy (); + + virtual bool IsValid() const; + virtual int DataRead(t4_i32 pos_, void* buffer_, int length_); + virtual void DataWrite(t4_i32 pos_, const void* buffer_, int length_); + virtual t4_i32 FileSize(); +}; + +///////////////////////////////////////////////////////////////////////////// + +#if q4_INLINE +#include "store.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/akregator/src/mk4storage/metakit/src/store.inl b/akregator/src/mk4storage/metakit/src/store.inl new file mode 100644 index 000000000..191ee7de7 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/store.inl @@ -0,0 +1,20 @@ +// store.inl -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Inlined members of the storage management classes + */ + +///////////////////////////////////////////////////////////////////////////// +// c4_Notifier + +d4_inline c4_Notifier::c4_Notifier (c4_Sequence* origin_) + : _origin (origin_), _chain (0), _next (0), + _type (kNone), _index (0), _propId (0), _count (0), + _cursor (0), _bytes (0) +{ + d4_assert(_origin != 0); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/string.cpp b/akregator/src/mk4storage/metakit/src/string.cpp new file mode 100644 index 000000000..33c8836c8 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/string.cpp @@ -0,0 +1,304 @@ +// string.cpp -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * yet another string implementation + */ + +#include "header.h" + +/* these definitions could be used instead of header.h ... + #define q4_UNIV 1 + #define d4_inline + #include "mk4str.h" + #define d4_reentrant + #define d4_assert(x) +*/ + +#if q4_UNIV // until end of source +///////////////////////////////////////////////////////////////////////////// + +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef _AIX +#include <strings.h> +#endif + +#if !q4_INLINE +#include "mk4str.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + +#if q4_MSVC || q4_WATC || q4_BORC || (q4_MWCW && __MWERKS__ < 0x3000) +#define strcasecmp stricmp +#elif q4_WINCE + + // MS C/C++ has this handy stricmp: a case-insensitive version of strcmp + // This version only works with 7-bit ASCII characters 0x00 through 0x7F + + static int stricmp(const char* p1, const char* p2) + { + int c1, c2; + +#ifdef d4_USE_UNOPTIMIZED_CODE + do + { + c1 = tolower(*p1++); + c2 = tolower(*p2++); + } while (c1 != 0 && c1 == c2); +#else + do + { + c1 = *p1++; + c2 = *p2++; + } while (c1 != 0 && (c1 == c2 || tolower(c1) == tolower(c2))); + + c1 = tolower(c1); + c2 = tolower(c2); +#endif + + return c1 - c2; + } + +#endif + +#if q4_WINCE + const char* strrchr(const char* p, char ch) + { + const char* q = 0; + while (*p) + if (*p++ == ch) + q = p; + return q; + } +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// This string class implement functionality which is very similar to that +// provided by the CString class of the Microsoft Framework Classes (MFC). +// +// There are also several major differences: +// +// 1) This class uses reference counting to avoid massive copying. +// Consequently, function return as well as assignment is very fast. +// 2) Strings of up to 255 bytes can contain any data, even null bytes. +// Longer strings can not contain any null bytes past position 255. +// 3) This class can produce a "const char*" without overhead, but it +// can also cast to the byte-counted "const unsigned char*" used +// everywhere in Macintosh applications (as StringPtr, Str255, etc). +// 4) This source code is not derived from Microsoft's code in any way. +// +// A good way to use this class, is to always use c4_String for function +// return values and "const [unsigned] char*" for all parameters. Together, +// these two choices will remove the need for nearly any messy casts. +// +// Note: MFC 4.0 has now adopted refcounts, and is a good alternative to +// this code (but a bit bulkier, it also has Unicode support). + + // 2001-11-27, stop releasing nullvec, to allow MT use + d4_reentrant static unsigned char* nullVec = 0; + +static int fInc(unsigned char* p) +{ + ++*p; + if (*p) + return 1; + + --*p; + return 0; +} + +inline static void fDec(unsigned char* p) +{ + --*p; + if (!*p && p != nullVec) + delete [] p; +} + +c4_String::c4_String (char ch, int n /* =1 */) +{ + if (n < 0) + n = 0; + + _value = new unsigned char [n + 3]; + + _value[0] = 1; // see Init() member + memset(_value + 2, ch, n); + _value[1] = (unsigned char) (n <= 255 ? n : 255); + _value[n+2] = 0; +} + +c4_String::c4_String (const char* p) +{ + Init(p, p != 0 ? strlen(p) : 0); +} + +c4_String::c4_String (const c4_String& s) +{ + if (fInc(s._value)) + _value = s._value; + else + Init(s.Data(), s.GetLength()); +} + +c4_String::~c4_String () +{ + fDec(_value); +} + +const c4_String& c4_String::operator= (const c4_String& s) +{ + unsigned char* oldVal = _value; + if (fInc(s._value)) + _value = s._value; + else + Init(s.Data(), s.GetLength()); + fDec(oldVal); + + return *this; +} + +c4_String operator+ (const c4_String& a, const c4_String& b) +{ + const int aCnt = a.GetLength(); + int sum = aCnt + b.GetLength(); + + c4_String result ('\0', sum); // set up correct size, then fix contents + memcpy(result._value + 2, a.Data(), aCnt); + memcpy(result._value + 2 + aCnt, b.Data(), sum - aCnt); + + return result; +} + +void c4_String::Init(const void* p, int n) +{ + if (p == NULL || n <= 0) + { + // Optimization to significantly speed-up init of empty strings: + // share a common entry, which avoids *LOTS* of tiny mem allocs. + // + // Especially "new [...] c4_String" will benefit a lot, as well as: + // + // c4_String s; // this would have caused a new allocation + // s = ... // then immediately drops the count back + // + // 2001/11/27: changed to never release this empty vector, for MT use + // the new logic is to completely ignore its ref count + + if (!nullVec) + { + // obtain a valid new empty string buffer to keep around + unsigned char* nv = new unsigned char [3]; + nv[0] = nv[1] = nv[2] = 0; + // only set static value after item is fully inited (avoid MT race) + nullVec = nv; + } + + _value = nullVec; // use this buffer as our empty string + return; // done... that was quick, wasn't it? + } + + _value = new unsigned char [n + 3]; + + _value[0] = 1; // many assumptions here: set the reference count to 1 + + if (n > 0) + memcpy(_value + 2, p, n); + _value[1] = (unsigned char) (n <= 255 ? n : 255); + _value[n+2] = 0; +} + +int c4_String::FullLength() const +{ + int n = _value[1]; + return n < 255 ? n : n + strlen((const char*) _value + 2 + 255); +} + +c4_String c4_String::Mid(int nFirst, int nCount) const +{ + if (nFirst >= GetLength()) + return c4_String (); + + if (nFirst + nCount > GetLength()) + nCount = GetLength() - nFirst; + + if (nFirst == 0 && nCount == GetLength()) + return *this; + + return c4_String (Data() + nFirst, nCount); +} + +c4_String c4_String::Left(int nCount) const +{ + if (nCount >= GetLength()) + return *this; + + return c4_String (Data(), nCount); +} + +c4_String c4_String::Right(int nCount) const +{ + if (nCount >= GetLength()) + return *this; + + return c4_String (Data() + GetLength() - nCount, nCount); +} + +bool operator== (const c4_String& a, const c4_String& b) +{ + return a._value == b._value || a.GetLength() == b.GetLength() && + memcmp(a.Data(), b.Data(), a.GetLength()) == 0; +} + +int c4_String::Compare(const char* str) const +{ + return Data() == str ? 0 : strcmp(Data(), str); +} + +int c4_String::CompareNoCase(const char* str) const +{ + return Data() == str ? 0 : strcasecmp(Data(), str); +} + +int c4_String::Find(char ch) const +{ + const char* p = strchr(Data(), ch); + return p != 0 ? p - Data() : -1; +} + +int c4_String::ReverseFind(char ch) const +{ + const char* p = strrchr(Data(), ch); + return p != 0 ? p - Data() : -1; +} + +int c4_String::FindOneOf(const char* set) const +{ + const char* p = strpbrk(Data(), set); + return p != 0 ? p - Data() : -1; +} + +int c4_String::Find(const char* sub) const +{ + const char* p = strstr(Data(), sub); + return p != 0 ? p - Data() : -1; +} + +c4_String c4_String::SpanIncluding(const char* set) const +{ + return Left(strspn(Data(), set)); +} + +c4_String c4_String::SpanExcluding(const char* set) const +{ + return Left(strcspn(Data(), set)); +} + +///////////////////////////////////////////////////////////////////////////// +#endif // q4_UNIV diff --git a/akregator/src/mk4storage/metakit/src/table.cpp b/akregator/src/mk4storage/metakit/src/table.cpp new file mode 100644 index 000000000..a857cee09 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/table.cpp @@ -0,0 +1,160 @@ +// table.cpp -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Loose ends, these should be moved + */ + +#include "header.h" +#include "handler.h" +#include "store.h" +#include "field.h" +#include "format.h" +#include "persist.h" + +///////////////////////////////////////////////////////////////////////////// +// Implemented in this file + + class c4_Bytes; + class c4_HandlerSeq; + +///////////////////////////////////////////////////////////////////////////// + +/** @class c4_Bytes + * + * Generic data buffer, with optional automatic clean up. + * + * These objects are used to pass around untyped data without concern about + * clean-up. They know whether the bytes need to be de-allocated when these + * objects go out of scope. Small amounts of data are stored in the object. + * + * Objects of this class are used a lot within Metakit to manipulate its own + * data items generically. The c4_BytesProp class allows storing binary + * data explicitly in a file. If such data files must be portable, then the + * application itself must define a generic format to deal with byte order. + * + * How to store an object in binary form in a row (this is not portable): + * @code + * struct MyStruct { ... }; + * MyStruct something; + * + * c4_BytesProp pData ("Data"); + * c4_Row row; + * + * pData (row) = c4_Bytes (&something, sizeof something); + * @endcode + */ + + /// Construct an object with contents, optionally as a copy +c4_Bytes::c4_Bytes (const void* buf_, int len_, bool copy_) + : _size (len_), _copy (copy_) +{ + _contents = (t4_byte*) buf_; // moved out of intializers for DEC CXX 5.7 + if (_copy) + _MakeCopy(); +} + + /// Copy constructor +c4_Bytes::c4_Bytes (const c4_Bytes& src_) + : _size (src_._size), _copy (src_._copy) +{ + _contents = src_._contents; // moved out of intializers for DEC CXX 5.7 + if (_copy || _contents == src_._buffer) + _MakeCopy(); +} + + /// Assignment, this may make a private copy of contents +c4_Bytes& c4_Bytes::operator= (const c4_Bytes& src_) +{ + if (&src_ != this) + { + _LoseCopy(); + + _contents = src_._contents; + _size = src_._size; + _copy = src_._copy; + + if (_copy || _contents == src_._buffer) + _MakeCopy(); + } + + return *this; +} + + /// Swap the contents and ownership of two byte objects +void c4_Bytes::Swap(c4_Bytes& bytes_) +{ + t4_byte* p = _contents; + int s = _size; + bool c = _copy; + + _contents = bytes_._contents; + _size = bytes_._size; + _copy = bytes_._copy; + + bytes_._contents = p; + bytes_._size = s; + bytes_._copy = c; + + // if either one is using its local buffer, swap those too + if (_contents == bytes_._buffer || p == _buffer) + { + t4_byte t [sizeof _buffer]; + + memcpy(t, _buffer, sizeof _buffer); + memcpy(_buffer, bytes_._buffer, sizeof _buffer); + memcpy(bytes_._buffer, t, sizeof _buffer); + + if (_contents == bytes_._buffer) + _contents = _buffer; + + if (bytes_._contents == _buffer) + bytes_._contents = bytes_._buffer; + } +} + +/// Define contents as a freshly allocated buffer of given size +t4_byte* c4_Bytes::SetBuffer(int length_) +{ +/* No substantial improvement measured: + Perhaps keep a correctly sized c4_Bytes object in each property? + It means c4_...Ref objects would need to store a pointer, not an id. + + if (length_ == _size) + return _contents; // no work needed, get out fast +*/ + _LoseCopy(); + + _size = length_; + _copy = _size > (int) sizeof _buffer; + + return _contents = _copy ? d4_new t4_byte [_size] : _buffer; +} + +/// Allocate a buffer and fills its contents with zero bytes +t4_byte* c4_Bytes::SetBufferClear(int length_) +{ + return (t4_byte*) memset(SetBuffer(length_), 0, length_); +} + +void c4_Bytes::_MakeCopy() +{ + d4_assert(_contents != 0); + + _copy = _size > (int) sizeof _buffer; + + if (_size > 0) + _contents = (t4_byte*) memcpy(_copy ? d4_new t4_byte [_size] + : _buffer, _contents, _size); +} + +/// Return true if the contents of both objects are equal +bool operator== (const c4_Bytes& a_, const c4_Bytes& b_) +{ + return a_._contents == b_._contents || + (a_._size == b_._size && + memcmp(a_._contents, b_._contents, a_._size) == 0); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/univ.cpp b/akregator/src/mk4storage/metakit/src/univ.cpp new file mode 100644 index 000000000..81a73015a --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/univ.cpp @@ -0,0 +1,227 @@ +// univ.cpp -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * A simple implementation of dynamic arrays + */ + +#include "header.h" + +#if q4_UNIV // until end of source +///////////////////////////////////////////////////////////////////////////// + +#include <stdlib.h> // malloc + +#if !q4_INLINE +#include "univ.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + +#if q4_UNIX || __MINGW32__ +#define _strdup strdup +#elif !q4_BORC && !q4_MSVC && !q4_WATC && !(q4_MWCW && defined(_WIN32)) && \ + !(q4_MWCW && __MWERKS__ >= 0x3000) + + static char* _strdup(const char* p) + { + if (!p) + return 0; + + char* s = (char*) malloc(strlen(p) + 1); + return strcpy(s, p); + } + +#endif + + // The Borland C++ RTL does not want file handle objects to cross + // DLL boundaries, so we add special fopen/fclose hooks to this DLL. + +#if q4_BORC + #include <stdio.h> + +#if q4_WIN32 + __declspec(dllexport) FILE* +#else + FILE* __export +#endif + f4_FileOpenInDLL(const char* name_, const char* mode_) + { + return fopen(name_, mode_); + } + +#if q4_WIN32 + __declspec(dllexport) +#else + int __export +#endif + f4_FileCloseInDLL(FILE* file_) + { + return fclose(file_); + } + +#endif + +///////////////////////////////////////////////////////////////////////////// +// c4_BaseArray + +c4_BaseArray::c4_BaseArray () + : _data (0), _size (0) +{ +} + +c4_BaseArray::~c4_BaseArray () +{ + SetLength(0); +} + +void c4_BaseArray::SetLength(int nNewSize) +{ + // 2001-11-25: use more granular allocation, as optimization + const int bits = 6; + + if (((_size - 1) ^ (nNewSize - 1)) >> bits) { + const int n = (nNewSize + (1<<bits) - 1) & -(1<<bits); + _data = _data == 0 ? n == 0 ? (char*) 0 + : (char*) malloc(n) + : n == 0 ? (free(_data), (char*) 0) + : (char*) realloc(_data, n); + } + + d4_assert(_data != 0 || nNewSize == 0); + + int n = _size; + _size = nNewSize; + + if (nNewSize > n) + memset(GetData(n), 0, nNewSize - n); +} + +void c4_BaseArray::Grow(int nIndex) +{ + if (nIndex > _size) + SetLength(nIndex); +} + +void c4_BaseArray::InsertAt(int nIndex, int nCount) +{ + SetLength(_size + nCount); + + int to = nIndex + nCount; + if (_size > to) + d4_memmove(GetData(to), GetData(nIndex), _size - to); +} + +void c4_BaseArray::RemoveAt(int nIndex, int nCount) +{ + int from = nIndex + nCount; + if (_size > from) + d4_memmove(GetData(nIndex), GetData(from), _size - from); + + SetLength(_size - nCount); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_DWordArray + +int c4_DWordArray::Add(t4_i32 newElement) +{ + int n = GetSize(); + _vector.Grow(Off(n + 1)); + SetAt(n, newElement); + return n; +} + +void c4_DWordArray::InsertAt(int nIndex, t4_i32 newElement, int nCount) +{ + _vector.InsertAt(Off(nIndex), nCount * sizeof (t4_i32)); + + while (--nCount >= 0) + SetAt(nIndex++, newElement); +} + +void c4_DWordArray::RemoveAt(int nIndex, int nCount) +{ + _vector.RemoveAt(Off(nIndex), nCount * sizeof (t4_i32)); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_PtrArray + +int c4_PtrArray::Add(void* newElement) +{ + int n = GetSize(); + _vector.Grow(Off(n + 1)); + SetAt(n, newElement); + return n; +} + +void c4_PtrArray::InsertAt(int nIndex, void* newElement, int nCount) +{ + _vector.InsertAt(Off(nIndex), nCount * sizeof (void*)); + + while (--nCount >= 0) + SetAt(nIndex++, newElement); +} + +void c4_PtrArray::RemoveAt(int nIndex, int nCount) +{ + _vector.RemoveAt(Off(nIndex), nCount * sizeof (void*)); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_StringArray + +c4_StringArray::~c4_StringArray() +{ + SetSize(0); +} + +void c4_StringArray::SetSize(int nNewSize, int) +{ + int i = nNewSize; + + while (i < GetSize()) + SetAt(i++, 0); + + _ptrs.SetSize(nNewSize); + + while (i < GetSize()) + _ptrs.SetAt(i++, ""); +} + +void c4_StringArray::SetAt(int nIndex, const char* newElement) +{ + char* s = (char*) _ptrs.GetAt(nIndex); + if (s && *s) + free(s); + + _ptrs.SetAt(nIndex, newElement && *newElement? _strdup(newElement) : ""); +} + +int c4_StringArray::Add(const char* newElement) +{ + int n = _ptrs.Add(0); + SetAt(n, newElement); + return n; +} + +void c4_StringArray::InsertAt(int nIndex, const char* newElement, int nCount) +{ + _ptrs.InsertAt(nIndex, 0, nCount); + + while (--nCount >= 0) + SetAt(nIndex++, newElement); +} + +void c4_StringArray::RemoveAt(int nIndex, int nCount) +{ + for (int i = 0; i < nCount; ++i) + SetAt(nIndex + i, 0); + + _ptrs.RemoveAt(nIndex, nCount); +} + +///////////////////////////////////////////////////////////////////////////// +#endif // q4_UNIV diff --git a/akregator/src/mk4storage/metakit/src/univ.h b/akregator/src/mk4storage/metakit/src/univ.h new file mode 100644 index 000000000..5558e8a4c --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/univ.h @@ -0,0 +1,115 @@ +// univ.h -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Definition of the container classes + */ + +#define q4_UNIV 1 + +#include "mk4str.h" + +///////////////////////////////////////////////////////////////////////////// + +class c4_BaseArray +{ +public: + c4_BaseArray (); + ~c4_BaseArray (); + + int GetLength() const; + void SetLength(int nNewSize); + + const void* GetData(int nIndex) const; + void* GetData(int nIndex); + + void Grow(int nIndex); + + void InsertAt(int nIndex, int nCount); + void RemoveAt(int nIndex, int nCount); + +private: + char* _data; + int _size; +// char _buffer[4]; +}; + +class c4_PtrArray +{ +public: + c4_PtrArray (); + ~c4_PtrArray (); + + int GetSize() const; + void SetSize(int nNewSize, int nGrowBy = -1); + + void* GetAt(int nIndex) const; + void SetAt(int nIndex, const void* newElement); + void*& ElementAt(int nIndex); + + int Add(void* newElement); + + void InsertAt(int nIndex, void* newElement, int nCount = 1); + void RemoveAt(int nIndex, int nCount = 1); + +private: + static int Off(int n_); + + c4_BaseArray _vector; +}; + +class c4_DWordArray +{ +public: + c4_DWordArray (); + ~c4_DWordArray (); + + int GetSize() const; + void SetSize(int nNewSize, int nGrowBy = -1); + + t4_i32 GetAt(int nIndex) const; + void SetAt(int nIndex, t4_i32 newElement); + t4_i32& ElementAt(int nIndex); + + int Add(t4_i32 newElement); + + void InsertAt(int nIndex, t4_i32 newElement, int nCount = 1); + void RemoveAt(int nIndex, int nCount = 1); + +private: + static int Off(int n_); + + c4_BaseArray _vector; +}; + +class c4_StringArray +{ +public: + c4_StringArray (); + ~c4_StringArray (); + + int GetSize() const; + void SetSize(int nNewSize, int nGrowBy = -1); + + const char* GetAt(int nIndex) const; + void SetAt(int nIndex, const char* newElement); +// c4_String& ElementAt(int nIndex); + + int Add(const char* newElement); + + void InsertAt(int nIndex, const char* newElement, int nCount = 1); + void RemoveAt(int nIndex, int nCount = 1); + +private: + c4_PtrArray _ptrs; +}; + +///////////////////////////////////////////////////////////////////////////// + +#if q4_INLINE + #include "univ.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// + diff --git a/akregator/src/mk4storage/metakit/src/univ.inl b/akregator/src/mk4storage/metakit/src/univ.inl new file mode 100644 index 000000000..45b086fb2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/univ.inl @@ -0,0 +1,126 @@ +// univ.inl -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Inlined members of the container classes + */ + +///////////////////////////////////////////////////////////////////////////// +// c4_BaseArray + +d4_inline int c4_BaseArray::GetLength() const +{ + return _size; +} + +d4_inline const void* c4_BaseArray::GetData(int nIndex) const +{ + return _data + nIndex; +} + +d4_inline void* c4_BaseArray::GetData(int nIndex) +{ + return _data + nIndex; +} + +///////////////////////////////////////////////////////////////////////////// +// c4_PtrArray + +d4_inline c4_PtrArray::c4_PtrArray () +{ +} + +d4_inline c4_PtrArray::~c4_PtrArray () +{ +} + +d4_inline int c4_PtrArray::Off(int n_) +{ + return n_ * sizeof (void*); +} + +d4_inline int c4_PtrArray::GetSize() const +{ + return _vector.GetLength() / sizeof (void*); +} + +d4_inline void c4_PtrArray::SetSize(int nNewSize, int) +{ + _vector.SetLength(Off(nNewSize)); +} + +d4_inline void* c4_PtrArray::GetAt(int nIndex) const +{ + return *(void* const*) _vector.GetData(Off(nIndex)); +} + +d4_inline void c4_PtrArray::SetAt(int nIndex, const void* newElement) +{ + *(const void**) _vector.GetData(Off(nIndex)) = newElement; +} + +d4_inline void*& c4_PtrArray::ElementAt(int nIndex) +{ + return *(void**) _vector.GetData(Off(nIndex)); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_DWordArray + +d4_inline c4_DWordArray::c4_DWordArray () +{ +} + +d4_inline c4_DWordArray::~c4_DWordArray () +{ +} + +d4_inline int c4_DWordArray::Off(int n_) +{ + return n_ * sizeof (t4_i32); +} + +d4_inline int c4_DWordArray::GetSize() const +{ + return _vector.GetLength() / sizeof (t4_i32); +} + +d4_inline void c4_DWordArray::SetSize(int nNewSize, int) +{ + _vector.SetLength(Off(nNewSize)); +} + +d4_inline t4_i32 c4_DWordArray::GetAt(int nIndex) const +{ + return *(const t4_i32*) _vector.GetData(Off(nIndex)); +} + +d4_inline void c4_DWordArray::SetAt(int nIndex, t4_i32 newElement) +{ + *(t4_i32*) _vector.GetData(Off(nIndex)) = newElement; +} + +d4_inline t4_i32& c4_DWordArray::ElementAt(int nIndex) +{ + return *(t4_i32*) _vector.GetData(Off(nIndex)); +} + +///////////////////////////////////////////////////////////////////////////// +// c4_StringArray + +d4_inline c4_StringArray::c4_StringArray () +{ +} + +d4_inline int c4_StringArray::GetSize() const +{ + return _ptrs.GetSize(); +} + +d4_inline const char* c4_StringArray::GetAt(int nIndex) const +{ + return (const char*) _ptrs.GetAt(nIndex); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/view.cpp b/akregator/src/mk4storage/metakit/src/view.cpp new file mode 100644 index 000000000..af2fc9fa2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/view.cpp @@ -0,0 +1,1271 @@ +// view.cpp -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Implementation of main classes not involved in persistence + */ + +#include "header.h" +#include "derived.h" +#include "custom.h" +#include "store.h" // for RelocateRows +#include "field.h" // for RelocateRows +#include "persist.h" +#include "remap.h" + +#if !q4_INLINE +#include "mk4.inl" +#endif + +///////////////////////////////////////////////////////////////////////////// +// c4_ThreadLock + +class c4_ThreadLock +{ +public: + c4_ThreadLock (); + + class Hold + { + public: + Hold (); + ~Hold (); + }; +}; + +///////////////////////////////////////////////////////////////////////////// + +#if q4_MULTI + +#if q4_WIN32 + +/* + * On Win32, use a critical section to protect the global symbol table. + * Also uses special thread-safe calls to inc/dec all reference counts. + * + * This implementation replaces the previous use of TLS, which cannot + * be used without special tricks in dynamically loaded DLL's, as is + * required for OCX/ActiveX use (which uses LoadLibrary). + * + * Note: Could have used MFC's CCriticalSection and CSingleLock classes, + * but the code below is so trivial that it hardly matters. + */ + +#if q4_MSVC && !q4_STRICT +#pragma warning(disable: 4201) // nonstandard extension used : ... +#endif +#include <windows.h> + + static CRITICAL_SECTION gCritSect; + + c4_ThreadLock::c4_ThreadLock () + { + InitializeCriticalSection(&gCritSect); + } + + c4_ThreadLock::Hold::Hold () + { + EnterCriticalSection(&gCritSect); + } + + c4_ThreadLock::Hold::~Hold () + { + LeaveCriticalSection(&gCritSect); + } + +#else /* q4_WIN32 */ + +#include <pthread.h> + + static pthread_mutex_t gMutex; + + d4_inline c4_ThreadLock::c4_ThreadLock () + { + pthread_mutex_init(&gMutex, 0); + } + + d4_inline c4_ThreadLock::Hold::Hold () + { + d4_dbgdef(int r =) + pthread_mutex_lock(&gMutex); + d4_assert(r == 0); + } + + d4_inline c4_ThreadLock::Hold::~Hold () + { + d4_dbgdef(int r =) + pthread_mutex_unlock(&gMutex); + d4_assert(r == 0); + } + +#endif /* q4_WIN32 */ + +#else /* q4_MULTI */ + +// All other implementations revert to the simple "thread-less" case. + + d4_inline c4_ThreadLock::c4_ThreadLock () + { + } + + d4_inline c4_ThreadLock::Hold::Hold () + { + } + + d4_inline c4_ThreadLock::Hold::~Hold () + { + } + +#endif + +///////////////////////////////////////////////////////////////////////////// + +#if q4_LOGPROPMODS + + static FILE* sPropModsFile = 0; + static int sPropModsProp = -1; + +FILE* f4_LogPropMods(FILE* fp_, int propId_) +{ + FILE* prevfp = sPropModsFile; + sPropModsFile = fp_; + sPropModsProp = propId_; + return prevfp; +} + +void f4_DoLogProp(const c4_Handler* hp_, int id_, const char* fmt_, int arg_) +{ + if (sPropModsFile != 0 && (sPropModsProp < 0 || sPropModsProp == id_)) { + fprintf(sPropModsFile, "handler 0x%x id %d: ", hp_, id_); + fprintf(sPropModsFile, fmt_, arg_); + } +} + +#endif + +///////////////////////////////////////////////////////////////////////////// + +/** @class c4_View + * + * A collection of data rows. This is the central public data structure of + * Metakit (often called "table", "array", or "relation" in other systems). + * + * Views are smart pointers to the actual collections, setting a view to a new + * value does not alter the collection to which this view pointed previously. + * + * The elements of views can be referred to by their 0-based index, which + * produces a row-reference of type c4_RowRef. These row references can + * be copied, used to get or set properties, or dereferenced (in which case + * an object of class c4_Row is returned). Taking the address of a row + * reference produces a c4_Cursor, which acts very much like a pointer. + * + * The following code creates a view with 1 row and 2 properties: + * @code + * c4_StringProp pName ("name"); + * c4_IntProp pAge ("age"); + * + * c4_Row data; + * pName (data) = "John Williams"; + * pAge (data) = 43; + * + * c4_View myView; + * myView.Add(row); + * @endcode + */ + +/// Construct a view based on a sequence +c4_View::c4_View (c4_Sequence* seq_) + : _seq (seq_) +{ + if (!_seq) + _seq = d4_new c4_HandlerSeq (0); + + _IncSeqRef(); +} + +/// Construct a view based on a custom viewer +c4_View::c4_View (c4_CustomViewer* viewer_) + : _seq (0) +{ + d4_assert(viewer_); + + _seq = d4_new c4_CustomSeq (viewer_); + + _IncSeqRef(); +} + +/// Construct a view based on an input stream +c4_View::c4_View (c4_Stream* stream_) + : _seq (c4_Persist::Load(stream_)) +{ + if (_seq == 0) + _seq = d4_new c4_HandlerSeq (0); + + _IncSeqRef(); +} + +/// Construct an empty view with one property +c4_View::c4_View (const c4_Property& prop_) + : _seq (d4_new c4_HandlerSeq (0)) +{ + _IncSeqRef(); + + _seq->PropIndex(prop_); +} + +/// Copy constructor +c4_View::c4_View (const c4_View& view_) + : _seq (view_._seq) +{ + _IncSeqRef(); +} + +/// Makes this view the same as another one. +c4_View& c4_View::operator= (const c4_View& view_) +{ + if (_seq != view_._seq) { + _DecSeqRef(); + _seq = view_._seq; + _IncSeqRef(); + } + return *this; +} + +/** Get a single data item in a generic way + * + * This can be used to access view data in a generalized way. + * Useful for c4_CustomViewers which are based on other views. + * @return true if the item is non-empty + */ +bool c4_View::GetItem(int row_, int col_, c4_Bytes& buf_) const +{ + const c4_Property& prop = NthProperty(col_); + return prop (GetAt(row_)).GetData(buf_); +} + +/// Set a single data item in a generic way +void c4_View::SetItem(int row_, int col_, const c4_Bytes& buf_) const +{ + const c4_Property& prop = NthProperty(col_); + prop (GetAt(row_)).SetData(buf_); +} + +/// Set an entry, growing the view if needed +void c4_View::SetAtGrow(int index_, const c4_RowRef& newElem_) +{ + if (index_ >= GetSize()) + SetSize(index_ + 1); + + _seq->SetAt(index_, &newElem_); +} + +/** Add a new entry, same as "SetAtGrow(GetSize(), ...)" + * @return the index of the newly added row + */ +int c4_View::Add(const c4_RowRef& newElem_) +{ + int i = GetSize(); + InsertAt(i, newElem_); + return i; +} + +/** Construct a new view with a copy of the data + * + * The copy is a deep copy, because subviews are always copied in full. + */ +c4_View c4_View::Duplicate() const +{ + // insert all rows, sharing any subviews as needed + c4_View result = Clone(); + result.InsertAt(0, _seq); + return result; +} + +/** Constructs a new view with the same structure but no data + * + * Structural information can only be maintain for the top level, + * subviews will be included but without any properties themselves. + */ +c4_View c4_View::Clone() const +{ + c4_View view; + + for (int i = 0; i < NumProperties(); ++i) + view._seq->PropIndex(NthProperty(i)); + + return view; +} + +/** Adds a property column to a view if not already present + * @return 0-based column position of the property + */ +int c4_View::AddProperty(const c4_Property& prop_) +{ + return _seq->PropIndex(prop_); +} + +/** Returns the N-th property (using zero-based indexing) + * @return reference to the specified property + */ +const c4_Property& c4_View::NthProperty( + int index_ ///< the zero-based property index + ) const +{ + return _seq->NthHandler(index_).Property(); +} + +/** Find the index of a property, given its name + * @return 0-based column index + * @retval -1 property not present in this view + */ +int c4_View::FindPropIndexByName( + const char* name_ ///< property name (case insensitive) + ) const +{ + // use a slow linear scan to find the untyped property by name + for (int i = 0; i < NumProperties(); ++i) { + c4_String s = NthProperty(i).Name(); + if (s.CompareNoCase(name_) == 0) + return i; + } + + return -1; +} + +/** Defines a column for a property. + * + * The following code defines an empty view with three properties: + * @code + * c4_IntProp p1, p2, p3; + * c4_View myView = (p1, p2, p3); + * @endcode + * @return the new view object (without any data rows) + * @sa c4_Property + */ +c4_View c4_View::operator, (const c4_Property& prop_) const +{ + c4_View view = Clone(); + view.AddProperty(prop_); + return view; +} + +/// Insert copies of all rows of the specified view +void c4_View::InsertAt(int index_, const c4_View& view_) +{ + int n = view_.GetSize(); + if (n > 0) { + c4_Row empty; + + InsertAt(index_, empty, n); + + for (int i = 0; i < n; ++i) + SetAt(index_ + i, view_[i]); + } +} + +bool c4_View::IsCompatibleWith(const c4_View& dest_) const +{ + // can't determine table without handlers (and can't be a table) + if (NumProperties() == 0 || dest_.NumProperties() == 0) + return false; + + c4_Sequence* s1 = _seq; + c4_Sequence* s2 = dest_._seq; + c4_HandlerSeq* h1 = (c4_HandlerSeq*) s1->HandlerContext(0); + c4_HandlerSeq* h2 = (c4_HandlerSeq*) s2->HandlerContext(0); + + // both must be real handler views, not derived ones + if (h1 != s1 || h2 != s2) + return false; + + // both must not contain any temporary handlers + if (s1->NumHandlers() != h1->NumFields() || + s2->NumHandlers() != h2->NumFields()) + return false; + + // both must be in the same storage + if (h1->Persist() == 0 || h1->Persist() != h2->Persist()) + return false; + + // both must have the same structure (is this expensive?) + c4_String d1 = h1->Definition().Description(true); + c4_String d2 = h1->Definition().Description(true); + return d1 == d2; // ignores all names +} + +/** Move attached rows to somewhere else in same storage + * + * There is a lot of trickery going on here. The whole point of this + * code is that moving rows between (compatible!) subviews should not + * use copying when potentially large memo's and subviews are involved. + * In that case, the best solution is really to move pointers, not data. + */ +void c4_View::RelocateRows(int from_, int count_, c4_View& dest_, int pos_) +{ + if (count_ < 0) + count_ = GetSize() - from_; + if (pos_ < 0) + pos_ = dest_.GetSize(); + + d4_assert(0 <= from_ && from_ <= GetSize()); + d4_assert(0 <= count_ && from_ + count_ <= GetSize()); + d4_assert(0 <= pos_ && pos_ <= dest_.GetSize()); + + if (count_ > 0) { + // the destination must not be inside the source rows + d4_assert(&dest_ != this || from_ > pos_ || pos_ >= from_ + count_); + + // this test is slow, so do it only as a debug check + d4_assert(IsCompatibleWith(dest_)); + + // make space, swap rows, drop originals + c4_Row empty; + dest_.InsertAt(pos_, empty, count_); + + // careful if insert moves origin + if (&dest_ == this && pos_ <= from_) + from_ += count_; + + for (int i = 0; i < count_; ++i) + ((c4_HandlerSeq*) _seq)->ExchangeEntries(from_ + i, + *(c4_HandlerSeq*) dest_._seq, pos_ + i); + + RemoveAt(from_, count_); + } +} + +/** Create view with all rows in natural (property-wise) order + * + * The result is virtual, it merely maintains a permutation to access the + * underlying view. This "derived" view uses change notification to track + * changes to the underlying view, but unfortunately there are some major + * limitations with this scheme - one of them being that deriving another + * view from this sorted one will not properly track changes. + */ +c4_View c4_View::Sort() const +{ + return f4_CreateSort(*_seq); +} + +/** Create view sorted according to the specified properties + * + * The result is virtual, it merely maintains a permutation to access the + * underlying view. This "derived" view uses change notification to track + * changes to the underlying view, but unfortunately there are some major + * limitations with this scheme - one of them being that deriving another + * view from this sorted one will not properly track changes. + */ +c4_View c4_View::SortOn(const c4_View& up_) const +{ + c4_Sequence* seq = f4_CreateProject(*_seq, *up_._seq, true); + + return f4_CreateSort(*seq); +} + +/** Create sorted view, with some properties sorted in reverse + * + * The result is virtual, it merely maintains a permutation to access the + * underlying view. This "derived" view uses change notification to track + * changes to the underlying view, but unfortunately there are some major + * limitations with this scheme - one of them being that deriving another + * view from this sorted one will not properly track changes. + */ +c4_View c4_View::SortOnReverse( + const c4_View& up_, ///< the view which defines the sort order + const c4_View& down_ ///< subset of up_, defines reverse order + ) const +{ + c4_Sequence* seq = f4_CreateProject(*_seq, *up_._seq, true); + + return f4_CreateSort(*seq, down_._seq); +} + +/** Create view with rows matching the specified value + * + * The result is virtual, it merely maintains a permutation to access the + * underlying view. This "derived" view uses change notification to track + * changes to the underlying view, but this only works when based on views + * which properly generate change notifications (.e. raw views, other + * selections, and projections). + */ +c4_View c4_View::Select(const c4_RowRef& crit_) const +{ + return f4_CreateFilter(*_seq, &crit_, &crit_); +} + +/** Create view with row values within the specified range + * + * The result is virtual, it merely maintains a permutation to access the + * underlying view. This "derived" view uses change notification to track + * changes to the underlying view, but this only works when based on views + * which properly generate change notifications (.e. raw views, other + * selections, and projections). + */ +c4_View c4_View::SelectRange( + const c4_RowRef& low_, ///< values of the lower bounds (inclusive) + const c4_RowRef& high_ ///< values of the upper bounds (inclusive) + ) const +{ + return f4_CreateFilter(*_seq, &low_, &high_); +} + +/** Create view with the specified property arrangement + * + * The result is virtual, it merely maintains a permutation to access the + * underlying view. This "derived" view uses change notification to track + * changes to the underlying view, but this only works when based on views + * which properly generate change notifications (.e. raw views, selections, + * and other projections). + */ +c4_View c4_View::Project(const c4_View& in_) const +{ + return f4_CreateProject(*_seq, *in_._seq, false); +} + +/** Create derived view with some properties omitted + * + * The result is virtual, it merely maintains a permutation to access the + * underlying view. This "derived" view uses change notification to track + * changes to the underlying view, but this only works when based on views + * which properly generate change notifications (.e. raw views, selections, + * and other projections). + */ +c4_View c4_View::ProjectWithout(const c4_View& out_) const +{ + return f4_CreateProject(*_seq, *_seq, false, out_._seq); +} + +/** Create view which is a segment/slice (default is up to end) + * + * Returns a view which is a subset, either a contiguous range, or + * a "slice" with element taken from every step_ entries. If the + * step is negative, the same entries are returned, but in reverse + * order (start_ is still lower index, it'll then be returned last). + * + * This view operation is based on a custom viewer and is modifiable. + */ +c4_View c4_View::Slice(int first_, int limit_, int step_) const +{ + return f4_CustSlice(*_seq, first_, limit_, step_); +} + +/** Create view which is the cartesian product with given view + * + * The cartesian product is defined as every combination of rows + * in both views. The number of entries is the product of the + * number of entries in the two views, properties which are present + * in both views will use the values defined in this view. + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::Product(const c4_View& view_) const +{ + return f4_CustProduct(*_seq, view_); +} + +/** Create view which remaps another given view + * + * Remapping constructs a view with the rows indicated by another + * view. The first property in the order_ view must be an int + * property with index values referring to this one. The size of + * the resulting view is determined by the order_ view and can + * differ, for example to act as a subset selection (if smaller). + * + * This view operation is based on a custom viewer and is modifiable. + */ +c4_View c4_View::RemapWith(const c4_View& view_) const +{ + return f4_CustRemapWith(*_seq, view_); +} + +/** Create view which pairs each row with corresponding row + * + * This is like a row-by-row concatenation. Both views must have + * the same number of rows, the result has all properties from + * this view plus any other properties from the other view. + * + * This view operation is based on a custom viewer and is modifiable. + */ +c4_View c4_View::Pair(const c4_View& view_) const +{ + return f4_CustPair(*_seq, view_); +} + +/** Create view with rows from another view appended + * + * Constructs a view which has all rows of this view, and all rows + * of the second view appended. The structure of the second view + * is assumed to be identical to this one. This operation is a bit + * similar to appending all rows from the second view, but it does + * not actually store the result anywhere, it just looks like it. + * + * This view operation is based on a custom viewer and is modifiable. + */ +c4_View c4_View::Concat(const c4_View& view_) const +{ + return f4_CustConcat(*_seq, view_); +} + +/** Create view with one property renamed (must be of same type) + * + * This view operation is based on a custom viewer and is modifiable. + */ +c4_View c4_View::Rename(const c4_Property& old_, const c4_Property& new_) const +{ + return f4_CustRename(*_seq, old_, new_); +} + +/** Create view with a subview, grouped by the specified properties + * + * This operation is similar to the SQL 'GROUP BY', but it takes + * advantage of the fact that Metakit supports nested views. The + * view returned from this member has one row per distinct group, + * with an extra view property holding the remaining properties. + * If there are N rows in the original view matching key X, then + * the result is a row for key X, with a subview of N rows. The + * properties of the subview are all the properties not in the key. + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::GroupBy( + const c4_View& keys_, ///< properties in this view determine grouping + const c4_ViewProp& result_ ///< name of new subview defined in result + ) const +{ + return f4_CustGroupBy(*_seq, keys_, result_); +} + +/** Create view with count of duplicates, when grouped by key + * + * This is similar to c4_View::GroupBy, but it determines only the + * number of rows in each group and does not create a nested view. + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::Counts( + const c4_View& keys_, ///< properties in this view determine grouping + const c4_IntProp& result_ ///< new count property defined in result + ) const +{ + return f4_CustGroupBy(*_seq, keys_, result_); // third arg is c4_IntProp +} + +/** Create view with all duplicate rows omitted + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::Unique() const +{ + c4_IntProp count ("#N#"); + return Counts(Clone(), count).ProjectWithout(count); +} + +/** Create view which is the set union (assumes no duplicate rows) + * + * Calculates the set union. This will only work if both input + * views are sets, i.e. they have no duplicate rows in them. + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::Union(const c4_View& view_) const +{ + return Concat(view_).Unique(); +} + +/** Create view with all rows also in the given view (no dups) + * + * Calculates the set intersection. This will only work if both + * input views are sets, i.e. they have no duplicate rows in them. + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::Intersect(const c4_View& view_) const +{ + c4_View v = Concat(view_); + + // assume neither view has any duplicates + c4_IntProp count ("#N#"); + return v.Counts(Clone(), count).Select(count [2]).ProjectWithout(count); +} + +/** Create view with all rows not in both views (no dups) + * + * Calculates the "XOR" of two sets. This will only work if both + * input views are sets, i.e. they have no duplicate rows in them. + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::Different(const c4_View& view_) const +{ + c4_View v = Concat(view_); + + // assume neither view has any duplicates + c4_IntProp count ("#N#"); + return v.Counts(Clone(), count).Select(count [1]).ProjectWithout(count); +} + +/** Create view with all rows not in the given view (no dups) + * + * Calculates set-difference of this view minus arg view. Result + * is a subset, unlike c4_View::Different. Will only work if both + * input views are sets, i.e. they have no duplicate rows in them. + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::Minus( + const c4_View& view_ ///< the second view + ) const +{ + // inefficient: calculate difference, then keep only those in self + return Intersect(Different(view_)); +} + +/** Create view with a specific subview expanded, like a join + * + * This operation is the inverse of c4_View::GroupBy, expanding + * all rows in specified subview and returning a view which looks + * as if the rows in each subview were "expanded in place". + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::JoinProp( + const c4_ViewProp& sub_, ///< name of the subview to expand + bool outer_ ///< true: keep rows with empty subviews + ) const +{ + return f4_CustJoinProp(*_seq, sub_, outer_); +} + +/** Create view which is the relational join on the given keys + * + * This view operation is based on a read-only custom viewer. + */ +c4_View c4_View::Join( + const c4_View& keys_, ///< properties in this view determine the join + const c4_View& view_, ///< second view participating in the join + bool outer_ ///< true: keep rows with no match in second view + ) const +{ + // inefficient: calculate difference, then keep only those in self + return f4_CustJoin(*_seq, keys_, view_, outer_); +} + +/** Create an identity view which only allows reading + * + * This view operation is based on a custom viewer. + */ +c4_View c4_View::ReadOnly() const +{ + return f4_CreateReadOnly(*_seq); +} + +/** Create mapped view which adds a hash lookup layer + * + * This view creates and manages a special hash map view, to implement a + * fast find on the key. The key is defined to consist of the first + * numKeys_ properties of the underlying view. + * + * The map_ view must be empty the first time this hash view is used, so + * that Metakit can fill it based on whatever rows are already present in + * the underlying view. After that, neither the underlying view nor the + * map view may be modified other than through this hash mapping layer. + * The defined structure of the map view must be "_H:I,_R:I". + * + * This view is modifiable. Insertions and changes to key field properties + * can cause rows to be repositioned to maintain hash uniqueness. Careful: + * when a row is changed in such a way that its key is the same as in another + * row, that other row will be deleted from the view. + * + * Example of use: + * @code + * c4_View data = storage.GetAs("people[name:S,age:I]"); + * c4_View datah = storage.GetAs("people_H[_H:I,_R:I]"); + * c4_View hash = raw.Hash(datah, 1); + * ... hash.GetSize() ... + * hash.Add(...) + * @endcode + */ +c4_View c4_View::Hash(const c4_View& map_, int numKeys_) const +{ + return f4_CreateHash(*_seq, numKeys_, map_._seq); +} + +/** Create mapped view which blocks its rows in two levels + * + * This view acts like a large flat view, even though the actual rows are + * stored in blocks, which are rebalanced automatically to maintain a good + * trade-off between block size and number of blocks. + * + * The underlying view must be defined with a single view property, with + * the structure of the subview being as needed. An example of a blocked + * view definition which will act like a single one containing 2 properties: + * @code + * c4_View raw = storage.GetAs("people[_B[name:S,age:I]]"); + * c4_View flat = raw.Blocked(); + * ... flat.GetSize() ... + * flat.InsertAt(...) + * @endcode + * + * This view operation is based on a custom viewer and is modifiable. + */ +c4_View c4_View::Blocked() const +{ + return f4_CreateBlocked(*_seq); +} + +/** Create mapped view which keeps its rows ordered + * + * This is an identity view, which has as only use to inform Metakit that + * the underlying view can be considered to be sorted on its first numKeys_ + * properties. The effect is that c4_View::Find will try to use binary + * search when the search includes key properties (results will be identical + * to unordered views, the find will just be more efficient). + * + * This view is modifiable. Insertions and changes to key field properties + * can cause rows to be repositioned to maintain the sort order. Careful: + * when a row is changed in such a way that its key is the same as in another + * row, that other row will be deleted from the view. + * + * This view can be combined with c4_View::Blocked, to create a 2-level + * btree structure. + */ +c4_View c4_View::Ordered(int numKeys_) const +{ + return f4_CreateOrdered(*_seq, numKeys_); +} + +/** Create mapped view which maintains an index permutation + * + * This is an identity view which somewhat resembles the ordered view, it + * maintains a secondary "map" view to contain the permutation to act as + * an index. The indexed view presents the same order of rows as the + * underlying view, but the index map is set up in such a way that binary + * search is possible on the keys specified. When the "unique" parameter + * is true, insertions which would create a duplicate key are ignored. + * + * This view is modifiable. Careful: when a row is changed in such a way + * that its key is the same as in another row, that other row will be + * deleted from the view. + */ +c4_View c4_View::Indexed(const c4_View& map_, const c4_View& props_, + bool unique_) const +{ + return f4_CreateIndexed(*_seq, *map_._seq, props_, unique_); +} + +/** Return the index of the specified row in this view (or -1) + * + * This function can be used to "unmap" an index of a derived view back + * to the original underlying view. + */ +int c4_View::GetIndexOf(const c4_RowRef& row_) const +{ + c4_Cursor cursor = &row_; + + return cursor._seq->RemapIndex(cursor._index, _seq); +} + +/// Restrict the search range for rows +int c4_View::RestrictSearch(const c4_RowRef& c_, int& pos_, int& count_) +{ + return _seq->RestrictSearch(&c_, pos_, count_) ? 0 : ~0; +} + +/** Find index of the the next entry matching the specified key. + * + * Defaults to linear search, but hash- and ordered-views will use a better + * algorithm if possible. Only the properties present in the search key + * are used to determine whether a row matches the key. + * @return position where match occurred + * @retval -1 if not found + */ +int c4_View::Find( + const c4_RowRef& crit_, ///< the value to look for + int start_ ///< the index to start with + ) const +{ + d4_assert(start_ >= 0); + + c4_Row copy = crit_; // the lazy (and slow) solution: make a copy + + int count = GetSize() - start_; + if (_seq->RestrictSearch(©, start_, count)) { + c4_View refView = copy.Container(); + c4_Sequence* refSeq = refView._seq; + d4_assert(refSeq != 0); + + c4_Bytes data; + + for (int j = 0; j < count; ++j) { + int i; + + for (i = 0; i < refSeq->NumHandlers(); ++i) { + c4_Handler& h = refSeq->NthHandler(i); // no context issues + + if (!_seq->Get(start_ + j, h.PropId(), data)) + h.ClearBytes(data); + + if (h.Compare(0, data) != 0) // always row 0 + break; + } + + if (i == refSeq->NumHandlers()) + return start_ + j; + } + } + + return -1; +} + +/** Search for a key, using the native sort order of the view + * @return position where found, or where it may be inserted, + * this position can also be just past the last row + */ +int c4_View::Search(const c4_RowRef& crit_) const +{ + int l = -1, u = GetSize(); + while (l + 1 != u) { + const int m = (l + u) >> 1; + if (_seq->Compare(m, &crit_) < 0) + //if (crit_ > (*this)[m]) // Dec 2001: see comments below + l = m; + else + u = m; + } + + return u; +} + +/// Return number of matching keys, and pos of first one as arg +int c4_View::Locate(const c4_RowRef& crit_, int* pos_) const +{ + // Dec 2001: fixed a problem with searching of partial rows. + // + // There is an *extremely* tricky issue in here, in that the + // comparison operator for rows is not symmetric. So in the + // general case, "a == b" is not euivalent to "b == a". This + // is without doubt a design mistake (and should have at least + // been named differently). + // + // The reason is that the number of properties in both rowrefs + // need not be the same. Only the properties of the leftmost + // rowref are compared against the other one. This also applies + // to the other comparisons, i.e. !=, <, >, <=, and >=. + // + // All Compare calls below have been changed to use comparisons + // in the proper order and now use "rowref <op> rowref" syntax. + + c4_Cursor curr (*(c4_Sequence*) _seq, 0); // loses const + + int l = -1, u = GetSize(); + while (l + 1 != u) { + curr._index = (l + u) >> 1; + if (crit_ > *curr) + l = curr._index; + else + u = curr._index; + } + + if (pos_ != 0) + *pos_ = u; + + // only look for more if the search hit an exact match + curr._index = u; + if (u == GetSize() || crit_ != *curr) + return 0; + + // as Jon Bentley wrote in DDJ Apr 2000, setting l2 to -1 is better than u + int l2 = -1, u2 = GetSize(); + while (l2 + 1 != u2) { + curr._index = (l2 + u2) >> 1; + if (crit_ >= *curr) + l2 = curr._index; + else + u2 = curr._index; + } + + return u2 - u; +} + +/// Compare two views lexicographically (rows 0..N-1). +int c4_View::Compare(const c4_View& view_) const +{ + if (_seq == view_._seq) + return 0; + + int na = GetSize(); + int nb = view_.GetSize(); + int i; + + for (i = 0; i < na && i < nb; ++i) + if (GetAt(i) != view_.GetAt(i)) + return GetAt(i) < view_.GetAt(i) ? -1 : +1; + + return na == nb ? 0 : i < na ? +1 : -1; +} + +///////////////////////////////////////////////////////////////////////////// + +/** @class c4_Cursor + * + * An iterator for collections of rows (views). + * + * Cursor objects can be used to point to specific entries in a view. + * A cursor acts very much like a pointer to a row in a view, and is + * returned when taking the address of a c4_RowRef. Dereferencing + * a cursor leads to the original row reference again. You can construct a + * cursor for a c4_Row, but since such rows are not part of a collection, + * incrementing or decrementing these cursors is meaningless (and wrong). + * + * The usual range of pointer operations can be applied to these objects: + * pre/post-increment and decrement, adding or subtracting integer offsets, + * as well as the full range of comparison operators. If two cursors + * point to entries in the same view, their difference can be calculated. + * + * As with regular pointers, care must be taken to avoid running off of + * either end of a view (the debug build includes assertions to check this). + */ + +/** @class c4_RowRef + * + * Reference to a data row, can be used on either side of an assignment. + * + * Row references are created when dereferencing a c4_Cursor or when + * indexing an element of a c4_View. Assignment will change the + * corresponding item. Rows (objects of type c4_Row) are a special + * case of row references, consisting of a view with exactly one item. + * + * Internally, row references are very similar to cursors, in fact they are + * little more than a wrapper around them. The essential difference is one + * of semantics: comparing row references compares contents, copying row + * references copies the contents, whereas cursor comparison and copying + * deals with the pointer to the row, not its contents. + */ + +///////////////////////////////////////////////////////////////////////////// +// c4_Row + +c4_Row::c4_Row () + : c4_RowRef (* Allocate()) +{ +} + +c4_Row::c4_Row (const c4_Row& row_) + : c4_RowRef (* Allocate()) +{ + operator= (row_); +} + +c4_Row::c4_Row (const c4_RowRef& rowRef_) + : c4_RowRef (* Allocate()) +{ + operator= (rowRef_); +} + +c4_Row::~c4_Row () +{ + Release(_cursor); +} + +c4_Row& c4_Row::operator= (const c4_Row& row_) +{ + return operator= ((const c4_RowRef&) row_); +} + +/// Assignment from a reference to a row. +c4_Row& c4_Row::operator= (const c4_RowRef& rowRef_) +{ + d4_assert(_cursor._seq != 0); + + if (_cursor != &rowRef_) { + d4_assert(_cursor._index == 0); + _cursor._seq->SetAt(0, &rowRef_); + } + + return *this; +} + +/// Adds all properties and values into this row. +void c4_Row::ConcatRow(const c4_RowRef& rowRef_) +{ + d4_assert(_cursor._seq != 0); + + c4_Cursor cursor = &rowRef_; // trick to access private rowRef_._cursor + d4_assert(cursor._seq != 0); + + c4_Sequence& rhSeq = * cursor._seq; + + c4_Bytes data; + + for (int i = 0; i < rhSeq.NumHandlers(); ++i) { + c4_Handler& h = rhSeq.NthHandler(i); + + h.GetBytes(cursor._index, data); + _cursor._seq->Set(_cursor._index, h.Property(), data); + } +} + +c4_Row operator+ (const c4_RowRef& a_, const c4_RowRef& b_) +{ + c4_Row row = a_; + row.ConcatRow(b_); + return row; +} + +c4_Cursor c4_Row::Allocate() +{ + c4_Sequence* seq = d4_new c4_HandlerSeq (0); + seq->IncRef(); + + seq->Resize(1); + + return c4_Cursor (*seq, 0); +} + +void c4_Row::Release(c4_Cursor row_) +{ + d4_assert(row_._seq != 0); + d4_assert(row_._index == 0); + + row_._seq->DecRef(); +} + +///////////////////////////////////////////////////////////////////////////// + +/** @class c4_Property + * + * Base class for the basic data types. + * + * Property objects exist independently of view, row, and storage objects. + * They have a name and type, and can appear in any number of views. + * You will normally only use derived classes, to maintain strong typing. + */ + + // This is a workaround for the fact that the initialization order of + // static objects is not always adequate (implementation dependent). + // Extremely messy solution, to allow statically declared properties. + // + // These are the only static variables in the entire Metakit core lib. + + static c4_ThreadLock* sThreadLock = 0; + static c4_StringArray* sPropNames = 0; + static c4_DWordArray* sPropCounts = 0; + + /// Call this to get rid of some internal datastructues (on exit) + void c4_Property::CleanupInternalData() + { + delete sPropNames; + sPropNames = 0; // race + + delete sPropCounts; + sPropCounts = 0; // race + + delete sThreadLock; + sThreadLock = 0; // race + } + +c4_Property::c4_Property (char type_, const char* name_) + : _type (type_) +{ + if (sThreadLock == 0) + sThreadLock = d4_new c4_ThreadLock; + + c4_ThreadLock::Hold lock; // grabs the lock until end of scope + + if (sPropNames == 0) + sPropNames = d4_new c4_StringArray; + + if (sPropCounts == 0) + sPropCounts = d4_new c4_DWordArray; + + c4_String temp = name_; + + _id = sPropNames->GetSize(); + while (-- _id >= 0) { + const char* p = sPropNames->GetAt(_id); + // optimize for first char case-insensitive match + if (((*p ^ *name_) & ~0x20) == 0 && temp.CompareNoCase(p) == 0) + break; + } + + if (_id < 0) { + int size = sPropCounts->GetSize(); + + for (_id = 0; _id < size; ++_id) + if (sPropCounts->GetAt(_id) == 0) + break; + + if (_id >= size) { + sPropCounts->SetSize(_id + 1); + sPropNames->SetSize(_id + 1); + } + + sPropCounts->SetAt(_id, 0); + sPropNames->SetAt(_id, name_); + } + + Refs(+1); +} + +c4_Property::c4_Property (const c4_Property& prop_) + : _id (prop_.GetId()), _type (prop_.Type()) +{ + c4_ThreadLock::Hold lock; + + d4_assert(sPropCounts != 0); + d4_assert(sPropCounts->GetAt(_id) > 0); + + Refs(+1); +} + +c4_Property::~c4_Property () +{ + c4_ThreadLock::Hold lock; + + Refs(-1); +} + +void c4_Property::operator= (const c4_Property& prop_) +{ + c4_ThreadLock::Hold lock; + + prop_.Refs(+1); + Refs(-1); + + _id = prop_.GetId(); + _type = prop_.Type(); +} + + /// Return the name of this property +const char* c4_Property::Name() const +{ + c4_ThreadLock::Hold lock; + + d4_assert(sPropNames != 0); + return sPropNames->GetAt(_id); +} + +/** Adjust the reference count + * + * This is part of the implementation and shouldn't normally be called. + * This code is only called with the lock held, and always thread-safe. + */ +void c4_Property::Refs(int diff_) const +{ + d4_assert(diff_ == -1 || diff_ == +1); + + d4_assert(sPropCounts != 0); + sPropCounts->ElementAt(_id) += diff_; + +#if q4_CHECK + // get rid of the cache when the last property goes away + static t4_i32 sPropTotals; + + sPropTotals += diff_; + if (sPropTotals == 0) + CleanupInternalData(); +#endif +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/viewx.cpp b/akregator/src/mk4storage/metakit/src/viewx.cpp new file mode 100644 index 000000000..db30d14e5 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/viewx.cpp @@ -0,0 +1,857 @@ +// viewx.cpp -- +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +/** @file + * Implements c4_Sequence, c4_Reference, and c4_...Ref + */ + +#include "header.h" +#include "handler.h" +#include "store.h" +#include "column.h" + +///////////////////////////////////////////////////////////////////////////// + +c4_Sequence::c4_Sequence () + : _refCount (0), _dependencies (0), _propertyLimit (0), _tempBuf (0) +{ +} + +c4_Sequence::~c4_Sequence () +{ + d4_assert(_refCount == 0); + + d4_assert(!_dependencies); // there can be no dependencies left + + ClearCache(); + + delete _tempBuf; +} + +c4_Persist* c4_Sequence::Persist() const +{ + return 0; +} + + /// Increment the reference count of this sequence +void c4_Sequence::IncRef() +{ + ++_refCount; + + d4_assert(_refCount != 0); +} + + /// Decrement the reference count, delete objects when last +void c4_Sequence::DecRef() +{ + d4_assert(_refCount != 0); + + if (--_refCount == 0) + delete this; +} + + /// Return the current reference count +int c4_Sequence::NumRefs() const +{ + return _refCount; +} + + /// Compare the specified row with another one +int c4_Sequence::Compare(int index_, c4_Cursor cursor_) const +{ + d4_assert(cursor_._seq != 0); + + c4_Bytes data; + + for (int colNum = 0; colNum < NumHandlers(); ++colNum) + { + c4_Handler& h = NthHandler(colNum); + + const c4_Sequence* hc = HandlerContext(colNum); + int i = RemapIndex(index_, hc); + + if (!cursor_._seq->Get(cursor_._index, h.PropId(), data)) + h.ClearBytes(data); + + int f = h.Compare(i, data); + if (f != 0) + return f; + } + + return 0; +} + + /// Restrict the search range for rows +bool c4_Sequence::RestrictSearch(c4_Cursor, int&, int&) +{ + return true; +} + + /// Replace the contents of a specified row +void c4_Sequence::SetAt(int index_, c4_Cursor newElem_) +{ + d4_assert(newElem_._seq != 0); + + c4_Bytes data; + + c4_Notifier change (this); + if (GetDependencies()) + change.StartSetAt(index_, newElem_); + + for (int i = 0; i < newElem_._seq->NumHandlers(); ++i) + { + c4_Handler& h = newElem_._seq->NthHandler(i); + + // added 06-12-1999 to do index remapping for derived seq's + const c4_Sequence* hc = newElem_._seq->HandlerContext(i); + int ri = newElem_._seq->RemapIndex(newElem_._index, hc); + + h.GetBytes(ri, data); + +// Set(index_, cursor._seq->NthProperty(i), data); + int colNum = PropIndex(h.Property()); + d4_assert(colNum >= 0); + + NthHandler(colNum).Set(index_, data); + } + + // if number of props in dest is larger after adding, clear the rest + // this way, new props get copied and undefined props get cleared + if (newElem_._seq->NumHandlers() < NumHandlers()) + { + for (int j = 0; j < NumHandlers(); ++j) + { + c4_Handler& h = NthHandler(j); + + // if the property does not appear in the source + if (newElem_._seq->PropIndex(h.PropId()) < 0) + { + h.ClearBytes(data); + h.Set(index_, data); + } + } + } +} + + /// Remap the index to an underlying view +int c4_Sequence::RemapIndex(int index_, const c4_Sequence* seq_) const +{ + return seq_ == this ? index_ : -1; +} + + /// Gives access to a general purpose temporary buffer +c4_Bytes& c4_Sequence::Buffer() +{ + if (_tempBuf == 0) + _tempBuf = d4_new c4_Bytes; + return *_tempBuf; +} + + // 1.8.5: extra buffer to hold returned description strings +const char* c4_Sequence::UseTempBuffer(const char* str_) +{ + return strcpy((char*) Buffer().SetBuffer(strlen(str_) + 1), str_); +} + + /// Change number of rows, either by inserting or removing them +void c4_Sequence::Resize(int newSize_, int) +{ + if (NumHandlers() > 0) + { + int diff = newSize_ - NumRows(); + + if (diff > 0) + { + c4_Row empty; // make sure this doesn't recurse, see below + InsertAt(NumRows(), &empty, diff); + } + else if (diff < 0) + RemoveAt(newSize_, - diff); + } + else // need special case to avoid recursion for c4_Row allocations + SetNumRows(newSize_); +} + + /// Insert one or more rows into this sequence +void c4_Sequence::InsertAt(int index_, c4_Cursor newElem_, int count_) +{ + d4_assert(newElem_._seq != 0); + + c4_Notifier change (this); + if (GetDependencies()) + change.StartInsertAt(index_, newElem_, count_); + + SetNumRows(NumRows() + count_); + + c4_Bytes data; + + for (int i = 0; i < newElem_._seq->NumHandlers(); ++i) + { + c4_Handler& h = newElem_._seq->NthHandler(i); + + // added 06-12-1999 to do index remapping for derived seq's + const c4_Sequence* hc = newElem_._seq->HandlerContext(i); + int ri = newElem_._seq->RemapIndex(newElem_._index, hc); + + h.GetBytes(ri, data); + + int colNum = PropIndex(h.Property()); + d4_assert(colNum >= 0); + + if (h.Property().Type() == 'V') + { + // special treatment for subviews, insert empty, then overwrite + // changed 19990904 - probably fixes a long-standing limitation + c4_Bytes temp; + h.ClearBytes(temp); + + c4_Handler& h2 = NthHandler(colNum); + h2.Insert(index_, temp, count_); + for (int j = 0; j < count_; ++j) + h2.Set(index_ + j, data); + } + else + NthHandler(colNum).Insert(index_, data, count_); + } + + // if number of props in dest is larger after adding, clear the rest + // this way, new props get copied and undefined props get cleared + if (newElem_._seq->NumHandlers() < NumHandlers()) + { + for (int j = 0; j < NumHandlers(); ++j) + { + c4_Handler& h = NthHandler(j); + + // if the property does not appear in the source + if (newElem_._seq->PropIndex(h.PropId()) < 0) + { + h.ClearBytes(data); + h.Insert(index_, data, count_); + } + } + } +} + + /// Remove one or more rows from this sequence +void c4_Sequence::RemoveAt(int index_, int count_) +{ + c4_Notifier change (this); + if (GetDependencies()) + change.StartRemoveAt(index_, count_); + + SetNumRows(NumRows() - count_); + + //! careful, this does no index remapping, wrong for derived seq's + for (int i = 0; i < NumHandlers(); ++i) + NthHandler(i).Remove(index_, count_); +} + + /// Move a row to another position +void c4_Sequence::Move(int from_, int to_) +{ + c4_Notifier change (this); + if (GetDependencies()) + change.StartMove(from_, to_); + + //! careful, this does no index remapping, wrong for derived seq's + for (int i = 0; i < NumHandlers(); ++i) + NthHandler(i).Move(from_, to_); +} + + /// Return the id of the N-th property +int c4_Sequence::NthPropId(int index_) const +{ + return NthHandler(index_).PropId(); +} + +void c4_Sequence::ClearCache() +{ + if (_propertyLimit > 0) + { + delete [] _propertyMap; // property indexes may change + _propertyLimit = 0; + } +} + + /// Find the index of a property by its id +int c4_Sequence::PropIndex(int propId_) +{ +//! CACHING NOTE: derived views will fail if underlying view is restructured +// still, this cache is kept, since sort will fail anyway... +// The only safe change in these cases is adding new properties at the end. + + // use the map for the fastest result once known + if (propId_ < _propertyLimit && _propertyMap[propId_] >= 0) + return _propertyMap[propId_]; + + // locate the property using a linear search, return if not present + int n = NumHandlers(); + do + if (--n < 0) + return -1; + while (NthPropId(n) != propId_); + + // if the map is too small, resize it (with a little slack) + if (propId_ >= _propertyLimit) + { + int round = (propId_ + 8) & ~0x07; + short* vec = d4_new short [round]; + + for (int i = 0; i < round; ++i) + vec[i] = i < _propertyLimit ? _propertyMap[i] : -1; + + if (_propertyLimit > 0) + delete [] _propertyMap; + + _propertyMap = vec; + _propertyLimit = round; + } + + // we have a map, adjust the entry and return + return _propertyMap[propId_] = n; +} + + /// Find the index of a property, or create a new entry +int c4_Sequence::PropIndex(const c4_Property& prop_) +{ + int pos = PropIndex(prop_.GetId()); + if (pos >= 0) + { + d4_assert(NthHandler(pos).Property().Type() == prop_.Type()); + return pos; + } + + c4_Handler* h = CreateHandler(prop_); + d4_assert(h != 0); + + int i = AddHandler(h); + if (i >= 0 && NumRows() > 0) + { + c4_Bytes data; + h->ClearBytes(data); + h->Insert(0, data, NumRows()); + } + + return i; +} + +const char* c4_Sequence::Description() +{ + return 0; +} + +int c4_Sequence::ItemSize(int index_, int propId_) +{ + int colNum = PropIndex(propId_); + return colNum >= 0 ? NthHandler(colNum).ItemSize(index_) : -1; +} + +bool c4_Sequence::Get(int index_, int propId_, c4_Bytes& buf_) +{ + int colNum = PropIndex(propId_); + if (colNum < 0) + return false; + + NthHandler(colNum).GetBytes(index_, buf_); + return true; +} + +void c4_Sequence::Set(int index_, const c4_Property& prop_, const c4_Bytes& buf_) +{ + int colNum = PropIndex(prop_); + d4_assert(colNum >= 0); + + c4_Handler& h = NthHandler(colNum); + + c4_Notifier change (this); + if (GetDependencies()) + change.StartSet(index_, prop_.GetId(), buf_); + + if (buf_.Size()) + h.Set(index_, buf_); + else + { + c4_Bytes empty; + h.ClearBytes(empty); + h.Set(index_, empty); + } +} + + /// Register a sequence to receive change notifications +void c4_Sequence::Attach(c4_Sequence* child_) +{ + IncRef(); + + if (!_dependencies) + _dependencies = d4_new c4_Dependencies; + + _dependencies->Add(child_); +} + + /// Unregister a sequence which received change notifications +void c4_Sequence::Detach(c4_Sequence* child_) +{ + d4_assert(_dependencies != 0); + + if (!_dependencies->Remove(child_)) + { + delete _dependencies; + _dependencies = 0; + } + + DecRef(); +} + + /// Called just before a change is made to the sequence +c4_Notifier* c4_Sequence::PreChange(c4_Notifier&) +{ + d4_assert(0); // should not be called, because it should not attach + return 0; +} + + /// Called after changes have been made to the sequence +void c4_Sequence::PostChange(c4_Notifier&) +{ +} + +///////////////////////////////////////////////////////////////////////////// + +c4_Reference& c4_Reference::operator= (const c4_Reference& value_) +{ + c4_Bytes result; + value_.GetData(result); + SetData(result); + + return *this; +} + +bool operator== (const c4_Reference& a_, const c4_Reference& b_) +{ + c4_Bytes buf1; + bool f1 = a_.GetData(buf1); + + c4_Bytes buf2; + bool f2 = b_.GetData(buf2); + + // if absent, fill either with zero bytes to match length + if (!f1) + buf1.SetBufferClear(buf2.Size()); + if (!f2) + buf2.SetBufferClear(buf1.Size()); + + return buf1 == buf2; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_IntRef::operator t4_i32 () const +{ + c4_Bytes result; + if (!GetData(result)) + return 0; + + d4_assert(result.Size() == sizeof (t4_i32)); + return *(const t4_i32*) result.Contents(); +} + +c4_IntRef& c4_IntRef::operator= (t4_i32 value_) +{ + SetData(c4_Bytes (&value_, sizeof value_)); + return *this; +} + +///////////////////////////////////////////////////////////////////////////// +#if !q4_TINY +///////////////////////////////////////////////////////////////////////////// + +c4_LongRef::operator t4_i64 () const +{ + c4_Bytes result; + if (!GetData(result)) + { + static t4_i64 zero; + return zero; + } + + d4_assert(result.Size() == sizeof (t4_i64)); + return *(const t4_i64*) result.Contents(); +} + +c4_LongRef& c4_LongRef::operator= (t4_i64 value_) +{ + SetData(c4_Bytes (&value_, sizeof value_)); + return *this; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_FloatRef::operator double () const +{ + c4_Bytes result; + if (!GetData(result)) + return 0; + + d4_assert(result.Size() == sizeof (float)); + return *(const float*) result.Contents(); +} + +c4_FloatRef& c4_FloatRef::operator= (double value_) +{ + float v = (float) value_; // loses precision + SetData(c4_Bytes (&v, sizeof v)); + return *this; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_DoubleRef::operator double () const +{ + c4_Bytes result; + if (!GetData(result)) + return 0; + + d4_assert(result.Size() == sizeof (double)); + return *(const double*) result.Contents(); +} + +c4_DoubleRef& c4_DoubleRef::operator= (double value_) +{ + SetData(c4_Bytes (&value_, sizeof value_)); + return *this; +} + +///////////////////////////////////////////////////////////////////////////// +#endif // !q4_TINY +///////////////////////////////////////////////////////////////////////////// + +c4_BytesRef::operator c4_Bytes () const +{ + c4_Bytes result; + GetData(result); + + // the result must immediately be used, its lifetime may be limited + return result; +} + +c4_BytesRef& c4_BytesRef::operator= (const c4_Bytes& value_) +{ + SetData(value_); + return *this; +} + +c4_Bytes c4_BytesRef::Access(t4_i32 off_, int len_) const +{ + c4_Bytes& buffer = _cursor._seq->Buffer(); + + int colNum = _cursor._seq->PropIndex(_property.GetId()); + if (colNum >= 0) + { + c4_Handler& h = _cursor._seq->NthHandler(colNum); + int sz = h.ItemSize(_cursor._index); + if (len_ == 0 || off_ + len_ > sz) + len_ = sz - off_; + + c4_Column* col = h.GetNthMemoCol(_cursor._index, true); + if (col != 0) + { + + if (len_ > 0) { + col->FetchBytes(off_, len_, buffer, true); + return buffer; + } + } + else // do it the hard way for custom/mapped views (2002-03-13) + { + c4_Bytes result; + GetData(result); + d4_assert(off_ + len_ <= result.Size()); + return c4_Bytes (result.Contents() + off_, len_, true); + } + } + + return c4_Bytes (); +} + +bool c4_BytesRef::Modify(const c4_Bytes& buf_, t4_i32 off_, int diff_) const +{ + int colNum = _cursor._seq->PropIndex(_property.GetId()); + if (colNum >= 0) + { + c4_Handler& h = _cursor._seq->NthHandler(colNum); + const int n = buf_.Size(); + const t4_i32 limit = off_ + n; // past changed bytes + const t4_i32 overshoot = limit - h.ItemSize(_cursor._index); + + if (diff_ < overshoot) + diff_ = overshoot; + + c4_Column* col = h.GetNthMemoCol(_cursor._index, true); + if (col != 0) + { + if (diff_ < 0) + col->Shrink(limit, - diff_); + else if (diff_ > 0) + // insert bytes in the highest possible spot + // if a gap is created, it will contain garbage + col->Grow(overshoot > 0 ? col->ColSize() : + diff_ > n ? off_ : limit - diff_, diff_); + + col->StoreBytes(off_, buf_); + } + else // do it the hard way for custom/mapped views (2002-03-13) + { + c4_Bytes orig; + GetData(orig); + + c4_Bytes result; + t4_byte* ptr = result.SetBuffer(orig.Size() + diff_); + + memcpy(ptr, orig.Contents(), off_); + memcpy(ptr + off_, buf_.Contents(), n); + memcpy(ptr + off_ + n, orig.Contents() + off_, orig.Size() - off_); + + SetData(result); + } + return true; + } + + return false; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_StringRef::operator const char* () const +{ + c4_Bytes result; + GetData(result); + + return result.Size() > 0 ? (const char*) result.Contents() : ""; +} + +c4_StringRef& c4_StringRef::operator= (const char* value_) +{ + SetData(c4_Bytes (value_, strlen(value_) + 1)); + return *this; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_ViewRef::operator c4_View () const +{ + c4_Bytes result; + if (!GetData(result)) + return (c4_Sequence*) 0; // resolve ambiguity + + d4_assert(result.Size() == sizeof (c4_Sequence*)); + return *(c4_Sequence* const*) result.Contents(); +} + +c4_ViewRef& c4_ViewRef::operator= (const c4_View& value_) +{ + SetData(c4_Bytes (&value_._seq, sizeof value_._seq)); + return *this; +} + +///////////////////////////////////////////////////////////////////////////// + +c4_Stream::~c4_Stream () +{ +} + +///////////////////////////////////////////////////////////////////////////// + +c4_Strategy::c4_Strategy () + : _bytesFlipped (false), _failure (0), + _mapStart (0), _dataSize (0), _baseOffset (0), _rootPos (-1), _rootLen (-1) +{ +} + +c4_Strategy::~c4_Strategy () +{ + d4_assert(_mapStart == 0); +} + + /// Read a number of bytes +int c4_Strategy::DataRead(t4_i32, void*, int) +{ +/* + if (_mapStart != 0 && pos_ + length_ <= _dataSize) + { + memcpy(buffer_, _mapStart + pos_, length_); + return length_; + } +*/ + ++_failure; + return -1; +} + + /// Write a number of bytes, return true if successful +void c4_Strategy::DataWrite(t4_i32, const void*, int) +{ + ++_failure; +} + + /// Flush and truncate file +void c4_Strategy::DataCommit(t4_i32) +{ +} + + /// Override to support memory-mapped files +void c4_Strategy::ResetFileMapping() +{ +} + + /// Report total size of the datafile +t4_i32 c4_Strategy::FileSize() +{ + return _dataSize; +} + + /// Return a value to use as fresh generation counter +t4_i32 c4_Strategy::FreshGeneration() +{ + return 1; +} + + /// Define the base offset where data is stored +void c4_Strategy::SetBase(t4_i32 base_) +{ + t4_i32 off = base_ - _baseOffset; + _baseOffset = base_; + _dataSize -= off; + if (_mapStart != 0) + _mapStart += off; +} + +/* + end_ is file position to start from (0 defaults to FileSize()) + + result is the logical end of the datafile (or -1 if no data) + + This code uses a tiny state machine so all the code to read and decode + file marks is in one place within the loop. +*/ + + /// Scan datafile head/tail markers, return logical end of data +t4_i32 c4_Strategy::EndOfData(t4_i32 end_) +{ + enum { kStateAtEnd, kStateCommit, kStateHead, kStateOld, kStateDone }; + + t4_i32 pos = (end_ >= 0 ? end_ : FileSize()) - _baseOffset; + t4_i32 last = pos; + t4_i32 rootPos = 0; + t4_i32 rootLen = -1; // impossible value, flags old-style header + t4_byte mark [8]; + + for (int state = kStateAtEnd; state != kStateDone; ) + { + pos -= 8; + if (pos + _baseOffset < 0 && state != kStateOld) + { + // bad offset, try old-style header from start of file + pos = - _baseOffset; + state = kStateOld; + } + + if (DataRead(pos, &mark, sizeof mark) != sizeof mark) + return -1; + + t4_i32 count = 0; + for (int i = 1; i < 4; ++i) + count = (count << 8) + mark[i]; + + t4_i32 offset = 0; + for (int j = 4; j < 8; ++j) + offset = (offset << 8) + mark[j]; + + const bool isSkipTail = mark[0] == 0x80 && count == 0 && offset > 0; + const bool isCommitTail = mark[0] == 0x80 && count > 0 && offset > 0; + const bool isHeader = (mark[0] == 'J' || mark[0] == 'L') && + (mark[0] ^ mark[1]) == ('J' ^ 'L') && + mark[2] == 0x1A; + switch (state) + { + case kStateAtEnd: // no commit tail found yet + + if (isSkipTail) + { + pos -= offset; + last = pos; + } + else if (isCommitTail) + { + rootPos = offset; + rootLen = count; + state = kStateCommit; + } + else + { + pos = 8; + state = kStateOld; + } + break; + + case kStateCommit: // commit tail must be preceded by skip tail + + if (!isSkipTail) + return -1; + pos -= offset - 8; + state = kStateHead; + break; + + case kStateHead: // fetch the header + + if (!isHeader) + { + pos = 8; + state = kStateOld; + } + else + { + state = kStateDone; + } + break; + + case kStateOld: // old format, look for header in first 4 Kb + + if (isHeader && mark[3] == 0x80) + { + d4_assert(rootPos == 0); + for (int k = 8; --k >= 4; ) // old header is little-endian + rootPos = (rootPos << 8) + mark[k]; + state = kStateDone; + } + else + { + pos += 16; + if (pos > 4096) + return -1; + } + break; + } + } + + last += _baseOffset; // all seeks were relative to current offset + + if (end_ >= 0) // if end was specified, then adjust this strategy object + { + _baseOffset += pos; + d4_assert(_baseOffset >= 0); + if (_mapStart != 0) + { + _mapStart += pos; + _dataSize -= pos; + } + + _rootPos = rootPos; + _rootLen = rootLen; + } + + d4_assert(mark[0] == 'J' || mark[1] == 'J'); + _bytesFlipped = (char) *(const short*) mark != 'J'; + + return last; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/akregator/src/mk4storage/metakit/src/win.h b/akregator/src/mk4storage/metakit/src/win.h new file mode 100644 index 000000000..d27eb2445 --- /dev/null +++ b/akregator/src/mk4storage/metakit/src/win.h @@ -0,0 +1,33 @@ +// win.h -- +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +/** @file + * Configuration header for Windows builds + */ + +#if defined (_MSDOS) +#define q4_DOS 1 +#endif + +#if defined (_WINDOWS) +#define q4_WIN 1 +#endif + +#if defined (_WIN32) +#define q4_WIN32 1 +#endif + +#if defined (_WIN32_WCE) // check for Win CE +#define q4_WINCE 1 +#define q4_WIN32 1 +#endif + +#if q4_WIN32 // WIN32 implies WIN +#undef q4_WIN +#define q4_WIN 1 +#endif + +#if q4_WIN // WIN implies not DOS, even for Win3 +#undef q4_DOS +#endif diff --git a/akregator/src/mk4storage/metakit/tests/ok/b00.txt b/akregator/src/mk4storage/metakit/tests/ok/b00.txt new file mode 100644 index 000000000..6a37cfb5c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b00.txt @@ -0,0 +1,3 @@ +>>> Should fail +*** Failed: A(false) *** +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b01.txt b/akregator/src/mk4storage/metakit/tests/ok/b01.txt new file mode 100644 index 000000000..814999fb1 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b01.txt @@ -0,0 +1,2 @@ +>>> Should succeed +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b02.txt b/akregator/src/mk4storage/metakit/tests/ok/b02.txt new file mode 100644 index 000000000..ac0e86f67 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b02.txt @@ -0,0 +1,2 @@ +>>> Int property +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b03.txt b/akregator/src/mk4storage/metakit/tests/ok/b03.txt new file mode 100644 index 000000000..7f337457e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b03.txt @@ -0,0 +1,2 @@ +>>> Float property +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b04.txt b/akregator/src/mk4storage/metakit/tests/ok/b04.txt new file mode 100644 index 000000000..741c5e87d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b04.txt @@ -0,0 +1,2 @@ +>>> String property +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b05.txt b/akregator/src/mk4storage/metakit/tests/ok/b05.txt new file mode 100644 index 000000000..3abc4fc98 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b05.txt @@ -0,0 +1,2 @@ +>>> View property +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b06.txt b/akregator/src/mk4storage/metakit/tests/ok/b06.txt new file mode 100644 index 000000000..67a3a4402 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b06.txt @@ -0,0 +1,2 @@ +>>> View construction +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b07.txt b/akregator/src/mk4storage/metakit/tests/ok/b07.txt new file mode 100644 index 000000000..05bd95f60 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b07.txt @@ -0,0 +1,2 @@ +>>> Row manipulation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b08.txt b/akregator/src/mk4storage/metakit/tests/ok/b08.txt new file mode 100644 index 000000000..1d6cd6e10 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b08.txt @@ -0,0 +1,2 @@ +>>> Row expressions +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b09.txt b/akregator/src/mk4storage/metakit/tests/ok/b09.txt new file mode 100644 index 000000000..6f3c20ddb --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b09.txt @@ -0,0 +1,2 @@ +>>> View manipulation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b10.txt b/akregator/src/mk4storage/metakit/tests/ok/b10.txt new file mode 100644 index 000000000..55c9a3aac --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b10.txt @@ -0,0 +1,2 @@ +>>> View sorting +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b11.txt b/akregator/src/mk4storage/metakit/tests/ok/b11.txt new file mode 100644 index 000000000..16c5a04a1 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b11.txt @@ -0,0 +1,2 @@ +>>> View selection +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b12.txt b/akregator/src/mk4storage/metakit/tests/ok/b12.txt new file mode 100644 index 000000000..93e30ce6f --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b12.txt @@ -0,0 +1,2 @@ +>>> Add after remove +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b13.txt b/akregator/src/mk4storage/metakit/tests/ok/b13.txt new file mode 100644 index 000000000..d1a9a9b8e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b13.txt @@ -0,0 +1,2 @@ +>>> Clear view entry +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b14.txt b/akregator/src/mk4storage/metakit/tests/ok/b14.txt new file mode 100644 index 000000000..f166c430c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b14.txt @@ -0,0 +1,2 @@ +>>> Empty view outlives temp storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b15.txt b/akregator/src/mk4storage/metakit/tests/ok/b15.txt new file mode 100644 index 000000000..595ca0eb1 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b15.txt @@ -0,0 +1,2 @@ +>>> View outlives temp storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b16.txt b/akregator/src/mk4storage/metakit/tests/ok/b16.txt new file mode 100644 index 000000000..fb43bbf9d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b16.txt @@ -0,0 +1,2 @@ +>>> View outlives cleared temp storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b17.txt b/akregator/src/mk4storage/metakit/tests/ok/b17.txt new file mode 100644 index 000000000..0c61591bb --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b17.txt @@ -0,0 +1,2 @@ +>>> Double property +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b18.txt b/akregator/src/mk4storage/metakit/tests/ok/b18.txt new file mode 100644 index 000000000..e9ff0b495 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b18.txt @@ -0,0 +1,2 @@ +>>> SetAtGrow usage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b19.txt b/akregator/src/mk4storage/metakit/tests/ok/b19.txt new file mode 100644 index 000000000..99c176c63 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b19.txt @@ -0,0 +1,2 @@ +>>> Bytes property +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b20.txt b/akregator/src/mk4storage/metakit/tests/ok/b20.txt new file mode 100644 index 000000000..849ebf898 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b20.txt @@ -0,0 +1,2 @@ +>>> Search sorted view +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b21.txt b/akregator/src/mk4storage/metakit/tests/ok/b21.txt new file mode 100644 index 000000000..33cc19d26 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b21.txt @@ -0,0 +1,2 @@ +>>> Memo property +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b22.txt b/akregator/src/mk4storage/metakit/tests/ok/b22.txt new file mode 100644 index 000000000..c7612a0b9 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b22.txt @@ -0,0 +1,2 @@ +>>> Stored view references +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b23.txt b/akregator/src/mk4storage/metakit/tests/ok/b23.txt new file mode 100644 index 000000000..d8967bf62 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b23.txt @@ -0,0 +1,2 @@ +>>> Sort comparison fix +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b24.txt b/akregator/src/mk4storage/metakit/tests/ok/b24.txt new file mode 100644 index 000000000..dbf75a5c9 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b24.txt @@ -0,0 +1,2 @@ +>>> Custom view comparisons +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b25.txt b/akregator/src/mk4storage/metakit/tests/ok/b25.txt new file mode 100644 index 000000000..ab01b4fcc --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b25.txt @@ -0,0 +1,2 @@ +>>> Copy row from derived +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b26.txt b/akregator/src/mk4storage/metakit/tests/ok/b26.txt new file mode 100644 index 000000000..7fd6a5d37 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b26.txt @@ -0,0 +1,2 @@ +>>> Partial memo field access +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/b27.txt b/akregator/src/mk4storage/metakit/tests/ok/b27.txt new file mode 100644 index 000000000..156a2c92c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/b27.txt @@ -0,0 +1,2 @@ +>>> Copy value to another row +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c01.txt b/akregator/src/mk4storage/metakit/tests/ok/c01.txt new file mode 100644 index 000000000..ce7ebb77c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c01.txt @@ -0,0 +1,2 @@ +>>> Slice forward +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c02.txt b/akregator/src/mk4storage/metakit/tests/ok/c02.txt new file mode 100644 index 000000000..50b88f0f2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c02.txt @@ -0,0 +1,2 @@ +>>> Slice backward +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c03.txt b/akregator/src/mk4storage/metakit/tests/ok/c03.txt new file mode 100644 index 000000000..4feea348b --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c03.txt @@ -0,0 +1,2 @@ +>>> Slice reverse +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c04.txt b/akregator/src/mk4storage/metakit/tests/ok/c04.txt new file mode 100644 index 000000000..64bf550a2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c04.txt @@ -0,0 +1,2 @@ +>>> Cartesian product +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c05.txt b/akregator/src/mk4storage/metakit/tests/ok/c05.txt new file mode 100644 index 000000000..7fae13ec4 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c05.txt @@ -0,0 +1,2 @@ +>>> Remapping +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c06.txt b/akregator/src/mk4storage/metakit/tests/ok/c06.txt new file mode 100644 index 000000000..520d9f71c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c06.txt @@ -0,0 +1,2 @@ +>>> Pairwise combination +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c07.txt b/akregator/src/mk4storage/metakit/tests/ok/c07.txt new file mode 100644 index 000000000..169aa5052 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c07.txt @@ -0,0 +1,2 @@ +>>> Concatenate views +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c08.txt b/akregator/src/mk4storage/metakit/tests/ok/c08.txt new file mode 100644 index 000000000..773e1e52a --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c08.txt @@ -0,0 +1,2 @@ +>>> Rename property +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c09.txt b/akregator/src/mk4storage/metakit/tests/ok/c09.txt new file mode 100644 index 000000000..2d577394d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c09.txt @@ -0,0 +1,2 @@ +>>> GroupBy operation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c10.txt b/akregator/src/mk4storage/metakit/tests/ok/c10.txt new file mode 100644 index 000000000..ddb98fef9 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c10.txt @@ -0,0 +1,2 @@ +>>> Counts operation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c11.txt b/akregator/src/mk4storage/metakit/tests/ok/c11.txt new file mode 100644 index 000000000..6d70cd878 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c11.txt @@ -0,0 +1,2 @@ +>>> Unique operation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c12.txt b/akregator/src/mk4storage/metakit/tests/ok/c12.txt new file mode 100644 index 000000000..d66e764c9 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c12.txt @@ -0,0 +1,2 @@ +>>> Union operation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c13.txt b/akregator/src/mk4storage/metakit/tests/ok/c13.txt new file mode 100644 index 000000000..14f1e9721 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c13.txt @@ -0,0 +1,2 @@ +>>> Intersect operation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c14.txt b/akregator/src/mk4storage/metakit/tests/ok/c14.txt new file mode 100644 index 000000000..3edcec0b4 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c14.txt @@ -0,0 +1,2 @@ +>>> Different operation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c15.txt b/akregator/src/mk4storage/metakit/tests/ok/c15.txt new file mode 100644 index 000000000..c827c757a --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c15.txt @@ -0,0 +1,2 @@ +>>> Minus operation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c16.txt b/akregator/src/mk4storage/metakit/tests/ok/c16.txt new file mode 100644 index 000000000..55d9f6990 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c16.txt @@ -0,0 +1,2 @@ +>>> View comparisons +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c17.txt b/akregator/src/mk4storage/metakit/tests/ok/c17.txt new file mode 100644 index 000000000..cd2ac75e4 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c17.txt @@ -0,0 +1,2 @@ +>>> Join operation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c18.txt b/akregator/src/mk4storage/metakit/tests/ok/c18.txt new file mode 100644 index 000000000..dfdd45a89 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c18.txt @@ -0,0 +1,2 @@ +>>> Groupby sort fix +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c19.txt b/akregator/src/mk4storage/metakit/tests/ok/c19.txt new file mode 100644 index 000000000..469df00aa --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c19.txt @@ -0,0 +1,2 @@ +>>> JoinProp operation +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c20.txt b/akregator/src/mk4storage/metakit/tests/ok/c20.txt new file mode 100644 index 000000000..cea0b6516 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c20.txt @@ -0,0 +1,2 @@ +>>> Wide cartesian product +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c21.txt b/akregator/src/mk4storage/metakit/tests/ok/c21.txt new file mode 100644 index 000000000..679055b9c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c21.txt @@ -0,0 +1,2 @@ +>>> Join on compound key +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/c22.txt b/akregator/src/mk4storage/metakit/tests/ok/c22.txt new file mode 100644 index 000000000..1646d1a5d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/c22.txt @@ -0,0 +1,2 @@ +>>> Groupby with selection +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/d01.txt b/akregator/src/mk4storage/metakit/tests/ok/d01.txt new file mode 100644 index 000000000..46092d8c7 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/d01.txt @@ -0,0 +1,2 @@ +>>> Commit aside +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/d01a.txt b/akregator/src/mk4storage/metakit/tests/ok/d01a.txt new file mode 100644 index 000000000..fb8a3f195 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/d01a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/d01b.txt b/akregator/src/mk4storage/metakit/tests/ok/d01b.txt new file mode 100644 index 000000000..1440d4ebb --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/d01b.txt @@ -0,0 +1,19 @@ + VIEW 1 rows = _C:V + 0: subview '_C' + VIEW 4 rows = _O:I _D:V + 0: 8 + 0: subview '_D' + VIEW 1 rows = _K:I _R:I _B:B + 0: 0 0 (4b) + 1: 0 + 1: subview '_D' + VIEW 1 rows = _K:I _R:I _B:B + 0: 0 0 (5b) + 2: 0 + 2: subview '_D' + VIEW 1 rows = _K:I _R:I _B:B + 0: 0 0 (13b) + 3: 0 + 3: subview '_D' + VIEW 1 rows = _K:I _R:I _B:B + 0: 0 0 (13b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/e01.txt b/akregator/src/mk4storage/metakit/tests/ok/e01.txt new file mode 100644 index 000000000..665b9367d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e01.txt @@ -0,0 +1,2 @@ +>>> Extend new file +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/e01a.txt b/akregator/src/mk4storage/metakit/tests/ok/e01a.txt new file mode 100644 index 000000000..4f2b75602 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e01a.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 2 rows = p1:I + 0: 123 + 1: 456 diff --git a/akregator/src/mk4storage/metakit/tests/ok/e02.txt b/akregator/src/mk4storage/metakit/tests/ok/e02.txt new file mode 100644 index 000000000..6dd7e4e44 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e02.txt @@ -0,0 +1,2 @@ +>>> Extend committing twice +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/e02a.txt b/akregator/src/mk4storage/metakit/tests/ok/e02a.txt new file mode 100644 index 000000000..4f2b75602 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e02a.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 2 rows = p1:I + 0: 123 + 1: 456 diff --git a/akregator/src/mk4storage/metakit/tests/ok/e03.txt b/akregator/src/mk4storage/metakit/tests/ok/e03.txt new file mode 100644 index 000000000..8d58f9062 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e03.txt @@ -0,0 +1,2 @@ +>>> Read during extend +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/e03a.txt b/akregator/src/mk4storage/metakit/tests/ok/e03a.txt new file mode 100644 index 000000000..4f2b75602 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e03a.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 2 rows = p1:I + 0: 123 + 1: 456 diff --git a/akregator/src/mk4storage/metakit/tests/ok/e04.txt b/akregator/src/mk4storage/metakit/tests/ok/e04.txt new file mode 100644 index 000000000..c5ab0c727 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e04.txt @@ -0,0 +1,2 @@ +>>> Extend during read +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/e04a.txt b/akregator/src/mk4storage/metakit/tests/ok/e04a.txt new file mode 100644 index 000000000..2f613d763 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e04a.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 2 rows = p1:I + 0: 123 + 1: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/e05.txt b/akregator/src/mk4storage/metakit/tests/ok/e05.txt new file mode 100644 index 000000000..9314db303 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e05.txt @@ -0,0 +1,2 @@ +>>> Test memory mapping +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/e05a.txt b/akregator/src/mk4storage/metakit/tests/ok/e05a.txt new file mode 100644 index 000000000..a28a7cae2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e05a.txt @@ -0,0 +1 @@ + VIEW 1 rows = diff --git a/akregator/src/mk4storage/metakit/tests/ok/e06.txt b/akregator/src/mk4storage/metakit/tests/ok/e06.txt new file mode 100644 index 000000000..62dc3218f --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e06.txt @@ -0,0 +1,2 @@ +>>> Rollback during extend +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/e06a.txt b/akregator/src/mk4storage/metakit/tests/ok/e06a.txt new file mode 100644 index 000000000..4f2b75602 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/e06a.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 2 rows = p1:I + 0: 123 + 1: 456 diff --git a/akregator/src/mk4storage/metakit/tests/ok/f01.txt b/akregator/src/mk4storage/metakit/tests/ok/f01.txt new file mode 100644 index 000000000..412c99b76 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f01.txt @@ -0,0 +1,2 @@ +>>> Add view to format +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f01a.txt b/akregator/src/mk4storage/metakit/tests/ok/f01a.txt new file mode 100644 index 000000000..acb76114d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f01a.txt @@ -0,0 +1,8 @@ + VIEW 1 rows = a:V b:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 + 0: subview 'b' + VIEW 2 rows = p2:I + 0: 345 + 1: 567 diff --git a/akregator/src/mk4storage/metakit/tests/ok/f02.txt b/akregator/src/mk4storage/metakit/tests/ok/f02.txt new file mode 100644 index 000000000..8ed593070 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f02.txt @@ -0,0 +1,2 @@ +>>> Remove view from format +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f02a.txt b/akregator/src/mk4storage/metakit/tests/ok/f02a.txt new file mode 100644 index 000000000..700609bef --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f02a.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = b:V + 0: subview 'b' + VIEW 2 rows = p2:I + 0: 345 + 1: 567 diff --git a/akregator/src/mk4storage/metakit/tests/ok/f03.txt b/akregator/src/mk4storage/metakit/tests/ok/f03.txt new file mode 100644 index 000000000..461a5b7dc --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f03.txt @@ -0,0 +1,2 @@ +>>> Rollback format change +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f03a.txt b/akregator/src/mk4storage/metakit/tests/ok/f03a.txt new file mode 100644 index 000000000..fb8a3f195 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f03a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/f04.txt b/akregator/src/mk4storage/metakit/tests/ok/f04.txt new file mode 100644 index 000000000..237a42f23 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f04.txt @@ -0,0 +1,2 @@ +>>> Rearrange format +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f04a.txt b/akregator/src/mk4storage/metakit/tests/ok/f04a.txt new file mode 100644 index 000000000..08b06c501 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f04a.txt @@ -0,0 +1,8 @@ + VIEW 1 rows = b:V a:V + 0: subview 'b' + VIEW 2 rows = p2:I + 0: 345 + 1: 567 + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/f05.txt b/akregator/src/mk4storage/metakit/tests/ok/f05.txt new file mode 100644 index 000000000..f9fac025e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f05.txt @@ -0,0 +1,2 @@ +>>> Nested reformat +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f05a.txt b/akregator/src/mk4storage/metakit/tests/ok/f05a.txt new file mode 100644 index 000000000..2f3891813 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f05a.txt @@ -0,0 +1,8 @@ + VIEW 1 rows = a:V b:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 + 0: subview 'b' + VIEW 2 rows = p1:I p2:I + 0: 543 345 + 1: 765 567 diff --git a/akregator/src/mk4storage/metakit/tests/ok/f06.txt b/akregator/src/mk4storage/metakit/tests/ok/f06.txt new file mode 100644 index 000000000..039caebe6 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f06.txt @@ -0,0 +1,2 @@ +>>> Flip foreign data +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f07.txt b/akregator/src/mk4storage/metakit/tests/ok/f07.txt new file mode 100644 index 000000000..bf52b37b8 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f07.txt @@ -0,0 +1,2 @@ +>>> Automatic structure info (obsolete) +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f07a.txt b/akregator/src/mk4storage/metakit/tests/ok/f07a.txt new file mode 100644 index 000000000..79963d7b4 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f07a.txt @@ -0,0 +1,3 @@ + VIEW 1 rows = dict:V + 0: subview 'dict' + VIEW 0 rows = parent:I index:I view:V diff --git a/akregator/src/mk4storage/metakit/tests/ok/f08.txt b/akregator/src/mk4storage/metakit/tests/ok/f08.txt new file mode 100644 index 000000000..d4e88f89a --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f08.txt @@ -0,0 +1,2 @@ +>>> Automatic storage format +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f08a.txt b/akregator/src/mk4storage/metakit/tests/ok/f08a.txt new file mode 100644 index 000000000..7a56c7fcf --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f08a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = dict:V + 0: subview 'dict' + VIEW 3 rows = p1:S p2:S + 0: 'One' 'Two' + 1: '' '' + 2: 'One' 'Two' diff --git a/akregator/src/mk4storage/metakit/tests/ok/f09.txt b/akregator/src/mk4storage/metakit/tests/ok/f09.txt new file mode 100644 index 000000000..d1040e7ff --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f09.txt @@ -0,0 +1,2 @@ +>>> Partial restructuring +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f09a.txt b/akregator/src/mk4storage/metakit/tests/ok/f09a.txt new file mode 100644 index 000000000..c26f86755 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f09a.txt @@ -0,0 +1,13 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 10 rows = p1:I p2:I p3:I + 0: 1000 2000 3000 + 1: 1001 0 0 + 2: 1002 2002 0 + 3: 1003 0 3003 + 4: 1004 2004 0 + 5: 1005 0 0 + 6: 1006 2006 3006 + 7: 1007 0 0 + 8: 1008 2008 0 + 9: 1009 0 3009 diff --git a/akregator/src/mk4storage/metakit/tests/ok/f10.txt b/akregator/src/mk4storage/metakit/tests/ok/f10.txt new file mode 100644 index 000000000..848dbdddc --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f10.txt @@ -0,0 +1,2 @@ +>>> Committed restructuring +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f10a.txt b/akregator/src/mk4storage/metakit/tests/ok/f10a.txt new file mode 100644 index 000000000..c26f86755 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f10a.txt @@ -0,0 +1,13 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 10 rows = p1:I p2:I p3:I + 0: 1000 2000 3000 + 1: 1001 0 0 + 2: 1002 2002 0 + 3: 1003 0 3003 + 4: 1004 2004 0 + 5: 1005 0 0 + 6: 1006 2006 3006 + 7: 1007 0 0 + 8: 1008 2008 0 + 9: 1009 0 3009 diff --git a/akregator/src/mk4storage/metakit/tests/ok/f11.txt b/akregator/src/mk4storage/metakit/tests/ok/f11.txt new file mode 100644 index 000000000..583ec58ae --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f11.txt @@ -0,0 +1,2 @@ +>>> Delete missing view +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/f11a.txt b/akregator/src/mk4storage/metakit/tests/ok/f11a.txt new file mode 100644 index 000000000..a28a7cae2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/f11a.txt @@ -0,0 +1 @@ + VIEW 1 rows = diff --git a/akregator/src/mk4storage/metakit/tests/ok/l00.txt b/akregator/src/mk4storage/metakit/tests/ok/l00.txt new file mode 100644 index 000000000..b94a9a630 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l00.txt @@ -0,0 +1,2 @@ +>>> Lots of properties +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/l00a.txt b/akregator/src/mk4storage/metakit/tests/ok/l00a.txt new file mode 100644 index 000000000..bb0f5c661 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l00a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I p2:I p3:I p4:I p5:I p6:I p7:I p8:I p9:I p10:I p11:I p12:I p13:I p14:I p15:I p16:I p17:I p18:I p19:I p20:I p21:I p22:I p23:I p24:I p25:I p26:I p27:I p28:I p29:I p30:I p31:I p32:I p33:I p34:I p35:I p36:I p37:I p38:I p39:I p40:I p41:I p42:I p43:I p44:I p45:I p46:I p47:I p48:I p49:I p50:I p51:I p52:I p53:I p54:I p55:I p56:I p57:I p58:I p59:I p60:I p61:I p62:I p63:I p64:I p65:I p66:I p67:I p68:I p69:I p70:I p71:I p72:I p73:I p74:I p75:I p76:I p77:I p78:I p79:I p80:I p81:I p82:I p83:I p84:I p85:I p86:I p87:I p88:I p89:I p90:I p91:I p92:I p93:I p94:I p95:I p96:I p97:I p98:I p99:I p100:I p101:I p102:I p103:I p104:I p105:I p106:I p107:I p108:I p109:I p110:I p111:I p112:I p113:I p114:I p115:I p116:I p117:I p118:I p119:I p120:I p121:I p122:I p123:I p124:I p125:I p126:I p127:I p128:I p129:I p130:I p131:I p132:I p133:I p134:I p135:I p136:I p137:I p138:I p139:I p140:I p141:I p142:I p143:I p144:I p145:I p146:I p147:I p148:I p149:I + 0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 123 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/akregator/src/mk4storage/metakit/tests/ok/l01.txt b/akregator/src/mk4storage/metakit/tests/ok/l01.txt new file mode 100644 index 000000000..842c943de --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l01.txt @@ -0,0 +1,2 @@ +>>> Over 32 Kb of integers +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/l01a.txt b/akregator/src/mk4storage/metakit/tests/ok/l01a.txt new file mode 100644 index 000000000..69cad2436 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l01a.txt @@ -0,0 +1,9003 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 9000 rows = p1:I + 0: 1000000 + 1: 1000001 + 2: 1000002 + 3: 1000003 + 4: 1000004 + 5: 1000005 + 6: 1000006 + 7: 1000007 + 8: 1000008 + 9: 1000009 + 10: 1000010 + 11: 1000011 + 12: 1000012 + 13: 1000013 + 14: 1000014 + 15: 1000015 + 16: 1000016 + 17: 1000017 + 18: 1000018 + 19: 1000019 + 20: 1000020 + 21: 1000021 + 22: 1000022 + 23: 1000023 + 24: 1000024 + 25: 1000025 + 26: 1000026 + 27: 1000027 + 28: 1000028 + 29: 1000029 + 30: 1000030 + 31: 1000031 + 32: 1000032 + 33: 1000033 + 34: 1000034 + 35: 1000035 + 36: 1000036 + 37: 1000037 + 38: 1000038 + 39: 1000039 + 40: 1000040 + 41: 1000041 + 42: 1000042 + 43: 1000043 + 44: 1000044 + 45: 1000045 + 46: 1000046 + 47: 1000047 + 48: 1000048 + 49: 1000049 + 50: 1000050 + 51: 1000051 + 52: 1000052 + 53: 1000053 + 54: 1000054 + 55: 1000055 + 56: 1000056 + 57: 1000057 + 58: 1000058 + 59: 1000059 + 60: 1000060 + 61: 1000061 + 62: 1000062 + 63: 1000063 + 64: 1000064 + 65: 1000065 + 66: 1000066 + 67: 1000067 + 68: 1000068 + 69: 1000069 + 70: 1000070 + 71: 1000071 + 72: 1000072 + 73: 1000073 + 74: 1000074 + 75: 1000075 + 76: 1000076 + 77: 1000077 + 78: 1000078 + 79: 1000079 + 80: 1000080 + 81: 1000081 + 82: 1000082 + 83: 1000083 + 84: 1000084 + 85: 1000085 + 86: 1000086 + 87: 1000087 + 88: 1000088 + 89: 1000089 + 90: 1000090 + 91: 1000091 + 92: 1000092 + 93: 1000093 + 94: 1000094 + 95: 1000095 + 96: 1000096 + 97: 1000097 + 98: 1000098 + 99: 1000099 + 100: 1000100 + 101: 1000101 + 102: 1000102 + 103: 1000103 + 104: 1000104 + 105: 1000105 + 106: 1000106 + 107: 1000107 + 108: 1000108 + 109: 1000109 + 110: 1000110 + 111: 1000111 + 112: 1000112 + 113: 1000113 + 114: 1000114 + 115: 1000115 + 116: 1000116 + 117: 1000117 + 118: 1000118 + 119: 1000119 + 120: 1000120 + 121: 1000121 + 122: 1000122 + 123: 1000123 + 124: 1000124 + 125: 1000125 + 126: 1000126 + 127: 1000127 + 128: 1000128 + 129: 1000129 + 130: 1000130 + 131: 1000131 + 132: 1000132 + 133: 1000133 + 134: 1000134 + 135: 1000135 + 136: 1000136 + 137: 1000137 + 138: 1000138 + 139: 1000139 + 140: 1000140 + 141: 1000141 + 142: 1000142 + 143: 1000143 + 144: 1000144 + 145: 1000145 + 146: 1000146 + 147: 1000147 + 148: 1000148 + 149: 1000149 + 150: 1000150 + 151: 1000151 + 152: 1000152 + 153: 1000153 + 154: 1000154 + 155: 1000155 + 156: 1000156 + 157: 1000157 + 158: 1000158 + 159: 1000159 + 160: 1000160 + 161: 1000161 + 162: 1000162 + 163: 1000163 + 164: 1000164 + 165: 1000165 + 166: 1000166 + 167: 1000167 + 168: 1000168 + 169: 1000169 + 170: 1000170 + 171: 1000171 + 172: 1000172 + 173: 1000173 + 174: 1000174 + 175: 1000175 + 176: 1000176 + 177: 1000177 + 178: 1000178 + 179: 1000179 + 180: 1000180 + 181: 1000181 + 182: 1000182 + 183: 1000183 + 184: 1000184 + 185: 1000185 + 186: 1000186 + 187: 1000187 + 188: 1000188 + 189: 1000189 + 190: 1000190 + 191: 1000191 + 192: 1000192 + 193: 1000193 + 194: 1000194 + 195: 1000195 + 196: 1000196 + 197: 1000197 + 198: 1000198 + 199: 1000199 + 200: 1000200 + 201: 1000201 + 202: 1000202 + 203: 1000203 + 204: 1000204 + 205: 1000205 + 206: 1000206 + 207: 1000207 + 208: 1000208 + 209: 1000209 + 210: 1000210 + 211: 1000211 + 212: 1000212 + 213: 1000213 + 214: 1000214 + 215: 1000215 + 216: 1000216 + 217: 1000217 + 218: 1000218 + 219: 1000219 + 220: 1000220 + 221: 1000221 + 222: 1000222 + 223: 1000223 + 224: 1000224 + 225: 1000225 + 226: 1000226 + 227: 1000227 + 228: 1000228 + 229: 1000229 + 230: 1000230 + 231: 1000231 + 232: 1000232 + 233: 1000233 + 234: 1000234 + 235: 1000235 + 236: 1000236 + 237: 1000237 + 238: 1000238 + 239: 1000239 + 240: 1000240 + 241: 1000241 + 242: 1000242 + 243: 1000243 + 244: 1000244 + 245: 1000245 + 246: 1000246 + 247: 1000247 + 248: 1000248 + 249: 1000249 + 250: 1000250 + 251: 1000251 + 252: 1000252 + 253: 1000253 + 254: 1000254 + 255: 1000255 + 256: 1000256 + 257: 1000257 + 258: 1000258 + 259: 1000259 + 260: 1000260 + 261: 1000261 + 262: 1000262 + 263: 1000263 + 264: 1000264 + 265: 1000265 + 266: 1000266 + 267: 1000267 + 268: 1000268 + 269: 1000269 + 270: 1000270 + 271: 1000271 + 272: 1000272 + 273: 1000273 + 274: 1000274 + 275: 1000275 + 276: 1000276 + 277: 1000277 + 278: 1000278 + 279: 1000279 + 280: 1000280 + 281: 1000281 + 282: 1000282 + 283: 1000283 + 284: 1000284 + 285: 1000285 + 286: 1000286 + 287: 1000287 + 288: 1000288 + 289: 1000289 + 290: 1000290 + 291: 1000291 + 292: 1000292 + 293: 1000293 + 294: 1000294 + 295: 1000295 + 296: 1000296 + 297: 1000297 + 298: 1000298 + 299: 1000299 + 300: 1000300 + 301: 1000301 + 302: 1000302 + 303: 1000303 + 304: 1000304 + 305: 1000305 + 306: 1000306 + 307: 1000307 + 308: 1000308 + 309: 1000309 + 310: 1000310 + 311: 1000311 + 312: 1000312 + 313: 1000313 + 314: 1000314 + 315: 1000315 + 316: 1000316 + 317: 1000317 + 318: 1000318 + 319: 1000319 + 320: 1000320 + 321: 1000321 + 322: 1000322 + 323: 1000323 + 324: 1000324 + 325: 1000325 + 326: 1000326 + 327: 1000327 + 328: 1000328 + 329: 1000329 + 330: 1000330 + 331: 1000331 + 332: 1000332 + 333: 1000333 + 334: 1000334 + 335: 1000335 + 336: 1000336 + 337: 1000337 + 338: 1000338 + 339: 1000339 + 340: 1000340 + 341: 1000341 + 342: 1000342 + 343: 1000343 + 344: 1000344 + 345: 1000345 + 346: 1000346 + 347: 1000347 + 348: 1000348 + 349: 1000349 + 350: 1000350 + 351: 1000351 + 352: 1000352 + 353: 1000353 + 354: 1000354 + 355: 1000355 + 356: 1000356 + 357: 1000357 + 358: 1000358 + 359: 1000359 + 360: 1000360 + 361: 1000361 + 362: 1000362 + 363: 1000363 + 364: 1000364 + 365: 1000365 + 366: 1000366 + 367: 1000367 + 368: 1000368 + 369: 1000369 + 370: 1000370 + 371: 1000371 + 372: 1000372 + 373: 1000373 + 374: 1000374 + 375: 1000375 + 376: 1000376 + 377: 1000377 + 378: 1000378 + 379: 1000379 + 380: 1000380 + 381: 1000381 + 382: 1000382 + 383: 1000383 + 384: 1000384 + 385: 1000385 + 386: 1000386 + 387: 1000387 + 388: 1000388 + 389: 1000389 + 390: 1000390 + 391: 1000391 + 392: 1000392 + 393: 1000393 + 394: 1000394 + 395: 1000395 + 396: 1000396 + 397: 1000397 + 398: 1000398 + 399: 1000399 + 400: 1000400 + 401: 1000401 + 402: 1000402 + 403: 1000403 + 404: 1000404 + 405: 1000405 + 406: 1000406 + 407: 1000407 + 408: 1000408 + 409: 1000409 + 410: 1000410 + 411: 1000411 + 412: 1000412 + 413: 1000413 + 414: 1000414 + 415: 1000415 + 416: 1000416 + 417: 1000417 + 418: 1000418 + 419: 1000419 + 420: 1000420 + 421: 1000421 + 422: 1000422 + 423: 1000423 + 424: 1000424 + 425: 1000425 + 426: 1000426 + 427: 1000427 + 428: 1000428 + 429: 1000429 + 430: 1000430 + 431: 1000431 + 432: 1000432 + 433: 1000433 + 434: 1000434 + 435: 1000435 + 436: 1000436 + 437: 1000437 + 438: 1000438 + 439: 1000439 + 440: 1000440 + 441: 1000441 + 442: 1000442 + 443: 1000443 + 444: 1000444 + 445: 1000445 + 446: 1000446 + 447: 1000447 + 448: 1000448 + 449: 1000449 + 450: 1000450 + 451: 1000451 + 452: 1000452 + 453: 1000453 + 454: 1000454 + 455: 1000455 + 456: 1000456 + 457: 1000457 + 458: 1000458 + 459: 1000459 + 460: 1000460 + 461: 1000461 + 462: 1000462 + 463: 1000463 + 464: 1000464 + 465: 1000465 + 466: 1000466 + 467: 1000467 + 468: 1000468 + 469: 1000469 + 470: 1000470 + 471: 1000471 + 472: 1000472 + 473: 1000473 + 474: 1000474 + 475: 1000475 + 476: 1000476 + 477: 1000477 + 478: 1000478 + 479: 1000479 + 480: 1000480 + 481: 1000481 + 482: 1000482 + 483: 1000483 + 484: 1000484 + 485: 1000485 + 486: 1000486 + 487: 1000487 + 488: 1000488 + 489: 1000489 + 490: 1000490 + 491: 1000491 + 492: 1000492 + 493: 1000493 + 494: 1000494 + 495: 1000495 + 496: 1000496 + 497: 1000497 + 498: 1000498 + 499: 1000499 + 500: 1000500 + 501: 1000501 + 502: 1000502 + 503: 1000503 + 504: 1000504 + 505: 1000505 + 506: 1000506 + 507: 1000507 + 508: 1000508 + 509: 1000509 + 510: 1000510 + 511: 1000511 + 512: 1000512 + 513: 1000513 + 514: 1000514 + 515: 1000515 + 516: 1000516 + 517: 1000517 + 518: 1000518 + 519: 1000519 + 520: 1000520 + 521: 1000521 + 522: 1000522 + 523: 1000523 + 524: 1000524 + 525: 1000525 + 526: 1000526 + 527: 1000527 + 528: 1000528 + 529: 1000529 + 530: 1000530 + 531: 1000531 + 532: 1000532 + 533: 1000533 + 534: 1000534 + 535: 1000535 + 536: 1000536 + 537: 1000537 + 538: 1000538 + 539: 1000539 + 540: 1000540 + 541: 1000541 + 542: 1000542 + 543: 1000543 + 544: 1000544 + 545: 1000545 + 546: 1000546 + 547: 1000547 + 548: 1000548 + 549: 1000549 + 550: 1000550 + 551: 1000551 + 552: 1000552 + 553: 1000553 + 554: 1000554 + 555: 1000555 + 556: 1000556 + 557: 1000557 + 558: 1000558 + 559: 1000559 + 560: 1000560 + 561: 1000561 + 562: 1000562 + 563: 1000563 + 564: 1000564 + 565: 1000565 + 566: 1000566 + 567: 1000567 + 568: 1000568 + 569: 1000569 + 570: 1000570 + 571: 1000571 + 572: 1000572 + 573: 1000573 + 574: 1000574 + 575: 1000575 + 576: 1000576 + 577: 1000577 + 578: 1000578 + 579: 1000579 + 580: 1000580 + 581: 1000581 + 582: 1000582 + 583: 1000583 + 584: 1000584 + 585: 1000585 + 586: 1000586 + 587: 1000587 + 588: 1000588 + 589: 1000589 + 590: 1000590 + 591: 1000591 + 592: 1000592 + 593: 1000593 + 594: 1000594 + 595: 1000595 + 596: 1000596 + 597: 1000597 + 598: 1000598 + 599: 1000599 + 600: 1000600 + 601: 1000601 + 602: 1000602 + 603: 1000603 + 604: 1000604 + 605: 1000605 + 606: 1000606 + 607: 1000607 + 608: 1000608 + 609: 1000609 + 610: 1000610 + 611: 1000611 + 612: 1000612 + 613: 1000613 + 614: 1000614 + 615: 1000615 + 616: 1000616 + 617: 1000617 + 618: 1000618 + 619: 1000619 + 620: 1000620 + 621: 1000621 + 622: 1000622 + 623: 1000623 + 624: 1000624 + 625: 1000625 + 626: 1000626 + 627: 1000627 + 628: 1000628 + 629: 1000629 + 630: 1000630 + 631: 1000631 + 632: 1000632 + 633: 1000633 + 634: 1000634 + 635: 1000635 + 636: 1000636 + 637: 1000637 + 638: 1000638 + 639: 1000639 + 640: 1000640 + 641: 1000641 + 642: 1000642 + 643: 1000643 + 644: 1000644 + 645: 1000645 + 646: 1000646 + 647: 1000647 + 648: 1000648 + 649: 1000649 + 650: 1000650 + 651: 1000651 + 652: 1000652 + 653: 1000653 + 654: 1000654 + 655: 1000655 + 656: 1000656 + 657: 1000657 + 658: 1000658 + 659: 1000659 + 660: 1000660 + 661: 1000661 + 662: 1000662 + 663: 1000663 + 664: 1000664 + 665: 1000665 + 666: 1000666 + 667: 1000667 + 668: 1000668 + 669: 1000669 + 670: 1000670 + 671: 1000671 + 672: 1000672 + 673: 1000673 + 674: 1000674 + 675: 1000675 + 676: 1000676 + 677: 1000677 + 678: 1000678 + 679: 1000679 + 680: 1000680 + 681: 1000681 + 682: 1000682 + 683: 1000683 + 684: 1000684 + 685: 1000685 + 686: 1000686 + 687: 1000687 + 688: 1000688 + 689: 1000689 + 690: 1000690 + 691: 1000691 + 692: 1000692 + 693: 1000693 + 694: 1000694 + 695: 1000695 + 696: 1000696 + 697: 1000697 + 698: 1000698 + 699: 1000699 + 700: 1000700 + 701: 1000701 + 702: 1000702 + 703: 1000703 + 704: 1000704 + 705: 1000705 + 706: 1000706 + 707: 1000707 + 708: 1000708 + 709: 1000709 + 710: 1000710 + 711: 1000711 + 712: 1000712 + 713: 1000713 + 714: 1000714 + 715: 1000715 + 716: 1000716 + 717: 1000717 + 718: 1000718 + 719: 1000719 + 720: 1000720 + 721: 1000721 + 722: 1000722 + 723: 1000723 + 724: 1000724 + 725: 1000725 + 726: 1000726 + 727: 1000727 + 728: 1000728 + 729: 1000729 + 730: 1000730 + 731: 1000731 + 732: 1000732 + 733: 1000733 + 734: 1000734 + 735: 1000735 + 736: 1000736 + 737: 1000737 + 738: 1000738 + 739: 1000739 + 740: 1000740 + 741: 1000741 + 742: 1000742 + 743: 1000743 + 744: 1000744 + 745: 1000745 + 746: 1000746 + 747: 1000747 + 748: 1000748 + 749: 1000749 + 750: 1000750 + 751: 1000751 + 752: 1000752 + 753: 1000753 + 754: 1000754 + 755: 1000755 + 756: 1000756 + 757: 1000757 + 758: 1000758 + 759: 1000759 + 760: 1000760 + 761: 1000761 + 762: 1000762 + 763: 1000763 + 764: 1000764 + 765: 1000765 + 766: 1000766 + 767: 1000767 + 768: 1000768 + 769: 1000769 + 770: 1000770 + 771: 1000771 + 772: 1000772 + 773: 1000773 + 774: 1000774 + 775: 1000775 + 776: 1000776 + 777: 1000777 + 778: 1000778 + 779: 1000779 + 780: 1000780 + 781: 1000781 + 782: 1000782 + 783: 1000783 + 784: 1000784 + 785: 1000785 + 786: 1000786 + 787: 1000787 + 788: 1000788 + 789: 1000789 + 790: 1000790 + 791: 1000791 + 792: 1000792 + 793: 1000793 + 794: 1000794 + 795: 1000795 + 796: 1000796 + 797: 1000797 + 798: 1000798 + 799: 1000799 + 800: 1000800 + 801: 1000801 + 802: 1000802 + 803: 1000803 + 804: 1000804 + 805: 1000805 + 806: 1000806 + 807: 1000807 + 808: 1000808 + 809: 1000809 + 810: 1000810 + 811: 1000811 + 812: 1000812 + 813: 1000813 + 814: 1000814 + 815: 1000815 + 816: 1000816 + 817: 1000817 + 818: 1000818 + 819: 1000819 + 820: 1000820 + 821: 1000821 + 822: 1000822 + 823: 1000823 + 824: 1000824 + 825: 1000825 + 826: 1000826 + 827: 1000827 + 828: 1000828 + 829: 1000829 + 830: 1000830 + 831: 1000831 + 832: 1000832 + 833: 1000833 + 834: 1000834 + 835: 1000835 + 836: 1000836 + 837: 1000837 + 838: 1000838 + 839: 1000839 + 840: 1000840 + 841: 1000841 + 842: 1000842 + 843: 1000843 + 844: 1000844 + 845: 1000845 + 846: 1000846 + 847: 1000847 + 848: 1000848 + 849: 1000849 + 850: 1000850 + 851: 1000851 + 852: 1000852 + 853: 1000853 + 854: 1000854 + 855: 1000855 + 856: 1000856 + 857: 1000857 + 858: 1000858 + 859: 1000859 + 860: 1000860 + 861: 1000861 + 862: 1000862 + 863: 1000863 + 864: 1000864 + 865: 1000865 + 866: 1000866 + 867: 1000867 + 868: 1000868 + 869: 1000869 + 870: 1000870 + 871: 1000871 + 872: 1000872 + 873: 1000873 + 874: 1000874 + 875: 1000875 + 876: 1000876 + 877: 1000877 + 878: 1000878 + 879: 1000879 + 880: 1000880 + 881: 1000881 + 882: 1000882 + 883: 1000883 + 884: 1000884 + 885: 1000885 + 886: 1000886 + 887: 1000887 + 888: 1000888 + 889: 1000889 + 890: 1000890 + 891: 1000891 + 892: 1000892 + 893: 1000893 + 894: 1000894 + 895: 1000895 + 896: 1000896 + 897: 1000897 + 898: 1000898 + 899: 1000899 + 900: 1000900 + 901: 1000901 + 902: 1000902 + 903: 1000903 + 904: 1000904 + 905: 1000905 + 906: 1000906 + 907: 1000907 + 908: 1000908 + 909: 1000909 + 910: 1000910 + 911: 1000911 + 912: 1000912 + 913: 1000913 + 914: 1000914 + 915: 1000915 + 916: 1000916 + 917: 1000917 + 918: 1000918 + 919: 1000919 + 920: 1000920 + 921: 1000921 + 922: 1000922 + 923: 1000923 + 924: 1000924 + 925: 1000925 + 926: 1000926 + 927: 1000927 + 928: 1000928 + 929: 1000929 + 930: 1000930 + 931: 1000931 + 932: 1000932 + 933: 1000933 + 934: 1000934 + 935: 1000935 + 936: 1000936 + 937: 1000937 + 938: 1000938 + 939: 1000939 + 940: 1000940 + 941: 1000941 + 942: 1000942 + 943: 1000943 + 944: 1000944 + 945: 1000945 + 946: 1000946 + 947: 1000947 + 948: 1000948 + 949: 1000949 + 950: 1000950 + 951: 1000951 + 952: 1000952 + 953: 1000953 + 954: 1000954 + 955: 1000955 + 956: 1000956 + 957: 1000957 + 958: 1000958 + 959: 1000959 + 960: 1000960 + 961: 1000961 + 962: 1000962 + 963: 1000963 + 964: 1000964 + 965: 1000965 + 966: 1000966 + 967: 1000967 + 968: 1000968 + 969: 1000969 + 970: 1000970 + 971: 1000971 + 972: 1000972 + 973: 1000973 + 974: 1000974 + 975: 1000975 + 976: 1000976 + 977: 1000977 + 978: 1000978 + 979: 1000979 + 980: 1000980 + 981: 1000981 + 982: 1000982 + 983: 1000983 + 984: 1000984 + 985: 1000985 + 986: 1000986 + 987: 1000987 + 988: 1000988 + 989: 1000989 + 990: 1000990 + 991: 1000991 + 992: 1000992 + 993: 1000993 + 994: 1000994 + 995: 1000995 + 996: 1000996 + 997: 1000997 + 998: 1000998 + 999: 1000999 + 1000: 1001000 + 1001: 1001001 + 1002: 1001002 + 1003: 1001003 + 1004: 1001004 + 1005: 1001005 + 1006: 1001006 + 1007: 1001007 + 1008: 1001008 + 1009: 1001009 + 1010: 1001010 + 1011: 1001011 + 1012: 1001012 + 1013: 1001013 + 1014: 1001014 + 1015: 1001015 + 1016: 1001016 + 1017: 1001017 + 1018: 1001018 + 1019: 1001019 + 1020: 1001020 + 1021: 1001021 + 1022: 1001022 + 1023: 1001023 + 1024: 1001024 + 1025: 1001025 + 1026: 1001026 + 1027: 1001027 + 1028: 1001028 + 1029: 1001029 + 1030: 1001030 + 1031: 1001031 + 1032: 1001032 + 1033: 1001033 + 1034: 1001034 + 1035: 1001035 + 1036: 1001036 + 1037: 1001037 + 1038: 1001038 + 1039: 1001039 + 1040: 1001040 + 1041: 1001041 + 1042: 1001042 + 1043: 1001043 + 1044: 1001044 + 1045: 1001045 + 1046: 1001046 + 1047: 1001047 + 1048: 1001048 + 1049: 1001049 + 1050: 1001050 + 1051: 1001051 + 1052: 1001052 + 1053: 1001053 + 1054: 1001054 + 1055: 1001055 + 1056: 1001056 + 1057: 1001057 + 1058: 1001058 + 1059: 1001059 + 1060: 1001060 + 1061: 1001061 + 1062: 1001062 + 1063: 1001063 + 1064: 1001064 + 1065: 1001065 + 1066: 1001066 + 1067: 1001067 + 1068: 1001068 + 1069: 1001069 + 1070: 1001070 + 1071: 1001071 + 1072: 1001072 + 1073: 1001073 + 1074: 1001074 + 1075: 1001075 + 1076: 1001076 + 1077: 1001077 + 1078: 1001078 + 1079: 1001079 + 1080: 1001080 + 1081: 1001081 + 1082: 1001082 + 1083: 1001083 + 1084: 1001084 + 1085: 1001085 + 1086: 1001086 + 1087: 1001087 + 1088: 1001088 + 1089: 1001089 + 1090: 1001090 + 1091: 1001091 + 1092: 1001092 + 1093: 1001093 + 1094: 1001094 + 1095: 1001095 + 1096: 1001096 + 1097: 1001097 + 1098: 1001098 + 1099: 1001099 + 1100: 1001100 + 1101: 1001101 + 1102: 1001102 + 1103: 1001103 + 1104: 1001104 + 1105: 1001105 + 1106: 1001106 + 1107: 1001107 + 1108: 1001108 + 1109: 1001109 + 1110: 1001110 + 1111: 1001111 + 1112: 1001112 + 1113: 1001113 + 1114: 1001114 + 1115: 1001115 + 1116: 1001116 + 1117: 1001117 + 1118: 1001118 + 1119: 1001119 + 1120: 1001120 + 1121: 1001121 + 1122: 1001122 + 1123: 1001123 + 1124: 1001124 + 1125: 1001125 + 1126: 1001126 + 1127: 1001127 + 1128: 1001128 + 1129: 1001129 + 1130: 1001130 + 1131: 1001131 + 1132: 1001132 + 1133: 1001133 + 1134: 1001134 + 1135: 1001135 + 1136: 1001136 + 1137: 1001137 + 1138: 1001138 + 1139: 1001139 + 1140: 1001140 + 1141: 1001141 + 1142: 1001142 + 1143: 1001143 + 1144: 1001144 + 1145: 1001145 + 1146: 1001146 + 1147: 1001147 + 1148: 1001148 + 1149: 1001149 + 1150: 1001150 + 1151: 1001151 + 1152: 1001152 + 1153: 1001153 + 1154: 1001154 + 1155: 1001155 + 1156: 1001156 + 1157: 1001157 + 1158: 1001158 + 1159: 1001159 + 1160: 1001160 + 1161: 1001161 + 1162: 1001162 + 1163: 1001163 + 1164: 1001164 + 1165: 1001165 + 1166: 1001166 + 1167: 1001167 + 1168: 1001168 + 1169: 1001169 + 1170: 1001170 + 1171: 1001171 + 1172: 1001172 + 1173: 1001173 + 1174: 1001174 + 1175: 1001175 + 1176: 1001176 + 1177: 1001177 + 1178: 1001178 + 1179: 1001179 + 1180: 1001180 + 1181: 1001181 + 1182: 1001182 + 1183: 1001183 + 1184: 1001184 + 1185: 1001185 + 1186: 1001186 + 1187: 1001187 + 1188: 1001188 + 1189: 1001189 + 1190: 1001190 + 1191: 1001191 + 1192: 1001192 + 1193: 1001193 + 1194: 1001194 + 1195: 1001195 + 1196: 1001196 + 1197: 1001197 + 1198: 1001198 + 1199: 1001199 + 1200: 1001200 + 1201: 1001201 + 1202: 1001202 + 1203: 1001203 + 1204: 1001204 + 1205: 1001205 + 1206: 1001206 + 1207: 1001207 + 1208: 1001208 + 1209: 1001209 + 1210: 1001210 + 1211: 1001211 + 1212: 1001212 + 1213: 1001213 + 1214: 1001214 + 1215: 1001215 + 1216: 1001216 + 1217: 1001217 + 1218: 1001218 + 1219: 1001219 + 1220: 1001220 + 1221: 1001221 + 1222: 1001222 + 1223: 1001223 + 1224: 1001224 + 1225: 1001225 + 1226: 1001226 + 1227: 1001227 + 1228: 1001228 + 1229: 1001229 + 1230: 1001230 + 1231: 1001231 + 1232: 1001232 + 1233: 1001233 + 1234: 1001234 + 1235: 1001235 + 1236: 1001236 + 1237: 1001237 + 1238: 1001238 + 1239: 1001239 + 1240: 1001240 + 1241: 1001241 + 1242: 1001242 + 1243: 1001243 + 1244: 1001244 + 1245: 1001245 + 1246: 1001246 + 1247: 1001247 + 1248: 1001248 + 1249: 1001249 + 1250: 1001250 + 1251: 1001251 + 1252: 1001252 + 1253: 1001253 + 1254: 1001254 + 1255: 1001255 + 1256: 1001256 + 1257: 1001257 + 1258: 1001258 + 1259: 1001259 + 1260: 1001260 + 1261: 1001261 + 1262: 1001262 + 1263: 1001263 + 1264: 1001264 + 1265: 1001265 + 1266: 1001266 + 1267: 1001267 + 1268: 1001268 + 1269: 1001269 + 1270: 1001270 + 1271: 1001271 + 1272: 1001272 + 1273: 1001273 + 1274: 1001274 + 1275: 1001275 + 1276: 1001276 + 1277: 1001277 + 1278: 1001278 + 1279: 1001279 + 1280: 1001280 + 1281: 1001281 + 1282: 1001282 + 1283: 1001283 + 1284: 1001284 + 1285: 1001285 + 1286: 1001286 + 1287: 1001287 + 1288: 1001288 + 1289: 1001289 + 1290: 1001290 + 1291: 1001291 + 1292: 1001292 + 1293: 1001293 + 1294: 1001294 + 1295: 1001295 + 1296: 1001296 + 1297: 1001297 + 1298: 1001298 + 1299: 1001299 + 1300: 1001300 + 1301: 1001301 + 1302: 1001302 + 1303: 1001303 + 1304: 1001304 + 1305: 1001305 + 1306: 1001306 + 1307: 1001307 + 1308: 1001308 + 1309: 1001309 + 1310: 1001310 + 1311: 1001311 + 1312: 1001312 + 1313: 1001313 + 1314: 1001314 + 1315: 1001315 + 1316: 1001316 + 1317: 1001317 + 1318: 1001318 + 1319: 1001319 + 1320: 1001320 + 1321: 1001321 + 1322: 1001322 + 1323: 1001323 + 1324: 1001324 + 1325: 1001325 + 1326: 1001326 + 1327: 1001327 + 1328: 1001328 + 1329: 1001329 + 1330: 1001330 + 1331: 1001331 + 1332: 1001332 + 1333: 1001333 + 1334: 1001334 + 1335: 1001335 + 1336: 1001336 + 1337: 1001337 + 1338: 1001338 + 1339: 1001339 + 1340: 1001340 + 1341: 1001341 + 1342: 1001342 + 1343: 1001343 + 1344: 1001344 + 1345: 1001345 + 1346: 1001346 + 1347: 1001347 + 1348: 1001348 + 1349: 1001349 + 1350: 1001350 + 1351: 1001351 + 1352: 1001352 + 1353: 1001353 + 1354: 1001354 + 1355: 1001355 + 1356: 1001356 + 1357: 1001357 + 1358: 1001358 + 1359: 1001359 + 1360: 1001360 + 1361: 1001361 + 1362: 1001362 + 1363: 1001363 + 1364: 1001364 + 1365: 1001365 + 1366: 1001366 + 1367: 1001367 + 1368: 1001368 + 1369: 1001369 + 1370: 1001370 + 1371: 1001371 + 1372: 1001372 + 1373: 1001373 + 1374: 1001374 + 1375: 1001375 + 1376: 1001376 + 1377: 1001377 + 1378: 1001378 + 1379: 1001379 + 1380: 1001380 + 1381: 1001381 + 1382: 1001382 + 1383: 1001383 + 1384: 1001384 + 1385: 1001385 + 1386: 1001386 + 1387: 1001387 + 1388: 1001388 + 1389: 1001389 + 1390: 1001390 + 1391: 1001391 + 1392: 1001392 + 1393: 1001393 + 1394: 1001394 + 1395: 1001395 + 1396: 1001396 + 1397: 1001397 + 1398: 1001398 + 1399: 1001399 + 1400: 1001400 + 1401: 1001401 + 1402: 1001402 + 1403: 1001403 + 1404: 1001404 + 1405: 1001405 + 1406: 1001406 + 1407: 1001407 + 1408: 1001408 + 1409: 1001409 + 1410: 1001410 + 1411: 1001411 + 1412: 1001412 + 1413: 1001413 + 1414: 1001414 + 1415: 1001415 + 1416: 1001416 + 1417: 1001417 + 1418: 1001418 + 1419: 1001419 + 1420: 1001420 + 1421: 1001421 + 1422: 1001422 + 1423: 1001423 + 1424: 1001424 + 1425: 1001425 + 1426: 1001426 + 1427: 1001427 + 1428: 1001428 + 1429: 1001429 + 1430: 1001430 + 1431: 1001431 + 1432: 1001432 + 1433: 1001433 + 1434: 1001434 + 1435: 1001435 + 1436: 1001436 + 1437: 1001437 + 1438: 1001438 + 1439: 1001439 + 1440: 1001440 + 1441: 1001441 + 1442: 1001442 + 1443: 1001443 + 1444: 1001444 + 1445: 1001445 + 1446: 1001446 + 1447: 1001447 + 1448: 1001448 + 1449: 1001449 + 1450: 1001450 + 1451: 1001451 + 1452: 1001452 + 1453: 1001453 + 1454: 1001454 + 1455: 1001455 + 1456: 1001456 + 1457: 1001457 + 1458: 1001458 + 1459: 1001459 + 1460: 1001460 + 1461: 1001461 + 1462: 1001462 + 1463: 1001463 + 1464: 1001464 + 1465: 1001465 + 1466: 1001466 + 1467: 1001467 + 1468: 1001468 + 1469: 1001469 + 1470: 1001470 + 1471: 1001471 + 1472: 1001472 + 1473: 1001473 + 1474: 1001474 + 1475: 1001475 + 1476: 1001476 + 1477: 1001477 + 1478: 1001478 + 1479: 1001479 + 1480: 1001480 + 1481: 1001481 + 1482: 1001482 + 1483: 1001483 + 1484: 1001484 + 1485: 1001485 + 1486: 1001486 + 1487: 1001487 + 1488: 1001488 + 1489: 1001489 + 1490: 1001490 + 1491: 1001491 + 1492: 1001492 + 1493: 1001493 + 1494: 1001494 + 1495: 1001495 + 1496: 1001496 + 1497: 1001497 + 1498: 1001498 + 1499: 1001499 + 1500: 1001500 + 1501: 1001501 + 1502: 1001502 + 1503: 1001503 + 1504: 1001504 + 1505: 1001505 + 1506: 1001506 + 1507: 1001507 + 1508: 1001508 + 1509: 1001509 + 1510: 1001510 + 1511: 1001511 + 1512: 1001512 + 1513: 1001513 + 1514: 1001514 + 1515: 1001515 + 1516: 1001516 + 1517: 1001517 + 1518: 1001518 + 1519: 1001519 + 1520: 1001520 + 1521: 1001521 + 1522: 1001522 + 1523: 1001523 + 1524: 1001524 + 1525: 1001525 + 1526: 1001526 + 1527: 1001527 + 1528: 1001528 + 1529: 1001529 + 1530: 1001530 + 1531: 1001531 + 1532: 1001532 + 1533: 1001533 + 1534: 1001534 + 1535: 1001535 + 1536: 1001536 + 1537: 1001537 + 1538: 1001538 + 1539: 1001539 + 1540: 1001540 + 1541: 1001541 + 1542: 1001542 + 1543: 1001543 + 1544: 1001544 + 1545: 1001545 + 1546: 1001546 + 1547: 1001547 + 1548: 1001548 + 1549: 1001549 + 1550: 1001550 + 1551: 1001551 + 1552: 1001552 + 1553: 1001553 + 1554: 1001554 + 1555: 1001555 + 1556: 1001556 + 1557: 1001557 + 1558: 1001558 + 1559: 1001559 + 1560: 1001560 + 1561: 1001561 + 1562: 1001562 + 1563: 1001563 + 1564: 1001564 + 1565: 1001565 + 1566: 1001566 + 1567: 1001567 + 1568: 1001568 + 1569: 1001569 + 1570: 1001570 + 1571: 1001571 + 1572: 1001572 + 1573: 1001573 + 1574: 1001574 + 1575: 1001575 + 1576: 1001576 + 1577: 1001577 + 1578: 1001578 + 1579: 1001579 + 1580: 1001580 + 1581: 1001581 + 1582: 1001582 + 1583: 1001583 + 1584: 1001584 + 1585: 1001585 + 1586: 1001586 + 1587: 1001587 + 1588: 1001588 + 1589: 1001589 + 1590: 1001590 + 1591: 1001591 + 1592: 1001592 + 1593: 1001593 + 1594: 1001594 + 1595: 1001595 + 1596: 1001596 + 1597: 1001597 + 1598: 1001598 + 1599: 1001599 + 1600: 1001600 + 1601: 1001601 + 1602: 1001602 + 1603: 1001603 + 1604: 1001604 + 1605: 1001605 + 1606: 1001606 + 1607: 1001607 + 1608: 1001608 + 1609: 1001609 + 1610: 1001610 + 1611: 1001611 + 1612: 1001612 + 1613: 1001613 + 1614: 1001614 + 1615: 1001615 + 1616: 1001616 + 1617: 1001617 + 1618: 1001618 + 1619: 1001619 + 1620: 1001620 + 1621: 1001621 + 1622: 1001622 + 1623: 1001623 + 1624: 1001624 + 1625: 1001625 + 1626: 1001626 + 1627: 1001627 + 1628: 1001628 + 1629: 1001629 + 1630: 1001630 + 1631: 1001631 + 1632: 1001632 + 1633: 1001633 + 1634: 1001634 + 1635: 1001635 + 1636: 1001636 + 1637: 1001637 + 1638: 1001638 + 1639: 1001639 + 1640: 1001640 + 1641: 1001641 + 1642: 1001642 + 1643: 1001643 + 1644: 1001644 + 1645: 1001645 + 1646: 1001646 + 1647: 1001647 + 1648: 1001648 + 1649: 1001649 + 1650: 1001650 + 1651: 1001651 + 1652: 1001652 + 1653: 1001653 + 1654: 1001654 + 1655: 1001655 + 1656: 1001656 + 1657: 1001657 + 1658: 1001658 + 1659: 1001659 + 1660: 1001660 + 1661: 1001661 + 1662: 1001662 + 1663: 1001663 + 1664: 1001664 + 1665: 1001665 + 1666: 1001666 + 1667: 1001667 + 1668: 1001668 + 1669: 1001669 + 1670: 1001670 + 1671: 1001671 + 1672: 1001672 + 1673: 1001673 + 1674: 1001674 + 1675: 1001675 + 1676: 1001676 + 1677: 1001677 + 1678: 1001678 + 1679: 1001679 + 1680: 1001680 + 1681: 1001681 + 1682: 1001682 + 1683: 1001683 + 1684: 1001684 + 1685: 1001685 + 1686: 1001686 + 1687: 1001687 + 1688: 1001688 + 1689: 1001689 + 1690: 1001690 + 1691: 1001691 + 1692: 1001692 + 1693: 1001693 + 1694: 1001694 + 1695: 1001695 + 1696: 1001696 + 1697: 1001697 + 1698: 1001698 + 1699: 1001699 + 1700: 1001700 + 1701: 1001701 + 1702: 1001702 + 1703: 1001703 + 1704: 1001704 + 1705: 1001705 + 1706: 1001706 + 1707: 1001707 + 1708: 1001708 + 1709: 1001709 + 1710: 1001710 + 1711: 1001711 + 1712: 1001712 + 1713: 1001713 + 1714: 1001714 + 1715: 1001715 + 1716: 1001716 + 1717: 1001717 + 1718: 1001718 + 1719: 1001719 + 1720: 1001720 + 1721: 1001721 + 1722: 1001722 + 1723: 1001723 + 1724: 1001724 + 1725: 1001725 + 1726: 1001726 + 1727: 1001727 + 1728: 1001728 + 1729: 1001729 + 1730: 1001730 + 1731: 1001731 + 1732: 1001732 + 1733: 1001733 + 1734: 1001734 + 1735: 1001735 + 1736: 1001736 + 1737: 1001737 + 1738: 1001738 + 1739: 1001739 + 1740: 1001740 + 1741: 1001741 + 1742: 1001742 + 1743: 1001743 + 1744: 1001744 + 1745: 1001745 + 1746: 1001746 + 1747: 1001747 + 1748: 1001748 + 1749: 1001749 + 1750: 1001750 + 1751: 1001751 + 1752: 1001752 + 1753: 1001753 + 1754: 1001754 + 1755: 1001755 + 1756: 1001756 + 1757: 1001757 + 1758: 1001758 + 1759: 1001759 + 1760: 1001760 + 1761: 1001761 + 1762: 1001762 + 1763: 1001763 + 1764: 1001764 + 1765: 1001765 + 1766: 1001766 + 1767: 1001767 + 1768: 1001768 + 1769: 1001769 + 1770: 1001770 + 1771: 1001771 + 1772: 1001772 + 1773: 1001773 + 1774: 1001774 + 1775: 1001775 + 1776: 1001776 + 1777: 1001777 + 1778: 1001778 + 1779: 1001779 + 1780: 1001780 + 1781: 1001781 + 1782: 1001782 + 1783: 1001783 + 1784: 1001784 + 1785: 1001785 + 1786: 1001786 + 1787: 1001787 + 1788: 1001788 + 1789: 1001789 + 1790: 1001790 + 1791: 1001791 + 1792: 1001792 + 1793: 1001793 + 1794: 1001794 + 1795: 1001795 + 1796: 1001796 + 1797: 1001797 + 1798: 1001798 + 1799: 1001799 + 1800: 1001800 + 1801: 1001801 + 1802: 1001802 + 1803: 1001803 + 1804: 1001804 + 1805: 1001805 + 1806: 1001806 + 1807: 1001807 + 1808: 1001808 + 1809: 1001809 + 1810: 1001810 + 1811: 1001811 + 1812: 1001812 + 1813: 1001813 + 1814: 1001814 + 1815: 1001815 + 1816: 1001816 + 1817: 1001817 + 1818: 1001818 + 1819: 1001819 + 1820: 1001820 + 1821: 1001821 + 1822: 1001822 + 1823: 1001823 + 1824: 1001824 + 1825: 1001825 + 1826: 1001826 + 1827: 1001827 + 1828: 1001828 + 1829: 1001829 + 1830: 1001830 + 1831: 1001831 + 1832: 1001832 + 1833: 1001833 + 1834: 1001834 + 1835: 1001835 + 1836: 1001836 + 1837: 1001837 + 1838: 1001838 + 1839: 1001839 + 1840: 1001840 + 1841: 1001841 + 1842: 1001842 + 1843: 1001843 + 1844: 1001844 + 1845: 1001845 + 1846: 1001846 + 1847: 1001847 + 1848: 1001848 + 1849: 1001849 + 1850: 1001850 + 1851: 1001851 + 1852: 1001852 + 1853: 1001853 + 1854: 1001854 + 1855: 1001855 + 1856: 1001856 + 1857: 1001857 + 1858: 1001858 + 1859: 1001859 + 1860: 1001860 + 1861: 1001861 + 1862: 1001862 + 1863: 1001863 + 1864: 1001864 + 1865: 1001865 + 1866: 1001866 + 1867: 1001867 + 1868: 1001868 + 1869: 1001869 + 1870: 1001870 + 1871: 1001871 + 1872: 1001872 + 1873: 1001873 + 1874: 1001874 + 1875: 1001875 + 1876: 1001876 + 1877: 1001877 + 1878: 1001878 + 1879: 1001879 + 1880: 1001880 + 1881: 1001881 + 1882: 1001882 + 1883: 1001883 + 1884: 1001884 + 1885: 1001885 + 1886: 1001886 + 1887: 1001887 + 1888: 1001888 + 1889: 1001889 + 1890: 1001890 + 1891: 1001891 + 1892: 1001892 + 1893: 1001893 + 1894: 1001894 + 1895: 1001895 + 1896: 1001896 + 1897: 1001897 + 1898: 1001898 + 1899: 1001899 + 1900: 1001900 + 1901: 1001901 + 1902: 1001902 + 1903: 1001903 + 1904: 1001904 + 1905: 1001905 + 1906: 1001906 + 1907: 1001907 + 1908: 1001908 + 1909: 1001909 + 1910: 1001910 + 1911: 1001911 + 1912: 1001912 + 1913: 1001913 + 1914: 1001914 + 1915: 1001915 + 1916: 1001916 + 1917: 1001917 + 1918: 1001918 + 1919: 1001919 + 1920: 1001920 + 1921: 1001921 + 1922: 1001922 + 1923: 1001923 + 1924: 1001924 + 1925: 1001925 + 1926: 1001926 + 1927: 1001927 + 1928: 1001928 + 1929: 1001929 + 1930: 1001930 + 1931: 1001931 + 1932: 1001932 + 1933: 1001933 + 1934: 1001934 + 1935: 1001935 + 1936: 1001936 + 1937: 1001937 + 1938: 1001938 + 1939: 1001939 + 1940: 1001940 + 1941: 1001941 + 1942: 1001942 + 1943: 1001943 + 1944: 1001944 + 1945: 1001945 + 1946: 1001946 + 1947: 1001947 + 1948: 1001948 + 1949: 1001949 + 1950: 1001950 + 1951: 1001951 + 1952: 1001952 + 1953: 1001953 + 1954: 1001954 + 1955: 1001955 + 1956: 1001956 + 1957: 1001957 + 1958: 1001958 + 1959: 1001959 + 1960: 1001960 + 1961: 1001961 + 1962: 1001962 + 1963: 1001963 + 1964: 1001964 + 1965: 1001965 + 1966: 1001966 + 1967: 1001967 + 1968: 1001968 + 1969: 1001969 + 1970: 1001970 + 1971: 1001971 + 1972: 1001972 + 1973: 1001973 + 1974: 1001974 + 1975: 1001975 + 1976: 1001976 + 1977: 1001977 + 1978: 1001978 + 1979: 1001979 + 1980: 1001980 + 1981: 1001981 + 1982: 1001982 + 1983: 1001983 + 1984: 1001984 + 1985: 1001985 + 1986: 1001986 + 1987: 1001987 + 1988: 1001988 + 1989: 1001989 + 1990: 1001990 + 1991: 1001991 + 1992: 1001992 + 1993: 1001993 + 1994: 1001994 + 1995: 1001995 + 1996: 1001996 + 1997: 1001997 + 1998: 1001998 + 1999: 1001999 + 2000: 1002000 + 2001: 1002001 + 2002: 1002002 + 2003: 1002003 + 2004: 1002004 + 2005: 1002005 + 2006: 1002006 + 2007: 1002007 + 2008: 1002008 + 2009: 1002009 + 2010: 1002010 + 2011: 1002011 + 2012: 1002012 + 2013: 1002013 + 2014: 1002014 + 2015: 1002015 + 2016: 1002016 + 2017: 1002017 + 2018: 1002018 + 2019: 1002019 + 2020: 1002020 + 2021: 1002021 + 2022: 1002022 + 2023: 1002023 + 2024: 1002024 + 2025: 1002025 + 2026: 1002026 + 2027: 1002027 + 2028: 1002028 + 2029: 1002029 + 2030: 1002030 + 2031: 1002031 + 2032: 1002032 + 2033: 1002033 + 2034: 1002034 + 2035: 1002035 + 2036: 1002036 + 2037: 1002037 + 2038: 1002038 + 2039: 1002039 + 2040: 1002040 + 2041: 1002041 + 2042: 1002042 + 2043: 1002043 + 2044: 1002044 + 2045: 1002045 + 2046: 1002046 + 2047: 1002047 + 2048: 1002048 + 2049: 1002049 + 2050: 1002050 + 2051: 1002051 + 2052: 1002052 + 2053: 1002053 + 2054: 1002054 + 2055: 1002055 + 2056: 1002056 + 2057: 1002057 + 2058: 1002058 + 2059: 1002059 + 2060: 1002060 + 2061: 1002061 + 2062: 1002062 + 2063: 1002063 + 2064: 1002064 + 2065: 1002065 + 2066: 1002066 + 2067: 1002067 + 2068: 1002068 + 2069: 1002069 + 2070: 1002070 + 2071: 1002071 + 2072: 1002072 + 2073: 1002073 + 2074: 1002074 + 2075: 1002075 + 2076: 1002076 + 2077: 1002077 + 2078: 1002078 + 2079: 1002079 + 2080: 1002080 + 2081: 1002081 + 2082: 1002082 + 2083: 1002083 + 2084: 1002084 + 2085: 1002085 + 2086: 1002086 + 2087: 1002087 + 2088: 1002088 + 2089: 1002089 + 2090: 1002090 + 2091: 1002091 + 2092: 1002092 + 2093: 1002093 + 2094: 1002094 + 2095: 1002095 + 2096: 1002096 + 2097: 1002097 + 2098: 1002098 + 2099: 1002099 + 2100: 1002100 + 2101: 1002101 + 2102: 1002102 + 2103: 1002103 + 2104: 1002104 + 2105: 1002105 + 2106: 1002106 + 2107: 1002107 + 2108: 1002108 + 2109: 1002109 + 2110: 1002110 + 2111: 1002111 + 2112: 1002112 + 2113: 1002113 + 2114: 1002114 + 2115: 1002115 + 2116: 1002116 + 2117: 1002117 + 2118: 1002118 + 2119: 1002119 + 2120: 1002120 + 2121: 1002121 + 2122: 1002122 + 2123: 1002123 + 2124: 1002124 + 2125: 1002125 + 2126: 1002126 + 2127: 1002127 + 2128: 1002128 + 2129: 1002129 + 2130: 1002130 + 2131: 1002131 + 2132: 1002132 + 2133: 1002133 + 2134: 1002134 + 2135: 1002135 + 2136: 1002136 + 2137: 1002137 + 2138: 1002138 + 2139: 1002139 + 2140: 1002140 + 2141: 1002141 + 2142: 1002142 + 2143: 1002143 + 2144: 1002144 + 2145: 1002145 + 2146: 1002146 + 2147: 1002147 + 2148: 1002148 + 2149: 1002149 + 2150: 1002150 + 2151: 1002151 + 2152: 1002152 + 2153: 1002153 + 2154: 1002154 + 2155: 1002155 + 2156: 1002156 + 2157: 1002157 + 2158: 1002158 + 2159: 1002159 + 2160: 1002160 + 2161: 1002161 + 2162: 1002162 + 2163: 1002163 + 2164: 1002164 + 2165: 1002165 + 2166: 1002166 + 2167: 1002167 + 2168: 1002168 + 2169: 1002169 + 2170: 1002170 + 2171: 1002171 + 2172: 1002172 + 2173: 1002173 + 2174: 1002174 + 2175: 1002175 + 2176: 1002176 + 2177: 1002177 + 2178: 1002178 + 2179: 1002179 + 2180: 1002180 + 2181: 1002181 + 2182: 1002182 + 2183: 1002183 + 2184: 1002184 + 2185: 1002185 + 2186: 1002186 + 2187: 1002187 + 2188: 1002188 + 2189: 1002189 + 2190: 1002190 + 2191: 1002191 + 2192: 1002192 + 2193: 1002193 + 2194: 1002194 + 2195: 1002195 + 2196: 1002196 + 2197: 1002197 + 2198: 1002198 + 2199: 1002199 + 2200: 1002200 + 2201: 1002201 + 2202: 1002202 + 2203: 1002203 + 2204: 1002204 + 2205: 1002205 + 2206: 1002206 + 2207: 1002207 + 2208: 1002208 + 2209: 1002209 + 2210: 1002210 + 2211: 1002211 + 2212: 1002212 + 2213: 1002213 + 2214: 1002214 + 2215: 1002215 + 2216: 1002216 + 2217: 1002217 + 2218: 1002218 + 2219: 1002219 + 2220: 1002220 + 2221: 1002221 + 2222: 1002222 + 2223: 1002223 + 2224: 1002224 + 2225: 1002225 + 2226: 1002226 + 2227: 1002227 + 2228: 1002228 + 2229: 1002229 + 2230: 1002230 + 2231: 1002231 + 2232: 1002232 + 2233: 1002233 + 2234: 1002234 + 2235: 1002235 + 2236: 1002236 + 2237: 1002237 + 2238: 1002238 + 2239: 1002239 + 2240: 1002240 + 2241: 1002241 + 2242: 1002242 + 2243: 1002243 + 2244: 1002244 + 2245: 1002245 + 2246: 1002246 + 2247: 1002247 + 2248: 1002248 + 2249: 1002249 + 2250: 1002250 + 2251: 1002251 + 2252: 1002252 + 2253: 1002253 + 2254: 1002254 + 2255: 1002255 + 2256: 1002256 + 2257: 1002257 + 2258: 1002258 + 2259: 1002259 + 2260: 1002260 + 2261: 1002261 + 2262: 1002262 + 2263: 1002263 + 2264: 1002264 + 2265: 1002265 + 2266: 1002266 + 2267: 1002267 + 2268: 1002268 + 2269: 1002269 + 2270: 1002270 + 2271: 1002271 + 2272: 1002272 + 2273: 1002273 + 2274: 1002274 + 2275: 1002275 + 2276: 1002276 + 2277: 1002277 + 2278: 1002278 + 2279: 1002279 + 2280: 1002280 + 2281: 1002281 + 2282: 1002282 + 2283: 1002283 + 2284: 1002284 + 2285: 1002285 + 2286: 1002286 + 2287: 1002287 + 2288: 1002288 + 2289: 1002289 + 2290: 1002290 + 2291: 1002291 + 2292: 1002292 + 2293: 1002293 + 2294: 1002294 + 2295: 1002295 + 2296: 1002296 + 2297: 1002297 + 2298: 1002298 + 2299: 1002299 + 2300: 1002300 + 2301: 1002301 + 2302: 1002302 + 2303: 1002303 + 2304: 1002304 + 2305: 1002305 + 2306: 1002306 + 2307: 1002307 + 2308: 1002308 + 2309: 1002309 + 2310: 1002310 + 2311: 1002311 + 2312: 1002312 + 2313: 1002313 + 2314: 1002314 + 2315: 1002315 + 2316: 1002316 + 2317: 1002317 + 2318: 1002318 + 2319: 1002319 + 2320: 1002320 + 2321: 1002321 + 2322: 1002322 + 2323: 1002323 + 2324: 1002324 + 2325: 1002325 + 2326: 1002326 + 2327: 1002327 + 2328: 1002328 + 2329: 1002329 + 2330: 1002330 + 2331: 1002331 + 2332: 1002332 + 2333: 1002333 + 2334: 1002334 + 2335: 1002335 + 2336: 1002336 + 2337: 1002337 + 2338: 1002338 + 2339: 1002339 + 2340: 1002340 + 2341: 1002341 + 2342: 1002342 + 2343: 1002343 + 2344: 1002344 + 2345: 1002345 + 2346: 1002346 + 2347: 1002347 + 2348: 1002348 + 2349: 1002349 + 2350: 1002350 + 2351: 1002351 + 2352: 1002352 + 2353: 1002353 + 2354: 1002354 + 2355: 1002355 + 2356: 1002356 + 2357: 1002357 + 2358: 1002358 + 2359: 1002359 + 2360: 1002360 + 2361: 1002361 + 2362: 1002362 + 2363: 1002363 + 2364: 1002364 + 2365: 1002365 + 2366: 1002366 + 2367: 1002367 + 2368: 1002368 + 2369: 1002369 + 2370: 1002370 + 2371: 1002371 + 2372: 1002372 + 2373: 1002373 + 2374: 1002374 + 2375: 1002375 + 2376: 1002376 + 2377: 1002377 + 2378: 1002378 + 2379: 1002379 + 2380: 1002380 + 2381: 1002381 + 2382: 1002382 + 2383: 1002383 + 2384: 1002384 + 2385: 1002385 + 2386: 1002386 + 2387: 1002387 + 2388: 1002388 + 2389: 1002389 + 2390: 1002390 + 2391: 1002391 + 2392: 1002392 + 2393: 1002393 + 2394: 1002394 + 2395: 1002395 + 2396: 1002396 + 2397: 1002397 + 2398: 1002398 + 2399: 1002399 + 2400: 1002400 + 2401: 1002401 + 2402: 1002402 + 2403: 1002403 + 2404: 1002404 + 2405: 1002405 + 2406: 1002406 + 2407: 1002407 + 2408: 1002408 + 2409: 1002409 + 2410: 1002410 + 2411: 1002411 + 2412: 1002412 + 2413: 1002413 + 2414: 1002414 + 2415: 1002415 + 2416: 1002416 + 2417: 1002417 + 2418: 1002418 + 2419: 1002419 + 2420: 1002420 + 2421: 1002421 + 2422: 1002422 + 2423: 1002423 + 2424: 1002424 + 2425: 1002425 + 2426: 1002426 + 2427: 1002427 + 2428: 1002428 + 2429: 1002429 + 2430: 1002430 + 2431: 1002431 + 2432: 1002432 + 2433: 1002433 + 2434: 1002434 + 2435: 1002435 + 2436: 1002436 + 2437: 1002437 + 2438: 1002438 + 2439: 1002439 + 2440: 1002440 + 2441: 1002441 + 2442: 1002442 + 2443: 1002443 + 2444: 1002444 + 2445: 1002445 + 2446: 1002446 + 2447: 1002447 + 2448: 1002448 + 2449: 1002449 + 2450: 1002450 + 2451: 1002451 + 2452: 1002452 + 2453: 1002453 + 2454: 1002454 + 2455: 1002455 + 2456: 1002456 + 2457: 1002457 + 2458: 1002458 + 2459: 1002459 + 2460: 1002460 + 2461: 1002461 + 2462: 1002462 + 2463: 1002463 + 2464: 1002464 + 2465: 1002465 + 2466: 1002466 + 2467: 1002467 + 2468: 1002468 + 2469: 1002469 + 2470: 1002470 + 2471: 1002471 + 2472: 1002472 + 2473: 1002473 + 2474: 1002474 + 2475: 1002475 + 2476: 1002476 + 2477: 1002477 + 2478: 1002478 + 2479: 1002479 + 2480: 1002480 + 2481: 1002481 + 2482: 1002482 + 2483: 1002483 + 2484: 1002484 + 2485: 1002485 + 2486: 1002486 + 2487: 1002487 + 2488: 1002488 + 2489: 1002489 + 2490: 1002490 + 2491: 1002491 + 2492: 1002492 + 2493: 1002493 + 2494: 1002494 + 2495: 1002495 + 2496: 1002496 + 2497: 1002497 + 2498: 1002498 + 2499: 1002499 + 2500: 1002500 + 2501: 1002501 + 2502: 1002502 + 2503: 1002503 + 2504: 1002504 + 2505: 1002505 + 2506: 1002506 + 2507: 1002507 + 2508: 1002508 + 2509: 1002509 + 2510: 1002510 + 2511: 1002511 + 2512: 1002512 + 2513: 1002513 + 2514: 1002514 + 2515: 1002515 + 2516: 1002516 + 2517: 1002517 + 2518: 1002518 + 2519: 1002519 + 2520: 1002520 + 2521: 1002521 + 2522: 1002522 + 2523: 1002523 + 2524: 1002524 + 2525: 1002525 + 2526: 1002526 + 2527: 1002527 + 2528: 1002528 + 2529: 1002529 + 2530: 1002530 + 2531: 1002531 + 2532: 1002532 + 2533: 1002533 + 2534: 1002534 + 2535: 1002535 + 2536: 1002536 + 2537: 1002537 + 2538: 1002538 + 2539: 1002539 + 2540: 1002540 + 2541: 1002541 + 2542: 1002542 + 2543: 1002543 + 2544: 1002544 + 2545: 1002545 + 2546: 1002546 + 2547: 1002547 + 2548: 1002548 + 2549: 1002549 + 2550: 1002550 + 2551: 1002551 + 2552: 1002552 + 2553: 1002553 + 2554: 1002554 + 2555: 1002555 + 2556: 1002556 + 2557: 1002557 + 2558: 1002558 + 2559: 1002559 + 2560: 1002560 + 2561: 1002561 + 2562: 1002562 + 2563: 1002563 + 2564: 1002564 + 2565: 1002565 + 2566: 1002566 + 2567: 1002567 + 2568: 1002568 + 2569: 1002569 + 2570: 1002570 + 2571: 1002571 + 2572: 1002572 + 2573: 1002573 + 2574: 1002574 + 2575: 1002575 + 2576: 1002576 + 2577: 1002577 + 2578: 1002578 + 2579: 1002579 + 2580: 1002580 + 2581: 1002581 + 2582: 1002582 + 2583: 1002583 + 2584: 1002584 + 2585: 1002585 + 2586: 1002586 + 2587: 1002587 + 2588: 1002588 + 2589: 1002589 + 2590: 1002590 + 2591: 1002591 + 2592: 1002592 + 2593: 1002593 + 2594: 1002594 + 2595: 1002595 + 2596: 1002596 + 2597: 1002597 + 2598: 1002598 + 2599: 1002599 + 2600: 1002600 + 2601: 1002601 + 2602: 1002602 + 2603: 1002603 + 2604: 1002604 + 2605: 1002605 + 2606: 1002606 + 2607: 1002607 + 2608: 1002608 + 2609: 1002609 + 2610: 1002610 + 2611: 1002611 + 2612: 1002612 + 2613: 1002613 + 2614: 1002614 + 2615: 1002615 + 2616: 1002616 + 2617: 1002617 + 2618: 1002618 + 2619: 1002619 + 2620: 1002620 + 2621: 1002621 + 2622: 1002622 + 2623: 1002623 + 2624: 1002624 + 2625: 1002625 + 2626: 1002626 + 2627: 1002627 + 2628: 1002628 + 2629: 1002629 + 2630: 1002630 + 2631: 1002631 + 2632: 1002632 + 2633: 1002633 + 2634: 1002634 + 2635: 1002635 + 2636: 1002636 + 2637: 1002637 + 2638: 1002638 + 2639: 1002639 + 2640: 1002640 + 2641: 1002641 + 2642: 1002642 + 2643: 1002643 + 2644: 1002644 + 2645: 1002645 + 2646: 1002646 + 2647: 1002647 + 2648: 1002648 + 2649: 1002649 + 2650: 1002650 + 2651: 1002651 + 2652: 1002652 + 2653: 1002653 + 2654: 1002654 + 2655: 1002655 + 2656: 1002656 + 2657: 1002657 + 2658: 1002658 + 2659: 1002659 + 2660: 1002660 + 2661: 1002661 + 2662: 1002662 + 2663: 1002663 + 2664: 1002664 + 2665: 1002665 + 2666: 1002666 + 2667: 1002667 + 2668: 1002668 + 2669: 1002669 + 2670: 1002670 + 2671: 1002671 + 2672: 1002672 + 2673: 1002673 + 2674: 1002674 + 2675: 1002675 + 2676: 1002676 + 2677: 1002677 + 2678: 1002678 + 2679: 1002679 + 2680: 1002680 + 2681: 1002681 + 2682: 1002682 + 2683: 1002683 + 2684: 1002684 + 2685: 1002685 + 2686: 1002686 + 2687: 1002687 + 2688: 1002688 + 2689: 1002689 + 2690: 1002690 + 2691: 1002691 + 2692: 1002692 + 2693: 1002693 + 2694: 1002694 + 2695: 1002695 + 2696: 1002696 + 2697: 1002697 + 2698: 1002698 + 2699: 1002699 + 2700: 1002700 + 2701: 1002701 + 2702: 1002702 + 2703: 1002703 + 2704: 1002704 + 2705: 1002705 + 2706: 1002706 + 2707: 1002707 + 2708: 1002708 + 2709: 1002709 + 2710: 1002710 + 2711: 1002711 + 2712: 1002712 + 2713: 1002713 + 2714: 1002714 + 2715: 1002715 + 2716: 1002716 + 2717: 1002717 + 2718: 1002718 + 2719: 1002719 + 2720: 1002720 + 2721: 1002721 + 2722: 1002722 + 2723: 1002723 + 2724: 1002724 + 2725: 1002725 + 2726: 1002726 + 2727: 1002727 + 2728: 1002728 + 2729: 1002729 + 2730: 1002730 + 2731: 1002731 + 2732: 1002732 + 2733: 1002733 + 2734: 1002734 + 2735: 1002735 + 2736: 1002736 + 2737: 1002737 + 2738: 1002738 + 2739: 1002739 + 2740: 1002740 + 2741: 1002741 + 2742: 1002742 + 2743: 1002743 + 2744: 1002744 + 2745: 1002745 + 2746: 1002746 + 2747: 1002747 + 2748: 1002748 + 2749: 1002749 + 2750: 1002750 + 2751: 1002751 + 2752: 1002752 + 2753: 1002753 + 2754: 1002754 + 2755: 1002755 + 2756: 1002756 + 2757: 1002757 + 2758: 1002758 + 2759: 1002759 + 2760: 1002760 + 2761: 1002761 + 2762: 1002762 + 2763: 1002763 + 2764: 1002764 + 2765: 1002765 + 2766: 1002766 + 2767: 1002767 + 2768: 1002768 + 2769: 1002769 + 2770: 1002770 + 2771: 1002771 + 2772: 1002772 + 2773: 1002773 + 2774: 1002774 + 2775: 1002775 + 2776: 1002776 + 2777: 1002777 + 2778: 1002778 + 2779: 1002779 + 2780: 1002780 + 2781: 1002781 + 2782: 1002782 + 2783: 1002783 + 2784: 1002784 + 2785: 1002785 + 2786: 1002786 + 2787: 1002787 + 2788: 1002788 + 2789: 1002789 + 2790: 1002790 + 2791: 1002791 + 2792: 1002792 + 2793: 1002793 + 2794: 1002794 + 2795: 1002795 + 2796: 1002796 + 2797: 1002797 + 2798: 1002798 + 2799: 1002799 + 2800: 1002800 + 2801: 1002801 + 2802: 1002802 + 2803: 1002803 + 2804: 1002804 + 2805: 1002805 + 2806: 1002806 + 2807: 1002807 + 2808: 1002808 + 2809: 1002809 + 2810: 1002810 + 2811: 1002811 + 2812: 1002812 + 2813: 1002813 + 2814: 1002814 + 2815: 1002815 + 2816: 1002816 + 2817: 1002817 + 2818: 1002818 + 2819: 1002819 + 2820: 1002820 + 2821: 1002821 + 2822: 1002822 + 2823: 1002823 + 2824: 1002824 + 2825: 1002825 + 2826: 1002826 + 2827: 1002827 + 2828: 1002828 + 2829: 1002829 + 2830: 1002830 + 2831: 1002831 + 2832: 1002832 + 2833: 1002833 + 2834: 1002834 + 2835: 1002835 + 2836: 1002836 + 2837: 1002837 + 2838: 1002838 + 2839: 1002839 + 2840: 1002840 + 2841: 1002841 + 2842: 1002842 + 2843: 1002843 + 2844: 1002844 + 2845: 1002845 + 2846: 1002846 + 2847: 1002847 + 2848: 1002848 + 2849: 1002849 + 2850: 1002850 + 2851: 1002851 + 2852: 1002852 + 2853: 1002853 + 2854: 1002854 + 2855: 1002855 + 2856: 1002856 + 2857: 1002857 + 2858: 1002858 + 2859: 1002859 + 2860: 1002860 + 2861: 1002861 + 2862: 1002862 + 2863: 1002863 + 2864: 1002864 + 2865: 1002865 + 2866: 1002866 + 2867: 1002867 + 2868: 1002868 + 2869: 1002869 + 2870: 1002870 + 2871: 1002871 + 2872: 1002872 + 2873: 1002873 + 2874: 1002874 + 2875: 1002875 + 2876: 1002876 + 2877: 1002877 + 2878: 1002878 + 2879: 1002879 + 2880: 1002880 + 2881: 1002881 + 2882: 1002882 + 2883: 1002883 + 2884: 1002884 + 2885: 1002885 + 2886: 1002886 + 2887: 1002887 + 2888: 1002888 + 2889: 1002889 + 2890: 1002890 + 2891: 1002891 + 2892: 1002892 + 2893: 1002893 + 2894: 1002894 + 2895: 1002895 + 2896: 1002896 + 2897: 1002897 + 2898: 1002898 + 2899: 1002899 + 2900: 1002900 + 2901: 1002901 + 2902: 1002902 + 2903: 1002903 + 2904: 1002904 + 2905: 1002905 + 2906: 1002906 + 2907: 1002907 + 2908: 1002908 + 2909: 1002909 + 2910: 1002910 + 2911: 1002911 + 2912: 1002912 + 2913: 1002913 + 2914: 1002914 + 2915: 1002915 + 2916: 1002916 + 2917: 1002917 + 2918: 1002918 + 2919: 1002919 + 2920: 1002920 + 2921: 1002921 + 2922: 1002922 + 2923: 1002923 + 2924: 1002924 + 2925: 1002925 + 2926: 1002926 + 2927: 1002927 + 2928: 1002928 + 2929: 1002929 + 2930: 1002930 + 2931: 1002931 + 2932: 1002932 + 2933: 1002933 + 2934: 1002934 + 2935: 1002935 + 2936: 1002936 + 2937: 1002937 + 2938: 1002938 + 2939: 1002939 + 2940: 1002940 + 2941: 1002941 + 2942: 1002942 + 2943: 1002943 + 2944: 1002944 + 2945: 1002945 + 2946: 1002946 + 2947: 1002947 + 2948: 1002948 + 2949: 1002949 + 2950: 1002950 + 2951: 1002951 + 2952: 1002952 + 2953: 1002953 + 2954: 1002954 + 2955: 1002955 + 2956: 1002956 + 2957: 1002957 + 2958: 1002958 + 2959: 1002959 + 2960: 1002960 + 2961: 1002961 + 2962: 1002962 + 2963: 1002963 + 2964: 1002964 + 2965: 1002965 + 2966: 1002966 + 2967: 1002967 + 2968: 1002968 + 2969: 1002969 + 2970: 1002970 + 2971: 1002971 + 2972: 1002972 + 2973: 1002973 + 2974: 1002974 + 2975: 1002975 + 2976: 1002976 + 2977: 1002977 + 2978: 1002978 + 2979: 1002979 + 2980: 1002980 + 2981: 1002981 + 2982: 1002982 + 2983: 1002983 + 2984: 1002984 + 2985: 1002985 + 2986: 1002986 + 2987: 1002987 + 2988: 1002988 + 2989: 1002989 + 2990: 1002990 + 2991: 1002991 + 2992: 1002992 + 2993: 1002993 + 2994: 1002994 + 2995: 1002995 + 2996: 1002996 + 2997: 1002997 + 2998: 1002998 + 2999: 1002999 + 3000: 1003000 + 3001: 1003001 + 3002: 1003002 + 3003: 1003003 + 3004: 1003004 + 3005: 1003005 + 3006: 1003006 + 3007: 1003007 + 3008: 1003008 + 3009: 1003009 + 3010: 1003010 + 3011: 1003011 + 3012: 1003012 + 3013: 1003013 + 3014: 1003014 + 3015: 1003015 + 3016: 1003016 + 3017: 1003017 + 3018: 1003018 + 3019: 1003019 + 3020: 1003020 + 3021: 1003021 + 3022: 1003022 + 3023: 1003023 + 3024: 1003024 + 3025: 1003025 + 3026: 1003026 + 3027: 1003027 + 3028: 1003028 + 3029: 1003029 + 3030: 1003030 + 3031: 1003031 + 3032: 1003032 + 3033: 1003033 + 3034: 1003034 + 3035: 1003035 + 3036: 1003036 + 3037: 1003037 + 3038: 1003038 + 3039: 1003039 + 3040: 1003040 + 3041: 1003041 + 3042: 1003042 + 3043: 1003043 + 3044: 1003044 + 3045: 1003045 + 3046: 1003046 + 3047: 1003047 + 3048: 1003048 + 3049: 1003049 + 3050: 1003050 + 3051: 1003051 + 3052: 1003052 + 3053: 1003053 + 3054: 1003054 + 3055: 1003055 + 3056: 1003056 + 3057: 1003057 + 3058: 1003058 + 3059: 1003059 + 3060: 1003060 + 3061: 1003061 + 3062: 1003062 + 3063: 1003063 + 3064: 1003064 + 3065: 1003065 + 3066: 1003066 + 3067: 1003067 + 3068: 1003068 + 3069: 1003069 + 3070: 1003070 + 3071: 1003071 + 3072: 1003072 + 3073: 1003073 + 3074: 1003074 + 3075: 1003075 + 3076: 1003076 + 3077: 1003077 + 3078: 1003078 + 3079: 1003079 + 3080: 1003080 + 3081: 1003081 + 3082: 1003082 + 3083: 1003083 + 3084: 1003084 + 3085: 1003085 + 3086: 1003086 + 3087: 1003087 + 3088: 1003088 + 3089: 1003089 + 3090: 1003090 + 3091: 1003091 + 3092: 1003092 + 3093: 1003093 + 3094: 1003094 + 3095: 1003095 + 3096: 1003096 + 3097: 1003097 + 3098: 1003098 + 3099: 1003099 + 3100: 1003100 + 3101: 1003101 + 3102: 1003102 + 3103: 1003103 + 3104: 1003104 + 3105: 1003105 + 3106: 1003106 + 3107: 1003107 + 3108: 1003108 + 3109: 1003109 + 3110: 1003110 + 3111: 1003111 + 3112: 1003112 + 3113: 1003113 + 3114: 1003114 + 3115: 1003115 + 3116: 1003116 + 3117: 1003117 + 3118: 1003118 + 3119: 1003119 + 3120: 1003120 + 3121: 1003121 + 3122: 1003122 + 3123: 1003123 + 3124: 1003124 + 3125: 1003125 + 3126: 1003126 + 3127: 1003127 + 3128: 1003128 + 3129: 1003129 + 3130: 1003130 + 3131: 1003131 + 3132: 1003132 + 3133: 1003133 + 3134: 1003134 + 3135: 1003135 + 3136: 1003136 + 3137: 1003137 + 3138: 1003138 + 3139: 1003139 + 3140: 1003140 + 3141: 1003141 + 3142: 1003142 + 3143: 1003143 + 3144: 1003144 + 3145: 1003145 + 3146: 1003146 + 3147: 1003147 + 3148: 1003148 + 3149: 1003149 + 3150: 1003150 + 3151: 1003151 + 3152: 1003152 + 3153: 1003153 + 3154: 1003154 + 3155: 1003155 + 3156: 1003156 + 3157: 1003157 + 3158: 1003158 + 3159: 1003159 + 3160: 1003160 + 3161: 1003161 + 3162: 1003162 + 3163: 1003163 + 3164: 1003164 + 3165: 1003165 + 3166: 1003166 + 3167: 1003167 + 3168: 1003168 + 3169: 1003169 + 3170: 1003170 + 3171: 1003171 + 3172: 1003172 + 3173: 1003173 + 3174: 1003174 + 3175: 1003175 + 3176: 1003176 + 3177: 1003177 + 3178: 1003178 + 3179: 1003179 + 3180: 1003180 + 3181: 1003181 + 3182: 1003182 + 3183: 1003183 + 3184: 1003184 + 3185: 1003185 + 3186: 1003186 + 3187: 1003187 + 3188: 1003188 + 3189: 1003189 + 3190: 1003190 + 3191: 1003191 + 3192: 1003192 + 3193: 1003193 + 3194: 1003194 + 3195: 1003195 + 3196: 1003196 + 3197: 1003197 + 3198: 1003198 + 3199: 1003199 + 3200: 1003200 + 3201: 1003201 + 3202: 1003202 + 3203: 1003203 + 3204: 1003204 + 3205: 1003205 + 3206: 1003206 + 3207: 1003207 + 3208: 1003208 + 3209: 1003209 + 3210: 1003210 + 3211: 1003211 + 3212: 1003212 + 3213: 1003213 + 3214: 1003214 + 3215: 1003215 + 3216: 1003216 + 3217: 1003217 + 3218: 1003218 + 3219: 1003219 + 3220: 1003220 + 3221: 1003221 + 3222: 1003222 + 3223: 1003223 + 3224: 1003224 + 3225: 1003225 + 3226: 1003226 + 3227: 1003227 + 3228: 1003228 + 3229: 1003229 + 3230: 1003230 + 3231: 1003231 + 3232: 1003232 + 3233: 1003233 + 3234: 1003234 + 3235: 1003235 + 3236: 1003236 + 3237: 1003237 + 3238: 1003238 + 3239: 1003239 + 3240: 1003240 + 3241: 1003241 + 3242: 1003242 + 3243: 1003243 + 3244: 1003244 + 3245: 1003245 + 3246: 1003246 + 3247: 1003247 + 3248: 1003248 + 3249: 1003249 + 3250: 1003250 + 3251: 1003251 + 3252: 1003252 + 3253: 1003253 + 3254: 1003254 + 3255: 1003255 + 3256: 1003256 + 3257: 1003257 + 3258: 1003258 + 3259: 1003259 + 3260: 1003260 + 3261: 1003261 + 3262: 1003262 + 3263: 1003263 + 3264: 1003264 + 3265: 1003265 + 3266: 1003266 + 3267: 1003267 + 3268: 1003268 + 3269: 1003269 + 3270: 1003270 + 3271: 1003271 + 3272: 1003272 + 3273: 1003273 + 3274: 1003274 + 3275: 1003275 + 3276: 1003276 + 3277: 1003277 + 3278: 1003278 + 3279: 1003279 + 3280: 1003280 + 3281: 1003281 + 3282: 1003282 + 3283: 1003283 + 3284: 1003284 + 3285: 1003285 + 3286: 1003286 + 3287: 1003287 + 3288: 1003288 + 3289: 1003289 + 3290: 1003290 + 3291: 1003291 + 3292: 1003292 + 3293: 1003293 + 3294: 1003294 + 3295: 1003295 + 3296: 1003296 + 3297: 1003297 + 3298: 1003298 + 3299: 1003299 + 3300: 1003300 + 3301: 1003301 + 3302: 1003302 + 3303: 1003303 + 3304: 1003304 + 3305: 1003305 + 3306: 1003306 + 3307: 1003307 + 3308: 1003308 + 3309: 1003309 + 3310: 1003310 + 3311: 1003311 + 3312: 1003312 + 3313: 1003313 + 3314: 1003314 + 3315: 1003315 + 3316: 1003316 + 3317: 1003317 + 3318: 1003318 + 3319: 1003319 + 3320: 1003320 + 3321: 1003321 + 3322: 1003322 + 3323: 1003323 + 3324: 1003324 + 3325: 1003325 + 3326: 1003326 + 3327: 1003327 + 3328: 1003328 + 3329: 1003329 + 3330: 1003330 + 3331: 1003331 + 3332: 1003332 + 3333: 1003333 + 3334: 1003334 + 3335: 1003335 + 3336: 1003336 + 3337: 1003337 + 3338: 1003338 + 3339: 1003339 + 3340: 1003340 + 3341: 1003341 + 3342: 1003342 + 3343: 1003343 + 3344: 1003344 + 3345: 1003345 + 3346: 1003346 + 3347: 1003347 + 3348: 1003348 + 3349: 1003349 + 3350: 1003350 + 3351: 1003351 + 3352: 1003352 + 3353: 1003353 + 3354: 1003354 + 3355: 1003355 + 3356: 1003356 + 3357: 1003357 + 3358: 1003358 + 3359: 1003359 + 3360: 1003360 + 3361: 1003361 + 3362: 1003362 + 3363: 1003363 + 3364: 1003364 + 3365: 1003365 + 3366: 1003366 + 3367: 1003367 + 3368: 1003368 + 3369: 1003369 + 3370: 1003370 + 3371: 1003371 + 3372: 1003372 + 3373: 1003373 + 3374: 1003374 + 3375: 1003375 + 3376: 1003376 + 3377: 1003377 + 3378: 1003378 + 3379: 1003379 + 3380: 1003380 + 3381: 1003381 + 3382: 1003382 + 3383: 1003383 + 3384: 1003384 + 3385: 1003385 + 3386: 1003386 + 3387: 1003387 + 3388: 1003388 + 3389: 1003389 + 3390: 1003390 + 3391: 1003391 + 3392: 1003392 + 3393: 1003393 + 3394: 1003394 + 3395: 1003395 + 3396: 1003396 + 3397: 1003397 + 3398: 1003398 + 3399: 1003399 + 3400: 1003400 + 3401: 1003401 + 3402: 1003402 + 3403: 1003403 + 3404: 1003404 + 3405: 1003405 + 3406: 1003406 + 3407: 1003407 + 3408: 1003408 + 3409: 1003409 + 3410: 1003410 + 3411: 1003411 + 3412: 1003412 + 3413: 1003413 + 3414: 1003414 + 3415: 1003415 + 3416: 1003416 + 3417: 1003417 + 3418: 1003418 + 3419: 1003419 + 3420: 1003420 + 3421: 1003421 + 3422: 1003422 + 3423: 1003423 + 3424: 1003424 + 3425: 1003425 + 3426: 1003426 + 3427: 1003427 + 3428: 1003428 + 3429: 1003429 + 3430: 1003430 + 3431: 1003431 + 3432: 1003432 + 3433: 1003433 + 3434: 1003434 + 3435: 1003435 + 3436: 1003436 + 3437: 1003437 + 3438: 1003438 + 3439: 1003439 + 3440: 1003440 + 3441: 1003441 + 3442: 1003442 + 3443: 1003443 + 3444: 1003444 + 3445: 1003445 + 3446: 1003446 + 3447: 1003447 + 3448: 1003448 + 3449: 1003449 + 3450: 1003450 + 3451: 1003451 + 3452: 1003452 + 3453: 1003453 + 3454: 1003454 + 3455: 1003455 + 3456: 1003456 + 3457: 1003457 + 3458: 1003458 + 3459: 1003459 + 3460: 1003460 + 3461: 1003461 + 3462: 1003462 + 3463: 1003463 + 3464: 1003464 + 3465: 1003465 + 3466: 1003466 + 3467: 1003467 + 3468: 1003468 + 3469: 1003469 + 3470: 1003470 + 3471: 1003471 + 3472: 1003472 + 3473: 1003473 + 3474: 1003474 + 3475: 1003475 + 3476: 1003476 + 3477: 1003477 + 3478: 1003478 + 3479: 1003479 + 3480: 1003480 + 3481: 1003481 + 3482: 1003482 + 3483: 1003483 + 3484: 1003484 + 3485: 1003485 + 3486: 1003486 + 3487: 1003487 + 3488: 1003488 + 3489: 1003489 + 3490: 1003490 + 3491: 1003491 + 3492: 1003492 + 3493: 1003493 + 3494: 1003494 + 3495: 1003495 + 3496: 1003496 + 3497: 1003497 + 3498: 1003498 + 3499: 1003499 + 3500: 1003500 + 3501: 1003501 + 3502: 1003502 + 3503: 1003503 + 3504: 1003504 + 3505: 1003505 + 3506: 1003506 + 3507: 1003507 + 3508: 1003508 + 3509: 1003509 + 3510: 1003510 + 3511: 1003511 + 3512: 1003512 + 3513: 1003513 + 3514: 1003514 + 3515: 1003515 + 3516: 1003516 + 3517: 1003517 + 3518: 1003518 + 3519: 1003519 + 3520: 1003520 + 3521: 1003521 + 3522: 1003522 + 3523: 1003523 + 3524: 1003524 + 3525: 1003525 + 3526: 1003526 + 3527: 1003527 + 3528: 1003528 + 3529: 1003529 + 3530: 1003530 + 3531: 1003531 + 3532: 1003532 + 3533: 1003533 + 3534: 1003534 + 3535: 1003535 + 3536: 1003536 + 3537: 1003537 + 3538: 1003538 + 3539: 1003539 + 3540: 1003540 + 3541: 1003541 + 3542: 1003542 + 3543: 1003543 + 3544: 1003544 + 3545: 1003545 + 3546: 1003546 + 3547: 1003547 + 3548: 1003548 + 3549: 1003549 + 3550: 1003550 + 3551: 1003551 + 3552: 1003552 + 3553: 1003553 + 3554: 1003554 + 3555: 1003555 + 3556: 1003556 + 3557: 1003557 + 3558: 1003558 + 3559: 1003559 + 3560: 1003560 + 3561: 1003561 + 3562: 1003562 + 3563: 1003563 + 3564: 1003564 + 3565: 1003565 + 3566: 1003566 + 3567: 1003567 + 3568: 1003568 + 3569: 1003569 + 3570: 1003570 + 3571: 1003571 + 3572: 1003572 + 3573: 1003573 + 3574: 1003574 + 3575: 1003575 + 3576: 1003576 + 3577: 1003577 + 3578: 1003578 + 3579: 1003579 + 3580: 1003580 + 3581: 1003581 + 3582: 1003582 + 3583: 1003583 + 3584: 1003584 + 3585: 1003585 + 3586: 1003586 + 3587: 1003587 + 3588: 1003588 + 3589: 1003589 + 3590: 1003590 + 3591: 1003591 + 3592: 1003592 + 3593: 1003593 + 3594: 1003594 + 3595: 1003595 + 3596: 1003596 + 3597: 1003597 + 3598: 1003598 + 3599: 1003599 + 3600: 1003600 + 3601: 1003601 + 3602: 1003602 + 3603: 1003603 + 3604: 1003604 + 3605: 1003605 + 3606: 1003606 + 3607: 1003607 + 3608: 1003608 + 3609: 1003609 + 3610: 1003610 + 3611: 1003611 + 3612: 1003612 + 3613: 1003613 + 3614: 1003614 + 3615: 1003615 + 3616: 1003616 + 3617: 1003617 + 3618: 1003618 + 3619: 1003619 + 3620: 1003620 + 3621: 1003621 + 3622: 1003622 + 3623: 1003623 + 3624: 1003624 + 3625: 1003625 + 3626: 1003626 + 3627: 1003627 + 3628: 1003628 + 3629: 1003629 + 3630: 1003630 + 3631: 1003631 + 3632: 1003632 + 3633: 1003633 + 3634: 1003634 + 3635: 1003635 + 3636: 1003636 + 3637: 1003637 + 3638: 1003638 + 3639: 1003639 + 3640: 1003640 + 3641: 1003641 + 3642: 1003642 + 3643: 1003643 + 3644: 1003644 + 3645: 1003645 + 3646: 1003646 + 3647: 1003647 + 3648: 1003648 + 3649: 1003649 + 3650: 1003650 + 3651: 1003651 + 3652: 1003652 + 3653: 1003653 + 3654: 1003654 + 3655: 1003655 + 3656: 1003656 + 3657: 1003657 + 3658: 1003658 + 3659: 1003659 + 3660: 1003660 + 3661: 1003661 + 3662: 1003662 + 3663: 1003663 + 3664: 1003664 + 3665: 1003665 + 3666: 1003666 + 3667: 1003667 + 3668: 1003668 + 3669: 1003669 + 3670: 1003670 + 3671: 1003671 + 3672: 1003672 + 3673: 1003673 + 3674: 1003674 + 3675: 1003675 + 3676: 1003676 + 3677: 1003677 + 3678: 1003678 + 3679: 1003679 + 3680: 1003680 + 3681: 1003681 + 3682: 1003682 + 3683: 1003683 + 3684: 1003684 + 3685: 1003685 + 3686: 1003686 + 3687: 1003687 + 3688: 1003688 + 3689: 1003689 + 3690: 1003690 + 3691: 1003691 + 3692: 1003692 + 3693: 1003693 + 3694: 1003694 + 3695: 1003695 + 3696: 1003696 + 3697: 1003697 + 3698: 1003698 + 3699: 1003699 + 3700: 1003700 + 3701: 1003701 + 3702: 1003702 + 3703: 1003703 + 3704: 1003704 + 3705: 1003705 + 3706: 1003706 + 3707: 1003707 + 3708: 1003708 + 3709: 1003709 + 3710: 1003710 + 3711: 1003711 + 3712: 1003712 + 3713: 1003713 + 3714: 1003714 + 3715: 1003715 + 3716: 1003716 + 3717: 1003717 + 3718: 1003718 + 3719: 1003719 + 3720: 1003720 + 3721: 1003721 + 3722: 1003722 + 3723: 1003723 + 3724: 1003724 + 3725: 1003725 + 3726: 1003726 + 3727: 1003727 + 3728: 1003728 + 3729: 1003729 + 3730: 1003730 + 3731: 1003731 + 3732: 1003732 + 3733: 1003733 + 3734: 1003734 + 3735: 1003735 + 3736: 1003736 + 3737: 1003737 + 3738: 1003738 + 3739: 1003739 + 3740: 1003740 + 3741: 1003741 + 3742: 1003742 + 3743: 1003743 + 3744: 1003744 + 3745: 1003745 + 3746: 1003746 + 3747: 1003747 + 3748: 1003748 + 3749: 1003749 + 3750: 1003750 + 3751: 1003751 + 3752: 1003752 + 3753: 1003753 + 3754: 1003754 + 3755: 1003755 + 3756: 1003756 + 3757: 1003757 + 3758: 1003758 + 3759: 1003759 + 3760: 1003760 + 3761: 1003761 + 3762: 1003762 + 3763: 1003763 + 3764: 1003764 + 3765: 1003765 + 3766: 1003766 + 3767: 1003767 + 3768: 1003768 + 3769: 1003769 + 3770: 1003770 + 3771: 1003771 + 3772: 1003772 + 3773: 1003773 + 3774: 1003774 + 3775: 1003775 + 3776: 1003776 + 3777: 1003777 + 3778: 1003778 + 3779: 1003779 + 3780: 1003780 + 3781: 1003781 + 3782: 1003782 + 3783: 1003783 + 3784: 1003784 + 3785: 1003785 + 3786: 1003786 + 3787: 1003787 + 3788: 1003788 + 3789: 1003789 + 3790: 1003790 + 3791: 1003791 + 3792: 1003792 + 3793: 1003793 + 3794: 1003794 + 3795: 1003795 + 3796: 1003796 + 3797: 1003797 + 3798: 1003798 + 3799: 1003799 + 3800: 1003800 + 3801: 1003801 + 3802: 1003802 + 3803: 1003803 + 3804: 1003804 + 3805: 1003805 + 3806: 1003806 + 3807: 1003807 + 3808: 1003808 + 3809: 1003809 + 3810: 1003810 + 3811: 1003811 + 3812: 1003812 + 3813: 1003813 + 3814: 1003814 + 3815: 1003815 + 3816: 1003816 + 3817: 1003817 + 3818: 1003818 + 3819: 1003819 + 3820: 1003820 + 3821: 1003821 + 3822: 1003822 + 3823: 1003823 + 3824: 1003824 + 3825: 1003825 + 3826: 1003826 + 3827: 1003827 + 3828: 1003828 + 3829: 1003829 + 3830: 1003830 + 3831: 1003831 + 3832: 1003832 + 3833: 1003833 + 3834: 1003834 + 3835: 1003835 + 3836: 1003836 + 3837: 1003837 + 3838: 1003838 + 3839: 1003839 + 3840: 1003840 + 3841: 1003841 + 3842: 1003842 + 3843: 1003843 + 3844: 1003844 + 3845: 1003845 + 3846: 1003846 + 3847: 1003847 + 3848: 1003848 + 3849: 1003849 + 3850: 1003850 + 3851: 1003851 + 3852: 1003852 + 3853: 1003853 + 3854: 1003854 + 3855: 1003855 + 3856: 1003856 + 3857: 1003857 + 3858: 1003858 + 3859: 1003859 + 3860: 1003860 + 3861: 1003861 + 3862: 1003862 + 3863: 1003863 + 3864: 1003864 + 3865: 1003865 + 3866: 1003866 + 3867: 1003867 + 3868: 1003868 + 3869: 1003869 + 3870: 1003870 + 3871: 1003871 + 3872: 1003872 + 3873: 1003873 + 3874: 1003874 + 3875: 1003875 + 3876: 1003876 + 3877: 1003877 + 3878: 1003878 + 3879: 1003879 + 3880: 1003880 + 3881: 1003881 + 3882: 1003882 + 3883: 1003883 + 3884: 1003884 + 3885: 1003885 + 3886: 1003886 + 3887: 1003887 + 3888: 1003888 + 3889: 1003889 + 3890: 1003890 + 3891: 1003891 + 3892: 1003892 + 3893: 1003893 + 3894: 1003894 + 3895: 1003895 + 3896: 1003896 + 3897: 1003897 + 3898: 1003898 + 3899: 1003899 + 3900: 1003900 + 3901: 1003901 + 3902: 1003902 + 3903: 1003903 + 3904: 1003904 + 3905: 1003905 + 3906: 1003906 + 3907: 1003907 + 3908: 1003908 + 3909: 1003909 + 3910: 1003910 + 3911: 1003911 + 3912: 1003912 + 3913: 1003913 + 3914: 1003914 + 3915: 1003915 + 3916: 1003916 + 3917: 1003917 + 3918: 1003918 + 3919: 1003919 + 3920: 1003920 + 3921: 1003921 + 3922: 1003922 + 3923: 1003923 + 3924: 1003924 + 3925: 1003925 + 3926: 1003926 + 3927: 1003927 + 3928: 1003928 + 3929: 1003929 + 3930: 1003930 + 3931: 1003931 + 3932: 1003932 + 3933: 1003933 + 3934: 1003934 + 3935: 1003935 + 3936: 1003936 + 3937: 1003937 + 3938: 1003938 + 3939: 1003939 + 3940: 1003940 + 3941: 1003941 + 3942: 1003942 + 3943: 1003943 + 3944: 1003944 + 3945: 1003945 + 3946: 1003946 + 3947: 1003947 + 3948: 1003948 + 3949: 1003949 + 3950: 1003950 + 3951: 1003951 + 3952: 1003952 + 3953: 1003953 + 3954: 1003954 + 3955: 1003955 + 3956: 1003956 + 3957: 1003957 + 3958: 1003958 + 3959: 1003959 + 3960: 1003960 + 3961: 1003961 + 3962: 1003962 + 3963: 1003963 + 3964: 1003964 + 3965: 1003965 + 3966: 1003966 + 3967: 1003967 + 3968: 1003968 + 3969: 1003969 + 3970: 1003970 + 3971: 1003971 + 3972: 1003972 + 3973: 1003973 + 3974: 1003974 + 3975: 1003975 + 3976: 1003976 + 3977: 1003977 + 3978: 1003978 + 3979: 1003979 + 3980: 1003980 + 3981: 1003981 + 3982: 1003982 + 3983: 1003983 + 3984: 1003984 + 3985: 1003985 + 3986: 1003986 + 3987: 1003987 + 3988: 1003988 + 3989: 1003989 + 3990: 1003990 + 3991: 1003991 + 3992: 1003992 + 3993: 1003993 + 3994: 1003994 + 3995: 1003995 + 3996: 1003996 + 3997: 1003997 + 3998: 1003998 + 3999: 1003999 + 4000: 1004000 + 4001: 1004001 + 4002: 1004002 + 4003: 1004003 + 4004: 1004004 + 4005: 1004005 + 4006: 1004006 + 4007: 1004007 + 4008: 1004008 + 4009: 1004009 + 4010: 1004010 + 4011: 1004011 + 4012: 1004012 + 4013: 1004013 + 4014: 1004014 + 4015: 1004015 + 4016: 1004016 + 4017: 1004017 + 4018: 1004018 + 4019: 1004019 + 4020: 1004020 + 4021: 1004021 + 4022: 1004022 + 4023: 1004023 + 4024: 1004024 + 4025: 1004025 + 4026: 1004026 + 4027: 1004027 + 4028: 1004028 + 4029: 1004029 + 4030: 1004030 + 4031: 1004031 + 4032: 1004032 + 4033: 1004033 + 4034: 1004034 + 4035: 1004035 + 4036: 1004036 + 4037: 1004037 + 4038: 1004038 + 4039: 1004039 + 4040: 1004040 + 4041: 1004041 + 4042: 1004042 + 4043: 1004043 + 4044: 1004044 + 4045: 1004045 + 4046: 1004046 + 4047: 1004047 + 4048: 1004048 + 4049: 1004049 + 4050: 1004050 + 4051: 1004051 + 4052: 1004052 + 4053: 1004053 + 4054: 1004054 + 4055: 1004055 + 4056: 1004056 + 4057: 1004057 + 4058: 1004058 + 4059: 1004059 + 4060: 1004060 + 4061: 1004061 + 4062: 1004062 + 4063: 1004063 + 4064: 1004064 + 4065: 1004065 + 4066: 1004066 + 4067: 1004067 + 4068: 1004068 + 4069: 1004069 + 4070: 1004070 + 4071: 1004071 + 4072: 1004072 + 4073: 1004073 + 4074: 1004074 + 4075: 1004075 + 4076: 1004076 + 4077: 1004077 + 4078: 1004078 + 4079: 1004079 + 4080: 1004080 + 4081: 1004081 + 4082: 1004082 + 4083: 1004083 + 4084: 1004084 + 4085: 1004085 + 4086: 1004086 + 4087: 1004087 + 4088: 1004088 + 4089: 1004089 + 4090: 1004090 + 4091: 1004091 + 4092: 1004092 + 4093: 1004093 + 4094: 1004094 + 4095: 1004095 + 4096: 1004096 + 4097: 1004097 + 4098: 1004098 + 4099: 1004099 + 4100: 1004100 + 4101: 1004101 + 4102: 1004102 + 4103: 1004103 + 4104: 1004104 + 4105: 1004105 + 4106: 1004106 + 4107: 1004107 + 4108: 1004108 + 4109: 1004109 + 4110: 1004110 + 4111: 1004111 + 4112: 1004112 + 4113: 1004113 + 4114: 1004114 + 4115: 1004115 + 4116: 1004116 + 4117: 1004117 + 4118: 1004118 + 4119: 1004119 + 4120: 1004120 + 4121: 1004121 + 4122: 1004122 + 4123: 1004123 + 4124: 1004124 + 4125: 1004125 + 4126: 1004126 + 4127: 1004127 + 4128: 1004128 + 4129: 1004129 + 4130: 1004130 + 4131: 1004131 + 4132: 1004132 + 4133: 1004133 + 4134: 1004134 + 4135: 1004135 + 4136: 1004136 + 4137: 1004137 + 4138: 1004138 + 4139: 1004139 + 4140: 1004140 + 4141: 1004141 + 4142: 1004142 + 4143: 1004143 + 4144: 1004144 + 4145: 1004145 + 4146: 1004146 + 4147: 1004147 + 4148: 1004148 + 4149: 1004149 + 4150: 1004150 + 4151: 1004151 + 4152: 1004152 + 4153: 1004153 + 4154: 1004154 + 4155: 1004155 + 4156: 1004156 + 4157: 1004157 + 4158: 1004158 + 4159: 1004159 + 4160: 1004160 + 4161: 1004161 + 4162: 1004162 + 4163: 1004163 + 4164: 1004164 + 4165: 1004165 + 4166: 1004166 + 4167: 1004167 + 4168: 1004168 + 4169: 1004169 + 4170: 1004170 + 4171: 1004171 + 4172: 1004172 + 4173: 1004173 + 4174: 1004174 + 4175: 1004175 + 4176: 1004176 + 4177: 1004177 + 4178: 1004178 + 4179: 1004179 + 4180: 1004180 + 4181: 1004181 + 4182: 1004182 + 4183: 1004183 + 4184: 1004184 + 4185: 1004185 + 4186: 1004186 + 4187: 1004187 + 4188: 1004188 + 4189: 1004189 + 4190: 1004190 + 4191: 1004191 + 4192: 1004192 + 4193: 1004193 + 4194: 1004194 + 4195: 1004195 + 4196: 1004196 + 4197: 1004197 + 4198: 1004198 + 4199: 1004199 + 4200: 1004200 + 4201: 1004201 + 4202: 1004202 + 4203: 1004203 + 4204: 1004204 + 4205: 1004205 + 4206: 1004206 + 4207: 1004207 + 4208: 1004208 + 4209: 1004209 + 4210: 1004210 + 4211: 1004211 + 4212: 1004212 + 4213: 1004213 + 4214: 1004214 + 4215: 1004215 + 4216: 1004216 + 4217: 1004217 + 4218: 1004218 + 4219: 1004219 + 4220: 1004220 + 4221: 1004221 + 4222: 1004222 + 4223: 1004223 + 4224: 1004224 + 4225: 1004225 + 4226: 1004226 + 4227: 1004227 + 4228: 1004228 + 4229: 1004229 + 4230: 1004230 + 4231: 1004231 + 4232: 1004232 + 4233: 1004233 + 4234: 1004234 + 4235: 1004235 + 4236: 1004236 + 4237: 1004237 + 4238: 1004238 + 4239: 1004239 + 4240: 1004240 + 4241: 1004241 + 4242: 1004242 + 4243: 1004243 + 4244: 1004244 + 4245: 1004245 + 4246: 1004246 + 4247: 1004247 + 4248: 1004248 + 4249: 1004249 + 4250: 1004250 + 4251: 1004251 + 4252: 1004252 + 4253: 1004253 + 4254: 1004254 + 4255: 1004255 + 4256: 1004256 + 4257: 1004257 + 4258: 1004258 + 4259: 1004259 + 4260: 1004260 + 4261: 1004261 + 4262: 1004262 + 4263: 1004263 + 4264: 1004264 + 4265: 1004265 + 4266: 1004266 + 4267: 1004267 + 4268: 1004268 + 4269: 1004269 + 4270: 1004270 + 4271: 1004271 + 4272: 1004272 + 4273: 1004273 + 4274: 1004274 + 4275: 1004275 + 4276: 1004276 + 4277: 1004277 + 4278: 1004278 + 4279: 1004279 + 4280: 1004280 + 4281: 1004281 + 4282: 1004282 + 4283: 1004283 + 4284: 1004284 + 4285: 1004285 + 4286: 1004286 + 4287: 1004287 + 4288: 1004288 + 4289: 1004289 + 4290: 1004290 + 4291: 1004291 + 4292: 1004292 + 4293: 1004293 + 4294: 1004294 + 4295: 1004295 + 4296: 1004296 + 4297: 1004297 + 4298: 1004298 + 4299: 1004299 + 4300: 1004300 + 4301: 1004301 + 4302: 1004302 + 4303: 1004303 + 4304: 1004304 + 4305: 1004305 + 4306: 1004306 + 4307: 1004307 + 4308: 1004308 + 4309: 1004309 + 4310: 1004310 + 4311: 1004311 + 4312: 1004312 + 4313: 1004313 + 4314: 1004314 + 4315: 1004315 + 4316: 1004316 + 4317: 1004317 + 4318: 1004318 + 4319: 1004319 + 4320: 1004320 + 4321: 1004321 + 4322: 1004322 + 4323: 1004323 + 4324: 1004324 + 4325: 1004325 + 4326: 1004326 + 4327: 1004327 + 4328: 1004328 + 4329: 1004329 + 4330: 1004330 + 4331: 1004331 + 4332: 1004332 + 4333: 1004333 + 4334: 1004334 + 4335: 1004335 + 4336: 1004336 + 4337: 1004337 + 4338: 1004338 + 4339: 1004339 + 4340: 1004340 + 4341: 1004341 + 4342: 1004342 + 4343: 1004343 + 4344: 1004344 + 4345: 1004345 + 4346: 1004346 + 4347: 1004347 + 4348: 1004348 + 4349: 1004349 + 4350: 1004350 + 4351: 1004351 + 4352: 1004352 + 4353: 1004353 + 4354: 1004354 + 4355: 1004355 + 4356: 1004356 + 4357: 1004357 + 4358: 1004358 + 4359: 1004359 + 4360: 1004360 + 4361: 1004361 + 4362: 1004362 + 4363: 1004363 + 4364: 1004364 + 4365: 1004365 + 4366: 1004366 + 4367: 1004367 + 4368: 1004368 + 4369: 1004369 + 4370: 1004370 + 4371: 1004371 + 4372: 1004372 + 4373: 1004373 + 4374: 1004374 + 4375: 1004375 + 4376: 1004376 + 4377: 1004377 + 4378: 1004378 + 4379: 1004379 + 4380: 1004380 + 4381: 1004381 + 4382: 1004382 + 4383: 1004383 + 4384: 1004384 + 4385: 1004385 + 4386: 1004386 + 4387: 1004387 + 4388: 1004388 + 4389: 1004389 + 4390: 1004390 + 4391: 1004391 + 4392: 1004392 + 4393: 1004393 + 4394: 1004394 + 4395: 1004395 + 4396: 1004396 + 4397: 1004397 + 4398: 1004398 + 4399: 1004399 + 4400: 1004400 + 4401: 1004401 + 4402: 1004402 + 4403: 1004403 + 4404: 1004404 + 4405: 1004405 + 4406: 1004406 + 4407: 1004407 + 4408: 1004408 + 4409: 1004409 + 4410: 1004410 + 4411: 1004411 + 4412: 1004412 + 4413: 1004413 + 4414: 1004414 + 4415: 1004415 + 4416: 1004416 + 4417: 1004417 + 4418: 1004418 + 4419: 1004419 + 4420: 1004420 + 4421: 1004421 + 4422: 1004422 + 4423: 1004423 + 4424: 1004424 + 4425: 1004425 + 4426: 1004426 + 4427: 1004427 + 4428: 1004428 + 4429: 1004429 + 4430: 1004430 + 4431: 1004431 + 4432: 1004432 + 4433: 1004433 + 4434: 1004434 + 4435: 1004435 + 4436: 1004436 + 4437: 1004437 + 4438: 1004438 + 4439: 1004439 + 4440: 1004440 + 4441: 1004441 + 4442: 1004442 + 4443: 1004443 + 4444: 1004444 + 4445: 1004445 + 4446: 1004446 + 4447: 1004447 + 4448: 1004448 + 4449: 1004449 + 4450: 1004450 + 4451: 1004451 + 4452: 1004452 + 4453: 1004453 + 4454: 1004454 + 4455: 1004455 + 4456: 1004456 + 4457: 1004457 + 4458: 1004458 + 4459: 1004459 + 4460: 1004460 + 4461: 1004461 + 4462: 1004462 + 4463: 1004463 + 4464: 1004464 + 4465: 1004465 + 4466: 1004466 + 4467: 1004467 + 4468: 1004468 + 4469: 1004469 + 4470: 1004470 + 4471: 1004471 + 4472: 1004472 + 4473: 1004473 + 4474: 1004474 + 4475: 1004475 + 4476: 1004476 + 4477: 1004477 + 4478: 1004478 + 4479: 1004479 + 4480: 1004480 + 4481: 1004481 + 4482: 1004482 + 4483: 1004483 + 4484: 1004484 + 4485: 1004485 + 4486: 1004486 + 4487: 1004487 + 4488: 1004488 + 4489: 1004489 + 4490: 1004490 + 4491: 1004491 + 4492: 1004492 + 4493: 1004493 + 4494: 1004494 + 4495: 1004495 + 4496: 1004496 + 4497: 1004497 + 4498: 1004498 + 4499: 1004499 + 4500: 1004500 + 4501: 1004501 + 4502: 1004502 + 4503: 1004503 + 4504: 1004504 + 4505: 1004505 + 4506: 1004506 + 4507: 1004507 + 4508: 1004508 + 4509: 1004509 + 4510: 1004510 + 4511: 1004511 + 4512: 1004512 + 4513: 1004513 + 4514: 1004514 + 4515: 1004515 + 4516: 1004516 + 4517: 1004517 + 4518: 1004518 + 4519: 1004519 + 4520: 1004520 + 4521: 1004521 + 4522: 1004522 + 4523: 1004523 + 4524: 1004524 + 4525: 1004525 + 4526: 1004526 + 4527: 1004527 + 4528: 1004528 + 4529: 1004529 + 4530: 1004530 + 4531: 1004531 + 4532: 1004532 + 4533: 1004533 + 4534: 1004534 + 4535: 1004535 + 4536: 1004536 + 4537: 1004537 + 4538: 1004538 + 4539: 1004539 + 4540: 1004540 + 4541: 1004541 + 4542: 1004542 + 4543: 1004543 + 4544: 1004544 + 4545: 1004545 + 4546: 1004546 + 4547: 1004547 + 4548: 1004548 + 4549: 1004549 + 4550: 1004550 + 4551: 1004551 + 4552: 1004552 + 4553: 1004553 + 4554: 1004554 + 4555: 1004555 + 4556: 1004556 + 4557: 1004557 + 4558: 1004558 + 4559: 1004559 + 4560: 1004560 + 4561: 1004561 + 4562: 1004562 + 4563: 1004563 + 4564: 1004564 + 4565: 1004565 + 4566: 1004566 + 4567: 1004567 + 4568: 1004568 + 4569: 1004569 + 4570: 1004570 + 4571: 1004571 + 4572: 1004572 + 4573: 1004573 + 4574: 1004574 + 4575: 1004575 + 4576: 1004576 + 4577: 1004577 + 4578: 1004578 + 4579: 1004579 + 4580: 1004580 + 4581: 1004581 + 4582: 1004582 + 4583: 1004583 + 4584: 1004584 + 4585: 1004585 + 4586: 1004586 + 4587: 1004587 + 4588: 1004588 + 4589: 1004589 + 4590: 1004590 + 4591: 1004591 + 4592: 1004592 + 4593: 1004593 + 4594: 1004594 + 4595: 1004595 + 4596: 1004596 + 4597: 1004597 + 4598: 1004598 + 4599: 1004599 + 4600: 1004600 + 4601: 1004601 + 4602: 1004602 + 4603: 1004603 + 4604: 1004604 + 4605: 1004605 + 4606: 1004606 + 4607: 1004607 + 4608: 1004608 + 4609: 1004609 + 4610: 1004610 + 4611: 1004611 + 4612: 1004612 + 4613: 1004613 + 4614: 1004614 + 4615: 1004615 + 4616: 1004616 + 4617: 1004617 + 4618: 1004618 + 4619: 1004619 + 4620: 1004620 + 4621: 1004621 + 4622: 1004622 + 4623: 1004623 + 4624: 1004624 + 4625: 1004625 + 4626: 1004626 + 4627: 1004627 + 4628: 1004628 + 4629: 1004629 + 4630: 1004630 + 4631: 1004631 + 4632: 1004632 + 4633: 1004633 + 4634: 1004634 + 4635: 1004635 + 4636: 1004636 + 4637: 1004637 + 4638: 1004638 + 4639: 1004639 + 4640: 1004640 + 4641: 1004641 + 4642: 1004642 + 4643: 1004643 + 4644: 1004644 + 4645: 1004645 + 4646: 1004646 + 4647: 1004647 + 4648: 1004648 + 4649: 1004649 + 4650: 1004650 + 4651: 1004651 + 4652: 1004652 + 4653: 1004653 + 4654: 1004654 + 4655: 1004655 + 4656: 1004656 + 4657: 1004657 + 4658: 1004658 + 4659: 1004659 + 4660: 1004660 + 4661: 1004661 + 4662: 1004662 + 4663: 1004663 + 4664: 1004664 + 4665: 1004665 + 4666: 1004666 + 4667: 1004667 + 4668: 1004668 + 4669: 1004669 + 4670: 1004670 + 4671: 1004671 + 4672: 1004672 + 4673: 1004673 + 4674: 1004674 + 4675: 1004675 + 4676: 1004676 + 4677: 1004677 + 4678: 1004678 + 4679: 1004679 + 4680: 1004680 + 4681: 1004681 + 4682: 1004682 + 4683: 1004683 + 4684: 1004684 + 4685: 1004685 + 4686: 1004686 + 4687: 1004687 + 4688: 1004688 + 4689: 1004689 + 4690: 1004690 + 4691: 1004691 + 4692: 1004692 + 4693: 1004693 + 4694: 1004694 + 4695: 1004695 + 4696: 1004696 + 4697: 1004697 + 4698: 1004698 + 4699: 1004699 + 4700: 1004700 + 4701: 1004701 + 4702: 1004702 + 4703: 1004703 + 4704: 1004704 + 4705: 1004705 + 4706: 1004706 + 4707: 1004707 + 4708: 1004708 + 4709: 1004709 + 4710: 1004710 + 4711: 1004711 + 4712: 1004712 + 4713: 1004713 + 4714: 1004714 + 4715: 1004715 + 4716: 1004716 + 4717: 1004717 + 4718: 1004718 + 4719: 1004719 + 4720: 1004720 + 4721: 1004721 + 4722: 1004722 + 4723: 1004723 + 4724: 1004724 + 4725: 1004725 + 4726: 1004726 + 4727: 1004727 + 4728: 1004728 + 4729: 1004729 + 4730: 1004730 + 4731: 1004731 + 4732: 1004732 + 4733: 1004733 + 4734: 1004734 + 4735: 1004735 + 4736: 1004736 + 4737: 1004737 + 4738: 1004738 + 4739: 1004739 + 4740: 1004740 + 4741: 1004741 + 4742: 1004742 + 4743: 1004743 + 4744: 1004744 + 4745: 1004745 + 4746: 1004746 + 4747: 1004747 + 4748: 1004748 + 4749: 1004749 + 4750: 1004750 + 4751: 1004751 + 4752: 1004752 + 4753: 1004753 + 4754: 1004754 + 4755: 1004755 + 4756: 1004756 + 4757: 1004757 + 4758: 1004758 + 4759: 1004759 + 4760: 1004760 + 4761: 1004761 + 4762: 1004762 + 4763: 1004763 + 4764: 1004764 + 4765: 1004765 + 4766: 1004766 + 4767: 1004767 + 4768: 1004768 + 4769: 1004769 + 4770: 1004770 + 4771: 1004771 + 4772: 1004772 + 4773: 1004773 + 4774: 1004774 + 4775: 1004775 + 4776: 1004776 + 4777: 1004777 + 4778: 1004778 + 4779: 1004779 + 4780: 1004780 + 4781: 1004781 + 4782: 1004782 + 4783: 1004783 + 4784: 1004784 + 4785: 1004785 + 4786: 1004786 + 4787: 1004787 + 4788: 1004788 + 4789: 1004789 + 4790: 1004790 + 4791: 1004791 + 4792: 1004792 + 4793: 1004793 + 4794: 1004794 + 4795: 1004795 + 4796: 1004796 + 4797: 1004797 + 4798: 1004798 + 4799: 1004799 + 4800: 1004800 + 4801: 1004801 + 4802: 1004802 + 4803: 1004803 + 4804: 1004804 + 4805: 1004805 + 4806: 1004806 + 4807: 1004807 + 4808: 1004808 + 4809: 1004809 + 4810: 1004810 + 4811: 1004811 + 4812: 1004812 + 4813: 1004813 + 4814: 1004814 + 4815: 1004815 + 4816: 1004816 + 4817: 1004817 + 4818: 1004818 + 4819: 1004819 + 4820: 1004820 + 4821: 1004821 + 4822: 1004822 + 4823: 1004823 + 4824: 1004824 + 4825: 1004825 + 4826: 1004826 + 4827: 1004827 + 4828: 1004828 + 4829: 1004829 + 4830: 1004830 + 4831: 1004831 + 4832: 1004832 + 4833: 1004833 + 4834: 1004834 + 4835: 1004835 + 4836: 1004836 + 4837: 1004837 + 4838: 1004838 + 4839: 1004839 + 4840: 1004840 + 4841: 1004841 + 4842: 1004842 + 4843: 1004843 + 4844: 1004844 + 4845: 1004845 + 4846: 1004846 + 4847: 1004847 + 4848: 1004848 + 4849: 1004849 + 4850: 1004850 + 4851: 1004851 + 4852: 1004852 + 4853: 1004853 + 4854: 1004854 + 4855: 1004855 + 4856: 1004856 + 4857: 1004857 + 4858: 1004858 + 4859: 1004859 + 4860: 1004860 + 4861: 1004861 + 4862: 1004862 + 4863: 1004863 + 4864: 1004864 + 4865: 1004865 + 4866: 1004866 + 4867: 1004867 + 4868: 1004868 + 4869: 1004869 + 4870: 1004870 + 4871: 1004871 + 4872: 1004872 + 4873: 1004873 + 4874: 1004874 + 4875: 1004875 + 4876: 1004876 + 4877: 1004877 + 4878: 1004878 + 4879: 1004879 + 4880: 1004880 + 4881: 1004881 + 4882: 1004882 + 4883: 1004883 + 4884: 1004884 + 4885: 1004885 + 4886: 1004886 + 4887: 1004887 + 4888: 1004888 + 4889: 1004889 + 4890: 1004890 + 4891: 1004891 + 4892: 1004892 + 4893: 1004893 + 4894: 1004894 + 4895: 1004895 + 4896: 1004896 + 4897: 1004897 + 4898: 1004898 + 4899: 1004899 + 4900: 1004900 + 4901: 1004901 + 4902: 1004902 + 4903: 1004903 + 4904: 1004904 + 4905: 1004905 + 4906: 1004906 + 4907: 1004907 + 4908: 1004908 + 4909: 1004909 + 4910: 1004910 + 4911: 1004911 + 4912: 1004912 + 4913: 1004913 + 4914: 1004914 + 4915: 1004915 + 4916: 1004916 + 4917: 1004917 + 4918: 1004918 + 4919: 1004919 + 4920: 1004920 + 4921: 1004921 + 4922: 1004922 + 4923: 1004923 + 4924: 1004924 + 4925: 1004925 + 4926: 1004926 + 4927: 1004927 + 4928: 1004928 + 4929: 1004929 + 4930: 1004930 + 4931: 1004931 + 4932: 1004932 + 4933: 1004933 + 4934: 1004934 + 4935: 1004935 + 4936: 1004936 + 4937: 1004937 + 4938: 1004938 + 4939: 1004939 + 4940: 1004940 + 4941: 1004941 + 4942: 1004942 + 4943: 1004943 + 4944: 1004944 + 4945: 1004945 + 4946: 1004946 + 4947: 1004947 + 4948: 1004948 + 4949: 1004949 + 4950: 1004950 + 4951: 1004951 + 4952: 1004952 + 4953: 1004953 + 4954: 1004954 + 4955: 1004955 + 4956: 1004956 + 4957: 1004957 + 4958: 1004958 + 4959: 1004959 + 4960: 1004960 + 4961: 1004961 + 4962: 1004962 + 4963: 1004963 + 4964: 1004964 + 4965: 1004965 + 4966: 1004966 + 4967: 1004967 + 4968: 1004968 + 4969: 1004969 + 4970: 1004970 + 4971: 1004971 + 4972: 1004972 + 4973: 1004973 + 4974: 1004974 + 4975: 1004975 + 4976: 1004976 + 4977: 1004977 + 4978: 1004978 + 4979: 1004979 + 4980: 1004980 + 4981: 1004981 + 4982: 1004982 + 4983: 1004983 + 4984: 1004984 + 4985: 1004985 + 4986: 1004986 + 4987: 1004987 + 4988: 1004988 + 4989: 1004989 + 4990: 1004990 + 4991: 1004991 + 4992: 1004992 + 4993: 1004993 + 4994: 1004994 + 4995: 1004995 + 4996: 1004996 + 4997: 1004997 + 4998: 1004998 + 4999: 1004999 + 5000: 1005000 + 5001: 1005001 + 5002: 1005002 + 5003: 1005003 + 5004: 1005004 + 5005: 1005005 + 5006: 1005006 + 5007: 1005007 + 5008: 1005008 + 5009: 1005009 + 5010: 1005010 + 5011: 1005011 + 5012: 1005012 + 5013: 1005013 + 5014: 1005014 + 5015: 1005015 + 5016: 1005016 + 5017: 1005017 + 5018: 1005018 + 5019: 1005019 + 5020: 1005020 + 5021: 1005021 + 5022: 1005022 + 5023: 1005023 + 5024: 1005024 + 5025: 1005025 + 5026: 1005026 + 5027: 1005027 + 5028: 1005028 + 5029: 1005029 + 5030: 1005030 + 5031: 1005031 + 5032: 1005032 + 5033: 1005033 + 5034: 1005034 + 5035: 1005035 + 5036: 1005036 + 5037: 1005037 + 5038: 1005038 + 5039: 1005039 + 5040: 1005040 + 5041: 1005041 + 5042: 1005042 + 5043: 1005043 + 5044: 1005044 + 5045: 1005045 + 5046: 1005046 + 5047: 1005047 + 5048: 1005048 + 5049: 1005049 + 5050: 1005050 + 5051: 1005051 + 5052: 1005052 + 5053: 1005053 + 5054: 1005054 + 5055: 1005055 + 5056: 1005056 + 5057: 1005057 + 5058: 1005058 + 5059: 1005059 + 5060: 1005060 + 5061: 1005061 + 5062: 1005062 + 5063: 1005063 + 5064: 1005064 + 5065: 1005065 + 5066: 1005066 + 5067: 1005067 + 5068: 1005068 + 5069: 1005069 + 5070: 1005070 + 5071: 1005071 + 5072: 1005072 + 5073: 1005073 + 5074: 1005074 + 5075: 1005075 + 5076: 1005076 + 5077: 1005077 + 5078: 1005078 + 5079: 1005079 + 5080: 1005080 + 5081: 1005081 + 5082: 1005082 + 5083: 1005083 + 5084: 1005084 + 5085: 1005085 + 5086: 1005086 + 5087: 1005087 + 5088: 1005088 + 5089: 1005089 + 5090: 1005090 + 5091: 1005091 + 5092: 1005092 + 5093: 1005093 + 5094: 1005094 + 5095: 1005095 + 5096: 1005096 + 5097: 1005097 + 5098: 1005098 + 5099: 1005099 + 5100: 1005100 + 5101: 1005101 + 5102: 1005102 + 5103: 1005103 + 5104: 1005104 + 5105: 1005105 + 5106: 1005106 + 5107: 1005107 + 5108: 1005108 + 5109: 1005109 + 5110: 1005110 + 5111: 1005111 + 5112: 1005112 + 5113: 1005113 + 5114: 1005114 + 5115: 1005115 + 5116: 1005116 + 5117: 1005117 + 5118: 1005118 + 5119: 1005119 + 5120: 1005120 + 5121: 1005121 + 5122: 1005122 + 5123: 1005123 + 5124: 1005124 + 5125: 1005125 + 5126: 1005126 + 5127: 1005127 + 5128: 1005128 + 5129: 1005129 + 5130: 1005130 + 5131: 1005131 + 5132: 1005132 + 5133: 1005133 + 5134: 1005134 + 5135: 1005135 + 5136: 1005136 + 5137: 1005137 + 5138: 1005138 + 5139: 1005139 + 5140: 1005140 + 5141: 1005141 + 5142: 1005142 + 5143: 1005143 + 5144: 1005144 + 5145: 1005145 + 5146: 1005146 + 5147: 1005147 + 5148: 1005148 + 5149: 1005149 + 5150: 1005150 + 5151: 1005151 + 5152: 1005152 + 5153: 1005153 + 5154: 1005154 + 5155: 1005155 + 5156: 1005156 + 5157: 1005157 + 5158: 1005158 + 5159: 1005159 + 5160: 1005160 + 5161: 1005161 + 5162: 1005162 + 5163: 1005163 + 5164: 1005164 + 5165: 1005165 + 5166: 1005166 + 5167: 1005167 + 5168: 1005168 + 5169: 1005169 + 5170: 1005170 + 5171: 1005171 + 5172: 1005172 + 5173: 1005173 + 5174: 1005174 + 5175: 1005175 + 5176: 1005176 + 5177: 1005177 + 5178: 1005178 + 5179: 1005179 + 5180: 1005180 + 5181: 1005181 + 5182: 1005182 + 5183: 1005183 + 5184: 1005184 + 5185: 1005185 + 5186: 1005186 + 5187: 1005187 + 5188: 1005188 + 5189: 1005189 + 5190: 1005190 + 5191: 1005191 + 5192: 1005192 + 5193: 1005193 + 5194: 1005194 + 5195: 1005195 + 5196: 1005196 + 5197: 1005197 + 5198: 1005198 + 5199: 1005199 + 5200: 1005200 + 5201: 1005201 + 5202: 1005202 + 5203: 1005203 + 5204: 1005204 + 5205: 1005205 + 5206: 1005206 + 5207: 1005207 + 5208: 1005208 + 5209: 1005209 + 5210: 1005210 + 5211: 1005211 + 5212: 1005212 + 5213: 1005213 + 5214: 1005214 + 5215: 1005215 + 5216: 1005216 + 5217: 1005217 + 5218: 1005218 + 5219: 1005219 + 5220: 1005220 + 5221: 1005221 + 5222: 1005222 + 5223: 1005223 + 5224: 1005224 + 5225: 1005225 + 5226: 1005226 + 5227: 1005227 + 5228: 1005228 + 5229: 1005229 + 5230: 1005230 + 5231: 1005231 + 5232: 1005232 + 5233: 1005233 + 5234: 1005234 + 5235: 1005235 + 5236: 1005236 + 5237: 1005237 + 5238: 1005238 + 5239: 1005239 + 5240: 1005240 + 5241: 1005241 + 5242: 1005242 + 5243: 1005243 + 5244: 1005244 + 5245: 1005245 + 5246: 1005246 + 5247: 1005247 + 5248: 1005248 + 5249: 1005249 + 5250: 1005250 + 5251: 1005251 + 5252: 1005252 + 5253: 1005253 + 5254: 1005254 + 5255: 1005255 + 5256: 1005256 + 5257: 1005257 + 5258: 1005258 + 5259: 1005259 + 5260: 1005260 + 5261: 1005261 + 5262: 1005262 + 5263: 1005263 + 5264: 1005264 + 5265: 1005265 + 5266: 1005266 + 5267: 1005267 + 5268: 1005268 + 5269: 1005269 + 5270: 1005270 + 5271: 1005271 + 5272: 1005272 + 5273: 1005273 + 5274: 1005274 + 5275: 1005275 + 5276: 1005276 + 5277: 1005277 + 5278: 1005278 + 5279: 1005279 + 5280: 1005280 + 5281: 1005281 + 5282: 1005282 + 5283: 1005283 + 5284: 1005284 + 5285: 1005285 + 5286: 1005286 + 5287: 1005287 + 5288: 1005288 + 5289: 1005289 + 5290: 1005290 + 5291: 1005291 + 5292: 1005292 + 5293: 1005293 + 5294: 1005294 + 5295: 1005295 + 5296: 1005296 + 5297: 1005297 + 5298: 1005298 + 5299: 1005299 + 5300: 1005300 + 5301: 1005301 + 5302: 1005302 + 5303: 1005303 + 5304: 1005304 + 5305: 1005305 + 5306: 1005306 + 5307: 1005307 + 5308: 1005308 + 5309: 1005309 + 5310: 1005310 + 5311: 1005311 + 5312: 1005312 + 5313: 1005313 + 5314: 1005314 + 5315: 1005315 + 5316: 1005316 + 5317: 1005317 + 5318: 1005318 + 5319: 1005319 + 5320: 1005320 + 5321: 1005321 + 5322: 1005322 + 5323: 1005323 + 5324: 1005324 + 5325: 1005325 + 5326: 1005326 + 5327: 1005327 + 5328: 1005328 + 5329: 1005329 + 5330: 1005330 + 5331: 1005331 + 5332: 1005332 + 5333: 1005333 + 5334: 1005334 + 5335: 1005335 + 5336: 1005336 + 5337: 1005337 + 5338: 1005338 + 5339: 1005339 + 5340: 1005340 + 5341: 1005341 + 5342: 1005342 + 5343: 1005343 + 5344: 1005344 + 5345: 1005345 + 5346: 1005346 + 5347: 1005347 + 5348: 1005348 + 5349: 1005349 + 5350: 1005350 + 5351: 1005351 + 5352: 1005352 + 5353: 1005353 + 5354: 1005354 + 5355: 1005355 + 5356: 1005356 + 5357: 1005357 + 5358: 1005358 + 5359: 1005359 + 5360: 1005360 + 5361: 1005361 + 5362: 1005362 + 5363: 1005363 + 5364: 1005364 + 5365: 1005365 + 5366: 1005366 + 5367: 1005367 + 5368: 1005368 + 5369: 1005369 + 5370: 1005370 + 5371: 1005371 + 5372: 1005372 + 5373: 1005373 + 5374: 1005374 + 5375: 1005375 + 5376: 1005376 + 5377: 1005377 + 5378: 1005378 + 5379: 1005379 + 5380: 1005380 + 5381: 1005381 + 5382: 1005382 + 5383: 1005383 + 5384: 1005384 + 5385: 1005385 + 5386: 1005386 + 5387: 1005387 + 5388: 1005388 + 5389: 1005389 + 5390: 1005390 + 5391: 1005391 + 5392: 1005392 + 5393: 1005393 + 5394: 1005394 + 5395: 1005395 + 5396: 1005396 + 5397: 1005397 + 5398: 1005398 + 5399: 1005399 + 5400: 1005400 + 5401: 1005401 + 5402: 1005402 + 5403: 1005403 + 5404: 1005404 + 5405: 1005405 + 5406: 1005406 + 5407: 1005407 + 5408: 1005408 + 5409: 1005409 + 5410: 1005410 + 5411: 1005411 + 5412: 1005412 + 5413: 1005413 + 5414: 1005414 + 5415: 1005415 + 5416: 1005416 + 5417: 1005417 + 5418: 1005418 + 5419: 1005419 + 5420: 1005420 + 5421: 1005421 + 5422: 1005422 + 5423: 1005423 + 5424: 1005424 + 5425: 1005425 + 5426: 1005426 + 5427: 1005427 + 5428: 1005428 + 5429: 1005429 + 5430: 1005430 + 5431: 1005431 + 5432: 1005432 + 5433: 1005433 + 5434: 1005434 + 5435: 1005435 + 5436: 1005436 + 5437: 1005437 + 5438: 1005438 + 5439: 1005439 + 5440: 1005440 + 5441: 1005441 + 5442: 1005442 + 5443: 1005443 + 5444: 1005444 + 5445: 1005445 + 5446: 1005446 + 5447: 1005447 + 5448: 1005448 + 5449: 1005449 + 5450: 1005450 + 5451: 1005451 + 5452: 1005452 + 5453: 1005453 + 5454: 1005454 + 5455: 1005455 + 5456: 1005456 + 5457: 1005457 + 5458: 1005458 + 5459: 1005459 + 5460: 1005460 + 5461: 1005461 + 5462: 1005462 + 5463: 1005463 + 5464: 1005464 + 5465: 1005465 + 5466: 1005466 + 5467: 1005467 + 5468: 1005468 + 5469: 1005469 + 5470: 1005470 + 5471: 1005471 + 5472: 1005472 + 5473: 1005473 + 5474: 1005474 + 5475: 1005475 + 5476: 1005476 + 5477: 1005477 + 5478: 1005478 + 5479: 1005479 + 5480: 1005480 + 5481: 1005481 + 5482: 1005482 + 5483: 1005483 + 5484: 1005484 + 5485: 1005485 + 5486: 1005486 + 5487: 1005487 + 5488: 1005488 + 5489: 1005489 + 5490: 1005490 + 5491: 1005491 + 5492: 1005492 + 5493: 1005493 + 5494: 1005494 + 5495: 1005495 + 5496: 1005496 + 5497: 1005497 + 5498: 1005498 + 5499: 1005499 + 5500: 1005500 + 5501: 1005501 + 5502: 1005502 + 5503: 1005503 + 5504: 1005504 + 5505: 1005505 + 5506: 1005506 + 5507: 1005507 + 5508: 1005508 + 5509: 1005509 + 5510: 1005510 + 5511: 1005511 + 5512: 1005512 + 5513: 1005513 + 5514: 1005514 + 5515: 1005515 + 5516: 1005516 + 5517: 1005517 + 5518: 1005518 + 5519: 1005519 + 5520: 1005520 + 5521: 1005521 + 5522: 1005522 + 5523: 1005523 + 5524: 1005524 + 5525: 1005525 + 5526: 1005526 + 5527: 1005527 + 5528: 1005528 + 5529: 1005529 + 5530: 1005530 + 5531: 1005531 + 5532: 1005532 + 5533: 1005533 + 5534: 1005534 + 5535: 1005535 + 5536: 1005536 + 5537: 1005537 + 5538: 1005538 + 5539: 1005539 + 5540: 1005540 + 5541: 1005541 + 5542: 1005542 + 5543: 1005543 + 5544: 1005544 + 5545: 1005545 + 5546: 1005546 + 5547: 1005547 + 5548: 1005548 + 5549: 1005549 + 5550: 1005550 + 5551: 1005551 + 5552: 1005552 + 5553: 1005553 + 5554: 1005554 + 5555: 1005555 + 5556: 1005556 + 5557: 1005557 + 5558: 1005558 + 5559: 1005559 + 5560: 1005560 + 5561: 1005561 + 5562: 1005562 + 5563: 1005563 + 5564: 1005564 + 5565: 1005565 + 5566: 1005566 + 5567: 1005567 + 5568: 1005568 + 5569: 1005569 + 5570: 1005570 + 5571: 1005571 + 5572: 1005572 + 5573: 1005573 + 5574: 1005574 + 5575: 1005575 + 5576: 1005576 + 5577: 1005577 + 5578: 1005578 + 5579: 1005579 + 5580: 1005580 + 5581: 1005581 + 5582: 1005582 + 5583: 1005583 + 5584: 1005584 + 5585: 1005585 + 5586: 1005586 + 5587: 1005587 + 5588: 1005588 + 5589: 1005589 + 5590: 1005590 + 5591: 1005591 + 5592: 1005592 + 5593: 1005593 + 5594: 1005594 + 5595: 1005595 + 5596: 1005596 + 5597: 1005597 + 5598: 1005598 + 5599: 1005599 + 5600: 1005600 + 5601: 1005601 + 5602: 1005602 + 5603: 1005603 + 5604: 1005604 + 5605: 1005605 + 5606: 1005606 + 5607: 1005607 + 5608: 1005608 + 5609: 1005609 + 5610: 1005610 + 5611: 1005611 + 5612: 1005612 + 5613: 1005613 + 5614: 1005614 + 5615: 1005615 + 5616: 1005616 + 5617: 1005617 + 5618: 1005618 + 5619: 1005619 + 5620: 1005620 + 5621: 1005621 + 5622: 1005622 + 5623: 1005623 + 5624: 1005624 + 5625: 1005625 + 5626: 1005626 + 5627: 1005627 + 5628: 1005628 + 5629: 1005629 + 5630: 1005630 + 5631: 1005631 + 5632: 1005632 + 5633: 1005633 + 5634: 1005634 + 5635: 1005635 + 5636: 1005636 + 5637: 1005637 + 5638: 1005638 + 5639: 1005639 + 5640: 1005640 + 5641: 1005641 + 5642: 1005642 + 5643: 1005643 + 5644: 1005644 + 5645: 1005645 + 5646: 1005646 + 5647: 1005647 + 5648: 1005648 + 5649: 1005649 + 5650: 1005650 + 5651: 1005651 + 5652: 1005652 + 5653: 1005653 + 5654: 1005654 + 5655: 1005655 + 5656: 1005656 + 5657: 1005657 + 5658: 1005658 + 5659: 1005659 + 5660: 1005660 + 5661: 1005661 + 5662: 1005662 + 5663: 1005663 + 5664: 1005664 + 5665: 1005665 + 5666: 1005666 + 5667: 1005667 + 5668: 1005668 + 5669: 1005669 + 5670: 1005670 + 5671: 1005671 + 5672: 1005672 + 5673: 1005673 + 5674: 1005674 + 5675: 1005675 + 5676: 1005676 + 5677: 1005677 + 5678: 1005678 + 5679: 1005679 + 5680: 1005680 + 5681: 1005681 + 5682: 1005682 + 5683: 1005683 + 5684: 1005684 + 5685: 1005685 + 5686: 1005686 + 5687: 1005687 + 5688: 1005688 + 5689: 1005689 + 5690: 1005690 + 5691: 1005691 + 5692: 1005692 + 5693: 1005693 + 5694: 1005694 + 5695: 1005695 + 5696: 1005696 + 5697: 1005697 + 5698: 1005698 + 5699: 1005699 + 5700: 1005700 + 5701: 1005701 + 5702: 1005702 + 5703: 1005703 + 5704: 1005704 + 5705: 1005705 + 5706: 1005706 + 5707: 1005707 + 5708: 1005708 + 5709: 1005709 + 5710: 1005710 + 5711: 1005711 + 5712: 1005712 + 5713: 1005713 + 5714: 1005714 + 5715: 1005715 + 5716: 1005716 + 5717: 1005717 + 5718: 1005718 + 5719: 1005719 + 5720: 1005720 + 5721: 1005721 + 5722: 1005722 + 5723: 1005723 + 5724: 1005724 + 5725: 1005725 + 5726: 1005726 + 5727: 1005727 + 5728: 1005728 + 5729: 1005729 + 5730: 1005730 + 5731: 1005731 + 5732: 1005732 + 5733: 1005733 + 5734: 1005734 + 5735: 1005735 + 5736: 1005736 + 5737: 1005737 + 5738: 1005738 + 5739: 1005739 + 5740: 1005740 + 5741: 1005741 + 5742: 1005742 + 5743: 1005743 + 5744: 1005744 + 5745: 1005745 + 5746: 1005746 + 5747: 1005747 + 5748: 1005748 + 5749: 1005749 + 5750: 1005750 + 5751: 1005751 + 5752: 1005752 + 5753: 1005753 + 5754: 1005754 + 5755: 1005755 + 5756: 1005756 + 5757: 1005757 + 5758: 1005758 + 5759: 1005759 + 5760: 1005760 + 5761: 1005761 + 5762: 1005762 + 5763: 1005763 + 5764: 1005764 + 5765: 1005765 + 5766: 1005766 + 5767: 1005767 + 5768: 1005768 + 5769: 1005769 + 5770: 1005770 + 5771: 1005771 + 5772: 1005772 + 5773: 1005773 + 5774: 1005774 + 5775: 1005775 + 5776: 1005776 + 5777: 1005777 + 5778: 1005778 + 5779: 1005779 + 5780: 1005780 + 5781: 1005781 + 5782: 1005782 + 5783: 1005783 + 5784: 1005784 + 5785: 1005785 + 5786: 1005786 + 5787: 1005787 + 5788: 1005788 + 5789: 1005789 + 5790: 1005790 + 5791: 1005791 + 5792: 1005792 + 5793: 1005793 + 5794: 1005794 + 5795: 1005795 + 5796: 1005796 + 5797: 1005797 + 5798: 1005798 + 5799: 1005799 + 5800: 1005800 + 5801: 1005801 + 5802: 1005802 + 5803: 1005803 + 5804: 1005804 + 5805: 1005805 + 5806: 1005806 + 5807: 1005807 + 5808: 1005808 + 5809: 1005809 + 5810: 1005810 + 5811: 1005811 + 5812: 1005812 + 5813: 1005813 + 5814: 1005814 + 5815: 1005815 + 5816: 1005816 + 5817: 1005817 + 5818: 1005818 + 5819: 1005819 + 5820: 1005820 + 5821: 1005821 + 5822: 1005822 + 5823: 1005823 + 5824: 1005824 + 5825: 1005825 + 5826: 1005826 + 5827: 1005827 + 5828: 1005828 + 5829: 1005829 + 5830: 1005830 + 5831: 1005831 + 5832: 1005832 + 5833: 1005833 + 5834: 1005834 + 5835: 1005835 + 5836: 1005836 + 5837: 1005837 + 5838: 1005838 + 5839: 1005839 + 5840: 1005840 + 5841: 1005841 + 5842: 1005842 + 5843: 1005843 + 5844: 1005844 + 5845: 1005845 + 5846: 1005846 + 5847: 1005847 + 5848: 1005848 + 5849: 1005849 + 5850: 1005850 + 5851: 1005851 + 5852: 1005852 + 5853: 1005853 + 5854: 1005854 + 5855: 1005855 + 5856: 1005856 + 5857: 1005857 + 5858: 1005858 + 5859: 1005859 + 5860: 1005860 + 5861: 1005861 + 5862: 1005862 + 5863: 1005863 + 5864: 1005864 + 5865: 1005865 + 5866: 1005866 + 5867: 1005867 + 5868: 1005868 + 5869: 1005869 + 5870: 1005870 + 5871: 1005871 + 5872: 1005872 + 5873: 1005873 + 5874: 1005874 + 5875: 1005875 + 5876: 1005876 + 5877: 1005877 + 5878: 1005878 + 5879: 1005879 + 5880: 1005880 + 5881: 1005881 + 5882: 1005882 + 5883: 1005883 + 5884: 1005884 + 5885: 1005885 + 5886: 1005886 + 5887: 1005887 + 5888: 1005888 + 5889: 1005889 + 5890: 1005890 + 5891: 1005891 + 5892: 1005892 + 5893: 1005893 + 5894: 1005894 + 5895: 1005895 + 5896: 1005896 + 5897: 1005897 + 5898: 1005898 + 5899: 1005899 + 5900: 1005900 + 5901: 1005901 + 5902: 1005902 + 5903: 1005903 + 5904: 1005904 + 5905: 1005905 + 5906: 1005906 + 5907: 1005907 + 5908: 1005908 + 5909: 1005909 + 5910: 1005910 + 5911: 1005911 + 5912: 1005912 + 5913: 1005913 + 5914: 1005914 + 5915: 1005915 + 5916: 1005916 + 5917: 1005917 + 5918: 1005918 + 5919: 1005919 + 5920: 1005920 + 5921: 1005921 + 5922: 1005922 + 5923: 1005923 + 5924: 1005924 + 5925: 1005925 + 5926: 1005926 + 5927: 1005927 + 5928: 1005928 + 5929: 1005929 + 5930: 1005930 + 5931: 1005931 + 5932: 1005932 + 5933: 1005933 + 5934: 1005934 + 5935: 1005935 + 5936: 1005936 + 5937: 1005937 + 5938: 1005938 + 5939: 1005939 + 5940: 1005940 + 5941: 1005941 + 5942: 1005942 + 5943: 1005943 + 5944: 1005944 + 5945: 1005945 + 5946: 1005946 + 5947: 1005947 + 5948: 1005948 + 5949: 1005949 + 5950: 1005950 + 5951: 1005951 + 5952: 1005952 + 5953: 1005953 + 5954: 1005954 + 5955: 1005955 + 5956: 1005956 + 5957: 1005957 + 5958: 1005958 + 5959: 1005959 + 5960: 1005960 + 5961: 1005961 + 5962: 1005962 + 5963: 1005963 + 5964: 1005964 + 5965: 1005965 + 5966: 1005966 + 5967: 1005967 + 5968: 1005968 + 5969: 1005969 + 5970: 1005970 + 5971: 1005971 + 5972: 1005972 + 5973: 1005973 + 5974: 1005974 + 5975: 1005975 + 5976: 1005976 + 5977: 1005977 + 5978: 1005978 + 5979: 1005979 + 5980: 1005980 + 5981: 1005981 + 5982: 1005982 + 5983: 1005983 + 5984: 1005984 + 5985: 1005985 + 5986: 1005986 + 5987: 1005987 + 5988: 1005988 + 5989: 1005989 + 5990: 1005990 + 5991: 1005991 + 5992: 1005992 + 5993: 1005993 + 5994: 1005994 + 5995: 1005995 + 5996: 1005996 + 5997: 1005997 + 5998: 1005998 + 5999: 1005999 + 6000: 1006000 + 6001: 1006001 + 6002: 1006002 + 6003: 1006003 + 6004: 1006004 + 6005: 1006005 + 6006: 1006006 + 6007: 1006007 + 6008: 1006008 + 6009: 1006009 + 6010: 1006010 + 6011: 1006011 + 6012: 1006012 + 6013: 1006013 + 6014: 1006014 + 6015: 1006015 + 6016: 1006016 + 6017: 1006017 + 6018: 1006018 + 6019: 1006019 + 6020: 1006020 + 6021: 1006021 + 6022: 1006022 + 6023: 1006023 + 6024: 1006024 + 6025: 1006025 + 6026: 1006026 + 6027: 1006027 + 6028: 1006028 + 6029: 1006029 + 6030: 1006030 + 6031: 1006031 + 6032: 1006032 + 6033: 1006033 + 6034: 1006034 + 6035: 1006035 + 6036: 1006036 + 6037: 1006037 + 6038: 1006038 + 6039: 1006039 + 6040: 1006040 + 6041: 1006041 + 6042: 1006042 + 6043: 1006043 + 6044: 1006044 + 6045: 1006045 + 6046: 1006046 + 6047: 1006047 + 6048: 1006048 + 6049: 1006049 + 6050: 1006050 + 6051: 1006051 + 6052: 1006052 + 6053: 1006053 + 6054: 1006054 + 6055: 1006055 + 6056: 1006056 + 6057: 1006057 + 6058: 1006058 + 6059: 1006059 + 6060: 1006060 + 6061: 1006061 + 6062: 1006062 + 6063: 1006063 + 6064: 1006064 + 6065: 1006065 + 6066: 1006066 + 6067: 1006067 + 6068: 1006068 + 6069: 1006069 + 6070: 1006070 + 6071: 1006071 + 6072: 1006072 + 6073: 1006073 + 6074: 1006074 + 6075: 1006075 + 6076: 1006076 + 6077: 1006077 + 6078: 1006078 + 6079: 1006079 + 6080: 1006080 + 6081: 1006081 + 6082: 1006082 + 6083: 1006083 + 6084: 1006084 + 6085: 1006085 + 6086: 1006086 + 6087: 1006087 + 6088: 1006088 + 6089: 1006089 + 6090: 1006090 + 6091: 1006091 + 6092: 1006092 + 6093: 1006093 + 6094: 1006094 + 6095: 1006095 + 6096: 1006096 + 6097: 1006097 + 6098: 1006098 + 6099: 1006099 + 6100: 1006100 + 6101: 1006101 + 6102: 1006102 + 6103: 1006103 + 6104: 1006104 + 6105: 1006105 + 6106: 1006106 + 6107: 1006107 + 6108: 1006108 + 6109: 1006109 + 6110: 1006110 + 6111: 1006111 + 6112: 1006112 + 6113: 1006113 + 6114: 1006114 + 6115: 1006115 + 6116: 1006116 + 6117: 1006117 + 6118: 1006118 + 6119: 1006119 + 6120: 1006120 + 6121: 1006121 + 6122: 1006122 + 6123: 1006123 + 6124: 1006124 + 6125: 1006125 + 6126: 1006126 + 6127: 1006127 + 6128: 1006128 + 6129: 1006129 + 6130: 1006130 + 6131: 1006131 + 6132: 1006132 + 6133: 1006133 + 6134: 1006134 + 6135: 1006135 + 6136: 1006136 + 6137: 1006137 + 6138: 1006138 + 6139: 1006139 + 6140: 1006140 + 6141: 1006141 + 6142: 1006142 + 6143: 1006143 + 6144: 1006144 + 6145: 1006145 + 6146: 1006146 + 6147: 1006147 + 6148: 1006148 + 6149: 1006149 + 6150: 1006150 + 6151: 1006151 + 6152: 1006152 + 6153: 1006153 + 6154: 1006154 + 6155: 1006155 + 6156: 1006156 + 6157: 1006157 + 6158: 1006158 + 6159: 1006159 + 6160: 1006160 + 6161: 1006161 + 6162: 1006162 + 6163: 1006163 + 6164: 1006164 + 6165: 1006165 + 6166: 1006166 + 6167: 1006167 + 6168: 1006168 + 6169: 1006169 + 6170: 1006170 + 6171: 1006171 + 6172: 1006172 + 6173: 1006173 + 6174: 1006174 + 6175: 1006175 + 6176: 1006176 + 6177: 1006177 + 6178: 1006178 + 6179: 1006179 + 6180: 1006180 + 6181: 1006181 + 6182: 1006182 + 6183: 1006183 + 6184: 1006184 + 6185: 1006185 + 6186: 1006186 + 6187: 1006187 + 6188: 1006188 + 6189: 1006189 + 6190: 1006190 + 6191: 1006191 + 6192: 1006192 + 6193: 1006193 + 6194: 1006194 + 6195: 1006195 + 6196: 1006196 + 6197: 1006197 + 6198: 1006198 + 6199: 1006199 + 6200: 1006200 + 6201: 1006201 + 6202: 1006202 + 6203: 1006203 + 6204: 1006204 + 6205: 1006205 + 6206: 1006206 + 6207: 1006207 + 6208: 1006208 + 6209: 1006209 + 6210: 1006210 + 6211: 1006211 + 6212: 1006212 + 6213: 1006213 + 6214: 1006214 + 6215: 1006215 + 6216: 1006216 + 6217: 1006217 + 6218: 1006218 + 6219: 1006219 + 6220: 1006220 + 6221: 1006221 + 6222: 1006222 + 6223: 1006223 + 6224: 1006224 + 6225: 1006225 + 6226: 1006226 + 6227: 1006227 + 6228: 1006228 + 6229: 1006229 + 6230: 1006230 + 6231: 1006231 + 6232: 1006232 + 6233: 1006233 + 6234: 1006234 + 6235: 1006235 + 6236: 1006236 + 6237: 1006237 + 6238: 1006238 + 6239: 1006239 + 6240: 1006240 + 6241: 1006241 + 6242: 1006242 + 6243: 1006243 + 6244: 1006244 + 6245: 1006245 + 6246: 1006246 + 6247: 1006247 + 6248: 1006248 + 6249: 1006249 + 6250: 1006250 + 6251: 1006251 + 6252: 1006252 + 6253: 1006253 + 6254: 1006254 + 6255: 1006255 + 6256: 1006256 + 6257: 1006257 + 6258: 1006258 + 6259: 1006259 + 6260: 1006260 + 6261: 1006261 + 6262: 1006262 + 6263: 1006263 + 6264: 1006264 + 6265: 1006265 + 6266: 1006266 + 6267: 1006267 + 6268: 1006268 + 6269: 1006269 + 6270: 1006270 + 6271: 1006271 + 6272: 1006272 + 6273: 1006273 + 6274: 1006274 + 6275: 1006275 + 6276: 1006276 + 6277: 1006277 + 6278: 1006278 + 6279: 1006279 + 6280: 1006280 + 6281: 1006281 + 6282: 1006282 + 6283: 1006283 + 6284: 1006284 + 6285: 1006285 + 6286: 1006286 + 6287: 1006287 + 6288: 1006288 + 6289: 1006289 + 6290: 1006290 + 6291: 1006291 + 6292: 1006292 + 6293: 1006293 + 6294: 1006294 + 6295: 1006295 + 6296: 1006296 + 6297: 1006297 + 6298: 1006298 + 6299: 1006299 + 6300: 1006300 + 6301: 1006301 + 6302: 1006302 + 6303: 1006303 + 6304: 1006304 + 6305: 1006305 + 6306: 1006306 + 6307: 1006307 + 6308: 1006308 + 6309: 1006309 + 6310: 1006310 + 6311: 1006311 + 6312: 1006312 + 6313: 1006313 + 6314: 1006314 + 6315: 1006315 + 6316: 1006316 + 6317: 1006317 + 6318: 1006318 + 6319: 1006319 + 6320: 1006320 + 6321: 1006321 + 6322: 1006322 + 6323: 1006323 + 6324: 1006324 + 6325: 1006325 + 6326: 1006326 + 6327: 1006327 + 6328: 1006328 + 6329: 1006329 + 6330: 1006330 + 6331: 1006331 + 6332: 1006332 + 6333: 1006333 + 6334: 1006334 + 6335: 1006335 + 6336: 1006336 + 6337: 1006337 + 6338: 1006338 + 6339: 1006339 + 6340: 1006340 + 6341: 1006341 + 6342: 1006342 + 6343: 1006343 + 6344: 1006344 + 6345: 1006345 + 6346: 1006346 + 6347: 1006347 + 6348: 1006348 + 6349: 1006349 + 6350: 1006350 + 6351: 1006351 + 6352: 1006352 + 6353: 1006353 + 6354: 1006354 + 6355: 1006355 + 6356: 1006356 + 6357: 1006357 + 6358: 1006358 + 6359: 1006359 + 6360: 1006360 + 6361: 1006361 + 6362: 1006362 + 6363: 1006363 + 6364: 1006364 + 6365: 1006365 + 6366: 1006366 + 6367: 1006367 + 6368: 1006368 + 6369: 1006369 + 6370: 1006370 + 6371: 1006371 + 6372: 1006372 + 6373: 1006373 + 6374: 1006374 + 6375: 1006375 + 6376: 1006376 + 6377: 1006377 + 6378: 1006378 + 6379: 1006379 + 6380: 1006380 + 6381: 1006381 + 6382: 1006382 + 6383: 1006383 + 6384: 1006384 + 6385: 1006385 + 6386: 1006386 + 6387: 1006387 + 6388: 1006388 + 6389: 1006389 + 6390: 1006390 + 6391: 1006391 + 6392: 1006392 + 6393: 1006393 + 6394: 1006394 + 6395: 1006395 + 6396: 1006396 + 6397: 1006397 + 6398: 1006398 + 6399: 1006399 + 6400: 1006400 + 6401: 1006401 + 6402: 1006402 + 6403: 1006403 + 6404: 1006404 + 6405: 1006405 + 6406: 1006406 + 6407: 1006407 + 6408: 1006408 + 6409: 1006409 + 6410: 1006410 + 6411: 1006411 + 6412: 1006412 + 6413: 1006413 + 6414: 1006414 + 6415: 1006415 + 6416: 1006416 + 6417: 1006417 + 6418: 1006418 + 6419: 1006419 + 6420: 1006420 + 6421: 1006421 + 6422: 1006422 + 6423: 1006423 + 6424: 1006424 + 6425: 1006425 + 6426: 1006426 + 6427: 1006427 + 6428: 1006428 + 6429: 1006429 + 6430: 1006430 + 6431: 1006431 + 6432: 1006432 + 6433: 1006433 + 6434: 1006434 + 6435: 1006435 + 6436: 1006436 + 6437: 1006437 + 6438: 1006438 + 6439: 1006439 + 6440: 1006440 + 6441: 1006441 + 6442: 1006442 + 6443: 1006443 + 6444: 1006444 + 6445: 1006445 + 6446: 1006446 + 6447: 1006447 + 6448: 1006448 + 6449: 1006449 + 6450: 1006450 + 6451: 1006451 + 6452: 1006452 + 6453: 1006453 + 6454: 1006454 + 6455: 1006455 + 6456: 1006456 + 6457: 1006457 + 6458: 1006458 + 6459: 1006459 + 6460: 1006460 + 6461: 1006461 + 6462: 1006462 + 6463: 1006463 + 6464: 1006464 + 6465: 1006465 + 6466: 1006466 + 6467: 1006467 + 6468: 1006468 + 6469: 1006469 + 6470: 1006470 + 6471: 1006471 + 6472: 1006472 + 6473: 1006473 + 6474: 1006474 + 6475: 1006475 + 6476: 1006476 + 6477: 1006477 + 6478: 1006478 + 6479: 1006479 + 6480: 1006480 + 6481: 1006481 + 6482: 1006482 + 6483: 1006483 + 6484: 1006484 + 6485: 1006485 + 6486: 1006486 + 6487: 1006487 + 6488: 1006488 + 6489: 1006489 + 6490: 1006490 + 6491: 1006491 + 6492: 1006492 + 6493: 1006493 + 6494: 1006494 + 6495: 1006495 + 6496: 1006496 + 6497: 1006497 + 6498: 1006498 + 6499: 1006499 + 6500: 1006500 + 6501: 1006501 + 6502: 1006502 + 6503: 1006503 + 6504: 1006504 + 6505: 1006505 + 6506: 1006506 + 6507: 1006507 + 6508: 1006508 + 6509: 1006509 + 6510: 1006510 + 6511: 1006511 + 6512: 1006512 + 6513: 1006513 + 6514: 1006514 + 6515: 1006515 + 6516: 1006516 + 6517: 1006517 + 6518: 1006518 + 6519: 1006519 + 6520: 1006520 + 6521: 1006521 + 6522: 1006522 + 6523: 1006523 + 6524: 1006524 + 6525: 1006525 + 6526: 1006526 + 6527: 1006527 + 6528: 1006528 + 6529: 1006529 + 6530: 1006530 + 6531: 1006531 + 6532: 1006532 + 6533: 1006533 + 6534: 1006534 + 6535: 1006535 + 6536: 1006536 + 6537: 1006537 + 6538: 1006538 + 6539: 1006539 + 6540: 1006540 + 6541: 1006541 + 6542: 1006542 + 6543: 1006543 + 6544: 1006544 + 6545: 1006545 + 6546: 1006546 + 6547: 1006547 + 6548: 1006548 + 6549: 1006549 + 6550: 1006550 + 6551: 1006551 + 6552: 1006552 + 6553: 1006553 + 6554: 1006554 + 6555: 1006555 + 6556: 1006556 + 6557: 1006557 + 6558: 1006558 + 6559: 1006559 + 6560: 1006560 + 6561: 1006561 + 6562: 1006562 + 6563: 1006563 + 6564: 1006564 + 6565: 1006565 + 6566: 1006566 + 6567: 1006567 + 6568: 1006568 + 6569: 1006569 + 6570: 1006570 + 6571: 1006571 + 6572: 1006572 + 6573: 1006573 + 6574: 1006574 + 6575: 1006575 + 6576: 1006576 + 6577: 1006577 + 6578: 1006578 + 6579: 1006579 + 6580: 1006580 + 6581: 1006581 + 6582: 1006582 + 6583: 1006583 + 6584: 1006584 + 6585: 1006585 + 6586: 1006586 + 6587: 1006587 + 6588: 1006588 + 6589: 1006589 + 6590: 1006590 + 6591: 1006591 + 6592: 1006592 + 6593: 1006593 + 6594: 1006594 + 6595: 1006595 + 6596: 1006596 + 6597: 1006597 + 6598: 1006598 + 6599: 1006599 + 6600: 1006600 + 6601: 1006601 + 6602: 1006602 + 6603: 1006603 + 6604: 1006604 + 6605: 1006605 + 6606: 1006606 + 6607: 1006607 + 6608: 1006608 + 6609: 1006609 + 6610: 1006610 + 6611: 1006611 + 6612: 1006612 + 6613: 1006613 + 6614: 1006614 + 6615: 1006615 + 6616: 1006616 + 6617: 1006617 + 6618: 1006618 + 6619: 1006619 + 6620: 1006620 + 6621: 1006621 + 6622: 1006622 + 6623: 1006623 + 6624: 1006624 + 6625: 1006625 + 6626: 1006626 + 6627: 1006627 + 6628: 1006628 + 6629: 1006629 + 6630: 1006630 + 6631: 1006631 + 6632: 1006632 + 6633: 1006633 + 6634: 1006634 + 6635: 1006635 + 6636: 1006636 + 6637: 1006637 + 6638: 1006638 + 6639: 1006639 + 6640: 1006640 + 6641: 1006641 + 6642: 1006642 + 6643: 1006643 + 6644: 1006644 + 6645: 1006645 + 6646: 1006646 + 6647: 1006647 + 6648: 1006648 + 6649: 1006649 + 6650: 1006650 + 6651: 1006651 + 6652: 1006652 + 6653: 1006653 + 6654: 1006654 + 6655: 1006655 + 6656: 1006656 + 6657: 1006657 + 6658: 1006658 + 6659: 1006659 + 6660: 1006660 + 6661: 1006661 + 6662: 1006662 + 6663: 1006663 + 6664: 1006664 + 6665: 1006665 + 6666: 1006666 + 6667: 1006667 + 6668: 1006668 + 6669: 1006669 + 6670: 1006670 + 6671: 1006671 + 6672: 1006672 + 6673: 1006673 + 6674: 1006674 + 6675: 1006675 + 6676: 1006676 + 6677: 1006677 + 6678: 1006678 + 6679: 1006679 + 6680: 1006680 + 6681: 1006681 + 6682: 1006682 + 6683: 1006683 + 6684: 1006684 + 6685: 1006685 + 6686: 1006686 + 6687: 1006687 + 6688: 1006688 + 6689: 1006689 + 6690: 1006690 + 6691: 1006691 + 6692: 1006692 + 6693: 1006693 + 6694: 1006694 + 6695: 1006695 + 6696: 1006696 + 6697: 1006697 + 6698: 1006698 + 6699: 1006699 + 6700: 1006700 + 6701: 1006701 + 6702: 1006702 + 6703: 1006703 + 6704: 1006704 + 6705: 1006705 + 6706: 1006706 + 6707: 1006707 + 6708: 1006708 + 6709: 1006709 + 6710: 1006710 + 6711: 1006711 + 6712: 1006712 + 6713: 1006713 + 6714: 1006714 + 6715: 1006715 + 6716: 1006716 + 6717: 1006717 + 6718: 1006718 + 6719: 1006719 + 6720: 1006720 + 6721: 1006721 + 6722: 1006722 + 6723: 1006723 + 6724: 1006724 + 6725: 1006725 + 6726: 1006726 + 6727: 1006727 + 6728: 1006728 + 6729: 1006729 + 6730: 1006730 + 6731: 1006731 + 6732: 1006732 + 6733: 1006733 + 6734: 1006734 + 6735: 1006735 + 6736: 1006736 + 6737: 1006737 + 6738: 1006738 + 6739: 1006739 + 6740: 1006740 + 6741: 1006741 + 6742: 1006742 + 6743: 1006743 + 6744: 1006744 + 6745: 1006745 + 6746: 1006746 + 6747: 1006747 + 6748: 1006748 + 6749: 1006749 + 6750: 1006750 + 6751: 1006751 + 6752: 1006752 + 6753: 1006753 + 6754: 1006754 + 6755: 1006755 + 6756: 1006756 + 6757: 1006757 + 6758: 1006758 + 6759: 1006759 + 6760: 1006760 + 6761: 1006761 + 6762: 1006762 + 6763: 1006763 + 6764: 1006764 + 6765: 1006765 + 6766: 1006766 + 6767: 1006767 + 6768: 1006768 + 6769: 1006769 + 6770: 1006770 + 6771: 1006771 + 6772: 1006772 + 6773: 1006773 + 6774: 1006774 + 6775: 1006775 + 6776: 1006776 + 6777: 1006777 + 6778: 1006778 + 6779: 1006779 + 6780: 1006780 + 6781: 1006781 + 6782: 1006782 + 6783: 1006783 + 6784: 1006784 + 6785: 1006785 + 6786: 1006786 + 6787: 1006787 + 6788: 1006788 + 6789: 1006789 + 6790: 1006790 + 6791: 1006791 + 6792: 1006792 + 6793: 1006793 + 6794: 1006794 + 6795: 1006795 + 6796: 1006796 + 6797: 1006797 + 6798: 1006798 + 6799: 1006799 + 6800: 1006800 + 6801: 1006801 + 6802: 1006802 + 6803: 1006803 + 6804: 1006804 + 6805: 1006805 + 6806: 1006806 + 6807: 1006807 + 6808: 1006808 + 6809: 1006809 + 6810: 1006810 + 6811: 1006811 + 6812: 1006812 + 6813: 1006813 + 6814: 1006814 + 6815: 1006815 + 6816: 1006816 + 6817: 1006817 + 6818: 1006818 + 6819: 1006819 + 6820: 1006820 + 6821: 1006821 + 6822: 1006822 + 6823: 1006823 + 6824: 1006824 + 6825: 1006825 + 6826: 1006826 + 6827: 1006827 + 6828: 1006828 + 6829: 1006829 + 6830: 1006830 + 6831: 1006831 + 6832: 1006832 + 6833: 1006833 + 6834: 1006834 + 6835: 1006835 + 6836: 1006836 + 6837: 1006837 + 6838: 1006838 + 6839: 1006839 + 6840: 1006840 + 6841: 1006841 + 6842: 1006842 + 6843: 1006843 + 6844: 1006844 + 6845: 1006845 + 6846: 1006846 + 6847: 1006847 + 6848: 1006848 + 6849: 1006849 + 6850: 1006850 + 6851: 1006851 + 6852: 1006852 + 6853: 1006853 + 6854: 1006854 + 6855: 1006855 + 6856: 1006856 + 6857: 1006857 + 6858: 1006858 + 6859: 1006859 + 6860: 1006860 + 6861: 1006861 + 6862: 1006862 + 6863: 1006863 + 6864: 1006864 + 6865: 1006865 + 6866: 1006866 + 6867: 1006867 + 6868: 1006868 + 6869: 1006869 + 6870: 1006870 + 6871: 1006871 + 6872: 1006872 + 6873: 1006873 + 6874: 1006874 + 6875: 1006875 + 6876: 1006876 + 6877: 1006877 + 6878: 1006878 + 6879: 1006879 + 6880: 1006880 + 6881: 1006881 + 6882: 1006882 + 6883: 1006883 + 6884: 1006884 + 6885: 1006885 + 6886: 1006886 + 6887: 1006887 + 6888: 1006888 + 6889: 1006889 + 6890: 1006890 + 6891: 1006891 + 6892: 1006892 + 6893: 1006893 + 6894: 1006894 + 6895: 1006895 + 6896: 1006896 + 6897: 1006897 + 6898: 1006898 + 6899: 1006899 + 6900: 1006900 + 6901: 1006901 + 6902: 1006902 + 6903: 1006903 + 6904: 1006904 + 6905: 1006905 + 6906: 1006906 + 6907: 1006907 + 6908: 1006908 + 6909: 1006909 + 6910: 1006910 + 6911: 1006911 + 6912: 1006912 + 6913: 1006913 + 6914: 1006914 + 6915: 1006915 + 6916: 1006916 + 6917: 1006917 + 6918: 1006918 + 6919: 1006919 + 6920: 1006920 + 6921: 1006921 + 6922: 1006922 + 6923: 1006923 + 6924: 1006924 + 6925: 1006925 + 6926: 1006926 + 6927: 1006927 + 6928: 1006928 + 6929: 1006929 + 6930: 1006930 + 6931: 1006931 + 6932: 1006932 + 6933: 1006933 + 6934: 1006934 + 6935: 1006935 + 6936: 1006936 + 6937: 1006937 + 6938: 1006938 + 6939: 1006939 + 6940: 1006940 + 6941: 1006941 + 6942: 1006942 + 6943: 1006943 + 6944: 1006944 + 6945: 1006945 + 6946: 1006946 + 6947: 1006947 + 6948: 1006948 + 6949: 1006949 + 6950: 1006950 + 6951: 1006951 + 6952: 1006952 + 6953: 1006953 + 6954: 1006954 + 6955: 1006955 + 6956: 1006956 + 6957: 1006957 + 6958: 1006958 + 6959: 1006959 + 6960: 1006960 + 6961: 1006961 + 6962: 1006962 + 6963: 1006963 + 6964: 1006964 + 6965: 1006965 + 6966: 1006966 + 6967: 1006967 + 6968: 1006968 + 6969: 1006969 + 6970: 1006970 + 6971: 1006971 + 6972: 1006972 + 6973: 1006973 + 6974: 1006974 + 6975: 1006975 + 6976: 1006976 + 6977: 1006977 + 6978: 1006978 + 6979: 1006979 + 6980: 1006980 + 6981: 1006981 + 6982: 1006982 + 6983: 1006983 + 6984: 1006984 + 6985: 1006985 + 6986: 1006986 + 6987: 1006987 + 6988: 1006988 + 6989: 1006989 + 6990: 1006990 + 6991: 1006991 + 6992: 1006992 + 6993: 1006993 + 6994: 1006994 + 6995: 1006995 + 6996: 1006996 + 6997: 1006997 + 6998: 1006998 + 6999: 1006999 + 7000: 1007000 + 7001: 1007001 + 7002: 1007002 + 7003: 1007003 + 7004: 1007004 + 7005: 1007005 + 7006: 1007006 + 7007: 1007007 + 7008: 1007008 + 7009: 1007009 + 7010: 1007010 + 7011: 1007011 + 7012: 1007012 + 7013: 1007013 + 7014: 1007014 + 7015: 1007015 + 7016: 1007016 + 7017: 1007017 + 7018: 1007018 + 7019: 1007019 + 7020: 1007020 + 7021: 1007021 + 7022: 1007022 + 7023: 1007023 + 7024: 1007024 + 7025: 1007025 + 7026: 1007026 + 7027: 1007027 + 7028: 1007028 + 7029: 1007029 + 7030: 1007030 + 7031: 1007031 + 7032: 1007032 + 7033: 1007033 + 7034: 1007034 + 7035: 1007035 + 7036: 1007036 + 7037: 1007037 + 7038: 1007038 + 7039: 1007039 + 7040: 1007040 + 7041: 1007041 + 7042: 1007042 + 7043: 1007043 + 7044: 1007044 + 7045: 1007045 + 7046: 1007046 + 7047: 1007047 + 7048: 1007048 + 7049: 1007049 + 7050: 1007050 + 7051: 1007051 + 7052: 1007052 + 7053: 1007053 + 7054: 1007054 + 7055: 1007055 + 7056: 1007056 + 7057: 1007057 + 7058: 1007058 + 7059: 1007059 + 7060: 1007060 + 7061: 1007061 + 7062: 1007062 + 7063: 1007063 + 7064: 1007064 + 7065: 1007065 + 7066: 1007066 + 7067: 1007067 + 7068: 1007068 + 7069: 1007069 + 7070: 1007070 + 7071: 1007071 + 7072: 1007072 + 7073: 1007073 + 7074: 1007074 + 7075: 1007075 + 7076: 1007076 + 7077: 1007077 + 7078: 1007078 + 7079: 1007079 + 7080: 1007080 + 7081: 1007081 + 7082: 1007082 + 7083: 1007083 + 7084: 1007084 + 7085: 1007085 + 7086: 1007086 + 7087: 1007087 + 7088: 1007088 + 7089: 1007089 + 7090: 1007090 + 7091: 1007091 + 7092: 1007092 + 7093: 1007093 + 7094: 1007094 + 7095: 1007095 + 7096: 1007096 + 7097: 1007097 + 7098: 1007098 + 7099: 1007099 + 7100: 1007100 + 7101: 1007101 + 7102: 1007102 + 7103: 1007103 + 7104: 1007104 + 7105: 1007105 + 7106: 1007106 + 7107: 1007107 + 7108: 1007108 + 7109: 1007109 + 7110: 1007110 + 7111: 1007111 + 7112: 1007112 + 7113: 1007113 + 7114: 1007114 + 7115: 1007115 + 7116: 1007116 + 7117: 1007117 + 7118: 1007118 + 7119: 1007119 + 7120: 1007120 + 7121: 1007121 + 7122: 1007122 + 7123: 1007123 + 7124: 1007124 + 7125: 1007125 + 7126: 1007126 + 7127: 1007127 + 7128: 1007128 + 7129: 1007129 + 7130: 1007130 + 7131: 1007131 + 7132: 1007132 + 7133: 1007133 + 7134: 1007134 + 7135: 1007135 + 7136: 1007136 + 7137: 1007137 + 7138: 1007138 + 7139: 1007139 + 7140: 1007140 + 7141: 1007141 + 7142: 1007142 + 7143: 1007143 + 7144: 1007144 + 7145: 1007145 + 7146: 1007146 + 7147: 1007147 + 7148: 1007148 + 7149: 1007149 + 7150: 1007150 + 7151: 1007151 + 7152: 1007152 + 7153: 1007153 + 7154: 1007154 + 7155: 1007155 + 7156: 1007156 + 7157: 1007157 + 7158: 1007158 + 7159: 1007159 + 7160: 1007160 + 7161: 1007161 + 7162: 1007162 + 7163: 1007163 + 7164: 1007164 + 7165: 1007165 + 7166: 1007166 + 7167: 1007167 + 7168: 1007168 + 7169: 1007169 + 7170: 1007170 + 7171: 1007171 + 7172: 1007172 + 7173: 1007173 + 7174: 1007174 + 7175: 1007175 + 7176: 1007176 + 7177: 1007177 + 7178: 1007178 + 7179: 1007179 + 7180: 1007180 + 7181: 1007181 + 7182: 1007182 + 7183: 1007183 + 7184: 1007184 + 7185: 1007185 + 7186: 1007186 + 7187: 1007187 + 7188: 1007188 + 7189: 1007189 + 7190: 1007190 + 7191: 1007191 + 7192: 1007192 + 7193: 1007193 + 7194: 1007194 + 7195: 1007195 + 7196: 1007196 + 7197: 1007197 + 7198: 1007198 + 7199: 1007199 + 7200: 1007200 + 7201: 1007201 + 7202: 1007202 + 7203: 1007203 + 7204: 1007204 + 7205: 1007205 + 7206: 1007206 + 7207: 1007207 + 7208: 1007208 + 7209: 1007209 + 7210: 1007210 + 7211: 1007211 + 7212: 1007212 + 7213: 1007213 + 7214: 1007214 + 7215: 1007215 + 7216: 1007216 + 7217: 1007217 + 7218: 1007218 + 7219: 1007219 + 7220: 1007220 + 7221: 1007221 + 7222: 1007222 + 7223: 1007223 + 7224: 1007224 + 7225: 1007225 + 7226: 1007226 + 7227: 1007227 + 7228: 1007228 + 7229: 1007229 + 7230: 1007230 + 7231: 1007231 + 7232: 1007232 + 7233: 1007233 + 7234: 1007234 + 7235: 1007235 + 7236: 1007236 + 7237: 1007237 + 7238: 1007238 + 7239: 1007239 + 7240: 1007240 + 7241: 1007241 + 7242: 1007242 + 7243: 1007243 + 7244: 1007244 + 7245: 1007245 + 7246: 1007246 + 7247: 1007247 + 7248: 1007248 + 7249: 1007249 + 7250: 1007250 + 7251: 1007251 + 7252: 1007252 + 7253: 1007253 + 7254: 1007254 + 7255: 1007255 + 7256: 1007256 + 7257: 1007257 + 7258: 1007258 + 7259: 1007259 + 7260: 1007260 + 7261: 1007261 + 7262: 1007262 + 7263: 1007263 + 7264: 1007264 + 7265: 1007265 + 7266: 1007266 + 7267: 1007267 + 7268: 1007268 + 7269: 1007269 + 7270: 1007270 + 7271: 1007271 + 7272: 1007272 + 7273: 1007273 + 7274: 1007274 + 7275: 1007275 + 7276: 1007276 + 7277: 1007277 + 7278: 1007278 + 7279: 1007279 + 7280: 1007280 + 7281: 1007281 + 7282: 1007282 + 7283: 1007283 + 7284: 1007284 + 7285: 1007285 + 7286: 1007286 + 7287: 1007287 + 7288: 1007288 + 7289: 1007289 + 7290: 1007290 + 7291: 1007291 + 7292: 1007292 + 7293: 1007293 + 7294: 1007294 + 7295: 1007295 + 7296: 1007296 + 7297: 1007297 + 7298: 1007298 + 7299: 1007299 + 7300: 1007300 + 7301: 1007301 + 7302: 1007302 + 7303: 1007303 + 7304: 1007304 + 7305: 1007305 + 7306: 1007306 + 7307: 1007307 + 7308: 1007308 + 7309: 1007309 + 7310: 1007310 + 7311: 1007311 + 7312: 1007312 + 7313: 1007313 + 7314: 1007314 + 7315: 1007315 + 7316: 1007316 + 7317: 1007317 + 7318: 1007318 + 7319: 1007319 + 7320: 1007320 + 7321: 1007321 + 7322: 1007322 + 7323: 1007323 + 7324: 1007324 + 7325: 1007325 + 7326: 1007326 + 7327: 1007327 + 7328: 1007328 + 7329: 1007329 + 7330: 1007330 + 7331: 1007331 + 7332: 1007332 + 7333: 1007333 + 7334: 1007334 + 7335: 1007335 + 7336: 1007336 + 7337: 1007337 + 7338: 1007338 + 7339: 1007339 + 7340: 1007340 + 7341: 1007341 + 7342: 1007342 + 7343: 1007343 + 7344: 1007344 + 7345: 1007345 + 7346: 1007346 + 7347: 1007347 + 7348: 1007348 + 7349: 1007349 + 7350: 1007350 + 7351: 1007351 + 7352: 1007352 + 7353: 1007353 + 7354: 1007354 + 7355: 1007355 + 7356: 1007356 + 7357: 1007357 + 7358: 1007358 + 7359: 1007359 + 7360: 1007360 + 7361: 1007361 + 7362: 1007362 + 7363: 1007363 + 7364: 1007364 + 7365: 1007365 + 7366: 1007366 + 7367: 1007367 + 7368: 1007368 + 7369: 1007369 + 7370: 1007370 + 7371: 1007371 + 7372: 1007372 + 7373: 1007373 + 7374: 1007374 + 7375: 1007375 + 7376: 1007376 + 7377: 1007377 + 7378: 1007378 + 7379: 1007379 + 7380: 1007380 + 7381: 1007381 + 7382: 1007382 + 7383: 1007383 + 7384: 1007384 + 7385: 1007385 + 7386: 1007386 + 7387: 1007387 + 7388: 1007388 + 7389: 1007389 + 7390: 1007390 + 7391: 1007391 + 7392: 1007392 + 7393: 1007393 + 7394: 1007394 + 7395: 1007395 + 7396: 1007396 + 7397: 1007397 + 7398: 1007398 + 7399: 1007399 + 7400: 1007400 + 7401: 1007401 + 7402: 1007402 + 7403: 1007403 + 7404: 1007404 + 7405: 1007405 + 7406: 1007406 + 7407: 1007407 + 7408: 1007408 + 7409: 1007409 + 7410: 1007410 + 7411: 1007411 + 7412: 1007412 + 7413: 1007413 + 7414: 1007414 + 7415: 1007415 + 7416: 1007416 + 7417: 1007417 + 7418: 1007418 + 7419: 1007419 + 7420: 1007420 + 7421: 1007421 + 7422: 1007422 + 7423: 1007423 + 7424: 1007424 + 7425: 1007425 + 7426: 1007426 + 7427: 1007427 + 7428: 1007428 + 7429: 1007429 + 7430: 1007430 + 7431: 1007431 + 7432: 1007432 + 7433: 1007433 + 7434: 1007434 + 7435: 1007435 + 7436: 1007436 + 7437: 1007437 + 7438: 1007438 + 7439: 1007439 + 7440: 1007440 + 7441: 1007441 + 7442: 1007442 + 7443: 1007443 + 7444: 1007444 + 7445: 1007445 + 7446: 1007446 + 7447: 1007447 + 7448: 1007448 + 7449: 1007449 + 7450: 1007450 + 7451: 1007451 + 7452: 1007452 + 7453: 1007453 + 7454: 1007454 + 7455: 1007455 + 7456: 1007456 + 7457: 1007457 + 7458: 1007458 + 7459: 1007459 + 7460: 1007460 + 7461: 1007461 + 7462: 1007462 + 7463: 1007463 + 7464: 1007464 + 7465: 1007465 + 7466: 1007466 + 7467: 1007467 + 7468: 1007468 + 7469: 1007469 + 7470: 1007470 + 7471: 1007471 + 7472: 1007472 + 7473: 1007473 + 7474: 1007474 + 7475: 1007475 + 7476: 1007476 + 7477: 1007477 + 7478: 1007478 + 7479: 1007479 + 7480: 1007480 + 7481: 1007481 + 7482: 1007482 + 7483: 1007483 + 7484: 1007484 + 7485: 1007485 + 7486: 1007486 + 7487: 1007487 + 7488: 1007488 + 7489: 1007489 + 7490: 1007490 + 7491: 1007491 + 7492: 1007492 + 7493: 1007493 + 7494: 1007494 + 7495: 1007495 + 7496: 1007496 + 7497: 1007497 + 7498: 1007498 + 7499: 1007499 + 7500: 1007500 + 7501: 1007501 + 7502: 1007502 + 7503: 1007503 + 7504: 1007504 + 7505: 1007505 + 7506: 1007506 + 7507: 1007507 + 7508: 1007508 + 7509: 1007509 + 7510: 1007510 + 7511: 1007511 + 7512: 1007512 + 7513: 1007513 + 7514: 1007514 + 7515: 1007515 + 7516: 1007516 + 7517: 1007517 + 7518: 1007518 + 7519: 1007519 + 7520: 1007520 + 7521: 1007521 + 7522: 1007522 + 7523: 1007523 + 7524: 1007524 + 7525: 1007525 + 7526: 1007526 + 7527: 1007527 + 7528: 1007528 + 7529: 1007529 + 7530: 1007530 + 7531: 1007531 + 7532: 1007532 + 7533: 1007533 + 7534: 1007534 + 7535: 1007535 + 7536: 1007536 + 7537: 1007537 + 7538: 1007538 + 7539: 1007539 + 7540: 1007540 + 7541: 1007541 + 7542: 1007542 + 7543: 1007543 + 7544: 1007544 + 7545: 1007545 + 7546: 1007546 + 7547: 1007547 + 7548: 1007548 + 7549: 1007549 + 7550: 1007550 + 7551: 1007551 + 7552: 1007552 + 7553: 1007553 + 7554: 1007554 + 7555: 1007555 + 7556: 1007556 + 7557: 1007557 + 7558: 1007558 + 7559: 1007559 + 7560: 1007560 + 7561: 1007561 + 7562: 1007562 + 7563: 1007563 + 7564: 1007564 + 7565: 1007565 + 7566: 1007566 + 7567: 1007567 + 7568: 1007568 + 7569: 1007569 + 7570: 1007570 + 7571: 1007571 + 7572: 1007572 + 7573: 1007573 + 7574: 1007574 + 7575: 1007575 + 7576: 1007576 + 7577: 1007577 + 7578: 1007578 + 7579: 1007579 + 7580: 1007580 + 7581: 1007581 + 7582: 1007582 + 7583: 1007583 + 7584: 1007584 + 7585: 1007585 + 7586: 1007586 + 7587: 1007587 + 7588: 1007588 + 7589: 1007589 + 7590: 1007590 + 7591: 1007591 + 7592: 1007592 + 7593: 1007593 + 7594: 1007594 + 7595: 1007595 + 7596: 1007596 + 7597: 1007597 + 7598: 1007598 + 7599: 1007599 + 7600: 1007600 + 7601: 1007601 + 7602: 1007602 + 7603: 1007603 + 7604: 1007604 + 7605: 1007605 + 7606: 1007606 + 7607: 1007607 + 7608: 1007608 + 7609: 1007609 + 7610: 1007610 + 7611: 1007611 + 7612: 1007612 + 7613: 1007613 + 7614: 1007614 + 7615: 1007615 + 7616: 1007616 + 7617: 1007617 + 7618: 1007618 + 7619: 1007619 + 7620: 1007620 + 7621: 1007621 + 7622: 1007622 + 7623: 1007623 + 7624: 1007624 + 7625: 1007625 + 7626: 1007626 + 7627: 1007627 + 7628: 1007628 + 7629: 1007629 + 7630: 1007630 + 7631: 1007631 + 7632: 1007632 + 7633: 1007633 + 7634: 1007634 + 7635: 1007635 + 7636: 1007636 + 7637: 1007637 + 7638: 1007638 + 7639: 1007639 + 7640: 1007640 + 7641: 1007641 + 7642: 1007642 + 7643: 1007643 + 7644: 1007644 + 7645: 1007645 + 7646: 1007646 + 7647: 1007647 + 7648: 1007648 + 7649: 1007649 + 7650: 1007650 + 7651: 1007651 + 7652: 1007652 + 7653: 1007653 + 7654: 1007654 + 7655: 1007655 + 7656: 1007656 + 7657: 1007657 + 7658: 1007658 + 7659: 1007659 + 7660: 1007660 + 7661: 1007661 + 7662: 1007662 + 7663: 1007663 + 7664: 1007664 + 7665: 1007665 + 7666: 1007666 + 7667: 1007667 + 7668: 1007668 + 7669: 1007669 + 7670: 1007670 + 7671: 1007671 + 7672: 1007672 + 7673: 1007673 + 7674: 1007674 + 7675: 1007675 + 7676: 1007676 + 7677: 1007677 + 7678: 1007678 + 7679: 1007679 + 7680: 1007680 + 7681: 1007681 + 7682: 1007682 + 7683: 1007683 + 7684: 1007684 + 7685: 1007685 + 7686: 1007686 + 7687: 1007687 + 7688: 1007688 + 7689: 1007689 + 7690: 1007690 + 7691: 1007691 + 7692: 1007692 + 7693: 1007693 + 7694: 1007694 + 7695: 1007695 + 7696: 1007696 + 7697: 1007697 + 7698: 1007698 + 7699: 1007699 + 7700: 1007700 + 7701: 1007701 + 7702: 1007702 + 7703: 1007703 + 7704: 1007704 + 7705: 1007705 + 7706: 1007706 + 7707: 1007707 + 7708: 1007708 + 7709: 1007709 + 7710: 1007710 + 7711: 1007711 + 7712: 1007712 + 7713: 1007713 + 7714: 1007714 + 7715: 1007715 + 7716: 1007716 + 7717: 1007717 + 7718: 1007718 + 7719: 1007719 + 7720: 1007720 + 7721: 1007721 + 7722: 1007722 + 7723: 1007723 + 7724: 1007724 + 7725: 1007725 + 7726: 1007726 + 7727: 1007727 + 7728: 1007728 + 7729: 1007729 + 7730: 1007730 + 7731: 1007731 + 7732: 1007732 + 7733: 1007733 + 7734: 1007734 + 7735: 1007735 + 7736: 1007736 + 7737: 1007737 + 7738: 1007738 + 7739: 1007739 + 7740: 1007740 + 7741: 1007741 + 7742: 1007742 + 7743: 1007743 + 7744: 1007744 + 7745: 1007745 + 7746: 1007746 + 7747: 1007747 + 7748: 1007748 + 7749: 1007749 + 7750: 1007750 + 7751: 1007751 + 7752: 1007752 + 7753: 1007753 + 7754: 1007754 + 7755: 1007755 + 7756: 1007756 + 7757: 1007757 + 7758: 1007758 + 7759: 1007759 + 7760: 1007760 + 7761: 1007761 + 7762: 1007762 + 7763: 1007763 + 7764: 1007764 + 7765: 1007765 + 7766: 1007766 + 7767: 1007767 + 7768: 1007768 + 7769: 1007769 + 7770: 1007770 + 7771: 1007771 + 7772: 1007772 + 7773: 1007773 + 7774: 1007774 + 7775: 1007775 + 7776: 1007776 + 7777: 1007777 + 7778: 1007778 + 7779: 1007779 + 7780: 1007780 + 7781: 1007781 + 7782: 1007782 + 7783: 1007783 + 7784: 1007784 + 7785: 1007785 + 7786: 1007786 + 7787: 1007787 + 7788: 1007788 + 7789: 1007789 + 7790: 1007790 + 7791: 1007791 + 7792: 1007792 + 7793: 1007793 + 7794: 1007794 + 7795: 1007795 + 7796: 1007796 + 7797: 1007797 + 7798: 1007798 + 7799: 1007799 + 7800: 1007800 + 7801: 1007801 + 7802: 1007802 + 7803: 1007803 + 7804: 1007804 + 7805: 1007805 + 7806: 1007806 + 7807: 1007807 + 7808: 1007808 + 7809: 1007809 + 7810: 1007810 + 7811: 1007811 + 7812: 1007812 + 7813: 1007813 + 7814: 1007814 + 7815: 1007815 + 7816: 1007816 + 7817: 1007817 + 7818: 1007818 + 7819: 1007819 + 7820: 1007820 + 7821: 1007821 + 7822: 1007822 + 7823: 1007823 + 7824: 1007824 + 7825: 1007825 + 7826: 1007826 + 7827: 1007827 + 7828: 1007828 + 7829: 1007829 + 7830: 1007830 + 7831: 1007831 + 7832: 1007832 + 7833: 1007833 + 7834: 1007834 + 7835: 1007835 + 7836: 1007836 + 7837: 1007837 + 7838: 1007838 + 7839: 1007839 + 7840: 1007840 + 7841: 1007841 + 7842: 1007842 + 7843: 1007843 + 7844: 1007844 + 7845: 1007845 + 7846: 1007846 + 7847: 1007847 + 7848: 1007848 + 7849: 1007849 + 7850: 1007850 + 7851: 1007851 + 7852: 1007852 + 7853: 1007853 + 7854: 1007854 + 7855: 1007855 + 7856: 1007856 + 7857: 1007857 + 7858: 1007858 + 7859: 1007859 + 7860: 1007860 + 7861: 1007861 + 7862: 1007862 + 7863: 1007863 + 7864: 1007864 + 7865: 1007865 + 7866: 1007866 + 7867: 1007867 + 7868: 1007868 + 7869: 1007869 + 7870: 1007870 + 7871: 1007871 + 7872: 1007872 + 7873: 1007873 + 7874: 1007874 + 7875: 1007875 + 7876: 1007876 + 7877: 1007877 + 7878: 1007878 + 7879: 1007879 + 7880: 1007880 + 7881: 1007881 + 7882: 1007882 + 7883: 1007883 + 7884: 1007884 + 7885: 1007885 + 7886: 1007886 + 7887: 1007887 + 7888: 1007888 + 7889: 1007889 + 7890: 1007890 + 7891: 1007891 + 7892: 1007892 + 7893: 1007893 + 7894: 1007894 + 7895: 1007895 + 7896: 1007896 + 7897: 1007897 + 7898: 1007898 + 7899: 1007899 + 7900: 1007900 + 7901: 1007901 + 7902: 1007902 + 7903: 1007903 + 7904: 1007904 + 7905: 1007905 + 7906: 1007906 + 7907: 1007907 + 7908: 1007908 + 7909: 1007909 + 7910: 1007910 + 7911: 1007911 + 7912: 1007912 + 7913: 1007913 + 7914: 1007914 + 7915: 1007915 + 7916: 1007916 + 7917: 1007917 + 7918: 1007918 + 7919: 1007919 + 7920: 1007920 + 7921: 1007921 + 7922: 1007922 + 7923: 1007923 + 7924: 1007924 + 7925: 1007925 + 7926: 1007926 + 7927: 1007927 + 7928: 1007928 + 7929: 1007929 + 7930: 1007930 + 7931: 1007931 + 7932: 1007932 + 7933: 1007933 + 7934: 1007934 + 7935: 1007935 + 7936: 1007936 + 7937: 1007937 + 7938: 1007938 + 7939: 1007939 + 7940: 1007940 + 7941: 1007941 + 7942: 1007942 + 7943: 1007943 + 7944: 1007944 + 7945: 1007945 + 7946: 1007946 + 7947: 1007947 + 7948: 1007948 + 7949: 1007949 + 7950: 1007950 + 7951: 1007951 + 7952: 1007952 + 7953: 1007953 + 7954: 1007954 + 7955: 1007955 + 7956: 1007956 + 7957: 1007957 + 7958: 1007958 + 7959: 1007959 + 7960: 1007960 + 7961: 1007961 + 7962: 1007962 + 7963: 1007963 + 7964: 1007964 + 7965: 1007965 + 7966: 1007966 + 7967: 1007967 + 7968: 1007968 + 7969: 1007969 + 7970: 1007970 + 7971: 1007971 + 7972: 1007972 + 7973: 1007973 + 7974: 1007974 + 7975: 1007975 + 7976: 1007976 + 7977: 1007977 + 7978: 1007978 + 7979: 1007979 + 7980: 1007980 + 7981: 1007981 + 7982: 1007982 + 7983: 1007983 + 7984: 1007984 + 7985: 1007985 + 7986: 1007986 + 7987: 1007987 + 7988: 1007988 + 7989: 1007989 + 7990: 1007990 + 7991: 1007991 + 7992: 1007992 + 7993: 1007993 + 7994: 1007994 + 7995: 1007995 + 7996: 1007996 + 7997: 1007997 + 7998: 1007998 + 7999: 1007999 + 8000: 1008000 + 8001: 1008001 + 8002: 1008002 + 8003: 1008003 + 8004: 1008004 + 8005: 1008005 + 8006: 1008006 + 8007: 1008007 + 8008: 1008008 + 8009: 1008009 + 8010: 1008010 + 8011: 1008011 + 8012: 1008012 + 8013: 1008013 + 8014: 1008014 + 8015: 1008015 + 8016: 1008016 + 8017: 1008017 + 8018: 1008018 + 8019: 1008019 + 8020: 1008020 + 8021: 1008021 + 8022: 1008022 + 8023: 1008023 + 8024: 1008024 + 8025: 1008025 + 8026: 1008026 + 8027: 1008027 + 8028: 1008028 + 8029: 1008029 + 8030: 1008030 + 8031: 1008031 + 8032: 1008032 + 8033: 1008033 + 8034: 1008034 + 8035: 1008035 + 8036: 1008036 + 8037: 1008037 + 8038: 1008038 + 8039: 1008039 + 8040: 1008040 + 8041: 1008041 + 8042: 1008042 + 8043: 1008043 + 8044: 1008044 + 8045: 1008045 + 8046: 1008046 + 8047: 1008047 + 8048: 1008048 + 8049: 1008049 + 8050: 1008050 + 8051: 1008051 + 8052: 1008052 + 8053: 1008053 + 8054: 1008054 + 8055: 1008055 + 8056: 1008056 + 8057: 1008057 + 8058: 1008058 + 8059: 1008059 + 8060: 1008060 + 8061: 1008061 + 8062: 1008062 + 8063: 1008063 + 8064: 1008064 + 8065: 1008065 + 8066: 1008066 + 8067: 1008067 + 8068: 1008068 + 8069: 1008069 + 8070: 1008070 + 8071: 1008071 + 8072: 1008072 + 8073: 1008073 + 8074: 1008074 + 8075: 1008075 + 8076: 1008076 + 8077: 1008077 + 8078: 1008078 + 8079: 1008079 + 8080: 1008080 + 8081: 1008081 + 8082: 1008082 + 8083: 1008083 + 8084: 1008084 + 8085: 1008085 + 8086: 1008086 + 8087: 1008087 + 8088: 1008088 + 8089: 1008089 + 8090: 1008090 + 8091: 1008091 + 8092: 1008092 + 8093: 1008093 + 8094: 1008094 + 8095: 1008095 + 8096: 1008096 + 8097: 1008097 + 8098: 1008098 + 8099: 1008099 + 8100: 1008100 + 8101: 1008101 + 8102: 1008102 + 8103: 1008103 + 8104: 1008104 + 8105: 1008105 + 8106: 1008106 + 8107: 1008107 + 8108: 1008108 + 8109: 1008109 + 8110: 1008110 + 8111: 1008111 + 8112: 1008112 + 8113: 1008113 + 8114: 1008114 + 8115: 1008115 + 8116: 1008116 + 8117: 1008117 + 8118: 1008118 + 8119: 1008119 + 8120: 1008120 + 8121: 1008121 + 8122: 1008122 + 8123: 1008123 + 8124: 1008124 + 8125: 1008125 + 8126: 1008126 + 8127: 1008127 + 8128: 1008128 + 8129: 1008129 + 8130: 1008130 + 8131: 1008131 + 8132: 1008132 + 8133: 1008133 + 8134: 1008134 + 8135: 1008135 + 8136: 1008136 + 8137: 1008137 + 8138: 1008138 + 8139: 1008139 + 8140: 1008140 + 8141: 1008141 + 8142: 1008142 + 8143: 1008143 + 8144: 1008144 + 8145: 1008145 + 8146: 1008146 + 8147: 1008147 + 8148: 1008148 + 8149: 1008149 + 8150: 1008150 + 8151: 1008151 + 8152: 1008152 + 8153: 1008153 + 8154: 1008154 + 8155: 1008155 + 8156: 1008156 + 8157: 1008157 + 8158: 1008158 + 8159: 1008159 + 8160: 1008160 + 8161: 1008161 + 8162: 1008162 + 8163: 1008163 + 8164: 1008164 + 8165: 1008165 + 8166: 1008166 + 8167: 1008167 + 8168: 1008168 + 8169: 1008169 + 8170: 1008170 + 8171: 1008171 + 8172: 1008172 + 8173: 1008173 + 8174: 1008174 + 8175: 1008175 + 8176: 1008176 + 8177: 1008177 + 8178: 1008178 + 8179: 1008179 + 8180: 1008180 + 8181: 1008181 + 8182: 1008182 + 8183: 1008183 + 8184: 1008184 + 8185: 1008185 + 8186: 1008186 + 8187: 1008187 + 8188: 1008188 + 8189: 1008189 + 8190: 1008190 + 8191: 1008191 + 8192: 1008192 + 8193: 1008193 + 8194: 1008194 + 8195: 1008195 + 8196: 1008196 + 8197: 1008197 + 8198: 1008198 + 8199: 1008199 + 8200: 1008200 + 8201: 1008201 + 8202: 1008202 + 8203: 1008203 + 8204: 1008204 + 8205: 1008205 + 8206: 1008206 + 8207: 1008207 + 8208: 1008208 + 8209: 1008209 + 8210: 1008210 + 8211: 1008211 + 8212: 1008212 + 8213: 1008213 + 8214: 1008214 + 8215: 1008215 + 8216: 1008216 + 8217: 1008217 + 8218: 1008218 + 8219: 1008219 + 8220: 1008220 + 8221: 1008221 + 8222: 1008222 + 8223: 1008223 + 8224: 1008224 + 8225: 1008225 + 8226: 1008226 + 8227: 1008227 + 8228: 1008228 + 8229: 1008229 + 8230: 1008230 + 8231: 1008231 + 8232: 1008232 + 8233: 1008233 + 8234: 1008234 + 8235: 1008235 + 8236: 1008236 + 8237: 1008237 + 8238: 1008238 + 8239: 1008239 + 8240: 1008240 + 8241: 1008241 + 8242: 1008242 + 8243: 1008243 + 8244: 1008244 + 8245: 1008245 + 8246: 1008246 + 8247: 1008247 + 8248: 1008248 + 8249: 1008249 + 8250: 1008250 + 8251: 1008251 + 8252: 1008252 + 8253: 1008253 + 8254: 1008254 + 8255: 1008255 + 8256: 1008256 + 8257: 1008257 + 8258: 1008258 + 8259: 1008259 + 8260: 1008260 + 8261: 1008261 + 8262: 1008262 + 8263: 1008263 + 8264: 1008264 + 8265: 1008265 + 8266: 1008266 + 8267: 1008267 + 8268: 1008268 + 8269: 1008269 + 8270: 1008270 + 8271: 1008271 + 8272: 1008272 + 8273: 1008273 + 8274: 1008274 + 8275: 1008275 + 8276: 1008276 + 8277: 1008277 + 8278: 1008278 + 8279: 1008279 + 8280: 1008280 + 8281: 1008281 + 8282: 1008282 + 8283: 1008283 + 8284: 1008284 + 8285: 1008285 + 8286: 1008286 + 8287: 1008287 + 8288: 1008288 + 8289: 1008289 + 8290: 1008290 + 8291: 1008291 + 8292: 1008292 + 8293: 1008293 + 8294: 1008294 + 8295: 1008295 + 8296: 1008296 + 8297: 1008297 + 8298: 1008298 + 8299: 1008299 + 8300: 1008300 + 8301: 1008301 + 8302: 1008302 + 8303: 1008303 + 8304: 1008304 + 8305: 1008305 + 8306: 1008306 + 8307: 1008307 + 8308: 1008308 + 8309: 1008309 + 8310: 1008310 + 8311: 1008311 + 8312: 1008312 + 8313: 1008313 + 8314: 1008314 + 8315: 1008315 + 8316: 1008316 + 8317: 1008317 + 8318: 1008318 + 8319: 1008319 + 8320: 1008320 + 8321: 1008321 + 8322: 1008322 + 8323: 1008323 + 8324: 1008324 + 8325: 1008325 + 8326: 1008326 + 8327: 1008327 + 8328: 1008328 + 8329: 1008329 + 8330: 1008330 + 8331: 1008331 + 8332: 1008332 + 8333: 1008333 + 8334: 1008334 + 8335: 1008335 + 8336: 1008336 + 8337: 1008337 + 8338: 1008338 + 8339: 1008339 + 8340: 1008340 + 8341: 1008341 + 8342: 1008342 + 8343: 1008343 + 8344: 1008344 + 8345: 1008345 + 8346: 1008346 + 8347: 1008347 + 8348: 1008348 + 8349: 1008349 + 8350: 1008350 + 8351: 1008351 + 8352: 1008352 + 8353: 1008353 + 8354: 1008354 + 8355: 1008355 + 8356: 1008356 + 8357: 1008357 + 8358: 1008358 + 8359: 1008359 + 8360: 1008360 + 8361: 1008361 + 8362: 1008362 + 8363: 1008363 + 8364: 1008364 + 8365: 1008365 + 8366: 1008366 + 8367: 1008367 + 8368: 1008368 + 8369: 1008369 + 8370: 1008370 + 8371: 1008371 + 8372: 1008372 + 8373: 1008373 + 8374: 1008374 + 8375: 1008375 + 8376: 1008376 + 8377: 1008377 + 8378: 1008378 + 8379: 1008379 + 8380: 1008380 + 8381: 1008381 + 8382: 1008382 + 8383: 1008383 + 8384: 1008384 + 8385: 1008385 + 8386: 1008386 + 8387: 1008387 + 8388: 1008388 + 8389: 1008389 + 8390: 1008390 + 8391: 1008391 + 8392: 1008392 + 8393: 1008393 + 8394: 1008394 + 8395: 1008395 + 8396: 1008396 + 8397: 1008397 + 8398: 1008398 + 8399: 1008399 + 8400: 1008400 + 8401: 1008401 + 8402: 1008402 + 8403: 1008403 + 8404: 1008404 + 8405: 1008405 + 8406: 1008406 + 8407: 1008407 + 8408: 1008408 + 8409: 1008409 + 8410: 1008410 + 8411: 1008411 + 8412: 1008412 + 8413: 1008413 + 8414: 1008414 + 8415: 1008415 + 8416: 1008416 + 8417: 1008417 + 8418: 1008418 + 8419: 1008419 + 8420: 1008420 + 8421: 1008421 + 8422: 1008422 + 8423: 1008423 + 8424: 1008424 + 8425: 1008425 + 8426: 1008426 + 8427: 1008427 + 8428: 1008428 + 8429: 1008429 + 8430: 1008430 + 8431: 1008431 + 8432: 1008432 + 8433: 1008433 + 8434: 1008434 + 8435: 1008435 + 8436: 1008436 + 8437: 1008437 + 8438: 1008438 + 8439: 1008439 + 8440: 1008440 + 8441: 1008441 + 8442: 1008442 + 8443: 1008443 + 8444: 1008444 + 8445: 1008445 + 8446: 1008446 + 8447: 1008447 + 8448: 1008448 + 8449: 1008449 + 8450: 1008450 + 8451: 1008451 + 8452: 1008452 + 8453: 1008453 + 8454: 1008454 + 8455: 1008455 + 8456: 1008456 + 8457: 1008457 + 8458: 1008458 + 8459: 1008459 + 8460: 1008460 + 8461: 1008461 + 8462: 1008462 + 8463: 1008463 + 8464: 1008464 + 8465: 1008465 + 8466: 1008466 + 8467: 1008467 + 8468: 1008468 + 8469: 1008469 + 8470: 1008470 + 8471: 1008471 + 8472: 1008472 + 8473: 1008473 + 8474: 1008474 + 8475: 1008475 + 8476: 1008476 + 8477: 1008477 + 8478: 1008478 + 8479: 1008479 + 8480: 1008480 + 8481: 1008481 + 8482: 1008482 + 8483: 1008483 + 8484: 1008484 + 8485: 1008485 + 8486: 1008486 + 8487: 1008487 + 8488: 1008488 + 8489: 1008489 + 8490: 1008490 + 8491: 1008491 + 8492: 1008492 + 8493: 1008493 + 8494: 1008494 + 8495: 1008495 + 8496: 1008496 + 8497: 1008497 + 8498: 1008498 + 8499: 1008499 + 8500: 1008500 + 8501: 1008501 + 8502: 1008502 + 8503: 1008503 + 8504: 1008504 + 8505: 1008505 + 8506: 1008506 + 8507: 1008507 + 8508: 1008508 + 8509: 1008509 + 8510: 1008510 + 8511: 1008511 + 8512: 1008512 + 8513: 1008513 + 8514: 1008514 + 8515: 1008515 + 8516: 1008516 + 8517: 1008517 + 8518: 1008518 + 8519: 1008519 + 8520: 1008520 + 8521: 1008521 + 8522: 1008522 + 8523: 1008523 + 8524: 1008524 + 8525: 1008525 + 8526: 1008526 + 8527: 1008527 + 8528: 1008528 + 8529: 1008529 + 8530: 1008530 + 8531: 1008531 + 8532: 1008532 + 8533: 1008533 + 8534: 1008534 + 8535: 1008535 + 8536: 1008536 + 8537: 1008537 + 8538: 1008538 + 8539: 1008539 + 8540: 1008540 + 8541: 1008541 + 8542: 1008542 + 8543: 1008543 + 8544: 1008544 + 8545: 1008545 + 8546: 1008546 + 8547: 1008547 + 8548: 1008548 + 8549: 1008549 + 8550: 1008550 + 8551: 1008551 + 8552: 1008552 + 8553: 1008553 + 8554: 1008554 + 8555: 1008555 + 8556: 1008556 + 8557: 1008557 + 8558: 1008558 + 8559: 1008559 + 8560: 1008560 + 8561: 1008561 + 8562: 1008562 + 8563: 1008563 + 8564: 1008564 + 8565: 1008565 + 8566: 1008566 + 8567: 1008567 + 8568: 1008568 + 8569: 1008569 + 8570: 1008570 + 8571: 1008571 + 8572: 1008572 + 8573: 1008573 + 8574: 1008574 + 8575: 1008575 + 8576: 1008576 + 8577: 1008577 + 8578: 1008578 + 8579: 1008579 + 8580: 1008580 + 8581: 1008581 + 8582: 1008582 + 8583: 1008583 + 8584: 1008584 + 8585: 1008585 + 8586: 1008586 + 8587: 1008587 + 8588: 1008588 + 8589: 1008589 + 8590: 1008590 + 8591: 1008591 + 8592: 1008592 + 8593: 1008593 + 8594: 1008594 + 8595: 1008595 + 8596: 1008596 + 8597: 1008597 + 8598: 1008598 + 8599: 1008599 + 8600: 1008600 + 8601: 1008601 + 8602: 1008602 + 8603: 1008603 + 8604: 1008604 + 8605: 1008605 + 8606: 1008606 + 8607: 1008607 + 8608: 1008608 + 8609: 1008609 + 8610: 1008610 + 8611: 1008611 + 8612: 1008612 + 8613: 1008613 + 8614: 1008614 + 8615: 1008615 + 8616: 1008616 + 8617: 1008617 + 8618: 1008618 + 8619: 1008619 + 8620: 1008620 + 8621: 1008621 + 8622: 1008622 + 8623: 1008623 + 8624: 1008624 + 8625: 1008625 + 8626: 1008626 + 8627: 1008627 + 8628: 1008628 + 8629: 1008629 + 8630: 1008630 + 8631: 1008631 + 8632: 1008632 + 8633: 1008633 + 8634: 1008634 + 8635: 1008635 + 8636: 1008636 + 8637: 1008637 + 8638: 1008638 + 8639: 1008639 + 8640: 1008640 + 8641: 1008641 + 8642: 1008642 + 8643: 1008643 + 8644: 1008644 + 8645: 1008645 + 8646: 1008646 + 8647: 1008647 + 8648: 1008648 + 8649: 1008649 + 8650: 1008650 + 8651: 1008651 + 8652: 1008652 + 8653: 1008653 + 8654: 1008654 + 8655: 1008655 + 8656: 1008656 + 8657: 1008657 + 8658: 1008658 + 8659: 1008659 + 8660: 1008660 + 8661: 1008661 + 8662: 1008662 + 8663: 1008663 + 8664: 1008664 + 8665: 1008665 + 8666: 1008666 + 8667: 1008667 + 8668: 1008668 + 8669: 1008669 + 8670: 1008670 + 8671: 1008671 + 8672: 1008672 + 8673: 1008673 + 8674: 1008674 + 8675: 1008675 + 8676: 1008676 + 8677: 1008677 + 8678: 1008678 + 8679: 1008679 + 8680: 1008680 + 8681: 1008681 + 8682: 1008682 + 8683: 1008683 + 8684: 1008684 + 8685: 1008685 + 8686: 1008686 + 8687: 1008687 + 8688: 1008688 + 8689: 1008689 + 8690: 1008690 + 8691: 1008691 + 8692: 1008692 + 8693: 1008693 + 8694: 1008694 + 8695: 1008695 + 8696: 1008696 + 8697: 1008697 + 8698: 1008698 + 8699: 1008699 + 8700: 1008700 + 8701: 1008701 + 8702: 1008702 + 8703: 1008703 + 8704: 1008704 + 8705: 1008705 + 8706: 1008706 + 8707: 1008707 + 8708: 1008708 + 8709: 1008709 + 8710: 1008710 + 8711: 1008711 + 8712: 1008712 + 8713: 1008713 + 8714: 1008714 + 8715: 1008715 + 8716: 1008716 + 8717: 1008717 + 8718: 1008718 + 8719: 1008719 + 8720: 1008720 + 8721: 1008721 + 8722: 1008722 + 8723: 1008723 + 8724: 1008724 + 8725: 1008725 + 8726: 1008726 + 8727: 1008727 + 8728: 1008728 + 8729: 1008729 + 8730: 1008730 + 8731: 1008731 + 8732: 1008732 + 8733: 1008733 + 8734: 1008734 + 8735: 1008735 + 8736: 1008736 + 8737: 1008737 + 8738: 1008738 + 8739: 1008739 + 8740: 1008740 + 8741: 1008741 + 8742: 1008742 + 8743: 1008743 + 8744: 1008744 + 8745: 1008745 + 8746: 1008746 + 8747: 1008747 + 8748: 1008748 + 8749: 1008749 + 8750: 1008750 + 8751: 1008751 + 8752: 1008752 + 8753: 1008753 + 8754: 1008754 + 8755: 1008755 + 8756: 1008756 + 8757: 1008757 + 8758: 1008758 + 8759: 1008759 + 8760: 1008760 + 8761: 1008761 + 8762: 1008762 + 8763: 1008763 + 8764: 1008764 + 8765: 1008765 + 8766: 1008766 + 8767: 1008767 + 8768: 1008768 + 8769: 1008769 + 8770: 1008770 + 8771: 1008771 + 8772: 1008772 + 8773: 1008773 + 8774: 1008774 + 8775: 1008775 + 8776: 1008776 + 8777: 1008777 + 8778: 1008778 + 8779: 1008779 + 8780: 1008780 + 8781: 1008781 + 8782: 1008782 + 8783: 1008783 + 8784: 1008784 + 8785: 1008785 + 8786: 1008786 + 8787: 1008787 + 8788: 1008788 + 8789: 1008789 + 8790: 1008790 + 8791: 1008791 + 8792: 1008792 + 8793: 1008793 + 8794: 1008794 + 8795: 1008795 + 8796: 1008796 + 8797: 1008797 + 8798: 1008798 + 8799: 1008799 + 8800: 1008800 + 8801: 1008801 + 8802: 1008802 + 8803: 1008803 + 8804: 1008804 + 8805: 1008805 + 8806: 1008806 + 8807: 1008807 + 8808: 1008808 + 8809: 1008809 + 8810: 1008810 + 8811: 1008811 + 8812: 1008812 + 8813: 1008813 + 8814: 1008814 + 8815: 1008815 + 8816: 1008816 + 8817: 1008817 + 8818: 1008818 + 8819: 1008819 + 8820: 1008820 + 8821: 1008821 + 8822: 1008822 + 8823: 1008823 + 8824: 1008824 + 8825: 1008825 + 8826: 1008826 + 8827: 1008827 + 8828: 1008828 + 8829: 1008829 + 8830: 1008830 + 8831: 1008831 + 8832: 1008832 + 8833: 1008833 + 8834: 1008834 + 8835: 1008835 + 8836: 1008836 + 8837: 1008837 + 8838: 1008838 + 8839: 1008839 + 8840: 1008840 + 8841: 1008841 + 8842: 1008842 + 8843: 1008843 + 8844: 1008844 + 8845: 1008845 + 8846: 1008846 + 8847: 1008847 + 8848: 1008848 + 8849: 1008849 + 8850: 1008850 + 8851: 1008851 + 8852: 1008852 + 8853: 1008853 + 8854: 1008854 + 8855: 1008855 + 8856: 1008856 + 8857: 1008857 + 8858: 1008858 + 8859: 1008859 + 8860: 1008860 + 8861: 1008861 + 8862: 1008862 + 8863: 1008863 + 8864: 1008864 + 8865: 1008865 + 8866: 1008866 + 8867: 1008867 + 8868: 1008868 + 8869: 1008869 + 8870: 1008870 + 8871: 1008871 + 8872: 1008872 + 8873: 1008873 + 8874: 1008874 + 8875: 1008875 + 8876: 1008876 + 8877: 1008877 + 8878: 1008878 + 8879: 1008879 + 8880: 1008880 + 8881: 1008881 + 8882: 1008882 + 8883: 1008883 + 8884: 1008884 + 8885: 1008885 + 8886: 1008886 + 8887: 1008887 + 8888: 1008888 + 8889: 1008889 + 8890: 1008890 + 8891: 1008891 + 8892: 1008892 + 8893: 1008893 + 8894: 1008894 + 8895: 1008895 + 8896: 1008896 + 8897: 1008897 + 8898: 1008898 + 8899: 1008899 + 8900: 1008900 + 8901: 1008901 + 8902: 1008902 + 8903: 1008903 + 8904: 1008904 + 8905: 1008905 + 8906: 1008906 + 8907: 1008907 + 8908: 1008908 + 8909: 1008909 + 8910: 1008910 + 8911: 1008911 + 8912: 1008912 + 8913: 1008913 + 8914: 1008914 + 8915: 1008915 + 8916: 1008916 + 8917: 1008917 + 8918: 1008918 + 8919: 1008919 + 8920: 1008920 + 8921: 1008921 + 8922: 1008922 + 8923: 1008923 + 8924: 1008924 + 8925: 1008925 + 8926: 1008926 + 8927: 1008927 + 8928: 1008928 + 8929: 1008929 + 8930: 1008930 + 8931: 1008931 + 8932: 1008932 + 8933: 1008933 + 8934: 1008934 + 8935: 1008935 + 8936: 1008936 + 8937: 1008937 + 8938: 1008938 + 8939: 1008939 + 8940: 1008940 + 8941: 1008941 + 8942: 1008942 + 8943: 1008943 + 8944: 1008944 + 8945: 1008945 + 8946: 1008946 + 8947: 1008947 + 8948: 1008948 + 8949: 1008949 + 8950: 1008950 + 8951: 1008951 + 8952: 1008952 + 8953: 1008953 + 8954: 1008954 + 8955: 1008955 + 8956: 1008956 + 8957: 1008957 + 8958: 1008958 + 8959: 1008959 + 8960: 1008960 + 8961: 1008961 + 8962: 1008962 + 8963: 1008963 + 8964: 1008964 + 8965: 1008965 + 8966: 1008966 + 8967: 1008967 + 8968: 1008968 + 8969: 1008969 + 8970: 1008970 + 8971: 1008971 + 8972: 1008972 + 8973: 1008973 + 8974: 1008974 + 8975: 1008975 + 8976: 1008976 + 8977: 1008977 + 8978: 1008978 + 8979: 1008979 + 8980: 1008980 + 8981: 1008981 + 8982: 1008982 + 8983: 1008983 + 8984: 1008984 + 8985: 1008985 + 8986: 1008986 + 8987: 1008987 + 8988: 1008988 + 8989: 1008989 + 8990: 1008990 + 8991: 1008991 + 8992: 1008992 + 8993: 1008993 + 8994: 1008994 + 8995: 1008995 + 8996: 1008996 + 8997: 1008997 + 8998: 1008998 + 8999: 1008999 diff --git a/akregator/src/mk4storage/metakit/tests/ok/l02.txt b/akregator/src/mk4storage/metakit/tests/ok/l02.txt new file mode 100644 index 000000000..a1bd366e9 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l02.txt @@ -0,0 +1,2 @@ +>>> Over 64 Kb of strings +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/l02a.txt b/akregator/src/mk4storage/metakit/tests/ok/l02a.txt new file mode 100644 index 000000000..133662334 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l02a.txt @@ -0,0 +1,3503 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3500 rows = p1:S + 0: 'Alice in Wonderland' + 1: 'The wizard of Oz' + 2: 'I'm singin' in the rain' + 3: 'Alice in Wonderland' + 4: 'The wizard of Oz' + 5: 'I'm singin' in the rain' + 6: 'Alice in Wonderland' + 7: 'The wizard of Oz' + 8: 'I'm singin' in the rain' + 9: 'Alice in Wonderland' + 10: 'The wizard of Oz' + 11: 'I'm singin' in the rain' + 12: 'Alice in Wonderland' + 13: 'The wizard of Oz' + 14: 'I'm singin' in the rain' + 15: 'Alice in Wonderland' + 16: 'The wizard of Oz' + 17: 'I'm singin' in the rain' + 18: 'Alice in Wonderland' + 19: 'The wizard of Oz' + 20: 'I'm singin' in the rain' + 21: 'Alice in Wonderland' + 22: 'The wizard of Oz' + 23: 'I'm singin' in the rain' + 24: 'Alice in Wonderland' + 25: 'The wizard of Oz' + 26: 'I'm singin' in the rain' + 27: 'Alice in Wonderland' + 28: 'The wizard of Oz' + 29: 'I'm singin' in the rain' + 30: 'Alice in Wonderland' + 31: 'The wizard of Oz' + 32: 'I'm singin' in the rain' + 33: 'Alice in Wonderland' + 34: 'The wizard of Oz' + 35: 'I'm singin' in the rain' + 36: 'Alice in Wonderland' + 37: 'The wizard of Oz' + 38: 'I'm singin' in the rain' + 39: 'Alice in Wonderland' + 40: 'The wizard of Oz' + 41: 'I'm singin' in the rain' + 42: 'Alice in Wonderland' + 43: 'The wizard of Oz' + 44: 'I'm singin' in the rain' + 45: 'Alice in Wonderland' + 46: 'The wizard of Oz' + 47: 'I'm singin' in the rain' + 48: 'Alice in Wonderland' + 49: 'The wizard of Oz' + 50: 'I'm singin' in the rain' + 51: 'Alice in Wonderland' + 52: 'The wizard of Oz' + 53: 'I'm singin' in the rain' + 54: 'Alice in Wonderland' + 55: 'The wizard of Oz' + 56: 'I'm singin' in the rain' + 57: 'Alice in Wonderland' + 58: 'The wizard of Oz' + 59: 'I'm singin' in the rain' + 60: 'Alice in Wonderland' + 61: 'The wizard of Oz' + 62: 'I'm singin' in the rain' + 63: 'Alice in Wonderland' + 64: 'The wizard of Oz' + 65: 'I'm singin' in the rain' + 66: 'Alice in Wonderland' + 67: 'The wizard of Oz' + 68: 'I'm singin' in the rain' + 69: 'Alice in Wonderland' + 70: 'The wizard of Oz' + 71: 'I'm singin' in the rain' + 72: 'Alice in Wonderland' + 73: 'The wizard of Oz' + 74: 'I'm singin' in the rain' + 75: 'Alice in Wonderland' + 76: 'The wizard of Oz' + 77: 'I'm singin' in the rain' + 78: 'Alice in Wonderland' + 79: 'The wizard of Oz' + 80: 'I'm singin' in the rain' + 81: 'Alice in Wonderland' + 82: 'The wizard of Oz' + 83: 'I'm singin' in the rain' + 84: 'Alice in Wonderland' + 85: 'The wizard of Oz' + 86: 'I'm singin' in the rain' + 87: 'Alice in Wonderland' + 88: 'The wizard of Oz' + 89: 'I'm singin' in the rain' + 90: 'Alice in Wonderland' + 91: 'The wizard of Oz' + 92: 'I'm singin' in the rain' + 93: 'Alice in Wonderland' + 94: 'The wizard of Oz' + 95: 'I'm singin' in the rain' + 96: 'Alice in Wonderland' + 97: 'The wizard of Oz' + 98: 'I'm singin' in the rain' + 99: 'Alice in Wonderland' + 100: 'The wizard of Oz' + 101: 'I'm singin' in the rain' + 102: 'Alice in Wonderland' + 103: 'The wizard of Oz' + 104: 'I'm singin' in the rain' + 105: 'Alice in Wonderland' + 106: 'The wizard of Oz' + 107: 'I'm singin' in the rain' + 108: 'Alice in Wonderland' + 109: 'The wizard of Oz' + 110: 'I'm singin' in the rain' + 111: 'Alice in Wonderland' + 112: 'The wizard of Oz' + 113: 'I'm singin' in the rain' + 114: 'Alice in Wonderland' + 115: 'The wizard of Oz' + 116: 'I'm singin' in the rain' + 117: 'Alice in Wonderland' + 118: 'The wizard of Oz' + 119: 'I'm singin' in the rain' + 120: 'Alice in Wonderland' + 121: 'The wizard of Oz' + 122: 'I'm singin' in the rain' + 123: 'Alice in Wonderland' + 124: 'The wizard of Oz' + 125: 'I'm singin' in the rain' + 126: 'Alice in Wonderland' + 127: 'The wizard of Oz' + 128: 'I'm singin' in the rain' + 129: 'Alice in Wonderland' + 130: 'The wizard of Oz' + 131: 'I'm singin' in the rain' + 132: 'Alice in Wonderland' + 133: 'The wizard of Oz' + 134: 'I'm singin' in the rain' + 135: 'Alice in Wonderland' + 136: 'The wizard of Oz' + 137: 'I'm singin' in the rain' + 138: 'Alice in Wonderland' + 139: 'The wizard of Oz' + 140: 'I'm singin' in the rain' + 141: 'Alice in Wonderland' + 142: 'The wizard of Oz' + 143: 'I'm singin' in the rain' + 144: 'Alice in Wonderland' + 145: 'The wizard of Oz' + 146: 'I'm singin' in the rain' + 147: 'Alice in Wonderland' + 148: 'The wizard of Oz' + 149: 'I'm singin' in the rain' + 150: 'Alice in Wonderland' + 151: 'The wizard of Oz' + 152: 'I'm singin' in the rain' + 153: 'Alice in Wonderland' + 154: 'The wizard of Oz' + 155: 'I'm singin' in the rain' + 156: 'Alice in Wonderland' + 157: 'The wizard of Oz' + 158: 'I'm singin' in the rain' + 159: 'Alice in Wonderland' + 160: 'The wizard of Oz' + 161: 'I'm singin' in the rain' + 162: 'Alice in Wonderland' + 163: 'The wizard of Oz' + 164: 'I'm singin' in the rain' + 165: 'Alice in Wonderland' + 166: 'The wizard of Oz' + 167: 'I'm singin' in the rain' + 168: 'Alice in Wonderland' + 169: 'The wizard of Oz' + 170: 'I'm singin' in the rain' + 171: 'Alice in Wonderland' + 172: 'The wizard of Oz' + 173: 'I'm singin' in the rain' + 174: 'Alice in Wonderland' + 175: 'The wizard of Oz' + 176: 'I'm singin' in the rain' + 177: 'Alice in Wonderland' + 178: 'The wizard of Oz' + 179: 'I'm singin' in the rain' + 180: 'Alice in Wonderland' + 181: 'The wizard of Oz' + 182: 'I'm singin' in the rain' + 183: 'Alice in Wonderland' + 184: 'The wizard of Oz' + 185: 'I'm singin' in the rain' + 186: 'Alice in Wonderland' + 187: 'The wizard of Oz' + 188: 'I'm singin' in the rain' + 189: 'Alice in Wonderland' + 190: 'The wizard of Oz' + 191: 'I'm singin' in the rain' + 192: 'Alice in Wonderland' + 193: 'The wizard of Oz' + 194: 'I'm singin' in the rain' + 195: 'Alice in Wonderland' + 196: 'The wizard of Oz' + 197: 'I'm singin' in the rain' + 198: 'Alice in Wonderland' + 199: 'The wizard of Oz' + 200: 'I'm singin' in the rain' + 201: 'Alice in Wonderland' + 202: 'The wizard of Oz' + 203: 'I'm singin' in the rain' + 204: 'Alice in Wonderland' + 205: 'The wizard of Oz' + 206: 'I'm singin' in the rain' + 207: 'Alice in Wonderland' + 208: 'The wizard of Oz' + 209: 'I'm singin' in the rain' + 210: 'Alice in Wonderland' + 211: 'The wizard of Oz' + 212: 'I'm singin' in the rain' + 213: 'Alice in Wonderland' + 214: 'The wizard of Oz' + 215: 'I'm singin' in the rain' + 216: 'Alice in Wonderland' + 217: 'The wizard of Oz' + 218: 'I'm singin' in the rain' + 219: 'Alice in Wonderland' + 220: 'The wizard of Oz' + 221: 'I'm singin' in the rain' + 222: 'Alice in Wonderland' + 223: 'The wizard of Oz' + 224: 'I'm singin' in the rain' + 225: 'Alice in Wonderland' + 226: 'The wizard of Oz' + 227: 'I'm singin' in the rain' + 228: 'Alice in Wonderland' + 229: 'The wizard of Oz' + 230: 'I'm singin' in the rain' + 231: 'Alice in Wonderland' + 232: 'The wizard of Oz' + 233: 'I'm singin' in the rain' + 234: 'Alice in Wonderland' + 235: 'The wizard of Oz' + 236: 'I'm singin' in the rain' + 237: 'Alice in Wonderland' + 238: 'The wizard of Oz' + 239: 'I'm singin' in the rain' + 240: 'Alice in Wonderland' + 241: 'The wizard of Oz' + 242: 'I'm singin' in the rain' + 243: 'Alice in Wonderland' + 244: 'The wizard of Oz' + 245: 'I'm singin' in the rain' + 246: 'Alice in Wonderland' + 247: 'The wizard of Oz' + 248: 'I'm singin' in the rain' + 249: 'Alice in Wonderland' + 250: 'The wizard of Oz' + 251: 'I'm singin' in the rain' + 252: 'Alice in Wonderland' + 253: 'The wizard of Oz' + 254: 'I'm singin' in the rain' + 255: 'Alice in Wonderland' + 256: 'The wizard of Oz' + 257: 'I'm singin' in the rain' + 258: 'Alice in Wonderland' + 259: 'The wizard of Oz' + 260: 'I'm singin' in the rain' + 261: 'Alice in Wonderland' + 262: 'The wizard of Oz' + 263: 'I'm singin' in the rain' + 264: 'Alice in Wonderland' + 265: 'The wizard of Oz' + 266: 'I'm singin' in the rain' + 267: 'Alice in Wonderland' + 268: 'The wizard of Oz' + 269: 'I'm singin' in the rain' + 270: 'Alice in Wonderland' + 271: 'The wizard of Oz' + 272: 'I'm singin' in the rain' + 273: 'Alice in Wonderland' + 274: 'The wizard of Oz' + 275: 'I'm singin' in the rain' + 276: 'Alice in Wonderland' + 277: 'The wizard of Oz' + 278: 'I'm singin' in the rain' + 279: 'Alice in Wonderland' + 280: 'The wizard of Oz' + 281: 'I'm singin' in the rain' + 282: 'Alice in Wonderland' + 283: 'The wizard of Oz' + 284: 'I'm singin' in the rain' + 285: 'Alice in Wonderland' + 286: 'The wizard of Oz' + 287: 'I'm singin' in the rain' + 288: 'Alice in Wonderland' + 289: 'The wizard of Oz' + 290: 'I'm singin' in the rain' + 291: 'Alice in Wonderland' + 292: 'The wizard of Oz' + 293: 'I'm singin' in the rain' + 294: 'Alice in Wonderland' + 295: 'The wizard of Oz' + 296: 'I'm singin' in the rain' + 297: 'Alice in Wonderland' + 298: 'The wizard of Oz' + 299: 'I'm singin' in the rain' + 300: 'Alice in Wonderland' + 301: 'The wizard of Oz' + 302: 'I'm singin' in the rain' + 303: 'Alice in Wonderland' + 304: 'The wizard of Oz' + 305: 'I'm singin' in the rain' + 306: 'Alice in Wonderland' + 307: 'The wizard of Oz' + 308: 'I'm singin' in the rain' + 309: 'Alice in Wonderland' + 310: 'The wizard of Oz' + 311: 'I'm singin' in the rain' + 312: 'Alice in Wonderland' + 313: 'The wizard of Oz' + 314: 'I'm singin' in the rain' + 315: 'Alice in Wonderland' + 316: 'The wizard of Oz' + 317: 'I'm singin' in the rain' + 318: 'Alice in Wonderland' + 319: 'The wizard of Oz' + 320: 'I'm singin' in the rain' + 321: 'Alice in Wonderland' + 322: 'The wizard of Oz' + 323: 'I'm singin' in the rain' + 324: 'Alice in Wonderland' + 325: 'The wizard of Oz' + 326: 'I'm singin' in the rain' + 327: 'Alice in Wonderland' + 328: 'The wizard of Oz' + 329: 'I'm singin' in the rain' + 330: 'Alice in Wonderland' + 331: 'The wizard of Oz' + 332: 'I'm singin' in the rain' + 333: 'Alice in Wonderland' + 334: 'The wizard of Oz' + 335: 'I'm singin' in the rain' + 336: 'Alice in Wonderland' + 337: 'The wizard of Oz' + 338: 'I'm singin' in the rain' + 339: 'Alice in Wonderland' + 340: 'The wizard of Oz' + 341: 'I'm singin' in the rain' + 342: 'Alice in Wonderland' + 343: 'The wizard of Oz' + 344: 'I'm singin' in the rain' + 345: 'Alice in Wonderland' + 346: 'The wizard of Oz' + 347: 'I'm singin' in the rain' + 348: 'Alice in Wonderland' + 349: 'The wizard of Oz' + 350: 'I'm singin' in the rain' + 351: 'Alice in Wonderland' + 352: 'The wizard of Oz' + 353: 'I'm singin' in the rain' + 354: 'Alice in Wonderland' + 355: 'The wizard of Oz' + 356: 'I'm singin' in the rain' + 357: 'Alice in Wonderland' + 358: 'The wizard of Oz' + 359: 'I'm singin' in the rain' + 360: 'Alice in Wonderland' + 361: 'The wizard of Oz' + 362: 'I'm singin' in the rain' + 363: 'Alice in Wonderland' + 364: 'The wizard of Oz' + 365: 'I'm singin' in the rain' + 366: 'Alice in Wonderland' + 367: 'The wizard of Oz' + 368: 'I'm singin' in the rain' + 369: 'Alice in Wonderland' + 370: 'The wizard of Oz' + 371: 'I'm singin' in the rain' + 372: 'Alice in Wonderland' + 373: 'The wizard of Oz' + 374: 'I'm singin' in the rain' + 375: 'Alice in Wonderland' + 376: 'The wizard of Oz' + 377: 'I'm singin' in the rain' + 378: 'Alice in Wonderland' + 379: 'The wizard of Oz' + 380: 'I'm singin' in the rain' + 381: 'Alice in Wonderland' + 382: 'The wizard of Oz' + 383: 'I'm singin' in the rain' + 384: 'Alice in Wonderland' + 385: 'The wizard of Oz' + 386: 'I'm singin' in the rain' + 387: 'Alice in Wonderland' + 388: 'The wizard of Oz' + 389: 'I'm singin' in the rain' + 390: 'Alice in Wonderland' + 391: 'The wizard of Oz' + 392: 'I'm singin' in the rain' + 393: 'Alice in Wonderland' + 394: 'The wizard of Oz' + 395: 'I'm singin' in the rain' + 396: 'Alice in Wonderland' + 397: 'The wizard of Oz' + 398: 'I'm singin' in the rain' + 399: 'Alice in Wonderland' + 400: 'The wizard of Oz' + 401: 'I'm singin' in the rain' + 402: 'Alice in Wonderland' + 403: 'The wizard of Oz' + 404: 'I'm singin' in the rain' + 405: 'Alice in Wonderland' + 406: 'The wizard of Oz' + 407: 'I'm singin' in the rain' + 408: 'Alice in Wonderland' + 409: 'The wizard of Oz' + 410: 'I'm singin' in the rain' + 411: 'Alice in Wonderland' + 412: 'The wizard of Oz' + 413: 'I'm singin' in the rain' + 414: 'Alice in Wonderland' + 415: 'The wizard of Oz' + 416: 'I'm singin' in the rain' + 417: 'Alice in Wonderland' + 418: 'The wizard of Oz' + 419: 'I'm singin' in the rain' + 420: 'Alice in Wonderland' + 421: 'The wizard of Oz' + 422: 'I'm singin' in the rain' + 423: 'Alice in Wonderland' + 424: 'The wizard of Oz' + 425: 'I'm singin' in the rain' + 426: 'Alice in Wonderland' + 427: 'The wizard of Oz' + 428: 'I'm singin' in the rain' + 429: 'Alice in Wonderland' + 430: 'The wizard of Oz' + 431: 'I'm singin' in the rain' + 432: 'Alice in Wonderland' + 433: 'The wizard of Oz' + 434: 'I'm singin' in the rain' + 435: 'Alice in Wonderland' + 436: 'The wizard of Oz' + 437: 'I'm singin' in the rain' + 438: 'Alice in Wonderland' + 439: 'The wizard of Oz' + 440: 'I'm singin' in the rain' + 441: 'Alice in Wonderland' + 442: 'The wizard of Oz' + 443: 'I'm singin' in the rain' + 444: 'Alice in Wonderland' + 445: 'The wizard of Oz' + 446: 'I'm singin' in the rain' + 447: 'Alice in Wonderland' + 448: 'The wizard of Oz' + 449: 'I'm singin' in the rain' + 450: 'Alice in Wonderland' + 451: 'The wizard of Oz' + 452: 'I'm singin' in the rain' + 453: 'Alice in Wonderland' + 454: 'The wizard of Oz' + 455: 'I'm singin' in the rain' + 456: 'Alice in Wonderland' + 457: 'The wizard of Oz' + 458: 'I'm singin' in the rain' + 459: 'Alice in Wonderland' + 460: 'The wizard of Oz' + 461: 'I'm singin' in the rain' + 462: 'Alice in Wonderland' + 463: 'The wizard of Oz' + 464: 'I'm singin' in the rain' + 465: 'Alice in Wonderland' + 466: 'The wizard of Oz' + 467: 'I'm singin' in the rain' + 468: 'Alice in Wonderland' + 469: 'The wizard of Oz' + 470: 'I'm singin' in the rain' + 471: 'Alice in Wonderland' + 472: 'The wizard of Oz' + 473: 'I'm singin' in the rain' + 474: 'Alice in Wonderland' + 475: 'The wizard of Oz' + 476: 'I'm singin' in the rain' + 477: 'Alice in Wonderland' + 478: 'The wizard of Oz' + 479: 'I'm singin' in the rain' + 480: 'Alice in Wonderland' + 481: 'The wizard of Oz' + 482: 'I'm singin' in the rain' + 483: 'Alice in Wonderland' + 484: 'The wizard of Oz' + 485: 'I'm singin' in the rain' + 486: 'Alice in Wonderland' + 487: 'The wizard of Oz' + 488: 'I'm singin' in the rain' + 489: 'Alice in Wonderland' + 490: 'The wizard of Oz' + 491: 'I'm singin' in the rain' + 492: 'Alice in Wonderland' + 493: 'The wizard of Oz' + 494: 'I'm singin' in the rain' + 495: 'Alice in Wonderland' + 496: 'The wizard of Oz' + 497: 'I'm singin' in the rain' + 498: 'Alice in Wonderland' + 499: 'The wizard of Oz' + 500: 'I'm singin' in the rain' + 501: 'Alice in Wonderland' + 502: 'The wizard of Oz' + 503: 'I'm singin' in the rain' + 504: 'Alice in Wonderland' + 505: 'The wizard of Oz' + 506: 'I'm singin' in the rain' + 507: 'Alice in Wonderland' + 508: 'The wizard of Oz' + 509: 'I'm singin' in the rain' + 510: 'Alice in Wonderland' + 511: 'The wizard of Oz' + 512: 'I'm singin' in the rain' + 513: 'Alice in Wonderland' + 514: 'The wizard of Oz' + 515: 'I'm singin' in the rain' + 516: 'Alice in Wonderland' + 517: 'The wizard of Oz' + 518: 'I'm singin' in the rain' + 519: 'Alice in Wonderland' + 520: 'The wizard of Oz' + 521: 'I'm singin' in the rain' + 522: 'Alice in Wonderland' + 523: 'The wizard of Oz' + 524: 'I'm singin' in the rain' + 525: 'Alice in Wonderland' + 526: 'The wizard of Oz' + 527: 'I'm singin' in the rain' + 528: 'Alice in Wonderland' + 529: 'The wizard of Oz' + 530: 'I'm singin' in the rain' + 531: 'Alice in Wonderland' + 532: 'The wizard of Oz' + 533: 'I'm singin' in the rain' + 534: 'Alice in Wonderland' + 535: 'The wizard of Oz' + 536: 'I'm singin' in the rain' + 537: 'Alice in Wonderland' + 538: 'The wizard of Oz' + 539: 'I'm singin' in the rain' + 540: 'Alice in Wonderland' + 541: 'The wizard of Oz' + 542: 'I'm singin' in the rain' + 543: 'Alice in Wonderland' + 544: 'The wizard of Oz' + 545: 'I'm singin' in the rain' + 546: 'Alice in Wonderland' + 547: 'The wizard of Oz' + 548: 'I'm singin' in the rain' + 549: 'Alice in Wonderland' + 550: 'The wizard of Oz' + 551: 'I'm singin' in the rain' + 552: 'Alice in Wonderland' + 553: 'The wizard of Oz' + 554: 'I'm singin' in the rain' + 555: 'Alice in Wonderland' + 556: 'The wizard of Oz' + 557: 'I'm singin' in the rain' + 558: 'Alice in Wonderland' + 559: 'The wizard of Oz' + 560: 'I'm singin' in the rain' + 561: 'Alice in Wonderland' + 562: 'The wizard of Oz' + 563: 'I'm singin' in the rain' + 564: 'Alice in Wonderland' + 565: 'The wizard of Oz' + 566: 'I'm singin' in the rain' + 567: 'Alice in Wonderland' + 568: 'The wizard of Oz' + 569: 'I'm singin' in the rain' + 570: 'Alice in Wonderland' + 571: 'The wizard of Oz' + 572: 'I'm singin' in the rain' + 573: 'Alice in Wonderland' + 574: 'The wizard of Oz' + 575: 'I'm singin' in the rain' + 576: 'Alice in Wonderland' + 577: 'The wizard of Oz' + 578: 'I'm singin' in the rain' + 579: 'Alice in Wonderland' + 580: 'The wizard of Oz' + 581: 'I'm singin' in the rain' + 582: 'Alice in Wonderland' + 583: 'The wizard of Oz' + 584: 'I'm singin' in the rain' + 585: 'Alice in Wonderland' + 586: 'The wizard of Oz' + 587: 'I'm singin' in the rain' + 588: 'Alice in Wonderland' + 589: 'The wizard of Oz' + 590: 'I'm singin' in the rain' + 591: 'Alice in Wonderland' + 592: 'The wizard of Oz' + 593: 'I'm singin' in the rain' + 594: 'Alice in Wonderland' + 595: 'The wizard of Oz' + 596: 'I'm singin' in the rain' + 597: 'Alice in Wonderland' + 598: 'The wizard of Oz' + 599: 'I'm singin' in the rain' + 600: 'Alice in Wonderland' + 601: 'The wizard of Oz' + 602: 'I'm singin' in the rain' + 603: 'Alice in Wonderland' + 604: 'The wizard of Oz' + 605: 'I'm singin' in the rain' + 606: 'Alice in Wonderland' + 607: 'The wizard of Oz' + 608: 'I'm singin' in the rain' + 609: 'Alice in Wonderland' + 610: 'The wizard of Oz' + 611: 'I'm singin' in the rain' + 612: 'Alice in Wonderland' + 613: 'The wizard of Oz' + 614: 'I'm singin' in the rain' + 615: 'Alice in Wonderland' + 616: 'The wizard of Oz' + 617: 'I'm singin' in the rain' + 618: 'Alice in Wonderland' + 619: 'The wizard of Oz' + 620: 'I'm singin' in the rain' + 621: 'Alice in Wonderland' + 622: 'The wizard of Oz' + 623: 'I'm singin' in the rain' + 624: 'Alice in Wonderland' + 625: 'The wizard of Oz' + 626: 'I'm singin' in the rain' + 627: 'Alice in Wonderland' + 628: 'The wizard of Oz' + 629: 'I'm singin' in the rain' + 630: 'Alice in Wonderland' + 631: 'The wizard of Oz' + 632: 'I'm singin' in the rain' + 633: 'Alice in Wonderland' + 634: 'The wizard of Oz' + 635: 'I'm singin' in the rain' + 636: 'Alice in Wonderland' + 637: 'The wizard of Oz' + 638: 'I'm singin' in the rain' + 639: 'Alice in Wonderland' + 640: 'The wizard of Oz' + 641: 'I'm singin' in the rain' + 642: 'Alice in Wonderland' + 643: 'The wizard of Oz' + 644: 'I'm singin' in the rain' + 645: 'Alice in Wonderland' + 646: 'The wizard of Oz' + 647: 'I'm singin' in the rain' + 648: 'Alice in Wonderland' + 649: 'The wizard of Oz' + 650: 'I'm singin' in the rain' + 651: 'Alice in Wonderland' + 652: 'The wizard of Oz' + 653: 'I'm singin' in the rain' + 654: 'Alice in Wonderland' + 655: 'The wizard of Oz' + 656: 'I'm singin' in the rain' + 657: 'Alice in Wonderland' + 658: 'The wizard of Oz' + 659: 'I'm singin' in the rain' + 660: 'Alice in Wonderland' + 661: 'The wizard of Oz' + 662: 'I'm singin' in the rain' + 663: 'Alice in Wonderland' + 664: 'The wizard of Oz' + 665: 'I'm singin' in the rain' + 666: 'Alice in Wonderland' + 667: 'The wizard of Oz' + 668: 'I'm singin' in the rain' + 669: 'Alice in Wonderland' + 670: 'The wizard of Oz' + 671: 'I'm singin' in the rain' + 672: 'Alice in Wonderland' + 673: 'The wizard of Oz' + 674: 'I'm singin' in the rain' + 675: 'Alice in Wonderland' + 676: 'The wizard of Oz' + 677: 'I'm singin' in the rain' + 678: 'Alice in Wonderland' + 679: 'The wizard of Oz' + 680: 'I'm singin' in the rain' + 681: 'Alice in Wonderland' + 682: 'The wizard of Oz' + 683: 'I'm singin' in the rain' + 684: 'Alice in Wonderland' + 685: 'The wizard of Oz' + 686: 'I'm singin' in the rain' + 687: 'Alice in Wonderland' + 688: 'The wizard of Oz' + 689: 'I'm singin' in the rain' + 690: 'Alice in Wonderland' + 691: 'The wizard of Oz' + 692: 'I'm singin' in the rain' + 693: 'Alice in Wonderland' + 694: 'The wizard of Oz' + 695: 'I'm singin' in the rain' + 696: 'Alice in Wonderland' + 697: 'The wizard of Oz' + 698: 'I'm singin' in the rain' + 699: 'Alice in Wonderland' + 700: 'The wizard of Oz' + 701: 'I'm singin' in the rain' + 702: 'Alice in Wonderland' + 703: 'The wizard of Oz' + 704: 'I'm singin' in the rain' + 705: 'Alice in Wonderland' + 706: 'The wizard of Oz' + 707: 'I'm singin' in the rain' + 708: 'Alice in Wonderland' + 709: 'The wizard of Oz' + 710: 'I'm singin' in the rain' + 711: 'Alice in Wonderland' + 712: 'The wizard of Oz' + 713: 'I'm singin' in the rain' + 714: 'Alice in Wonderland' + 715: 'The wizard of Oz' + 716: 'I'm singin' in the rain' + 717: 'Alice in Wonderland' + 718: 'The wizard of Oz' + 719: 'I'm singin' in the rain' + 720: 'Alice in Wonderland' + 721: 'The wizard of Oz' + 722: 'I'm singin' in the rain' + 723: 'Alice in Wonderland' + 724: 'The wizard of Oz' + 725: 'I'm singin' in the rain' + 726: 'Alice in Wonderland' + 727: 'The wizard of Oz' + 728: 'I'm singin' in the rain' + 729: 'Alice in Wonderland' + 730: 'The wizard of Oz' + 731: 'I'm singin' in the rain' + 732: 'Alice in Wonderland' + 733: 'The wizard of Oz' + 734: 'I'm singin' in the rain' + 735: 'Alice in Wonderland' + 736: 'The wizard of Oz' + 737: 'I'm singin' in the rain' + 738: 'Alice in Wonderland' + 739: 'The wizard of Oz' + 740: 'I'm singin' in the rain' + 741: 'Alice in Wonderland' + 742: 'The wizard of Oz' + 743: 'I'm singin' in the rain' + 744: 'Alice in Wonderland' + 745: 'The wizard of Oz' + 746: 'I'm singin' in the rain' + 747: 'Alice in Wonderland' + 748: 'The wizard of Oz' + 749: 'I'm singin' in the rain' + 750: 'Alice in Wonderland' + 751: 'The wizard of Oz' + 752: 'I'm singin' in the rain' + 753: 'Alice in Wonderland' + 754: 'The wizard of Oz' + 755: 'I'm singin' in the rain' + 756: 'Alice in Wonderland' + 757: 'The wizard of Oz' + 758: 'I'm singin' in the rain' + 759: 'Alice in Wonderland' + 760: 'The wizard of Oz' + 761: 'I'm singin' in the rain' + 762: 'Alice in Wonderland' + 763: 'The wizard of Oz' + 764: 'I'm singin' in the rain' + 765: 'Alice in Wonderland' + 766: 'The wizard of Oz' + 767: 'I'm singin' in the rain' + 768: 'Alice in Wonderland' + 769: 'The wizard of Oz' + 770: 'I'm singin' in the rain' + 771: 'Alice in Wonderland' + 772: 'The wizard of Oz' + 773: 'I'm singin' in the rain' + 774: 'Alice in Wonderland' + 775: 'The wizard of Oz' + 776: 'I'm singin' in the rain' + 777: 'Alice in Wonderland' + 778: 'The wizard of Oz' + 779: 'I'm singin' in the rain' + 780: 'Alice in Wonderland' + 781: 'The wizard of Oz' + 782: 'I'm singin' in the rain' + 783: 'Alice in Wonderland' + 784: 'The wizard of Oz' + 785: 'I'm singin' in the rain' + 786: 'Alice in Wonderland' + 787: 'The wizard of Oz' + 788: 'I'm singin' in the rain' + 789: 'Alice in Wonderland' + 790: 'The wizard of Oz' + 791: 'I'm singin' in the rain' + 792: 'Alice in Wonderland' + 793: 'The wizard of Oz' + 794: 'I'm singin' in the rain' + 795: 'Alice in Wonderland' + 796: 'The wizard of Oz' + 797: 'I'm singin' in the rain' + 798: 'Alice in Wonderland' + 799: 'The wizard of Oz' + 800: 'I'm singin' in the rain' + 801: 'Alice in Wonderland' + 802: 'The wizard of Oz' + 803: 'I'm singin' in the rain' + 804: 'Alice in Wonderland' + 805: 'The wizard of Oz' + 806: 'I'm singin' in the rain' + 807: 'Alice in Wonderland' + 808: 'The wizard of Oz' + 809: 'I'm singin' in the rain' + 810: 'Alice in Wonderland' + 811: 'The wizard of Oz' + 812: 'I'm singin' in the rain' + 813: 'Alice in Wonderland' + 814: 'The wizard of Oz' + 815: 'I'm singin' in the rain' + 816: 'Alice in Wonderland' + 817: 'The wizard of Oz' + 818: 'I'm singin' in the rain' + 819: 'Alice in Wonderland' + 820: 'The wizard of Oz' + 821: 'I'm singin' in the rain' + 822: 'Alice in Wonderland' + 823: 'The wizard of Oz' + 824: 'I'm singin' in the rain' + 825: 'Alice in Wonderland' + 826: 'The wizard of Oz' + 827: 'I'm singin' in the rain' + 828: 'Alice in Wonderland' + 829: 'The wizard of Oz' + 830: 'I'm singin' in the rain' + 831: 'Alice in Wonderland' + 832: 'The wizard of Oz' + 833: 'I'm singin' in the rain' + 834: 'Alice in Wonderland' + 835: 'The wizard of Oz' + 836: 'I'm singin' in the rain' + 837: 'Alice in Wonderland' + 838: 'The wizard of Oz' + 839: 'I'm singin' in the rain' + 840: 'Alice in Wonderland' + 841: 'The wizard of Oz' + 842: 'I'm singin' in the rain' + 843: 'Alice in Wonderland' + 844: 'The wizard of Oz' + 845: 'I'm singin' in the rain' + 846: 'Alice in Wonderland' + 847: 'The wizard of Oz' + 848: 'I'm singin' in the rain' + 849: 'Alice in Wonderland' + 850: 'The wizard of Oz' + 851: 'I'm singin' in the rain' + 852: 'Alice in Wonderland' + 853: 'The wizard of Oz' + 854: 'I'm singin' in the rain' + 855: 'Alice in Wonderland' + 856: 'The wizard of Oz' + 857: 'I'm singin' in the rain' + 858: 'Alice in Wonderland' + 859: 'The wizard of Oz' + 860: 'I'm singin' in the rain' + 861: 'Alice in Wonderland' + 862: 'The wizard of Oz' + 863: 'I'm singin' in the rain' + 864: 'Alice in Wonderland' + 865: 'The wizard of Oz' + 866: 'I'm singin' in the rain' + 867: 'Alice in Wonderland' + 868: 'The wizard of Oz' + 869: 'I'm singin' in the rain' + 870: 'Alice in Wonderland' + 871: 'The wizard of Oz' + 872: 'I'm singin' in the rain' + 873: 'Alice in Wonderland' + 874: 'The wizard of Oz' + 875: 'I'm singin' in the rain' + 876: 'Alice in Wonderland' + 877: 'The wizard of Oz' + 878: 'I'm singin' in the rain' + 879: 'Alice in Wonderland' + 880: 'The wizard of Oz' + 881: 'I'm singin' in the rain' + 882: 'Alice in Wonderland' + 883: 'The wizard of Oz' + 884: 'I'm singin' in the rain' + 885: 'Alice in Wonderland' + 886: 'The wizard of Oz' + 887: 'I'm singin' in the rain' + 888: 'Alice in Wonderland' + 889: 'The wizard of Oz' + 890: 'I'm singin' in the rain' + 891: 'Alice in Wonderland' + 892: 'The wizard of Oz' + 893: 'I'm singin' in the rain' + 894: 'Alice in Wonderland' + 895: 'The wizard of Oz' + 896: 'I'm singin' in the rain' + 897: 'Alice in Wonderland' + 898: 'The wizard of Oz' + 899: 'I'm singin' in the rain' + 900: 'Alice in Wonderland' + 901: 'The wizard of Oz' + 902: 'I'm singin' in the rain' + 903: 'Alice in Wonderland' + 904: 'The wizard of Oz' + 905: 'I'm singin' in the rain' + 906: 'Alice in Wonderland' + 907: 'The wizard of Oz' + 908: 'I'm singin' in the rain' + 909: 'Alice in Wonderland' + 910: 'The wizard of Oz' + 911: 'I'm singin' in the rain' + 912: 'Alice in Wonderland' + 913: 'The wizard of Oz' + 914: 'I'm singin' in the rain' + 915: 'Alice in Wonderland' + 916: 'The wizard of Oz' + 917: 'I'm singin' in the rain' + 918: 'Alice in Wonderland' + 919: 'The wizard of Oz' + 920: 'I'm singin' in the rain' + 921: 'Alice in Wonderland' + 922: 'The wizard of Oz' + 923: 'I'm singin' in the rain' + 924: 'Alice in Wonderland' + 925: 'The wizard of Oz' + 926: 'I'm singin' in the rain' + 927: 'Alice in Wonderland' + 928: 'The wizard of Oz' + 929: 'I'm singin' in the rain' + 930: 'Alice in Wonderland' + 931: 'The wizard of Oz' + 932: 'I'm singin' in the rain' + 933: 'Alice in Wonderland' + 934: 'The wizard of Oz' + 935: 'I'm singin' in the rain' + 936: 'Alice in Wonderland' + 937: 'The wizard of Oz' + 938: 'I'm singin' in the rain' + 939: 'Alice in Wonderland' + 940: 'The wizard of Oz' + 941: 'I'm singin' in the rain' + 942: 'Alice in Wonderland' + 943: 'The wizard of Oz' + 944: 'I'm singin' in the rain' + 945: 'Alice in Wonderland' + 946: 'The wizard of Oz' + 947: 'I'm singin' in the rain' + 948: 'Alice in Wonderland' + 949: 'The wizard of Oz' + 950: 'I'm singin' in the rain' + 951: 'Alice in Wonderland' + 952: 'The wizard of Oz' + 953: 'I'm singin' in the rain' + 954: 'Alice in Wonderland' + 955: 'The wizard of Oz' + 956: 'I'm singin' in the rain' + 957: 'Alice in Wonderland' + 958: 'The wizard of Oz' + 959: 'I'm singin' in the rain' + 960: 'Alice in Wonderland' + 961: 'The wizard of Oz' + 962: 'I'm singin' in the rain' + 963: 'Alice in Wonderland' + 964: 'The wizard of Oz' + 965: 'I'm singin' in the rain' + 966: 'Alice in Wonderland' + 967: 'The wizard of Oz' + 968: 'I'm singin' in the rain' + 969: 'Alice in Wonderland' + 970: 'The wizard of Oz' + 971: 'I'm singin' in the rain' + 972: 'Alice in Wonderland' + 973: 'The wizard of Oz' + 974: 'I'm singin' in the rain' + 975: 'Alice in Wonderland' + 976: 'The wizard of Oz' + 977: 'I'm singin' in the rain' + 978: 'Alice in Wonderland' + 979: 'The wizard of Oz' + 980: 'I'm singin' in the rain' + 981: 'Alice in Wonderland' + 982: 'The wizard of Oz' + 983: 'I'm singin' in the rain' + 984: 'Alice in Wonderland' + 985: 'The wizard of Oz' + 986: 'I'm singin' in the rain' + 987: 'Alice in Wonderland' + 988: 'The wizard of Oz' + 989: 'I'm singin' in the rain' + 990: 'Alice in Wonderland' + 991: 'The wizard of Oz' + 992: 'I'm singin' in the rain' + 993: 'Alice in Wonderland' + 994: 'The wizard of Oz' + 995: 'I'm singin' in the rain' + 996: 'Alice in Wonderland' + 997: 'The wizard of Oz' + 998: 'I'm singin' in the rain' + 999: 'Alice in Wonderland' + 1000: 'The wizard of Oz' + 1001: 'I'm singin' in the rain' + 1002: 'Alice in Wonderland' + 1003: 'The wizard of Oz' + 1004: 'I'm singin' in the rain' + 1005: 'Alice in Wonderland' + 1006: 'The wizard of Oz' + 1007: 'I'm singin' in the rain' + 1008: 'Alice in Wonderland' + 1009: 'The wizard of Oz' + 1010: 'I'm singin' in the rain' + 1011: 'Alice in Wonderland' + 1012: 'The wizard of Oz' + 1013: 'I'm singin' in the rain' + 1014: 'Alice in Wonderland' + 1015: 'The wizard of Oz' + 1016: 'I'm singin' in the rain' + 1017: 'Alice in Wonderland' + 1018: 'The wizard of Oz' + 1019: 'I'm singin' in the rain' + 1020: 'Alice in Wonderland' + 1021: 'The wizard of Oz' + 1022: 'I'm singin' in the rain' + 1023: 'Alice in Wonderland' + 1024: 'The wizard of Oz' + 1025: 'I'm singin' in the rain' + 1026: 'Alice in Wonderland' + 1027: 'The wizard of Oz' + 1028: 'I'm singin' in the rain' + 1029: 'Alice in Wonderland' + 1030: 'The wizard of Oz' + 1031: 'I'm singin' in the rain' + 1032: 'Alice in Wonderland' + 1033: 'The wizard of Oz' + 1034: 'I'm singin' in the rain' + 1035: 'Alice in Wonderland' + 1036: 'The wizard of Oz' + 1037: 'I'm singin' in the rain' + 1038: 'Alice in Wonderland' + 1039: 'The wizard of Oz' + 1040: 'I'm singin' in the rain' + 1041: 'Alice in Wonderland' + 1042: 'The wizard of Oz' + 1043: 'I'm singin' in the rain' + 1044: 'Alice in Wonderland' + 1045: 'The wizard of Oz' + 1046: 'I'm singin' in the rain' + 1047: 'Alice in Wonderland' + 1048: 'The wizard of Oz' + 1049: 'I'm singin' in the rain' + 1050: 'Alice in Wonderland' + 1051: 'The wizard of Oz' + 1052: 'I'm singin' in the rain' + 1053: 'Alice in Wonderland' + 1054: 'The wizard of Oz' + 1055: 'I'm singin' in the rain' + 1056: 'Alice in Wonderland' + 1057: 'The wizard of Oz' + 1058: 'I'm singin' in the rain' + 1059: 'Alice in Wonderland' + 1060: 'The wizard of Oz' + 1061: 'I'm singin' in the rain' + 1062: 'Alice in Wonderland' + 1063: 'The wizard of Oz' + 1064: 'I'm singin' in the rain' + 1065: 'Alice in Wonderland' + 1066: 'The wizard of Oz' + 1067: 'I'm singin' in the rain' + 1068: 'Alice in Wonderland' + 1069: 'The wizard of Oz' + 1070: 'I'm singin' in the rain' + 1071: 'Alice in Wonderland' + 1072: 'The wizard of Oz' + 1073: 'I'm singin' in the rain' + 1074: 'Alice in Wonderland' + 1075: 'The wizard of Oz' + 1076: 'I'm singin' in the rain' + 1077: 'Alice in Wonderland' + 1078: 'The wizard of Oz' + 1079: 'I'm singin' in the rain' + 1080: 'Alice in Wonderland' + 1081: 'The wizard of Oz' + 1082: 'I'm singin' in the rain' + 1083: 'Alice in Wonderland' + 1084: 'The wizard of Oz' + 1085: 'I'm singin' in the rain' + 1086: 'Alice in Wonderland' + 1087: 'The wizard of Oz' + 1088: 'I'm singin' in the rain' + 1089: 'Alice in Wonderland' + 1090: 'The wizard of Oz' + 1091: 'I'm singin' in the rain' + 1092: 'Alice in Wonderland' + 1093: 'The wizard of Oz' + 1094: 'I'm singin' in the rain' + 1095: 'Alice in Wonderland' + 1096: 'The wizard of Oz' + 1097: 'I'm singin' in the rain' + 1098: 'Alice in Wonderland' + 1099: 'The wizard of Oz' + 1100: 'I'm singin' in the rain' + 1101: 'Alice in Wonderland' + 1102: 'The wizard of Oz' + 1103: 'I'm singin' in the rain' + 1104: 'Alice in Wonderland' + 1105: 'The wizard of Oz' + 1106: 'I'm singin' in the rain' + 1107: 'Alice in Wonderland' + 1108: 'The wizard of Oz' + 1109: 'I'm singin' in the rain' + 1110: 'Alice in Wonderland' + 1111: 'The wizard of Oz' + 1112: 'I'm singin' in the rain' + 1113: 'Alice in Wonderland' + 1114: 'The wizard of Oz' + 1115: 'I'm singin' in the rain' + 1116: 'Alice in Wonderland' + 1117: 'The wizard of Oz' + 1118: 'I'm singin' in the rain' + 1119: 'Alice in Wonderland' + 1120: 'The wizard of Oz' + 1121: 'I'm singin' in the rain' + 1122: 'Alice in Wonderland' + 1123: 'The wizard of Oz' + 1124: 'I'm singin' in the rain' + 1125: 'Alice in Wonderland' + 1126: 'The wizard of Oz' + 1127: 'I'm singin' in the rain' + 1128: 'Alice in Wonderland' + 1129: 'The wizard of Oz' + 1130: 'I'm singin' in the rain' + 1131: 'Alice in Wonderland' + 1132: 'The wizard of Oz' + 1133: 'I'm singin' in the rain' + 1134: 'Alice in Wonderland' + 1135: 'The wizard of Oz' + 1136: 'I'm singin' in the rain' + 1137: 'Alice in Wonderland' + 1138: 'The wizard of Oz' + 1139: 'I'm singin' in the rain' + 1140: 'Alice in Wonderland' + 1141: 'The wizard of Oz' + 1142: 'I'm singin' in the rain' + 1143: 'Alice in Wonderland' + 1144: 'The wizard of Oz' + 1145: 'I'm singin' in the rain' + 1146: 'Alice in Wonderland' + 1147: 'The wizard of Oz' + 1148: 'I'm singin' in the rain' + 1149: 'Alice in Wonderland' + 1150: 'The wizard of Oz' + 1151: 'I'm singin' in the rain' + 1152: 'Alice in Wonderland' + 1153: 'The wizard of Oz' + 1154: 'I'm singin' in the rain' + 1155: 'Alice in Wonderland' + 1156: 'The wizard of Oz' + 1157: 'I'm singin' in the rain' + 1158: 'Alice in Wonderland' + 1159: 'The wizard of Oz' + 1160: 'I'm singin' in the rain' + 1161: 'Alice in Wonderland' + 1162: 'The wizard of Oz' + 1163: 'I'm singin' in the rain' + 1164: 'Alice in Wonderland' + 1165: 'The wizard of Oz' + 1166: 'I'm singin' in the rain' + 1167: 'Alice in Wonderland' + 1168: 'The wizard of Oz' + 1169: 'I'm singin' in the rain' + 1170: 'Alice in Wonderland' + 1171: 'The wizard of Oz' + 1172: 'I'm singin' in the rain' + 1173: 'Alice in Wonderland' + 1174: 'The wizard of Oz' + 1175: 'I'm singin' in the rain' + 1176: 'Alice in Wonderland' + 1177: 'The wizard of Oz' + 1178: 'I'm singin' in the rain' + 1179: 'Alice in Wonderland' + 1180: 'The wizard of Oz' + 1181: 'I'm singin' in the rain' + 1182: 'Alice in Wonderland' + 1183: 'The wizard of Oz' + 1184: 'I'm singin' in the rain' + 1185: 'Alice in Wonderland' + 1186: 'The wizard of Oz' + 1187: 'I'm singin' in the rain' + 1188: 'Alice in Wonderland' + 1189: 'The wizard of Oz' + 1190: 'I'm singin' in the rain' + 1191: 'Alice in Wonderland' + 1192: 'The wizard of Oz' + 1193: 'I'm singin' in the rain' + 1194: 'Alice in Wonderland' + 1195: 'The wizard of Oz' + 1196: 'I'm singin' in the rain' + 1197: 'Alice in Wonderland' + 1198: 'The wizard of Oz' + 1199: 'I'm singin' in the rain' + 1200: 'Alice in Wonderland' + 1201: 'The wizard of Oz' + 1202: 'I'm singin' in the rain' + 1203: 'Alice in Wonderland' + 1204: 'The wizard of Oz' + 1205: 'I'm singin' in the rain' + 1206: 'Alice in Wonderland' + 1207: 'The wizard of Oz' + 1208: 'I'm singin' in the rain' + 1209: 'Alice in Wonderland' + 1210: 'The wizard of Oz' + 1211: 'I'm singin' in the rain' + 1212: 'Alice in Wonderland' + 1213: 'The wizard of Oz' + 1214: 'I'm singin' in the rain' + 1215: 'Alice in Wonderland' + 1216: 'The wizard of Oz' + 1217: 'I'm singin' in the rain' + 1218: 'Alice in Wonderland' + 1219: 'The wizard of Oz' + 1220: 'I'm singin' in the rain' + 1221: 'Alice in Wonderland' + 1222: 'The wizard of Oz' + 1223: 'I'm singin' in the rain' + 1224: 'Alice in Wonderland' + 1225: 'The wizard of Oz' + 1226: 'I'm singin' in the rain' + 1227: 'Alice in Wonderland' + 1228: 'The wizard of Oz' + 1229: 'I'm singin' in the rain' + 1230: 'Alice in Wonderland' + 1231: 'The wizard of Oz' + 1232: 'I'm singin' in the rain' + 1233: 'Alice in Wonderland' + 1234: 'The wizard of Oz' + 1235: 'I'm singin' in the rain' + 1236: 'Alice in Wonderland' + 1237: 'The wizard of Oz' + 1238: 'I'm singin' in the rain' + 1239: 'Alice in Wonderland' + 1240: 'The wizard of Oz' + 1241: 'I'm singin' in the rain' + 1242: 'Alice in Wonderland' + 1243: 'The wizard of Oz' + 1244: 'I'm singin' in the rain' + 1245: 'Alice in Wonderland' + 1246: 'The wizard of Oz' + 1247: 'I'm singin' in the rain' + 1248: 'Alice in Wonderland' + 1249: 'The wizard of Oz' + 1250: 'I'm singin' in the rain' + 1251: 'Alice in Wonderland' + 1252: 'The wizard of Oz' + 1253: 'I'm singin' in the rain' + 1254: 'Alice in Wonderland' + 1255: 'The wizard of Oz' + 1256: 'I'm singin' in the rain' + 1257: 'Alice in Wonderland' + 1258: 'The wizard of Oz' + 1259: 'I'm singin' in the rain' + 1260: 'Alice in Wonderland' + 1261: 'The wizard of Oz' + 1262: 'I'm singin' in the rain' + 1263: 'Alice in Wonderland' + 1264: 'The wizard of Oz' + 1265: 'I'm singin' in the rain' + 1266: 'Alice in Wonderland' + 1267: 'The wizard of Oz' + 1268: 'I'm singin' in the rain' + 1269: 'Alice in Wonderland' + 1270: 'The wizard of Oz' + 1271: 'I'm singin' in the rain' + 1272: 'Alice in Wonderland' + 1273: 'The wizard of Oz' + 1274: 'I'm singin' in the rain' + 1275: 'Alice in Wonderland' + 1276: 'The wizard of Oz' + 1277: 'I'm singin' in the rain' + 1278: 'Alice in Wonderland' + 1279: 'The wizard of Oz' + 1280: 'I'm singin' in the rain' + 1281: 'Alice in Wonderland' + 1282: 'The wizard of Oz' + 1283: 'I'm singin' in the rain' + 1284: 'Alice in Wonderland' + 1285: 'The wizard of Oz' + 1286: 'I'm singin' in the rain' + 1287: 'Alice in Wonderland' + 1288: 'The wizard of Oz' + 1289: 'I'm singin' in the rain' + 1290: 'Alice in Wonderland' + 1291: 'The wizard of Oz' + 1292: 'I'm singin' in the rain' + 1293: 'Alice in Wonderland' + 1294: 'The wizard of Oz' + 1295: 'I'm singin' in the rain' + 1296: 'Alice in Wonderland' + 1297: 'The wizard of Oz' + 1298: 'I'm singin' in the rain' + 1299: 'Alice in Wonderland' + 1300: 'The wizard of Oz' + 1301: 'I'm singin' in the rain' + 1302: 'Alice in Wonderland' + 1303: 'The wizard of Oz' + 1304: 'I'm singin' in the rain' + 1305: 'Alice in Wonderland' + 1306: 'The wizard of Oz' + 1307: 'I'm singin' in the rain' + 1308: 'Alice in Wonderland' + 1309: 'The wizard of Oz' + 1310: 'I'm singin' in the rain' + 1311: 'Alice in Wonderland' + 1312: 'The wizard of Oz' + 1313: 'I'm singin' in the rain' + 1314: 'Alice in Wonderland' + 1315: 'The wizard of Oz' + 1316: 'I'm singin' in the rain' + 1317: 'Alice in Wonderland' + 1318: 'The wizard of Oz' + 1319: 'I'm singin' in the rain' + 1320: 'Alice in Wonderland' + 1321: 'The wizard of Oz' + 1322: 'I'm singin' in the rain' + 1323: 'Alice in Wonderland' + 1324: 'The wizard of Oz' + 1325: 'I'm singin' in the rain' + 1326: 'Alice in Wonderland' + 1327: 'The wizard of Oz' + 1328: 'I'm singin' in the rain' + 1329: 'Alice in Wonderland' + 1330: 'The wizard of Oz' + 1331: 'I'm singin' in the rain' + 1332: 'Alice in Wonderland' + 1333: 'The wizard of Oz' + 1334: 'I'm singin' in the rain' + 1335: 'Alice in Wonderland' + 1336: 'The wizard of Oz' + 1337: 'I'm singin' in the rain' + 1338: 'Alice in Wonderland' + 1339: 'The wizard of Oz' + 1340: 'I'm singin' in the rain' + 1341: 'Alice in Wonderland' + 1342: 'The wizard of Oz' + 1343: 'I'm singin' in the rain' + 1344: 'Alice in Wonderland' + 1345: 'The wizard of Oz' + 1346: 'I'm singin' in the rain' + 1347: 'Alice in Wonderland' + 1348: 'The wizard of Oz' + 1349: 'I'm singin' in the rain' + 1350: 'Alice in Wonderland' + 1351: 'The wizard of Oz' + 1352: 'I'm singin' in the rain' + 1353: 'Alice in Wonderland' + 1354: 'The wizard of Oz' + 1355: 'I'm singin' in the rain' + 1356: 'Alice in Wonderland' + 1357: 'The wizard of Oz' + 1358: 'I'm singin' in the rain' + 1359: 'Alice in Wonderland' + 1360: 'The wizard of Oz' + 1361: 'I'm singin' in the rain' + 1362: 'Alice in Wonderland' + 1363: 'The wizard of Oz' + 1364: 'I'm singin' in the rain' + 1365: 'Alice in Wonderland' + 1366: 'The wizard of Oz' + 1367: 'I'm singin' in the rain' + 1368: 'Alice in Wonderland' + 1369: 'The wizard of Oz' + 1370: 'I'm singin' in the rain' + 1371: 'Alice in Wonderland' + 1372: 'The wizard of Oz' + 1373: 'I'm singin' in the rain' + 1374: 'Alice in Wonderland' + 1375: 'The wizard of Oz' + 1376: 'I'm singin' in the rain' + 1377: 'Alice in Wonderland' + 1378: 'The wizard of Oz' + 1379: 'I'm singin' in the rain' + 1380: 'Alice in Wonderland' + 1381: 'The wizard of Oz' + 1382: 'I'm singin' in the rain' + 1383: 'Alice in Wonderland' + 1384: 'The wizard of Oz' + 1385: 'I'm singin' in the rain' + 1386: 'Alice in Wonderland' + 1387: 'The wizard of Oz' + 1388: 'I'm singin' in the rain' + 1389: 'Alice in Wonderland' + 1390: 'The wizard of Oz' + 1391: 'I'm singin' in the rain' + 1392: 'Alice in Wonderland' + 1393: 'The wizard of Oz' + 1394: 'I'm singin' in the rain' + 1395: 'Alice in Wonderland' + 1396: 'The wizard of Oz' + 1397: 'I'm singin' in the rain' + 1398: 'Alice in Wonderland' + 1399: 'The wizard of Oz' + 1400: 'I'm singin' in the rain' + 1401: 'Alice in Wonderland' + 1402: 'The wizard of Oz' + 1403: 'I'm singin' in the rain' + 1404: 'Alice in Wonderland' + 1405: 'The wizard of Oz' + 1406: 'I'm singin' in the rain' + 1407: 'Alice in Wonderland' + 1408: 'The wizard of Oz' + 1409: 'I'm singin' in the rain' + 1410: 'Alice in Wonderland' + 1411: 'The wizard of Oz' + 1412: 'I'm singin' in the rain' + 1413: 'Alice in Wonderland' + 1414: 'The wizard of Oz' + 1415: 'I'm singin' in the rain' + 1416: 'Alice in Wonderland' + 1417: 'The wizard of Oz' + 1418: 'I'm singin' in the rain' + 1419: 'Alice in Wonderland' + 1420: 'The wizard of Oz' + 1421: 'I'm singin' in the rain' + 1422: 'Alice in Wonderland' + 1423: 'The wizard of Oz' + 1424: 'I'm singin' in the rain' + 1425: 'Alice in Wonderland' + 1426: 'The wizard of Oz' + 1427: 'I'm singin' in the rain' + 1428: 'Alice in Wonderland' + 1429: 'The wizard of Oz' + 1430: 'I'm singin' in the rain' + 1431: 'Alice in Wonderland' + 1432: 'The wizard of Oz' + 1433: 'I'm singin' in the rain' + 1434: 'Alice in Wonderland' + 1435: 'The wizard of Oz' + 1436: 'I'm singin' in the rain' + 1437: 'Alice in Wonderland' + 1438: 'The wizard of Oz' + 1439: 'I'm singin' in the rain' + 1440: 'Alice in Wonderland' + 1441: 'The wizard of Oz' + 1442: 'I'm singin' in the rain' + 1443: 'Alice in Wonderland' + 1444: 'The wizard of Oz' + 1445: 'I'm singin' in the rain' + 1446: 'Alice in Wonderland' + 1447: 'The wizard of Oz' + 1448: 'I'm singin' in the rain' + 1449: 'Alice in Wonderland' + 1450: 'The wizard of Oz' + 1451: 'I'm singin' in the rain' + 1452: 'Alice in Wonderland' + 1453: 'The wizard of Oz' + 1454: 'I'm singin' in the rain' + 1455: 'Alice in Wonderland' + 1456: 'The wizard of Oz' + 1457: 'I'm singin' in the rain' + 1458: 'Alice in Wonderland' + 1459: 'The wizard of Oz' + 1460: 'I'm singin' in the rain' + 1461: 'Alice in Wonderland' + 1462: 'The wizard of Oz' + 1463: 'I'm singin' in the rain' + 1464: 'Alice in Wonderland' + 1465: 'The wizard of Oz' + 1466: 'I'm singin' in the rain' + 1467: 'Alice in Wonderland' + 1468: 'The wizard of Oz' + 1469: 'I'm singin' in the rain' + 1470: 'Alice in Wonderland' + 1471: 'The wizard of Oz' + 1472: 'I'm singin' in the rain' + 1473: 'Alice in Wonderland' + 1474: 'The wizard of Oz' + 1475: 'I'm singin' in the rain' + 1476: 'Alice in Wonderland' + 1477: 'The wizard of Oz' + 1478: 'I'm singin' in the rain' + 1479: 'Alice in Wonderland' + 1480: 'The wizard of Oz' + 1481: 'I'm singin' in the rain' + 1482: 'Alice in Wonderland' + 1483: 'The wizard of Oz' + 1484: 'I'm singin' in the rain' + 1485: 'Alice in Wonderland' + 1486: 'The wizard of Oz' + 1487: 'I'm singin' in the rain' + 1488: 'Alice in Wonderland' + 1489: 'The wizard of Oz' + 1490: 'I'm singin' in the rain' + 1491: 'Alice in Wonderland' + 1492: 'The wizard of Oz' + 1493: 'I'm singin' in the rain' + 1494: 'Alice in Wonderland' + 1495: 'The wizard of Oz' + 1496: 'I'm singin' in the rain' + 1497: 'Alice in Wonderland' + 1498: 'The wizard of Oz' + 1499: 'I'm singin' in the rain' + 1500: 'Alice in Wonderland' + 1501: 'The wizard of Oz' + 1502: 'I'm singin' in the rain' + 1503: 'Alice in Wonderland' + 1504: 'The wizard of Oz' + 1505: 'I'm singin' in the rain' + 1506: 'Alice in Wonderland' + 1507: 'The wizard of Oz' + 1508: 'I'm singin' in the rain' + 1509: 'Alice in Wonderland' + 1510: 'The wizard of Oz' + 1511: 'I'm singin' in the rain' + 1512: 'Alice in Wonderland' + 1513: 'The wizard of Oz' + 1514: 'I'm singin' in the rain' + 1515: 'Alice in Wonderland' + 1516: 'The wizard of Oz' + 1517: 'I'm singin' in the rain' + 1518: 'Alice in Wonderland' + 1519: 'The wizard of Oz' + 1520: 'I'm singin' in the rain' + 1521: 'Alice in Wonderland' + 1522: 'The wizard of Oz' + 1523: 'I'm singin' in the rain' + 1524: 'Alice in Wonderland' + 1525: 'The wizard of Oz' + 1526: 'I'm singin' in the rain' + 1527: 'Alice in Wonderland' + 1528: 'The wizard of Oz' + 1529: 'I'm singin' in the rain' + 1530: 'Alice in Wonderland' + 1531: 'The wizard of Oz' + 1532: 'I'm singin' in the rain' + 1533: 'Alice in Wonderland' + 1534: 'The wizard of Oz' + 1535: 'I'm singin' in the rain' + 1536: 'Alice in Wonderland' + 1537: 'The wizard of Oz' + 1538: 'I'm singin' in the rain' + 1539: 'Alice in Wonderland' + 1540: 'The wizard of Oz' + 1541: 'I'm singin' in the rain' + 1542: 'Alice in Wonderland' + 1543: 'The wizard of Oz' + 1544: 'I'm singin' in the rain' + 1545: 'Alice in Wonderland' + 1546: 'The wizard of Oz' + 1547: 'I'm singin' in the rain' + 1548: 'Alice in Wonderland' + 1549: 'The wizard of Oz' + 1550: 'I'm singin' in the rain' + 1551: 'Alice in Wonderland' + 1552: 'The wizard of Oz' + 1553: 'I'm singin' in the rain' + 1554: 'Alice in Wonderland' + 1555: 'The wizard of Oz' + 1556: 'I'm singin' in the rain' + 1557: 'Alice in Wonderland' + 1558: 'The wizard of Oz' + 1559: 'I'm singin' in the rain' + 1560: 'Alice in Wonderland' + 1561: 'The wizard of Oz' + 1562: 'I'm singin' in the rain' + 1563: 'Alice in Wonderland' + 1564: 'The wizard of Oz' + 1565: 'I'm singin' in the rain' + 1566: 'Alice in Wonderland' + 1567: 'The wizard of Oz' + 1568: 'I'm singin' in the rain' + 1569: 'Alice in Wonderland' + 1570: 'The wizard of Oz' + 1571: 'I'm singin' in the rain' + 1572: 'Alice in Wonderland' + 1573: 'The wizard of Oz' + 1574: 'I'm singin' in the rain' + 1575: 'Alice in Wonderland' + 1576: 'The wizard of Oz' + 1577: 'I'm singin' in the rain' + 1578: 'Alice in Wonderland' + 1579: 'The wizard of Oz' + 1580: 'I'm singin' in the rain' + 1581: 'Alice in Wonderland' + 1582: 'The wizard of Oz' + 1583: 'I'm singin' in the rain' + 1584: 'Alice in Wonderland' + 1585: 'The wizard of Oz' + 1586: 'I'm singin' in the rain' + 1587: 'Alice in Wonderland' + 1588: 'The wizard of Oz' + 1589: 'I'm singin' in the rain' + 1590: 'Alice in Wonderland' + 1591: 'The wizard of Oz' + 1592: 'I'm singin' in the rain' + 1593: 'Alice in Wonderland' + 1594: 'The wizard of Oz' + 1595: 'I'm singin' in the rain' + 1596: 'Alice in Wonderland' + 1597: 'The wizard of Oz' + 1598: 'I'm singin' in the rain' + 1599: 'Alice in Wonderland' + 1600: 'The wizard of Oz' + 1601: 'I'm singin' in the rain' + 1602: 'Alice in Wonderland' + 1603: 'The wizard of Oz' + 1604: 'I'm singin' in the rain' + 1605: 'Alice in Wonderland' + 1606: 'The wizard of Oz' + 1607: 'I'm singin' in the rain' + 1608: 'Alice in Wonderland' + 1609: 'The wizard of Oz' + 1610: 'I'm singin' in the rain' + 1611: 'Alice in Wonderland' + 1612: 'The wizard of Oz' + 1613: 'I'm singin' in the rain' + 1614: 'Alice in Wonderland' + 1615: 'The wizard of Oz' + 1616: 'I'm singin' in the rain' + 1617: 'Alice in Wonderland' + 1618: 'The wizard of Oz' + 1619: 'I'm singin' in the rain' + 1620: 'Alice in Wonderland' + 1621: 'The wizard of Oz' + 1622: 'I'm singin' in the rain' + 1623: 'Alice in Wonderland' + 1624: 'The wizard of Oz' + 1625: 'I'm singin' in the rain' + 1626: 'Alice in Wonderland' + 1627: 'The wizard of Oz' + 1628: 'I'm singin' in the rain' + 1629: 'Alice in Wonderland' + 1630: 'The wizard of Oz' + 1631: 'I'm singin' in the rain' + 1632: 'Alice in Wonderland' + 1633: 'The wizard of Oz' + 1634: 'I'm singin' in the rain' + 1635: 'Alice in Wonderland' + 1636: 'The wizard of Oz' + 1637: 'I'm singin' in the rain' + 1638: 'Alice in Wonderland' + 1639: 'The wizard of Oz' + 1640: 'I'm singin' in the rain' + 1641: 'Alice in Wonderland' + 1642: 'The wizard of Oz' + 1643: 'I'm singin' in the rain' + 1644: 'Alice in Wonderland' + 1645: 'The wizard of Oz' + 1646: 'I'm singin' in the rain' + 1647: 'Alice in Wonderland' + 1648: 'The wizard of Oz' + 1649: 'I'm singin' in the rain' + 1650: 'Alice in Wonderland' + 1651: 'The wizard of Oz' + 1652: 'I'm singin' in the rain' + 1653: 'Alice in Wonderland' + 1654: 'The wizard of Oz' + 1655: 'I'm singin' in the rain' + 1656: 'Alice in Wonderland' + 1657: 'The wizard of Oz' + 1658: 'I'm singin' in the rain' + 1659: 'Alice in Wonderland' + 1660: 'The wizard of Oz' + 1661: 'I'm singin' in the rain' + 1662: 'Alice in Wonderland' + 1663: 'The wizard of Oz' + 1664: 'I'm singin' in the rain' + 1665: 'Alice in Wonderland' + 1666: 'The wizard of Oz' + 1667: 'I'm singin' in the rain' + 1668: 'Alice in Wonderland' + 1669: 'The wizard of Oz' + 1670: 'I'm singin' in the rain' + 1671: 'Alice in Wonderland' + 1672: 'The wizard of Oz' + 1673: 'I'm singin' in the rain' + 1674: 'Alice in Wonderland' + 1675: 'The wizard of Oz' + 1676: 'I'm singin' in the rain' + 1677: 'Alice in Wonderland' + 1678: 'The wizard of Oz' + 1679: 'I'm singin' in the rain' + 1680: 'Alice in Wonderland' + 1681: 'The wizard of Oz' + 1682: 'I'm singin' in the rain' + 1683: 'Alice in Wonderland' + 1684: 'The wizard of Oz' + 1685: 'I'm singin' in the rain' + 1686: 'Alice in Wonderland' + 1687: 'The wizard of Oz' + 1688: 'I'm singin' in the rain' + 1689: 'Alice in Wonderland' + 1690: 'The wizard of Oz' + 1691: 'I'm singin' in the rain' + 1692: 'Alice in Wonderland' + 1693: 'The wizard of Oz' + 1694: 'I'm singin' in the rain' + 1695: 'Alice in Wonderland' + 1696: 'The wizard of Oz' + 1697: 'I'm singin' in the rain' + 1698: 'Alice in Wonderland' + 1699: 'The wizard of Oz' + 1700: 'I'm singin' in the rain' + 1701: 'Alice in Wonderland' + 1702: 'The wizard of Oz' + 1703: 'I'm singin' in the rain' + 1704: 'Alice in Wonderland' + 1705: 'The wizard of Oz' + 1706: 'I'm singin' in the rain' + 1707: 'Alice in Wonderland' + 1708: 'The wizard of Oz' + 1709: 'I'm singin' in the rain' + 1710: 'Alice in Wonderland' + 1711: 'The wizard of Oz' + 1712: 'I'm singin' in the rain' + 1713: 'Alice in Wonderland' + 1714: 'The wizard of Oz' + 1715: 'I'm singin' in the rain' + 1716: 'Alice in Wonderland' + 1717: 'The wizard of Oz' + 1718: 'I'm singin' in the rain' + 1719: 'Alice in Wonderland' + 1720: 'The wizard of Oz' + 1721: 'I'm singin' in the rain' + 1722: 'Alice in Wonderland' + 1723: 'The wizard of Oz' + 1724: 'I'm singin' in the rain' + 1725: 'Alice in Wonderland' + 1726: 'The wizard of Oz' + 1727: 'I'm singin' in the rain' + 1728: 'Alice in Wonderland' + 1729: 'The wizard of Oz' + 1730: 'I'm singin' in the rain' + 1731: 'Alice in Wonderland' + 1732: 'The wizard of Oz' + 1733: 'I'm singin' in the rain' + 1734: 'Alice in Wonderland' + 1735: 'The wizard of Oz' + 1736: 'I'm singin' in the rain' + 1737: 'Alice in Wonderland' + 1738: 'The wizard of Oz' + 1739: 'I'm singin' in the rain' + 1740: 'Alice in Wonderland' + 1741: 'The wizard of Oz' + 1742: 'I'm singin' in the rain' + 1743: 'Alice in Wonderland' + 1744: 'The wizard of Oz' + 1745: 'I'm singin' in the rain' + 1746: 'Alice in Wonderland' + 1747: 'The wizard of Oz' + 1748: 'I'm singin' in the rain' + 1749: 'Alice in Wonderland' + 1750: 'The wizard of Oz' + 1751: 'I'm singin' in the rain' + 1752: 'Alice in Wonderland' + 1753: 'The wizard of Oz' + 1754: 'I'm singin' in the rain' + 1755: 'Alice in Wonderland' + 1756: 'The wizard of Oz' + 1757: 'I'm singin' in the rain' + 1758: 'Alice in Wonderland' + 1759: 'The wizard of Oz' + 1760: 'I'm singin' in the rain' + 1761: 'Alice in Wonderland' + 1762: 'The wizard of Oz' + 1763: 'I'm singin' in the rain' + 1764: 'Alice in Wonderland' + 1765: 'The wizard of Oz' + 1766: 'I'm singin' in the rain' + 1767: 'Alice in Wonderland' + 1768: 'The wizard of Oz' + 1769: 'I'm singin' in the rain' + 1770: 'Alice in Wonderland' + 1771: 'The wizard of Oz' + 1772: 'I'm singin' in the rain' + 1773: 'Alice in Wonderland' + 1774: 'The wizard of Oz' + 1775: 'I'm singin' in the rain' + 1776: 'Alice in Wonderland' + 1777: 'The wizard of Oz' + 1778: 'I'm singin' in the rain' + 1779: 'Alice in Wonderland' + 1780: 'The wizard of Oz' + 1781: 'I'm singin' in the rain' + 1782: 'Alice in Wonderland' + 1783: 'The wizard of Oz' + 1784: 'I'm singin' in the rain' + 1785: 'Alice in Wonderland' + 1786: 'The wizard of Oz' + 1787: 'I'm singin' in the rain' + 1788: 'Alice in Wonderland' + 1789: 'The wizard of Oz' + 1790: 'I'm singin' in the rain' + 1791: 'Alice in Wonderland' + 1792: 'The wizard of Oz' + 1793: 'I'm singin' in the rain' + 1794: 'Alice in Wonderland' + 1795: 'The wizard of Oz' + 1796: 'I'm singin' in the rain' + 1797: 'Alice in Wonderland' + 1798: 'The wizard of Oz' + 1799: 'I'm singin' in the rain' + 1800: 'Alice in Wonderland' + 1801: 'The wizard of Oz' + 1802: 'I'm singin' in the rain' + 1803: 'Alice in Wonderland' + 1804: 'The wizard of Oz' + 1805: 'I'm singin' in the rain' + 1806: 'Alice in Wonderland' + 1807: 'The wizard of Oz' + 1808: 'I'm singin' in the rain' + 1809: 'Alice in Wonderland' + 1810: 'The wizard of Oz' + 1811: 'I'm singin' in the rain' + 1812: 'Alice in Wonderland' + 1813: 'The wizard of Oz' + 1814: 'I'm singin' in the rain' + 1815: 'Alice in Wonderland' + 1816: 'The wizard of Oz' + 1817: 'I'm singin' in the rain' + 1818: 'Alice in Wonderland' + 1819: 'The wizard of Oz' + 1820: 'I'm singin' in the rain' + 1821: 'Alice in Wonderland' + 1822: 'The wizard of Oz' + 1823: 'I'm singin' in the rain' + 1824: 'Alice in Wonderland' + 1825: 'The wizard of Oz' + 1826: 'I'm singin' in the rain' + 1827: 'Alice in Wonderland' + 1828: 'The wizard of Oz' + 1829: 'I'm singin' in the rain' + 1830: 'Alice in Wonderland' + 1831: 'The wizard of Oz' + 1832: 'I'm singin' in the rain' + 1833: 'Alice in Wonderland' + 1834: 'The wizard of Oz' + 1835: 'I'm singin' in the rain' + 1836: 'Alice in Wonderland' + 1837: 'The wizard of Oz' + 1838: 'I'm singin' in the rain' + 1839: 'Alice in Wonderland' + 1840: 'The wizard of Oz' + 1841: 'I'm singin' in the rain' + 1842: 'Alice in Wonderland' + 1843: 'The wizard of Oz' + 1844: 'I'm singin' in the rain' + 1845: 'Alice in Wonderland' + 1846: 'The wizard of Oz' + 1847: 'I'm singin' in the rain' + 1848: 'Alice in Wonderland' + 1849: 'The wizard of Oz' + 1850: 'I'm singin' in the rain' + 1851: 'Alice in Wonderland' + 1852: 'The wizard of Oz' + 1853: 'I'm singin' in the rain' + 1854: 'Alice in Wonderland' + 1855: 'The wizard of Oz' + 1856: 'I'm singin' in the rain' + 1857: 'Alice in Wonderland' + 1858: 'The wizard of Oz' + 1859: 'I'm singin' in the rain' + 1860: 'Alice in Wonderland' + 1861: 'The wizard of Oz' + 1862: 'I'm singin' in the rain' + 1863: 'Alice in Wonderland' + 1864: 'The wizard of Oz' + 1865: 'I'm singin' in the rain' + 1866: 'Alice in Wonderland' + 1867: 'The wizard of Oz' + 1868: 'I'm singin' in the rain' + 1869: 'Alice in Wonderland' + 1870: 'The wizard of Oz' + 1871: 'I'm singin' in the rain' + 1872: 'Alice in Wonderland' + 1873: 'The wizard of Oz' + 1874: 'I'm singin' in the rain' + 1875: 'Alice in Wonderland' + 1876: 'The wizard of Oz' + 1877: 'I'm singin' in the rain' + 1878: 'Alice in Wonderland' + 1879: 'The wizard of Oz' + 1880: 'I'm singin' in the rain' + 1881: 'Alice in Wonderland' + 1882: 'The wizard of Oz' + 1883: 'I'm singin' in the rain' + 1884: 'Alice in Wonderland' + 1885: 'The wizard of Oz' + 1886: 'I'm singin' in the rain' + 1887: 'Alice in Wonderland' + 1888: 'The wizard of Oz' + 1889: 'I'm singin' in the rain' + 1890: 'Alice in Wonderland' + 1891: 'The wizard of Oz' + 1892: 'I'm singin' in the rain' + 1893: 'Alice in Wonderland' + 1894: 'The wizard of Oz' + 1895: 'I'm singin' in the rain' + 1896: 'Alice in Wonderland' + 1897: 'The wizard of Oz' + 1898: 'I'm singin' in the rain' + 1899: 'Alice in Wonderland' + 1900: 'The wizard of Oz' + 1901: 'I'm singin' in the rain' + 1902: 'Alice in Wonderland' + 1903: 'The wizard of Oz' + 1904: 'I'm singin' in the rain' + 1905: 'Alice in Wonderland' + 1906: 'The wizard of Oz' + 1907: 'I'm singin' in the rain' + 1908: 'Alice in Wonderland' + 1909: 'The wizard of Oz' + 1910: 'I'm singin' in the rain' + 1911: 'Alice in Wonderland' + 1912: 'The wizard of Oz' + 1913: 'I'm singin' in the rain' + 1914: 'Alice in Wonderland' + 1915: 'The wizard of Oz' + 1916: 'I'm singin' in the rain' + 1917: 'Alice in Wonderland' + 1918: 'The wizard of Oz' + 1919: 'I'm singin' in the rain' + 1920: 'Alice in Wonderland' + 1921: 'The wizard of Oz' + 1922: 'I'm singin' in the rain' + 1923: 'Alice in Wonderland' + 1924: 'The wizard of Oz' + 1925: 'I'm singin' in the rain' + 1926: 'Alice in Wonderland' + 1927: 'The wizard of Oz' + 1928: 'I'm singin' in the rain' + 1929: 'Alice in Wonderland' + 1930: 'The wizard of Oz' + 1931: 'I'm singin' in the rain' + 1932: 'Alice in Wonderland' + 1933: 'The wizard of Oz' + 1934: 'I'm singin' in the rain' + 1935: 'Alice in Wonderland' + 1936: 'The wizard of Oz' + 1937: 'I'm singin' in the rain' + 1938: 'Alice in Wonderland' + 1939: 'The wizard of Oz' + 1940: 'I'm singin' in the rain' + 1941: 'Alice in Wonderland' + 1942: 'The wizard of Oz' + 1943: 'I'm singin' in the rain' + 1944: 'Alice in Wonderland' + 1945: 'The wizard of Oz' + 1946: 'I'm singin' in the rain' + 1947: 'Alice in Wonderland' + 1948: 'The wizard of Oz' + 1949: 'I'm singin' in the rain' + 1950: 'Alice in Wonderland' + 1951: 'The wizard of Oz' + 1952: 'I'm singin' in the rain' + 1953: 'Alice in Wonderland' + 1954: 'The wizard of Oz' + 1955: 'I'm singin' in the rain' + 1956: 'Alice in Wonderland' + 1957: 'The wizard of Oz' + 1958: 'I'm singin' in the rain' + 1959: 'Alice in Wonderland' + 1960: 'The wizard of Oz' + 1961: 'I'm singin' in the rain' + 1962: 'Alice in Wonderland' + 1963: 'The wizard of Oz' + 1964: 'I'm singin' in the rain' + 1965: 'Alice in Wonderland' + 1966: 'The wizard of Oz' + 1967: 'I'm singin' in the rain' + 1968: 'Alice in Wonderland' + 1969: 'The wizard of Oz' + 1970: 'I'm singin' in the rain' + 1971: 'Alice in Wonderland' + 1972: 'The wizard of Oz' + 1973: 'I'm singin' in the rain' + 1974: 'Alice in Wonderland' + 1975: 'The wizard of Oz' + 1976: 'I'm singin' in the rain' + 1977: 'Alice in Wonderland' + 1978: 'The wizard of Oz' + 1979: 'I'm singin' in the rain' + 1980: 'Alice in Wonderland' + 1981: 'The wizard of Oz' + 1982: 'I'm singin' in the rain' + 1983: 'Alice in Wonderland' + 1984: 'The wizard of Oz' + 1985: 'I'm singin' in the rain' + 1986: 'Alice in Wonderland' + 1987: 'The wizard of Oz' + 1988: 'I'm singin' in the rain' + 1989: 'Alice in Wonderland' + 1990: 'The wizard of Oz' + 1991: 'I'm singin' in the rain' + 1992: 'Alice in Wonderland' + 1993: 'The wizard of Oz' + 1994: 'I'm singin' in the rain' + 1995: 'Alice in Wonderland' + 1996: 'The wizard of Oz' + 1997: 'I'm singin' in the rain' + 1998: 'Alice in Wonderland' + 1999: 'The wizard of Oz' + 2000: 'I'm singin' in the rain' + 2001: 'Alice in Wonderland' + 2002: 'The wizard of Oz' + 2003: 'I'm singin' in the rain' + 2004: 'Alice in Wonderland' + 2005: 'The wizard of Oz' + 2006: 'I'm singin' in the rain' + 2007: 'Alice in Wonderland' + 2008: 'The wizard of Oz' + 2009: 'I'm singin' in the rain' + 2010: 'Alice in Wonderland' + 2011: 'The wizard of Oz' + 2012: 'I'm singin' in the rain' + 2013: 'Alice in Wonderland' + 2014: 'The wizard of Oz' + 2015: 'I'm singin' in the rain' + 2016: 'Alice in Wonderland' + 2017: 'The wizard of Oz' + 2018: 'I'm singin' in the rain' + 2019: 'Alice in Wonderland' + 2020: 'The wizard of Oz' + 2021: 'I'm singin' in the rain' + 2022: 'Alice in Wonderland' + 2023: 'The wizard of Oz' + 2024: 'I'm singin' in the rain' + 2025: 'Alice in Wonderland' + 2026: 'The wizard of Oz' + 2027: 'I'm singin' in the rain' + 2028: 'Alice in Wonderland' + 2029: 'The wizard of Oz' + 2030: 'I'm singin' in the rain' + 2031: 'Alice in Wonderland' + 2032: 'The wizard of Oz' + 2033: 'I'm singin' in the rain' + 2034: 'Alice in Wonderland' + 2035: 'The wizard of Oz' + 2036: 'I'm singin' in the rain' + 2037: 'Alice in Wonderland' + 2038: 'The wizard of Oz' + 2039: 'I'm singin' in the rain' + 2040: 'Alice in Wonderland' + 2041: 'The wizard of Oz' + 2042: 'I'm singin' in the rain' + 2043: 'Alice in Wonderland' + 2044: 'The wizard of Oz' + 2045: 'I'm singin' in the rain' + 2046: 'Alice in Wonderland' + 2047: 'The wizard of Oz' + 2048: 'I'm singin' in the rain' + 2049: 'Alice in Wonderland' + 2050: 'The wizard of Oz' + 2051: 'I'm singin' in the rain' + 2052: 'Alice in Wonderland' + 2053: 'The wizard of Oz' + 2054: 'I'm singin' in the rain' + 2055: 'Alice in Wonderland' + 2056: 'The wizard of Oz' + 2057: 'I'm singin' in the rain' + 2058: 'Alice in Wonderland' + 2059: 'The wizard of Oz' + 2060: 'I'm singin' in the rain' + 2061: 'Alice in Wonderland' + 2062: 'The wizard of Oz' + 2063: 'I'm singin' in the rain' + 2064: 'Alice in Wonderland' + 2065: 'The wizard of Oz' + 2066: 'I'm singin' in the rain' + 2067: 'Alice in Wonderland' + 2068: 'The wizard of Oz' + 2069: 'I'm singin' in the rain' + 2070: 'Alice in Wonderland' + 2071: 'The wizard of Oz' + 2072: 'I'm singin' in the rain' + 2073: 'Alice in Wonderland' + 2074: 'The wizard of Oz' + 2075: 'I'm singin' in the rain' + 2076: 'Alice in Wonderland' + 2077: 'The wizard of Oz' + 2078: 'I'm singin' in the rain' + 2079: 'Alice in Wonderland' + 2080: 'The wizard of Oz' + 2081: 'I'm singin' in the rain' + 2082: 'Alice in Wonderland' + 2083: 'The wizard of Oz' + 2084: 'I'm singin' in the rain' + 2085: 'Alice in Wonderland' + 2086: 'The wizard of Oz' + 2087: 'I'm singin' in the rain' + 2088: 'Alice in Wonderland' + 2089: 'The wizard of Oz' + 2090: 'I'm singin' in the rain' + 2091: 'Alice in Wonderland' + 2092: 'The wizard of Oz' + 2093: 'I'm singin' in the rain' + 2094: 'Alice in Wonderland' + 2095: 'The wizard of Oz' + 2096: 'I'm singin' in the rain' + 2097: 'Alice in Wonderland' + 2098: 'The wizard of Oz' + 2099: 'I'm singin' in the rain' + 2100: 'Alice in Wonderland' + 2101: 'The wizard of Oz' + 2102: 'I'm singin' in the rain' + 2103: 'Alice in Wonderland' + 2104: 'The wizard of Oz' + 2105: 'I'm singin' in the rain' + 2106: 'Alice in Wonderland' + 2107: 'The wizard of Oz' + 2108: 'I'm singin' in the rain' + 2109: 'Alice in Wonderland' + 2110: 'The wizard of Oz' + 2111: 'I'm singin' in the rain' + 2112: 'Alice in Wonderland' + 2113: 'The wizard of Oz' + 2114: 'I'm singin' in the rain' + 2115: 'Alice in Wonderland' + 2116: 'The wizard of Oz' + 2117: 'I'm singin' in the rain' + 2118: 'Alice in Wonderland' + 2119: 'The wizard of Oz' + 2120: 'I'm singin' in the rain' + 2121: 'Alice in Wonderland' + 2122: 'The wizard of Oz' + 2123: 'I'm singin' in the rain' + 2124: 'Alice in Wonderland' + 2125: 'The wizard of Oz' + 2126: 'I'm singin' in the rain' + 2127: 'Alice in Wonderland' + 2128: 'The wizard of Oz' + 2129: 'I'm singin' in the rain' + 2130: 'Alice in Wonderland' + 2131: 'The wizard of Oz' + 2132: 'I'm singin' in the rain' + 2133: 'Alice in Wonderland' + 2134: 'The wizard of Oz' + 2135: 'I'm singin' in the rain' + 2136: 'Alice in Wonderland' + 2137: 'The wizard of Oz' + 2138: 'I'm singin' in the rain' + 2139: 'Alice in Wonderland' + 2140: 'The wizard of Oz' + 2141: 'I'm singin' in the rain' + 2142: 'Alice in Wonderland' + 2143: 'The wizard of Oz' + 2144: 'I'm singin' in the rain' + 2145: 'Alice in Wonderland' + 2146: 'The wizard of Oz' + 2147: 'I'm singin' in the rain' + 2148: 'Alice in Wonderland' + 2149: 'The wizard of Oz' + 2150: 'I'm singin' in the rain' + 2151: 'Alice in Wonderland' + 2152: 'The wizard of Oz' + 2153: 'I'm singin' in the rain' + 2154: 'Alice in Wonderland' + 2155: 'The wizard of Oz' + 2156: 'I'm singin' in the rain' + 2157: 'Alice in Wonderland' + 2158: 'The wizard of Oz' + 2159: 'I'm singin' in the rain' + 2160: 'Alice in Wonderland' + 2161: 'The wizard of Oz' + 2162: 'I'm singin' in the rain' + 2163: 'Alice in Wonderland' + 2164: 'The wizard of Oz' + 2165: 'I'm singin' in the rain' + 2166: 'Alice in Wonderland' + 2167: 'The wizard of Oz' + 2168: 'I'm singin' in the rain' + 2169: 'Alice in Wonderland' + 2170: 'The wizard of Oz' + 2171: 'I'm singin' in the rain' + 2172: 'Alice in Wonderland' + 2173: 'The wizard of Oz' + 2174: 'I'm singin' in the rain' + 2175: 'Alice in Wonderland' + 2176: 'The wizard of Oz' + 2177: 'I'm singin' in the rain' + 2178: 'Alice in Wonderland' + 2179: 'The wizard of Oz' + 2180: 'I'm singin' in the rain' + 2181: 'Alice in Wonderland' + 2182: 'The wizard of Oz' + 2183: 'I'm singin' in the rain' + 2184: 'Alice in Wonderland' + 2185: 'The wizard of Oz' + 2186: 'I'm singin' in the rain' + 2187: 'Alice in Wonderland' + 2188: 'The wizard of Oz' + 2189: 'I'm singin' in the rain' + 2190: 'Alice in Wonderland' + 2191: 'The wizard of Oz' + 2192: 'I'm singin' in the rain' + 2193: 'Alice in Wonderland' + 2194: 'The wizard of Oz' + 2195: 'I'm singin' in the rain' + 2196: 'Alice in Wonderland' + 2197: 'The wizard of Oz' + 2198: 'I'm singin' in the rain' + 2199: 'Alice in Wonderland' + 2200: 'The wizard of Oz' + 2201: 'I'm singin' in the rain' + 2202: 'Alice in Wonderland' + 2203: 'The wizard of Oz' + 2204: 'I'm singin' in the rain' + 2205: 'Alice in Wonderland' + 2206: 'The wizard of Oz' + 2207: 'I'm singin' in the rain' + 2208: 'Alice in Wonderland' + 2209: 'The wizard of Oz' + 2210: 'I'm singin' in the rain' + 2211: 'Alice in Wonderland' + 2212: 'The wizard of Oz' + 2213: 'I'm singin' in the rain' + 2214: 'Alice in Wonderland' + 2215: 'The wizard of Oz' + 2216: 'I'm singin' in the rain' + 2217: 'Alice in Wonderland' + 2218: 'The wizard of Oz' + 2219: 'I'm singin' in the rain' + 2220: 'Alice in Wonderland' + 2221: 'The wizard of Oz' + 2222: 'I'm singin' in the rain' + 2223: 'Alice in Wonderland' + 2224: 'The wizard of Oz' + 2225: 'I'm singin' in the rain' + 2226: 'Alice in Wonderland' + 2227: 'The wizard of Oz' + 2228: 'I'm singin' in the rain' + 2229: 'Alice in Wonderland' + 2230: 'The wizard of Oz' + 2231: 'I'm singin' in the rain' + 2232: 'Alice in Wonderland' + 2233: 'The wizard of Oz' + 2234: 'I'm singin' in the rain' + 2235: 'Alice in Wonderland' + 2236: 'The wizard of Oz' + 2237: 'I'm singin' in the rain' + 2238: 'Alice in Wonderland' + 2239: 'The wizard of Oz' + 2240: 'I'm singin' in the rain' + 2241: 'Alice in Wonderland' + 2242: 'The wizard of Oz' + 2243: 'I'm singin' in the rain' + 2244: 'Alice in Wonderland' + 2245: 'The wizard of Oz' + 2246: 'I'm singin' in the rain' + 2247: 'Alice in Wonderland' + 2248: 'The wizard of Oz' + 2249: 'I'm singin' in the rain' + 2250: 'Alice in Wonderland' + 2251: 'The wizard of Oz' + 2252: 'I'm singin' in the rain' + 2253: 'Alice in Wonderland' + 2254: 'The wizard of Oz' + 2255: 'I'm singin' in the rain' + 2256: 'Alice in Wonderland' + 2257: 'The wizard of Oz' + 2258: 'I'm singin' in the rain' + 2259: 'Alice in Wonderland' + 2260: 'The wizard of Oz' + 2261: 'I'm singin' in the rain' + 2262: 'Alice in Wonderland' + 2263: 'The wizard of Oz' + 2264: 'I'm singin' in the rain' + 2265: 'Alice in Wonderland' + 2266: 'The wizard of Oz' + 2267: 'I'm singin' in the rain' + 2268: 'Alice in Wonderland' + 2269: 'The wizard of Oz' + 2270: 'I'm singin' in the rain' + 2271: 'Alice in Wonderland' + 2272: 'The wizard of Oz' + 2273: 'I'm singin' in the rain' + 2274: 'Alice in Wonderland' + 2275: 'The wizard of Oz' + 2276: 'I'm singin' in the rain' + 2277: 'Alice in Wonderland' + 2278: 'The wizard of Oz' + 2279: 'I'm singin' in the rain' + 2280: 'Alice in Wonderland' + 2281: 'The wizard of Oz' + 2282: 'I'm singin' in the rain' + 2283: 'Alice in Wonderland' + 2284: 'The wizard of Oz' + 2285: 'I'm singin' in the rain' + 2286: 'Alice in Wonderland' + 2287: 'The wizard of Oz' + 2288: 'I'm singin' in the rain' + 2289: 'Alice in Wonderland' + 2290: 'The wizard of Oz' + 2291: 'I'm singin' in the rain' + 2292: 'Alice in Wonderland' + 2293: 'The wizard of Oz' + 2294: 'I'm singin' in the rain' + 2295: 'Alice in Wonderland' + 2296: 'The wizard of Oz' + 2297: 'I'm singin' in the rain' + 2298: 'Alice in Wonderland' + 2299: 'The wizard of Oz' + 2300: 'I'm singin' in the rain' + 2301: 'Alice in Wonderland' + 2302: 'The wizard of Oz' + 2303: 'I'm singin' in the rain' + 2304: 'Alice in Wonderland' + 2305: 'The wizard of Oz' + 2306: 'I'm singin' in the rain' + 2307: 'Alice in Wonderland' + 2308: 'The wizard of Oz' + 2309: 'I'm singin' in the rain' + 2310: 'Alice in Wonderland' + 2311: 'The wizard of Oz' + 2312: 'I'm singin' in the rain' + 2313: 'Alice in Wonderland' + 2314: 'The wizard of Oz' + 2315: 'I'm singin' in the rain' + 2316: 'Alice in Wonderland' + 2317: 'The wizard of Oz' + 2318: 'I'm singin' in the rain' + 2319: 'Alice in Wonderland' + 2320: 'The wizard of Oz' + 2321: 'I'm singin' in the rain' + 2322: 'Alice in Wonderland' + 2323: 'The wizard of Oz' + 2324: 'I'm singin' in the rain' + 2325: 'Alice in Wonderland' + 2326: 'The wizard of Oz' + 2327: 'I'm singin' in the rain' + 2328: 'Alice in Wonderland' + 2329: 'The wizard of Oz' + 2330: 'I'm singin' in the rain' + 2331: 'Alice in Wonderland' + 2332: 'The wizard of Oz' + 2333: 'I'm singin' in the rain' + 2334: 'Alice in Wonderland' + 2335: 'The wizard of Oz' + 2336: 'I'm singin' in the rain' + 2337: 'Alice in Wonderland' + 2338: 'The wizard of Oz' + 2339: 'I'm singin' in the rain' + 2340: 'Alice in Wonderland' + 2341: 'The wizard of Oz' + 2342: 'I'm singin' in the rain' + 2343: 'Alice in Wonderland' + 2344: 'The wizard of Oz' + 2345: 'I'm singin' in the rain' + 2346: 'Alice in Wonderland' + 2347: 'The wizard of Oz' + 2348: 'I'm singin' in the rain' + 2349: 'Alice in Wonderland' + 2350: 'The wizard of Oz' + 2351: 'I'm singin' in the rain' + 2352: 'Alice in Wonderland' + 2353: 'The wizard of Oz' + 2354: 'I'm singin' in the rain' + 2355: 'Alice in Wonderland' + 2356: 'The wizard of Oz' + 2357: 'I'm singin' in the rain' + 2358: 'Alice in Wonderland' + 2359: 'The wizard of Oz' + 2360: 'I'm singin' in the rain' + 2361: 'Alice in Wonderland' + 2362: 'The wizard of Oz' + 2363: 'I'm singin' in the rain' + 2364: 'Alice in Wonderland' + 2365: 'The wizard of Oz' + 2366: 'I'm singin' in the rain' + 2367: 'Alice in Wonderland' + 2368: 'The wizard of Oz' + 2369: 'I'm singin' in the rain' + 2370: 'Alice in Wonderland' + 2371: 'The wizard of Oz' + 2372: 'I'm singin' in the rain' + 2373: 'Alice in Wonderland' + 2374: 'The wizard of Oz' + 2375: 'I'm singin' in the rain' + 2376: 'Alice in Wonderland' + 2377: 'The wizard of Oz' + 2378: 'I'm singin' in the rain' + 2379: 'Alice in Wonderland' + 2380: 'The wizard of Oz' + 2381: 'I'm singin' in the rain' + 2382: 'Alice in Wonderland' + 2383: 'The wizard of Oz' + 2384: 'I'm singin' in the rain' + 2385: 'Alice in Wonderland' + 2386: 'The wizard of Oz' + 2387: 'I'm singin' in the rain' + 2388: 'Alice in Wonderland' + 2389: 'The wizard of Oz' + 2390: 'I'm singin' in the rain' + 2391: 'Alice in Wonderland' + 2392: 'The wizard of Oz' + 2393: 'I'm singin' in the rain' + 2394: 'Alice in Wonderland' + 2395: 'The wizard of Oz' + 2396: 'I'm singin' in the rain' + 2397: 'Alice in Wonderland' + 2398: 'The wizard of Oz' + 2399: 'I'm singin' in the rain' + 2400: 'Alice in Wonderland' + 2401: 'The wizard of Oz' + 2402: 'I'm singin' in the rain' + 2403: 'Alice in Wonderland' + 2404: 'The wizard of Oz' + 2405: 'I'm singin' in the rain' + 2406: 'Alice in Wonderland' + 2407: 'The wizard of Oz' + 2408: 'I'm singin' in the rain' + 2409: 'Alice in Wonderland' + 2410: 'The wizard of Oz' + 2411: 'I'm singin' in the rain' + 2412: 'Alice in Wonderland' + 2413: 'The wizard of Oz' + 2414: 'I'm singin' in the rain' + 2415: 'Alice in Wonderland' + 2416: 'The wizard of Oz' + 2417: 'I'm singin' in the rain' + 2418: 'Alice in Wonderland' + 2419: 'The wizard of Oz' + 2420: 'I'm singin' in the rain' + 2421: 'Alice in Wonderland' + 2422: 'The wizard of Oz' + 2423: 'I'm singin' in the rain' + 2424: 'Alice in Wonderland' + 2425: 'The wizard of Oz' + 2426: 'I'm singin' in the rain' + 2427: 'Alice in Wonderland' + 2428: 'The wizard of Oz' + 2429: 'I'm singin' in the rain' + 2430: 'Alice in Wonderland' + 2431: 'The wizard of Oz' + 2432: 'I'm singin' in the rain' + 2433: 'Alice in Wonderland' + 2434: 'The wizard of Oz' + 2435: 'I'm singin' in the rain' + 2436: 'Alice in Wonderland' + 2437: 'The wizard of Oz' + 2438: 'I'm singin' in the rain' + 2439: 'Alice in Wonderland' + 2440: 'The wizard of Oz' + 2441: 'I'm singin' in the rain' + 2442: 'Alice in Wonderland' + 2443: 'The wizard of Oz' + 2444: 'I'm singin' in the rain' + 2445: 'Alice in Wonderland' + 2446: 'The wizard of Oz' + 2447: 'I'm singin' in the rain' + 2448: 'Alice in Wonderland' + 2449: 'The wizard of Oz' + 2450: 'I'm singin' in the rain' + 2451: 'Alice in Wonderland' + 2452: 'The wizard of Oz' + 2453: 'I'm singin' in the rain' + 2454: 'Alice in Wonderland' + 2455: 'The wizard of Oz' + 2456: 'I'm singin' in the rain' + 2457: 'Alice in Wonderland' + 2458: 'The wizard of Oz' + 2459: 'I'm singin' in the rain' + 2460: 'Alice in Wonderland' + 2461: 'The wizard of Oz' + 2462: 'I'm singin' in the rain' + 2463: 'Alice in Wonderland' + 2464: 'The wizard of Oz' + 2465: 'I'm singin' in the rain' + 2466: 'Alice in Wonderland' + 2467: 'The wizard of Oz' + 2468: 'I'm singin' in the rain' + 2469: 'Alice in Wonderland' + 2470: 'The wizard of Oz' + 2471: 'I'm singin' in the rain' + 2472: 'Alice in Wonderland' + 2473: 'The wizard of Oz' + 2474: 'I'm singin' in the rain' + 2475: 'Alice in Wonderland' + 2476: 'The wizard of Oz' + 2477: 'I'm singin' in the rain' + 2478: 'Alice in Wonderland' + 2479: 'The wizard of Oz' + 2480: 'I'm singin' in the rain' + 2481: 'Alice in Wonderland' + 2482: 'The wizard of Oz' + 2483: 'I'm singin' in the rain' + 2484: 'Alice in Wonderland' + 2485: 'The wizard of Oz' + 2486: 'I'm singin' in the rain' + 2487: 'Alice in Wonderland' + 2488: 'The wizard of Oz' + 2489: 'I'm singin' in the rain' + 2490: 'Alice in Wonderland' + 2491: 'The wizard of Oz' + 2492: 'I'm singin' in the rain' + 2493: 'Alice in Wonderland' + 2494: 'The wizard of Oz' + 2495: 'I'm singin' in the rain' + 2496: 'Alice in Wonderland' + 2497: 'The wizard of Oz' + 2498: 'I'm singin' in the rain' + 2499: 'Alice in Wonderland' + 2500: 'The wizard of Oz' + 2501: 'I'm singin' in the rain' + 2502: 'Alice in Wonderland' + 2503: 'The wizard of Oz' + 2504: 'I'm singin' in the rain' + 2505: 'Alice in Wonderland' + 2506: 'The wizard of Oz' + 2507: 'I'm singin' in the rain' + 2508: 'Alice in Wonderland' + 2509: 'The wizard of Oz' + 2510: 'I'm singin' in the rain' + 2511: 'Alice in Wonderland' + 2512: 'The wizard of Oz' + 2513: 'I'm singin' in the rain' + 2514: 'Alice in Wonderland' + 2515: 'The wizard of Oz' + 2516: 'I'm singin' in the rain' + 2517: 'Alice in Wonderland' + 2518: 'The wizard of Oz' + 2519: 'I'm singin' in the rain' + 2520: 'Alice in Wonderland' + 2521: 'The wizard of Oz' + 2522: 'I'm singin' in the rain' + 2523: 'Alice in Wonderland' + 2524: 'The wizard of Oz' + 2525: 'I'm singin' in the rain' + 2526: 'Alice in Wonderland' + 2527: 'The wizard of Oz' + 2528: 'I'm singin' in the rain' + 2529: 'Alice in Wonderland' + 2530: 'The wizard of Oz' + 2531: 'I'm singin' in the rain' + 2532: 'Alice in Wonderland' + 2533: 'The wizard of Oz' + 2534: 'I'm singin' in the rain' + 2535: 'Alice in Wonderland' + 2536: 'The wizard of Oz' + 2537: 'I'm singin' in the rain' + 2538: 'Alice in Wonderland' + 2539: 'The wizard of Oz' + 2540: 'I'm singin' in the rain' + 2541: 'Alice in Wonderland' + 2542: 'The wizard of Oz' + 2543: 'I'm singin' in the rain' + 2544: 'Alice in Wonderland' + 2545: 'The wizard of Oz' + 2546: 'I'm singin' in the rain' + 2547: 'Alice in Wonderland' + 2548: 'The wizard of Oz' + 2549: 'I'm singin' in the rain' + 2550: 'Alice in Wonderland' + 2551: 'The wizard of Oz' + 2552: 'I'm singin' in the rain' + 2553: 'Alice in Wonderland' + 2554: 'The wizard of Oz' + 2555: 'I'm singin' in the rain' + 2556: 'Alice in Wonderland' + 2557: 'The wizard of Oz' + 2558: 'I'm singin' in the rain' + 2559: 'Alice in Wonderland' + 2560: 'The wizard of Oz' + 2561: 'I'm singin' in the rain' + 2562: 'Alice in Wonderland' + 2563: 'The wizard of Oz' + 2564: 'I'm singin' in the rain' + 2565: 'Alice in Wonderland' + 2566: 'The wizard of Oz' + 2567: 'I'm singin' in the rain' + 2568: 'Alice in Wonderland' + 2569: 'The wizard of Oz' + 2570: 'I'm singin' in the rain' + 2571: 'Alice in Wonderland' + 2572: 'The wizard of Oz' + 2573: 'I'm singin' in the rain' + 2574: 'Alice in Wonderland' + 2575: 'The wizard of Oz' + 2576: 'I'm singin' in the rain' + 2577: 'Alice in Wonderland' + 2578: 'The wizard of Oz' + 2579: 'I'm singin' in the rain' + 2580: 'Alice in Wonderland' + 2581: 'The wizard of Oz' + 2582: 'I'm singin' in the rain' + 2583: 'Alice in Wonderland' + 2584: 'The wizard of Oz' + 2585: 'I'm singin' in the rain' + 2586: 'Alice in Wonderland' + 2587: 'The wizard of Oz' + 2588: 'I'm singin' in the rain' + 2589: 'Alice in Wonderland' + 2590: 'The wizard of Oz' + 2591: 'I'm singin' in the rain' + 2592: 'Alice in Wonderland' + 2593: 'The wizard of Oz' + 2594: 'I'm singin' in the rain' + 2595: 'Alice in Wonderland' + 2596: 'The wizard of Oz' + 2597: 'I'm singin' in the rain' + 2598: 'Alice in Wonderland' + 2599: 'The wizard of Oz' + 2600: 'I'm singin' in the rain' + 2601: 'Alice in Wonderland' + 2602: 'The wizard of Oz' + 2603: 'I'm singin' in the rain' + 2604: 'Alice in Wonderland' + 2605: 'The wizard of Oz' + 2606: 'I'm singin' in the rain' + 2607: 'Alice in Wonderland' + 2608: 'The wizard of Oz' + 2609: 'I'm singin' in the rain' + 2610: 'Alice in Wonderland' + 2611: 'The wizard of Oz' + 2612: 'I'm singin' in the rain' + 2613: 'Alice in Wonderland' + 2614: 'The wizard of Oz' + 2615: 'I'm singin' in the rain' + 2616: 'Alice in Wonderland' + 2617: 'The wizard of Oz' + 2618: 'I'm singin' in the rain' + 2619: 'Alice in Wonderland' + 2620: 'The wizard of Oz' + 2621: 'I'm singin' in the rain' + 2622: 'Alice in Wonderland' + 2623: 'The wizard of Oz' + 2624: 'I'm singin' in the rain' + 2625: 'Alice in Wonderland' + 2626: 'The wizard of Oz' + 2627: 'I'm singin' in the rain' + 2628: 'Alice in Wonderland' + 2629: 'The wizard of Oz' + 2630: 'I'm singin' in the rain' + 2631: 'Alice in Wonderland' + 2632: 'The wizard of Oz' + 2633: 'I'm singin' in the rain' + 2634: 'Alice in Wonderland' + 2635: 'The wizard of Oz' + 2636: 'I'm singin' in the rain' + 2637: 'Alice in Wonderland' + 2638: 'The wizard of Oz' + 2639: 'I'm singin' in the rain' + 2640: 'Alice in Wonderland' + 2641: 'The wizard of Oz' + 2642: 'I'm singin' in the rain' + 2643: 'Alice in Wonderland' + 2644: 'The wizard of Oz' + 2645: 'I'm singin' in the rain' + 2646: 'Alice in Wonderland' + 2647: 'The wizard of Oz' + 2648: 'I'm singin' in the rain' + 2649: 'Alice in Wonderland' + 2650: 'The wizard of Oz' + 2651: 'I'm singin' in the rain' + 2652: 'Alice in Wonderland' + 2653: 'The wizard of Oz' + 2654: 'I'm singin' in the rain' + 2655: 'Alice in Wonderland' + 2656: 'The wizard of Oz' + 2657: 'I'm singin' in the rain' + 2658: 'Alice in Wonderland' + 2659: 'The wizard of Oz' + 2660: 'I'm singin' in the rain' + 2661: 'Alice in Wonderland' + 2662: 'The wizard of Oz' + 2663: 'I'm singin' in the rain' + 2664: 'Alice in Wonderland' + 2665: 'The wizard of Oz' + 2666: 'I'm singin' in the rain' + 2667: 'Alice in Wonderland' + 2668: 'The wizard of Oz' + 2669: 'I'm singin' in the rain' + 2670: 'Alice in Wonderland' + 2671: 'The wizard of Oz' + 2672: 'I'm singin' in the rain' + 2673: 'Alice in Wonderland' + 2674: 'The wizard of Oz' + 2675: 'I'm singin' in the rain' + 2676: 'Alice in Wonderland' + 2677: 'The wizard of Oz' + 2678: 'I'm singin' in the rain' + 2679: 'Alice in Wonderland' + 2680: 'The wizard of Oz' + 2681: 'I'm singin' in the rain' + 2682: 'Alice in Wonderland' + 2683: 'The wizard of Oz' + 2684: 'I'm singin' in the rain' + 2685: 'Alice in Wonderland' + 2686: 'The wizard of Oz' + 2687: 'I'm singin' in the rain' + 2688: 'Alice in Wonderland' + 2689: 'The wizard of Oz' + 2690: 'I'm singin' in the rain' + 2691: 'Alice in Wonderland' + 2692: 'The wizard of Oz' + 2693: 'I'm singin' in the rain' + 2694: 'Alice in Wonderland' + 2695: 'The wizard of Oz' + 2696: 'I'm singin' in the rain' + 2697: 'Alice in Wonderland' + 2698: 'The wizard of Oz' + 2699: 'I'm singin' in the rain' + 2700: 'Alice in Wonderland' + 2701: 'The wizard of Oz' + 2702: 'I'm singin' in the rain' + 2703: 'Alice in Wonderland' + 2704: 'The wizard of Oz' + 2705: 'I'm singin' in the rain' + 2706: 'Alice in Wonderland' + 2707: 'The wizard of Oz' + 2708: 'I'm singin' in the rain' + 2709: 'Alice in Wonderland' + 2710: 'The wizard of Oz' + 2711: 'I'm singin' in the rain' + 2712: 'Alice in Wonderland' + 2713: 'The wizard of Oz' + 2714: 'I'm singin' in the rain' + 2715: 'Alice in Wonderland' + 2716: 'The wizard of Oz' + 2717: 'I'm singin' in the rain' + 2718: 'Alice in Wonderland' + 2719: 'The wizard of Oz' + 2720: 'I'm singin' in the rain' + 2721: 'Alice in Wonderland' + 2722: 'The wizard of Oz' + 2723: 'I'm singin' in the rain' + 2724: 'Alice in Wonderland' + 2725: 'The wizard of Oz' + 2726: 'I'm singin' in the rain' + 2727: 'Alice in Wonderland' + 2728: 'The wizard of Oz' + 2729: 'I'm singin' in the rain' + 2730: 'Alice in Wonderland' + 2731: 'The wizard of Oz' + 2732: 'I'm singin' in the rain' + 2733: 'Alice in Wonderland' + 2734: 'The wizard of Oz' + 2735: 'I'm singin' in the rain' + 2736: 'Alice in Wonderland' + 2737: 'The wizard of Oz' + 2738: 'I'm singin' in the rain' + 2739: 'Alice in Wonderland' + 2740: 'The wizard of Oz' + 2741: 'I'm singin' in the rain' + 2742: 'Alice in Wonderland' + 2743: 'The wizard of Oz' + 2744: 'I'm singin' in the rain' + 2745: 'Alice in Wonderland' + 2746: 'The wizard of Oz' + 2747: 'I'm singin' in the rain' + 2748: 'Alice in Wonderland' + 2749: 'The wizard of Oz' + 2750: 'I'm singin' in the rain' + 2751: 'Alice in Wonderland' + 2752: 'The wizard of Oz' + 2753: 'I'm singin' in the rain' + 2754: 'Alice in Wonderland' + 2755: 'The wizard of Oz' + 2756: 'I'm singin' in the rain' + 2757: 'Alice in Wonderland' + 2758: 'The wizard of Oz' + 2759: 'I'm singin' in the rain' + 2760: 'Alice in Wonderland' + 2761: 'The wizard of Oz' + 2762: 'I'm singin' in the rain' + 2763: 'Alice in Wonderland' + 2764: 'The wizard of Oz' + 2765: 'I'm singin' in the rain' + 2766: 'Alice in Wonderland' + 2767: 'The wizard of Oz' + 2768: 'I'm singin' in the rain' + 2769: 'Alice in Wonderland' + 2770: 'The wizard of Oz' + 2771: 'I'm singin' in the rain' + 2772: 'Alice in Wonderland' + 2773: 'The wizard of Oz' + 2774: 'I'm singin' in the rain' + 2775: 'Alice in Wonderland' + 2776: 'The wizard of Oz' + 2777: 'I'm singin' in the rain' + 2778: 'Alice in Wonderland' + 2779: 'The wizard of Oz' + 2780: 'I'm singin' in the rain' + 2781: 'Alice in Wonderland' + 2782: 'The wizard of Oz' + 2783: 'I'm singin' in the rain' + 2784: 'Alice in Wonderland' + 2785: 'The wizard of Oz' + 2786: 'I'm singin' in the rain' + 2787: 'Alice in Wonderland' + 2788: 'The wizard of Oz' + 2789: 'I'm singin' in the rain' + 2790: 'Alice in Wonderland' + 2791: 'The wizard of Oz' + 2792: 'I'm singin' in the rain' + 2793: 'Alice in Wonderland' + 2794: 'The wizard of Oz' + 2795: 'I'm singin' in the rain' + 2796: 'Alice in Wonderland' + 2797: 'The wizard of Oz' + 2798: 'I'm singin' in the rain' + 2799: 'Alice in Wonderland' + 2800: 'The wizard of Oz' + 2801: 'I'm singin' in the rain' + 2802: 'Alice in Wonderland' + 2803: 'The wizard of Oz' + 2804: 'I'm singin' in the rain' + 2805: 'Alice in Wonderland' + 2806: 'The wizard of Oz' + 2807: 'I'm singin' in the rain' + 2808: 'Alice in Wonderland' + 2809: 'The wizard of Oz' + 2810: 'I'm singin' in the rain' + 2811: 'Alice in Wonderland' + 2812: 'The wizard of Oz' + 2813: 'I'm singin' in the rain' + 2814: 'Alice in Wonderland' + 2815: 'The wizard of Oz' + 2816: 'I'm singin' in the rain' + 2817: 'Alice in Wonderland' + 2818: 'The wizard of Oz' + 2819: 'I'm singin' in the rain' + 2820: 'Alice in Wonderland' + 2821: 'The wizard of Oz' + 2822: 'I'm singin' in the rain' + 2823: 'Alice in Wonderland' + 2824: 'The wizard of Oz' + 2825: 'I'm singin' in the rain' + 2826: 'Alice in Wonderland' + 2827: 'The wizard of Oz' + 2828: 'I'm singin' in the rain' + 2829: 'Alice in Wonderland' + 2830: 'The wizard of Oz' + 2831: 'I'm singin' in the rain' + 2832: 'Alice in Wonderland' + 2833: 'The wizard of Oz' + 2834: 'I'm singin' in the rain' + 2835: 'Alice in Wonderland' + 2836: 'The wizard of Oz' + 2837: 'I'm singin' in the rain' + 2838: 'Alice in Wonderland' + 2839: 'The wizard of Oz' + 2840: 'I'm singin' in the rain' + 2841: 'Alice in Wonderland' + 2842: 'The wizard of Oz' + 2843: 'I'm singin' in the rain' + 2844: 'Alice in Wonderland' + 2845: 'The wizard of Oz' + 2846: 'I'm singin' in the rain' + 2847: 'Alice in Wonderland' + 2848: 'The wizard of Oz' + 2849: 'I'm singin' in the rain' + 2850: 'Alice in Wonderland' + 2851: 'The wizard of Oz' + 2852: 'I'm singin' in the rain' + 2853: 'Alice in Wonderland' + 2854: 'The wizard of Oz' + 2855: 'I'm singin' in the rain' + 2856: 'Alice in Wonderland' + 2857: 'The wizard of Oz' + 2858: 'I'm singin' in the rain' + 2859: 'Alice in Wonderland' + 2860: 'The wizard of Oz' + 2861: 'I'm singin' in the rain' + 2862: 'Alice in Wonderland' + 2863: 'The wizard of Oz' + 2864: 'I'm singin' in the rain' + 2865: 'Alice in Wonderland' + 2866: 'The wizard of Oz' + 2867: 'I'm singin' in the rain' + 2868: 'Alice in Wonderland' + 2869: 'The wizard of Oz' + 2870: 'I'm singin' in the rain' + 2871: 'Alice in Wonderland' + 2872: 'The wizard of Oz' + 2873: 'I'm singin' in the rain' + 2874: 'Alice in Wonderland' + 2875: 'The wizard of Oz' + 2876: 'I'm singin' in the rain' + 2877: 'Alice in Wonderland' + 2878: 'The wizard of Oz' + 2879: 'I'm singin' in the rain' + 2880: 'Alice in Wonderland' + 2881: 'The wizard of Oz' + 2882: 'I'm singin' in the rain' + 2883: 'Alice in Wonderland' + 2884: 'The wizard of Oz' + 2885: 'I'm singin' in the rain' + 2886: 'Alice in Wonderland' + 2887: 'The wizard of Oz' + 2888: 'I'm singin' in the rain' + 2889: 'Alice in Wonderland' + 2890: 'The wizard of Oz' + 2891: 'I'm singin' in the rain' + 2892: 'Alice in Wonderland' + 2893: 'The wizard of Oz' + 2894: 'I'm singin' in the rain' + 2895: 'Alice in Wonderland' + 2896: 'The wizard of Oz' + 2897: 'I'm singin' in the rain' + 2898: 'Alice in Wonderland' + 2899: 'The wizard of Oz' + 2900: 'I'm singin' in the rain' + 2901: 'Alice in Wonderland' + 2902: 'The wizard of Oz' + 2903: 'I'm singin' in the rain' + 2904: 'Alice in Wonderland' + 2905: 'The wizard of Oz' + 2906: 'I'm singin' in the rain' + 2907: 'Alice in Wonderland' + 2908: 'The wizard of Oz' + 2909: 'I'm singin' in the rain' + 2910: 'Alice in Wonderland' + 2911: 'The wizard of Oz' + 2912: 'I'm singin' in the rain' + 2913: 'Alice in Wonderland' + 2914: 'The wizard of Oz' + 2915: 'I'm singin' in the rain' + 2916: 'Alice in Wonderland' + 2917: 'The wizard of Oz' + 2918: 'I'm singin' in the rain' + 2919: 'Alice in Wonderland' + 2920: 'The wizard of Oz' + 2921: 'I'm singin' in the rain' + 2922: 'Alice in Wonderland' + 2923: 'The wizard of Oz' + 2924: 'I'm singin' in the rain' + 2925: 'Alice in Wonderland' + 2926: 'The wizard of Oz' + 2927: 'I'm singin' in the rain' + 2928: 'Alice in Wonderland' + 2929: 'The wizard of Oz' + 2930: 'I'm singin' in the rain' + 2931: 'Alice in Wonderland' + 2932: 'The wizard of Oz' + 2933: 'I'm singin' in the rain' + 2934: 'Alice in Wonderland' + 2935: 'The wizard of Oz' + 2936: 'I'm singin' in the rain' + 2937: 'Alice in Wonderland' + 2938: 'The wizard of Oz' + 2939: 'I'm singin' in the rain' + 2940: 'Alice in Wonderland' + 2941: 'The wizard of Oz' + 2942: 'I'm singin' in the rain' + 2943: 'Alice in Wonderland' + 2944: 'The wizard of Oz' + 2945: 'I'm singin' in the rain' + 2946: 'Alice in Wonderland' + 2947: 'The wizard of Oz' + 2948: 'I'm singin' in the rain' + 2949: 'Alice in Wonderland' + 2950: 'The wizard of Oz' + 2951: 'I'm singin' in the rain' + 2952: 'Alice in Wonderland' + 2953: 'The wizard of Oz' + 2954: 'I'm singin' in the rain' + 2955: 'Alice in Wonderland' + 2956: 'The wizard of Oz' + 2957: 'I'm singin' in the rain' + 2958: 'Alice in Wonderland' + 2959: 'The wizard of Oz' + 2960: 'I'm singin' in the rain' + 2961: 'Alice in Wonderland' + 2962: 'The wizard of Oz' + 2963: 'I'm singin' in the rain' + 2964: 'Alice in Wonderland' + 2965: 'The wizard of Oz' + 2966: 'I'm singin' in the rain' + 2967: 'Alice in Wonderland' + 2968: 'The wizard of Oz' + 2969: 'I'm singin' in the rain' + 2970: 'Alice in Wonderland' + 2971: 'The wizard of Oz' + 2972: 'I'm singin' in the rain' + 2973: 'Alice in Wonderland' + 2974: 'The wizard of Oz' + 2975: 'I'm singin' in the rain' + 2976: 'Alice in Wonderland' + 2977: 'The wizard of Oz' + 2978: 'I'm singin' in the rain' + 2979: 'Alice in Wonderland' + 2980: 'The wizard of Oz' + 2981: 'I'm singin' in the rain' + 2982: 'Alice in Wonderland' + 2983: 'The wizard of Oz' + 2984: 'I'm singin' in the rain' + 2985: 'Alice in Wonderland' + 2986: 'The wizard of Oz' + 2987: 'I'm singin' in the rain' + 2988: 'Alice in Wonderland' + 2989: 'The wizard of Oz' + 2990: 'I'm singin' in the rain' + 2991: 'Alice in Wonderland' + 2992: 'The wizard of Oz' + 2993: 'I'm singin' in the rain' + 2994: 'Alice in Wonderland' + 2995: 'The wizard of Oz' + 2996: 'I'm singin' in the rain' + 2997: 'Alice in Wonderland' + 2998: 'The wizard of Oz' + 2999: 'I'm singin' in the rain' + 3000: 'Alice in Wonderland' + 3001: 'The wizard of Oz' + 3002: 'I'm singin' in the rain' + 3003: 'Alice in Wonderland' + 3004: 'The wizard of Oz' + 3005: 'I'm singin' in the rain' + 3006: 'Alice in Wonderland' + 3007: 'The wizard of Oz' + 3008: 'I'm singin' in the rain' + 3009: 'Alice in Wonderland' + 3010: 'The wizard of Oz' + 3011: 'I'm singin' in the rain' + 3012: 'Alice in Wonderland' + 3013: 'The wizard of Oz' + 3014: 'I'm singin' in the rain' + 3015: 'Alice in Wonderland' + 3016: 'The wizard of Oz' + 3017: 'I'm singin' in the rain' + 3018: 'Alice in Wonderland' + 3019: 'The wizard of Oz' + 3020: 'I'm singin' in the rain' + 3021: 'Alice in Wonderland' + 3022: 'The wizard of Oz' + 3023: 'I'm singin' in the rain' + 3024: 'Alice in Wonderland' + 3025: 'The wizard of Oz' + 3026: 'I'm singin' in the rain' + 3027: 'Alice in Wonderland' + 3028: 'The wizard of Oz' + 3029: 'I'm singin' in the rain' + 3030: 'Alice in Wonderland' + 3031: 'The wizard of Oz' + 3032: 'I'm singin' in the rain' + 3033: 'Alice in Wonderland' + 3034: 'The wizard of Oz' + 3035: 'I'm singin' in the rain' + 3036: 'Alice in Wonderland' + 3037: 'The wizard of Oz' + 3038: 'I'm singin' in the rain' + 3039: 'Alice in Wonderland' + 3040: 'The wizard of Oz' + 3041: 'I'm singin' in the rain' + 3042: 'Alice in Wonderland' + 3043: 'The wizard of Oz' + 3044: 'I'm singin' in the rain' + 3045: 'Alice in Wonderland' + 3046: 'The wizard of Oz' + 3047: 'I'm singin' in the rain' + 3048: 'Alice in Wonderland' + 3049: 'The wizard of Oz' + 3050: 'I'm singin' in the rain' + 3051: 'Alice in Wonderland' + 3052: 'The wizard of Oz' + 3053: 'I'm singin' in the rain' + 3054: 'Alice in Wonderland' + 3055: 'The wizard of Oz' + 3056: 'I'm singin' in the rain' + 3057: 'Alice in Wonderland' + 3058: 'The wizard of Oz' + 3059: 'I'm singin' in the rain' + 3060: 'Alice in Wonderland' + 3061: 'The wizard of Oz' + 3062: 'I'm singin' in the rain' + 3063: 'Alice in Wonderland' + 3064: 'The wizard of Oz' + 3065: 'I'm singin' in the rain' + 3066: 'Alice in Wonderland' + 3067: 'The wizard of Oz' + 3068: 'I'm singin' in the rain' + 3069: 'Alice in Wonderland' + 3070: 'The wizard of Oz' + 3071: 'I'm singin' in the rain' + 3072: 'Alice in Wonderland' + 3073: 'The wizard of Oz' + 3074: 'I'm singin' in the rain' + 3075: 'Alice in Wonderland' + 3076: 'The wizard of Oz' + 3077: 'I'm singin' in the rain' + 3078: 'Alice in Wonderland' + 3079: 'The wizard of Oz' + 3080: 'I'm singin' in the rain' + 3081: 'Alice in Wonderland' + 3082: 'The wizard of Oz' + 3083: 'I'm singin' in the rain' + 3084: 'Alice in Wonderland' + 3085: 'The wizard of Oz' + 3086: 'I'm singin' in the rain' + 3087: 'Alice in Wonderland' + 3088: 'The wizard of Oz' + 3089: 'I'm singin' in the rain' + 3090: 'Alice in Wonderland' + 3091: 'The wizard of Oz' + 3092: 'I'm singin' in the rain' + 3093: 'Alice in Wonderland' + 3094: 'The wizard of Oz' + 3095: 'I'm singin' in the rain' + 3096: 'Alice in Wonderland' + 3097: 'The wizard of Oz' + 3098: 'I'm singin' in the rain' + 3099: 'Alice in Wonderland' + 3100: 'The wizard of Oz' + 3101: 'I'm singin' in the rain' + 3102: 'Alice in Wonderland' + 3103: 'The wizard of Oz' + 3104: 'I'm singin' in the rain' + 3105: 'Alice in Wonderland' + 3106: 'The wizard of Oz' + 3107: 'I'm singin' in the rain' + 3108: 'Alice in Wonderland' + 3109: 'The wizard of Oz' + 3110: 'I'm singin' in the rain' + 3111: 'Alice in Wonderland' + 3112: 'The wizard of Oz' + 3113: 'I'm singin' in the rain' + 3114: 'Alice in Wonderland' + 3115: 'The wizard of Oz' + 3116: 'I'm singin' in the rain' + 3117: 'Alice in Wonderland' + 3118: 'The wizard of Oz' + 3119: 'I'm singin' in the rain' + 3120: 'Alice in Wonderland' + 3121: 'The wizard of Oz' + 3122: 'I'm singin' in the rain' + 3123: 'Alice in Wonderland' + 3124: 'The wizard of Oz' + 3125: 'I'm singin' in the rain' + 3126: 'Alice in Wonderland' + 3127: 'The wizard of Oz' + 3128: 'I'm singin' in the rain' + 3129: 'Alice in Wonderland' + 3130: 'The wizard of Oz' + 3131: 'I'm singin' in the rain' + 3132: 'Alice in Wonderland' + 3133: 'The wizard of Oz' + 3134: 'I'm singin' in the rain' + 3135: 'Alice in Wonderland' + 3136: 'The wizard of Oz' + 3137: 'I'm singin' in the rain' + 3138: 'Alice in Wonderland' + 3139: 'The wizard of Oz' + 3140: 'I'm singin' in the rain' + 3141: 'Alice in Wonderland' + 3142: 'The wizard of Oz' + 3143: 'I'm singin' in the rain' + 3144: 'Alice in Wonderland' + 3145: 'The wizard of Oz' + 3146: 'I'm singin' in the rain' + 3147: 'Alice in Wonderland' + 3148: 'The wizard of Oz' + 3149: 'I'm singin' in the rain' + 3150: 'Alice in Wonderland' + 3151: 'The wizard of Oz' + 3152: 'I'm singin' in the rain' + 3153: 'Alice in Wonderland' + 3154: 'The wizard of Oz' + 3155: 'I'm singin' in the rain' + 3156: 'Alice in Wonderland' + 3157: 'The wizard of Oz' + 3158: 'I'm singin' in the rain' + 3159: 'Alice in Wonderland' + 3160: 'The wizard of Oz' + 3161: 'I'm singin' in the rain' + 3162: 'Alice in Wonderland' + 3163: 'The wizard of Oz' + 3164: 'I'm singin' in the rain' + 3165: 'Alice in Wonderland' + 3166: 'The wizard of Oz' + 3167: 'I'm singin' in the rain' + 3168: 'Alice in Wonderland' + 3169: 'The wizard of Oz' + 3170: 'I'm singin' in the rain' + 3171: 'Alice in Wonderland' + 3172: 'The wizard of Oz' + 3173: 'I'm singin' in the rain' + 3174: 'Alice in Wonderland' + 3175: 'The wizard of Oz' + 3176: 'I'm singin' in the rain' + 3177: 'Alice in Wonderland' + 3178: 'The wizard of Oz' + 3179: 'I'm singin' in the rain' + 3180: 'Alice in Wonderland' + 3181: 'The wizard of Oz' + 3182: 'I'm singin' in the rain' + 3183: 'Alice in Wonderland' + 3184: 'The wizard of Oz' + 3185: 'I'm singin' in the rain' + 3186: 'Alice in Wonderland' + 3187: 'The wizard of Oz' + 3188: 'I'm singin' in the rain' + 3189: 'Alice in Wonderland' + 3190: 'The wizard of Oz' + 3191: 'I'm singin' in the rain' + 3192: 'Alice in Wonderland' + 3193: 'The wizard of Oz' + 3194: 'I'm singin' in the rain' + 3195: 'Alice in Wonderland' + 3196: 'The wizard of Oz' + 3197: 'I'm singin' in the rain' + 3198: 'Alice in Wonderland' + 3199: 'The wizard of Oz' + 3200: 'I'm singin' in the rain' + 3201: 'Alice in Wonderland' + 3202: 'The wizard of Oz' + 3203: 'I'm singin' in the rain' + 3204: 'Alice in Wonderland' + 3205: 'The wizard of Oz' + 3206: 'I'm singin' in the rain' + 3207: 'Alice in Wonderland' + 3208: 'The wizard of Oz' + 3209: 'I'm singin' in the rain' + 3210: 'Alice in Wonderland' + 3211: 'The wizard of Oz' + 3212: 'I'm singin' in the rain' + 3213: 'Alice in Wonderland' + 3214: 'The wizard of Oz' + 3215: 'I'm singin' in the rain' + 3216: 'Alice in Wonderland' + 3217: 'The wizard of Oz' + 3218: 'I'm singin' in the rain' + 3219: 'Alice in Wonderland' + 3220: 'The wizard of Oz' + 3221: 'I'm singin' in the rain' + 3222: 'Alice in Wonderland' + 3223: 'The wizard of Oz' + 3224: 'I'm singin' in the rain' + 3225: 'Alice in Wonderland' + 3226: 'The wizard of Oz' + 3227: 'I'm singin' in the rain' + 3228: 'Alice in Wonderland' + 3229: 'The wizard of Oz' + 3230: 'I'm singin' in the rain' + 3231: 'Alice in Wonderland' + 3232: 'The wizard of Oz' + 3233: 'I'm singin' in the rain' + 3234: 'Alice in Wonderland' + 3235: 'The wizard of Oz' + 3236: 'I'm singin' in the rain' + 3237: 'Alice in Wonderland' + 3238: 'The wizard of Oz' + 3239: 'I'm singin' in the rain' + 3240: 'Alice in Wonderland' + 3241: 'The wizard of Oz' + 3242: 'I'm singin' in the rain' + 3243: 'Alice in Wonderland' + 3244: 'The wizard of Oz' + 3245: 'I'm singin' in the rain' + 3246: 'Alice in Wonderland' + 3247: 'The wizard of Oz' + 3248: 'I'm singin' in the rain' + 3249: 'Alice in Wonderland' + 3250: 'The wizard of Oz' + 3251: 'I'm singin' in the rain' + 3252: 'Alice in Wonderland' + 3253: 'The wizard of Oz' + 3254: 'I'm singin' in the rain' + 3255: 'Alice in Wonderland' + 3256: 'The wizard of Oz' + 3257: 'I'm singin' in the rain' + 3258: 'Alice in Wonderland' + 3259: 'The wizard of Oz' + 3260: 'I'm singin' in the rain' + 3261: 'Alice in Wonderland' + 3262: 'The wizard of Oz' + 3263: 'I'm singin' in the rain' + 3264: 'Alice in Wonderland' + 3265: 'The wizard of Oz' + 3266: 'I'm singin' in the rain' + 3267: 'Alice in Wonderland' + 3268: 'The wizard of Oz' + 3269: 'I'm singin' in the rain' + 3270: 'Alice in Wonderland' + 3271: 'The wizard of Oz' + 3272: 'I'm singin' in the rain' + 3273: 'Alice in Wonderland' + 3274: 'The wizard of Oz' + 3275: 'I'm singin' in the rain' + 3276: 'Alice in Wonderland' + 3277: 'The wizard of Oz' + 3278: 'I'm singin' in the rain' + 3279: 'Alice in Wonderland' + 3280: 'The wizard of Oz' + 3281: 'I'm singin' in the rain' + 3282: 'Alice in Wonderland' + 3283: 'The wizard of Oz' + 3284: 'I'm singin' in the rain' + 3285: 'Alice in Wonderland' + 3286: 'The wizard of Oz' + 3287: 'I'm singin' in the rain' + 3288: 'Alice in Wonderland' + 3289: 'The wizard of Oz' + 3290: 'I'm singin' in the rain' + 3291: 'Alice in Wonderland' + 3292: 'The wizard of Oz' + 3293: 'I'm singin' in the rain' + 3294: 'Alice in Wonderland' + 3295: 'The wizard of Oz' + 3296: 'I'm singin' in the rain' + 3297: 'Alice in Wonderland' + 3298: 'The wizard of Oz' + 3299: 'I'm singin' in the rain' + 3300: 'Alice in Wonderland' + 3301: 'The wizard of Oz' + 3302: 'I'm singin' in the rain' + 3303: 'Alice in Wonderland' + 3304: 'The wizard of Oz' + 3305: 'I'm singin' in the rain' + 3306: 'Alice in Wonderland' + 3307: 'The wizard of Oz' + 3308: 'I'm singin' in the rain' + 3309: 'Alice in Wonderland' + 3310: 'The wizard of Oz' + 3311: 'I'm singin' in the rain' + 3312: 'Alice in Wonderland' + 3313: 'The wizard of Oz' + 3314: 'I'm singin' in the rain' + 3315: 'Alice in Wonderland' + 3316: 'The wizard of Oz' + 3317: 'I'm singin' in the rain' + 3318: 'Alice in Wonderland' + 3319: 'The wizard of Oz' + 3320: 'I'm singin' in the rain' + 3321: 'Alice in Wonderland' + 3322: 'The wizard of Oz' + 3323: 'I'm singin' in the rain' + 3324: 'Alice in Wonderland' + 3325: 'The wizard of Oz' + 3326: 'I'm singin' in the rain' + 3327: 'Alice in Wonderland' + 3328: 'The wizard of Oz' + 3329: 'I'm singin' in the rain' + 3330: 'Alice in Wonderland' + 3331: 'The wizard of Oz' + 3332: 'I'm singin' in the rain' + 3333: 'Alice in Wonderland' + 3334: 'The wizard of Oz' + 3335: 'I'm singin' in the rain' + 3336: 'Alice in Wonderland' + 3337: 'The wizard of Oz' + 3338: 'I'm singin' in the rain' + 3339: 'Alice in Wonderland' + 3340: 'The wizard of Oz' + 3341: 'I'm singin' in the rain' + 3342: 'Alice in Wonderland' + 3343: 'The wizard of Oz' + 3344: 'I'm singin' in the rain' + 3345: 'Alice in Wonderland' + 3346: 'The wizard of Oz' + 3347: 'I'm singin' in the rain' + 3348: 'Alice in Wonderland' + 3349: 'The wizard of Oz' + 3350: 'I'm singin' in the rain' + 3351: 'Alice in Wonderland' + 3352: 'The wizard of Oz' + 3353: 'I'm singin' in the rain' + 3354: 'Alice in Wonderland' + 3355: 'The wizard of Oz' + 3356: 'I'm singin' in the rain' + 3357: 'Alice in Wonderland' + 3358: 'The wizard of Oz' + 3359: 'I'm singin' in the rain' + 3360: 'Alice in Wonderland' + 3361: 'The wizard of Oz' + 3362: 'I'm singin' in the rain' + 3363: 'Alice in Wonderland' + 3364: 'The wizard of Oz' + 3365: 'I'm singin' in the rain' + 3366: 'Alice in Wonderland' + 3367: 'The wizard of Oz' + 3368: 'I'm singin' in the rain' + 3369: 'Alice in Wonderland' + 3370: 'The wizard of Oz' + 3371: 'I'm singin' in the rain' + 3372: 'Alice in Wonderland' + 3373: 'The wizard of Oz' + 3374: 'I'm singin' in the rain' + 3375: 'Alice in Wonderland' + 3376: 'The wizard of Oz' + 3377: 'I'm singin' in the rain' + 3378: 'Alice in Wonderland' + 3379: 'The wizard of Oz' + 3380: 'I'm singin' in the rain' + 3381: 'Alice in Wonderland' + 3382: 'The wizard of Oz' + 3383: 'I'm singin' in the rain' + 3384: 'Alice in Wonderland' + 3385: 'The wizard of Oz' + 3386: 'I'm singin' in the rain' + 3387: 'Alice in Wonderland' + 3388: 'The wizard of Oz' + 3389: 'I'm singin' in the rain' + 3390: 'Alice in Wonderland' + 3391: 'The wizard of Oz' + 3392: 'I'm singin' in the rain' + 3393: 'Alice in Wonderland' + 3394: 'The wizard of Oz' + 3395: 'I'm singin' in the rain' + 3396: 'Alice in Wonderland' + 3397: 'The wizard of Oz' + 3398: 'I'm singin' in the rain' + 3399: 'Alice in Wonderland' + 3400: 'The wizard of Oz' + 3401: 'I'm singin' in the rain' + 3402: 'Alice in Wonderland' + 3403: 'The wizard of Oz' + 3404: 'I'm singin' in the rain' + 3405: 'Alice in Wonderland' + 3406: 'The wizard of Oz' + 3407: 'I'm singin' in the rain' + 3408: 'Alice in Wonderland' + 3409: 'The wizard of Oz' + 3410: 'I'm singin' in the rain' + 3411: 'Alice in Wonderland' + 3412: 'The wizard of Oz' + 3413: 'I'm singin' in the rain' + 3414: 'Alice in Wonderland' + 3415: 'The wizard of Oz' + 3416: 'I'm singin' in the rain' + 3417: 'Alice in Wonderland' + 3418: 'The wizard of Oz' + 3419: 'I'm singin' in the rain' + 3420: 'Alice in Wonderland' + 3421: 'The wizard of Oz' + 3422: 'I'm singin' in the rain' + 3423: 'Alice in Wonderland' + 3424: 'The wizard of Oz' + 3425: 'I'm singin' in the rain' + 3426: 'Alice in Wonderland' + 3427: 'The wizard of Oz' + 3428: 'I'm singin' in the rain' + 3429: 'Alice in Wonderland' + 3430: 'The wizard of Oz' + 3431: 'I'm singin' in the rain' + 3432: 'Alice in Wonderland' + 3433: 'The wizard of Oz' + 3434: 'I'm singin' in the rain' + 3435: 'Alice in Wonderland' + 3436: 'The wizard of Oz' + 3437: 'I'm singin' in the rain' + 3438: 'Alice in Wonderland' + 3439: 'The wizard of Oz' + 3440: 'I'm singin' in the rain' + 3441: 'Alice in Wonderland' + 3442: 'The wizard of Oz' + 3443: 'I'm singin' in the rain' + 3444: 'Alice in Wonderland' + 3445: 'The wizard of Oz' + 3446: 'I'm singin' in the rain' + 3447: 'Alice in Wonderland' + 3448: 'The wizard of Oz' + 3449: 'I'm singin' in the rain' + 3450: 'Alice in Wonderland' + 3451: 'The wizard of Oz' + 3452: 'I'm singin' in the rain' + 3453: 'Alice in Wonderland' + 3454: 'The wizard of Oz' + 3455: 'I'm singin' in the rain' + 3456: 'Alice in Wonderland' + 3457: 'The wizard of Oz' + 3458: 'I'm singin' in the rain' + 3459: 'Alice in Wonderland' + 3460: 'The wizard of Oz' + 3461: 'I'm singin' in the rain' + 3462: 'Alice in Wonderland' + 3463: 'The wizard of Oz' + 3464: 'I'm singin' in the rain' + 3465: 'Alice in Wonderland' + 3466: 'The wizard of Oz' + 3467: 'I'm singin' in the rain' + 3468: 'Alice in Wonderland' + 3469: 'The wizard of Oz' + 3470: 'I'm singin' in the rain' + 3471: 'Alice in Wonderland' + 3472: 'The wizard of Oz' + 3473: 'I'm singin' in the rain' + 3474: 'Alice in Wonderland' + 3475: 'The wizard of Oz' + 3476: 'I'm singin' in the rain' + 3477: 'Alice in Wonderland' + 3478: 'The wizard of Oz' + 3479: 'I'm singin' in the rain' + 3480: 'Alice in Wonderland' + 3481: 'The wizard of Oz' + 3482: 'I'm singin' in the rain' + 3483: 'Alice in Wonderland' + 3484: 'The wizard of Oz' + 3485: 'I'm singin' in the rain' + 3486: 'Alice in Wonderland' + 3487: 'The wizard of Oz' + 3488: 'I'm singin' in the rain' + 3489: 'Alice in Wonderland' + 3490: 'The wizard of Oz' + 3491: 'I'm singin' in the rain' + 3492: 'Alice in Wonderland' + 3493: 'The wizard of Oz' + 3494: 'I'm singin' in the rain' + 3495: 'Alice in Wonderland' + 3496: 'The wizard of Oz' + 3497: 'I'm singin' in the rain' + 3498: 'Alice in Wonderland' + 3499: 'The wizard of Oz' diff --git a/akregator/src/mk4storage/metakit/tests/ok/l03.txt b/akregator/src/mk4storage/metakit/tests/ok/l03.txt new file mode 100644 index 000000000..82e31887f --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l03.txt @@ -0,0 +1,2 @@ +>>> Force sections in storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/l03a.txt b/akregator/src/mk4storage/metakit/tests/ok/l03a.txt new file mode 100644 index 000000000..daff458fa --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l03a.txt @@ -0,0 +1,1503 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 500 rows = p1:V + 0: subview 'p1' + VIEW 1 rows = p2:I + 0: 9000 + 1: subview 'p1' + VIEW 1 rows = p2:I + 0: 9001 + 2: subview 'p1' + VIEW 1 rows = p2:I + 0: 9002 + 3: subview 'p1' + VIEW 1 rows = p2:I + 0: 9003 + 4: subview 'p1' + VIEW 1 rows = p2:I + 0: 9004 + 5: subview 'p1' + VIEW 1 rows = p2:I + 0: 9005 + 6: subview 'p1' + VIEW 1 rows = p2:I + 0: 9006 + 7: subview 'p1' + VIEW 1 rows = p2:I + 0: 9007 + 8: subview 'p1' + VIEW 1 rows = p2:I + 0: 9008 + 9: subview 'p1' + VIEW 1 rows = p2:I + 0: 9009 + 10: subview 'p1' + VIEW 1 rows = p2:I + 0: 9010 + 11: subview 'p1' + VIEW 1 rows = p2:I + 0: 9011 + 12: subview 'p1' + VIEW 1 rows = p2:I + 0: 9012 + 13: subview 'p1' + VIEW 1 rows = p2:I + 0: 9013 + 14: subview 'p1' + VIEW 1 rows = p2:I + 0: 9014 + 15: subview 'p1' + VIEW 1 rows = p2:I + 0: 9015 + 16: subview 'p1' + VIEW 1 rows = p2:I + 0: 9016 + 17: subview 'p1' + VIEW 1 rows = p2:I + 0: 9017 + 18: subview 'p1' + VIEW 1 rows = p2:I + 0: 9018 + 19: subview 'p1' + VIEW 1 rows = p2:I + 0: 9019 + 20: subview 'p1' + VIEW 1 rows = p2:I + 0: 9020 + 21: subview 'p1' + VIEW 1 rows = p2:I + 0: 9021 + 22: subview 'p1' + VIEW 1 rows = p2:I + 0: 9022 + 23: subview 'p1' + VIEW 1 rows = p2:I + 0: 9023 + 24: subview 'p1' + VIEW 1 rows = p2:I + 0: 9024 + 25: subview 'p1' + VIEW 1 rows = p2:I + 0: 9025 + 26: subview 'p1' + VIEW 1 rows = p2:I + 0: 9026 + 27: subview 'p1' + VIEW 1 rows = p2:I + 0: 9027 + 28: subview 'p1' + VIEW 1 rows = p2:I + 0: 9028 + 29: subview 'p1' + VIEW 1 rows = p2:I + 0: 9029 + 30: subview 'p1' + VIEW 1 rows = p2:I + 0: 9030 + 31: subview 'p1' + VIEW 1 rows = p2:I + 0: 9031 + 32: subview 'p1' + VIEW 1 rows = p2:I + 0: 9032 + 33: subview 'p1' + VIEW 1 rows = p2:I + 0: 9033 + 34: subview 'p1' + VIEW 1 rows = p2:I + 0: 9034 + 35: subview 'p1' + VIEW 1 rows = p2:I + 0: 9035 + 36: subview 'p1' + VIEW 1 rows = p2:I + 0: 9036 + 37: subview 'p1' + VIEW 1 rows = p2:I + 0: 9037 + 38: subview 'p1' + VIEW 1 rows = p2:I + 0: 9038 + 39: subview 'p1' + VIEW 1 rows = p2:I + 0: 9039 + 40: subview 'p1' + VIEW 1 rows = p2:I + 0: 9040 + 41: subview 'p1' + VIEW 1 rows = p2:I + 0: 9041 + 42: subview 'p1' + VIEW 1 rows = p2:I + 0: 9042 + 43: subview 'p1' + VIEW 1 rows = p2:I + 0: 9043 + 44: subview 'p1' + VIEW 1 rows = p2:I + 0: 9044 + 45: subview 'p1' + VIEW 1 rows = p2:I + 0: 9045 + 46: subview 'p1' + VIEW 1 rows = p2:I + 0: 9046 + 47: subview 'p1' + VIEW 1 rows = p2:I + 0: 9047 + 48: subview 'p1' + VIEW 1 rows = p2:I + 0: 9048 + 49: subview 'p1' + VIEW 1 rows = p2:I + 0: 9049 + 50: subview 'p1' + VIEW 1 rows = p2:I + 0: 9050 + 51: subview 'p1' + VIEW 1 rows = p2:I + 0: 9051 + 52: subview 'p1' + VIEW 1 rows = p2:I + 0: 9052 + 53: subview 'p1' + VIEW 1 rows = p2:I + 0: 9053 + 54: subview 'p1' + VIEW 1 rows = p2:I + 0: 9054 + 55: subview 'p1' + VIEW 1 rows = p2:I + 0: 9055 + 56: subview 'p1' + VIEW 1 rows = p2:I + 0: 9056 + 57: subview 'p1' + VIEW 1 rows = p2:I + 0: 9057 + 58: subview 'p1' + VIEW 1 rows = p2:I + 0: 9058 + 59: subview 'p1' + VIEW 1 rows = p2:I + 0: 9059 + 60: subview 'p1' + VIEW 1 rows = p2:I + 0: 9060 + 61: subview 'p1' + VIEW 1 rows = p2:I + 0: 9061 + 62: subview 'p1' + VIEW 1 rows = p2:I + 0: 9062 + 63: subview 'p1' + VIEW 1 rows = p2:I + 0: 9063 + 64: subview 'p1' + VIEW 1 rows = p2:I + 0: 9064 + 65: subview 'p1' + VIEW 1 rows = p2:I + 0: 9065 + 66: subview 'p1' + VIEW 1 rows = p2:I + 0: 9066 + 67: subview 'p1' + VIEW 1 rows = p2:I + 0: 9067 + 68: subview 'p1' + VIEW 1 rows = p2:I + 0: 9068 + 69: subview 'p1' + VIEW 1 rows = p2:I + 0: 9069 + 70: subview 'p1' + VIEW 1 rows = p2:I + 0: 9070 + 71: subview 'p1' + VIEW 1 rows = p2:I + 0: 9071 + 72: subview 'p1' + VIEW 1 rows = p2:I + 0: 9072 + 73: subview 'p1' + VIEW 1 rows = p2:I + 0: 9073 + 74: subview 'p1' + VIEW 1 rows = p2:I + 0: 9074 + 75: subview 'p1' + VIEW 1 rows = p2:I + 0: 9075 + 76: subview 'p1' + VIEW 1 rows = p2:I + 0: 9076 + 77: subview 'p1' + VIEW 1 rows = p2:I + 0: 9077 + 78: subview 'p1' + VIEW 1 rows = p2:I + 0: 9078 + 79: subview 'p1' + VIEW 1 rows = p2:I + 0: 9079 + 80: subview 'p1' + VIEW 1 rows = p2:I + 0: 9080 + 81: subview 'p1' + VIEW 1 rows = p2:I + 0: 9081 + 82: subview 'p1' + VIEW 1 rows = p2:I + 0: 9082 + 83: subview 'p1' + VIEW 1 rows = p2:I + 0: 9083 + 84: subview 'p1' + VIEW 1 rows = p2:I + 0: 9084 + 85: subview 'p1' + VIEW 1 rows = p2:I + 0: 9085 + 86: subview 'p1' + VIEW 1 rows = p2:I + 0: 9086 + 87: subview 'p1' + VIEW 1 rows = p2:I + 0: 9087 + 88: subview 'p1' + VIEW 1 rows = p2:I + 0: 9088 + 89: subview 'p1' + VIEW 1 rows = p2:I + 0: 9089 + 90: subview 'p1' + VIEW 1 rows = p2:I + 0: 9090 + 91: subview 'p1' + VIEW 1 rows = p2:I + 0: 9091 + 92: subview 'p1' + VIEW 1 rows = p2:I + 0: 9092 + 93: subview 'p1' + VIEW 1 rows = p2:I + 0: 9093 + 94: subview 'p1' + VIEW 1 rows = p2:I + 0: 9094 + 95: subview 'p1' + VIEW 1 rows = p2:I + 0: 9095 + 96: subview 'p1' + VIEW 1 rows = p2:I + 0: 9096 + 97: subview 'p1' + VIEW 1 rows = p2:I + 0: 9097 + 98: subview 'p1' + VIEW 1 rows = p2:I + 0: 9098 + 99: subview 'p1' + VIEW 1 rows = p2:I + 0: 9099 + 100: subview 'p1' + VIEW 1 rows = p2:I + 0: 9100 + 101: subview 'p1' + VIEW 1 rows = p2:I + 0: 9101 + 102: subview 'p1' + VIEW 1 rows = p2:I + 0: 9102 + 103: subview 'p1' + VIEW 1 rows = p2:I + 0: 9103 + 104: subview 'p1' + VIEW 1 rows = p2:I + 0: 9104 + 105: subview 'p1' + VIEW 1 rows = p2:I + 0: 9105 + 106: subview 'p1' + VIEW 1 rows = p2:I + 0: 9106 + 107: subview 'p1' + VIEW 1 rows = p2:I + 0: 9107 + 108: subview 'p1' + VIEW 1 rows = p2:I + 0: 9108 + 109: subview 'p1' + VIEW 1 rows = p2:I + 0: 9109 + 110: subview 'p1' + VIEW 1 rows = p2:I + 0: 9110 + 111: subview 'p1' + VIEW 1 rows = p2:I + 0: 9111 + 112: subview 'p1' + VIEW 1 rows = p2:I + 0: 9112 + 113: subview 'p1' + VIEW 1 rows = p2:I + 0: 9113 + 114: subview 'p1' + VIEW 1 rows = p2:I + 0: 9114 + 115: subview 'p1' + VIEW 1 rows = p2:I + 0: 9115 + 116: subview 'p1' + VIEW 1 rows = p2:I + 0: 9116 + 117: subview 'p1' + VIEW 1 rows = p2:I + 0: 9117 + 118: subview 'p1' + VIEW 1 rows = p2:I + 0: 9118 + 119: subview 'p1' + VIEW 1 rows = p2:I + 0: 9119 + 120: subview 'p1' + VIEW 1 rows = p2:I + 0: 9120 + 121: subview 'p1' + VIEW 1 rows = p2:I + 0: 9121 + 122: subview 'p1' + VIEW 1 rows = p2:I + 0: 9122 + 123: subview 'p1' + VIEW 1 rows = p2:I + 0: 9123 + 124: subview 'p1' + VIEW 1 rows = p2:I + 0: 9124 + 125: subview 'p1' + VIEW 1 rows = p2:I + 0: 9125 + 126: subview 'p1' + VIEW 1 rows = p2:I + 0: 9126 + 127: subview 'p1' + VIEW 1 rows = p2:I + 0: 9127 + 128: subview 'p1' + VIEW 1 rows = p2:I + 0: 9128 + 129: subview 'p1' + VIEW 1 rows = p2:I + 0: 9129 + 130: subview 'p1' + VIEW 1 rows = p2:I + 0: 9130 + 131: subview 'p1' + VIEW 1 rows = p2:I + 0: 9131 + 132: subview 'p1' + VIEW 1 rows = p2:I + 0: 9132 + 133: subview 'p1' + VIEW 1 rows = p2:I + 0: 9133 + 134: subview 'p1' + VIEW 1 rows = p2:I + 0: 9134 + 135: subview 'p1' + VIEW 1 rows = p2:I + 0: 9135 + 136: subview 'p1' + VIEW 1 rows = p2:I + 0: 9136 + 137: subview 'p1' + VIEW 1 rows = p2:I + 0: 9137 + 138: subview 'p1' + VIEW 1 rows = p2:I + 0: 9138 + 139: subview 'p1' + VIEW 1 rows = p2:I + 0: 9139 + 140: subview 'p1' + VIEW 1 rows = p2:I + 0: 9140 + 141: subview 'p1' + VIEW 1 rows = p2:I + 0: 9141 + 142: subview 'p1' + VIEW 1 rows = p2:I + 0: 9142 + 143: subview 'p1' + VIEW 1 rows = p2:I + 0: 9143 + 144: subview 'p1' + VIEW 1 rows = p2:I + 0: 9144 + 145: subview 'p1' + VIEW 1 rows = p2:I + 0: 9145 + 146: subview 'p1' + VIEW 1 rows = p2:I + 0: 9146 + 147: subview 'p1' + VIEW 1 rows = p2:I + 0: 9147 + 148: subview 'p1' + VIEW 1 rows = p2:I + 0: 9148 + 149: subview 'p1' + VIEW 1 rows = p2:I + 0: 9149 + 150: subview 'p1' + VIEW 1 rows = p2:I + 0: 9150 + 151: subview 'p1' + VIEW 1 rows = p2:I + 0: 9151 + 152: subview 'p1' + VIEW 1 rows = p2:I + 0: 9152 + 153: subview 'p1' + VIEW 1 rows = p2:I + 0: 9153 + 154: subview 'p1' + VIEW 1 rows = p2:I + 0: 9154 + 155: subview 'p1' + VIEW 1 rows = p2:I + 0: 9155 + 156: subview 'p1' + VIEW 1 rows = p2:I + 0: 9156 + 157: subview 'p1' + VIEW 1 rows = p2:I + 0: 9157 + 158: subview 'p1' + VIEW 1 rows = p2:I + 0: 9158 + 159: subview 'p1' + VIEW 1 rows = p2:I + 0: 9159 + 160: subview 'p1' + VIEW 1 rows = p2:I + 0: 9160 + 161: subview 'p1' + VIEW 1 rows = p2:I + 0: 9161 + 162: subview 'p1' + VIEW 1 rows = p2:I + 0: 9162 + 163: subview 'p1' + VIEW 1 rows = p2:I + 0: 9163 + 164: subview 'p1' + VIEW 1 rows = p2:I + 0: 9164 + 165: subview 'p1' + VIEW 1 rows = p2:I + 0: 9165 + 166: subview 'p1' + VIEW 1 rows = p2:I + 0: 9166 + 167: subview 'p1' + VIEW 1 rows = p2:I + 0: 9167 + 168: subview 'p1' + VIEW 1 rows = p2:I + 0: 9168 + 169: subview 'p1' + VIEW 1 rows = p2:I + 0: 9169 + 170: subview 'p1' + VIEW 1 rows = p2:I + 0: 9170 + 171: subview 'p1' + VIEW 1 rows = p2:I + 0: 9171 + 172: subview 'p1' + VIEW 1 rows = p2:I + 0: 9172 + 173: subview 'p1' + VIEW 1 rows = p2:I + 0: 9173 + 174: subview 'p1' + VIEW 1 rows = p2:I + 0: 9174 + 175: subview 'p1' + VIEW 1 rows = p2:I + 0: 9175 + 176: subview 'p1' + VIEW 1 rows = p2:I + 0: 9176 + 177: subview 'p1' + VIEW 1 rows = p2:I + 0: 9177 + 178: subview 'p1' + VIEW 1 rows = p2:I + 0: 9178 + 179: subview 'p1' + VIEW 1 rows = p2:I + 0: 9179 + 180: subview 'p1' + VIEW 1 rows = p2:I + 0: 9180 + 181: subview 'p1' + VIEW 1 rows = p2:I + 0: 9181 + 182: subview 'p1' + VIEW 1 rows = p2:I + 0: 9182 + 183: subview 'p1' + VIEW 1 rows = p2:I + 0: 9183 + 184: subview 'p1' + VIEW 1 rows = p2:I + 0: 9184 + 185: subview 'p1' + VIEW 1 rows = p2:I + 0: 9185 + 186: subview 'p1' + VIEW 1 rows = p2:I + 0: 9186 + 187: subview 'p1' + VIEW 1 rows = p2:I + 0: 9187 + 188: subview 'p1' + VIEW 1 rows = p2:I + 0: 9188 + 189: subview 'p1' + VIEW 1 rows = p2:I + 0: 9189 + 190: subview 'p1' + VIEW 1 rows = p2:I + 0: 9190 + 191: subview 'p1' + VIEW 1 rows = p2:I + 0: 9191 + 192: subview 'p1' + VIEW 1 rows = p2:I + 0: 9192 + 193: subview 'p1' + VIEW 1 rows = p2:I + 0: 9193 + 194: subview 'p1' + VIEW 1 rows = p2:I + 0: 9194 + 195: subview 'p1' + VIEW 1 rows = p2:I + 0: 9195 + 196: subview 'p1' + VIEW 1 rows = p2:I + 0: 9196 + 197: subview 'p1' + VIEW 1 rows = p2:I + 0: 9197 + 198: subview 'p1' + VIEW 1 rows = p2:I + 0: 9198 + 199: subview 'p1' + VIEW 1 rows = p2:I + 0: 9199 + 200: subview 'p1' + VIEW 1 rows = p2:I + 0: 9200 + 201: subview 'p1' + VIEW 1 rows = p2:I + 0: 9201 + 202: subview 'p1' + VIEW 1 rows = p2:I + 0: 9202 + 203: subview 'p1' + VIEW 1 rows = p2:I + 0: 9203 + 204: subview 'p1' + VIEW 1 rows = p2:I + 0: 9204 + 205: subview 'p1' + VIEW 1 rows = p2:I + 0: 9205 + 206: subview 'p1' + VIEW 1 rows = p2:I + 0: 9206 + 207: subview 'p1' + VIEW 1 rows = p2:I + 0: 9207 + 208: subview 'p1' + VIEW 1 rows = p2:I + 0: 9208 + 209: subview 'p1' + VIEW 1 rows = p2:I + 0: 9209 + 210: subview 'p1' + VIEW 1 rows = p2:I + 0: 9210 + 211: subview 'p1' + VIEW 1 rows = p2:I + 0: 9211 + 212: subview 'p1' + VIEW 1 rows = p2:I + 0: 9212 + 213: subview 'p1' + VIEW 1 rows = p2:I + 0: 9213 + 214: subview 'p1' + VIEW 1 rows = p2:I + 0: 9214 + 215: subview 'p1' + VIEW 1 rows = p2:I + 0: 9215 + 216: subview 'p1' + VIEW 1 rows = p2:I + 0: 9216 + 217: subview 'p1' + VIEW 1 rows = p2:I + 0: 9217 + 218: subview 'p1' + VIEW 1 rows = p2:I + 0: 9218 + 219: subview 'p1' + VIEW 1 rows = p2:I + 0: 9219 + 220: subview 'p1' + VIEW 1 rows = p2:I + 0: 9220 + 221: subview 'p1' + VIEW 1 rows = p2:I + 0: 9221 + 222: subview 'p1' + VIEW 1 rows = p2:I + 0: 9222 + 223: subview 'p1' + VIEW 1 rows = p2:I + 0: 9223 + 224: subview 'p1' + VIEW 1 rows = p2:I + 0: 9224 + 225: subview 'p1' + VIEW 1 rows = p2:I + 0: 9225 + 226: subview 'p1' + VIEW 1 rows = p2:I + 0: 9226 + 227: subview 'p1' + VIEW 1 rows = p2:I + 0: 9227 + 228: subview 'p1' + VIEW 1 rows = p2:I + 0: 9228 + 229: subview 'p1' + VIEW 1 rows = p2:I + 0: 9229 + 230: subview 'p1' + VIEW 1 rows = p2:I + 0: 9230 + 231: subview 'p1' + VIEW 1 rows = p2:I + 0: 9231 + 232: subview 'p1' + VIEW 1 rows = p2:I + 0: 9232 + 233: subview 'p1' + VIEW 1 rows = p2:I + 0: 9233 + 234: subview 'p1' + VIEW 1 rows = p2:I + 0: 9234 + 235: subview 'p1' + VIEW 1 rows = p2:I + 0: 9235 + 236: subview 'p1' + VIEW 1 rows = p2:I + 0: 9236 + 237: subview 'p1' + VIEW 1 rows = p2:I + 0: 9237 + 238: subview 'p1' + VIEW 1 rows = p2:I + 0: 9238 + 239: subview 'p1' + VIEW 1 rows = p2:I + 0: 9239 + 240: subview 'p1' + VIEW 1 rows = p2:I + 0: 9240 + 241: subview 'p1' + VIEW 1 rows = p2:I + 0: 9241 + 242: subview 'p1' + VIEW 1 rows = p2:I + 0: 9242 + 243: subview 'p1' + VIEW 1 rows = p2:I + 0: 9243 + 244: subview 'p1' + VIEW 1 rows = p2:I + 0: 9244 + 245: subview 'p1' + VIEW 1 rows = p2:I + 0: 9245 + 246: subview 'p1' + VIEW 1 rows = p2:I + 0: 9246 + 247: subview 'p1' + VIEW 1 rows = p2:I + 0: 9247 + 248: subview 'p1' + VIEW 1 rows = p2:I + 0: 9248 + 249: subview 'p1' + VIEW 1 rows = p2:I + 0: 9249 + 250: subview 'p1' + VIEW 1 rows = p2:I + 0: 9250 + 251: subview 'p1' + VIEW 1 rows = p2:I + 0: 9251 + 252: subview 'p1' + VIEW 1 rows = p2:I + 0: 9252 + 253: subview 'p1' + VIEW 1 rows = p2:I + 0: 9253 + 254: subview 'p1' + VIEW 1 rows = p2:I + 0: 9254 + 255: subview 'p1' + VIEW 1 rows = p2:I + 0: 9255 + 256: subview 'p1' + VIEW 1 rows = p2:I + 0: 9256 + 257: subview 'p1' + VIEW 1 rows = p2:I + 0: 9257 + 258: subview 'p1' + VIEW 1 rows = p2:I + 0: 9258 + 259: subview 'p1' + VIEW 1 rows = p2:I + 0: 9259 + 260: subview 'p1' + VIEW 1 rows = p2:I + 0: 9260 + 261: subview 'p1' + VIEW 1 rows = p2:I + 0: 9261 + 262: subview 'p1' + VIEW 1 rows = p2:I + 0: 9262 + 263: subview 'p1' + VIEW 1 rows = p2:I + 0: 9263 + 264: subview 'p1' + VIEW 1 rows = p2:I + 0: 9264 + 265: subview 'p1' + VIEW 1 rows = p2:I + 0: 9265 + 266: subview 'p1' + VIEW 1 rows = p2:I + 0: 9266 + 267: subview 'p1' + VIEW 1 rows = p2:I + 0: 9267 + 268: subview 'p1' + VIEW 1 rows = p2:I + 0: 9268 + 269: subview 'p1' + VIEW 1 rows = p2:I + 0: 9269 + 270: subview 'p1' + VIEW 1 rows = p2:I + 0: 9270 + 271: subview 'p1' + VIEW 1 rows = p2:I + 0: 9271 + 272: subview 'p1' + VIEW 1 rows = p2:I + 0: 9272 + 273: subview 'p1' + VIEW 1 rows = p2:I + 0: 9273 + 274: subview 'p1' + VIEW 1 rows = p2:I + 0: 9274 + 275: subview 'p1' + VIEW 1 rows = p2:I + 0: 9275 + 276: subview 'p1' + VIEW 1 rows = p2:I + 0: 9276 + 277: subview 'p1' + VIEW 1 rows = p2:I + 0: 9277 + 278: subview 'p1' + VIEW 1 rows = p2:I + 0: 9278 + 279: subview 'p1' + VIEW 1 rows = p2:I + 0: 9279 + 280: subview 'p1' + VIEW 1 rows = p2:I + 0: 9280 + 281: subview 'p1' + VIEW 1 rows = p2:I + 0: 9281 + 282: subview 'p1' + VIEW 1 rows = p2:I + 0: 9282 + 283: subview 'p1' + VIEW 1 rows = p2:I + 0: 9283 + 284: subview 'p1' + VIEW 1 rows = p2:I + 0: 9284 + 285: subview 'p1' + VIEW 1 rows = p2:I + 0: 9285 + 286: subview 'p1' + VIEW 1 rows = p2:I + 0: 9286 + 287: subview 'p1' + VIEW 1 rows = p2:I + 0: 9287 + 288: subview 'p1' + VIEW 1 rows = p2:I + 0: 9288 + 289: subview 'p1' + VIEW 1 rows = p2:I + 0: 9289 + 290: subview 'p1' + VIEW 1 rows = p2:I + 0: 9290 + 291: subview 'p1' + VIEW 1 rows = p2:I + 0: 9291 + 292: subview 'p1' + VIEW 1 rows = p2:I + 0: 9292 + 293: subview 'p1' + VIEW 1 rows = p2:I + 0: 9293 + 294: subview 'p1' + VIEW 1 rows = p2:I + 0: 9294 + 295: subview 'p1' + VIEW 1 rows = p2:I + 0: 9295 + 296: subview 'p1' + VIEW 1 rows = p2:I + 0: 9296 + 297: subview 'p1' + VIEW 1 rows = p2:I + 0: 9297 + 298: subview 'p1' + VIEW 1 rows = p2:I + 0: 9298 + 299: subview 'p1' + VIEW 1 rows = p2:I + 0: 9299 + 300: subview 'p1' + VIEW 1 rows = p2:I + 0: 9300 + 301: subview 'p1' + VIEW 1 rows = p2:I + 0: 9301 + 302: subview 'p1' + VIEW 1 rows = p2:I + 0: 9302 + 303: subview 'p1' + VIEW 1 rows = p2:I + 0: 9303 + 304: subview 'p1' + VIEW 1 rows = p2:I + 0: 9304 + 305: subview 'p1' + VIEW 1 rows = p2:I + 0: 9305 + 306: subview 'p1' + VIEW 1 rows = p2:I + 0: 9306 + 307: subview 'p1' + VIEW 1 rows = p2:I + 0: 9307 + 308: subview 'p1' + VIEW 1 rows = p2:I + 0: 9308 + 309: subview 'p1' + VIEW 1 rows = p2:I + 0: 9309 + 310: subview 'p1' + VIEW 1 rows = p2:I + 0: 9310 + 311: subview 'p1' + VIEW 1 rows = p2:I + 0: 9311 + 312: subview 'p1' + VIEW 1 rows = p2:I + 0: 9312 + 313: subview 'p1' + VIEW 1 rows = p2:I + 0: 9313 + 314: subview 'p1' + VIEW 1 rows = p2:I + 0: 9314 + 315: subview 'p1' + VIEW 1 rows = p2:I + 0: 9315 + 316: subview 'p1' + VIEW 1 rows = p2:I + 0: 9316 + 317: subview 'p1' + VIEW 1 rows = p2:I + 0: 9317 + 318: subview 'p1' + VIEW 1 rows = p2:I + 0: 9318 + 319: subview 'p1' + VIEW 1 rows = p2:I + 0: 9319 + 320: subview 'p1' + VIEW 1 rows = p2:I + 0: 9320 + 321: subview 'p1' + VIEW 1 rows = p2:I + 0: 9321 + 322: subview 'p1' + VIEW 1 rows = p2:I + 0: 9322 + 323: subview 'p1' + VIEW 1 rows = p2:I + 0: 9323 + 324: subview 'p1' + VIEW 1 rows = p2:I + 0: 9324 + 325: subview 'p1' + VIEW 1 rows = p2:I + 0: 9325 + 326: subview 'p1' + VIEW 1 rows = p2:I + 0: 9326 + 327: subview 'p1' + VIEW 1 rows = p2:I + 0: 9327 + 328: subview 'p1' + VIEW 1 rows = p2:I + 0: 9328 + 329: subview 'p1' + VIEW 1 rows = p2:I + 0: 9329 + 330: subview 'p1' + VIEW 1 rows = p2:I + 0: 9330 + 331: subview 'p1' + VIEW 1 rows = p2:I + 0: 9331 + 332: subview 'p1' + VIEW 1 rows = p2:I + 0: 9332 + 333: subview 'p1' + VIEW 1 rows = p2:I + 0: 9333 + 334: subview 'p1' + VIEW 1 rows = p2:I + 0: 9334 + 335: subview 'p1' + VIEW 1 rows = p2:I + 0: 9335 + 336: subview 'p1' + VIEW 1 rows = p2:I + 0: 9336 + 337: subview 'p1' + VIEW 1 rows = p2:I + 0: 9337 + 338: subview 'p1' + VIEW 1 rows = p2:I + 0: 9338 + 339: subview 'p1' + VIEW 1 rows = p2:I + 0: 9339 + 340: subview 'p1' + VIEW 1 rows = p2:I + 0: 9340 + 341: subview 'p1' + VIEW 1 rows = p2:I + 0: 9341 + 342: subview 'p1' + VIEW 1 rows = p2:I + 0: 9342 + 343: subview 'p1' + VIEW 1 rows = p2:I + 0: 9343 + 344: subview 'p1' + VIEW 1 rows = p2:I + 0: 9344 + 345: subview 'p1' + VIEW 1 rows = p2:I + 0: 9345 + 346: subview 'p1' + VIEW 1 rows = p2:I + 0: 9346 + 347: subview 'p1' + VIEW 1 rows = p2:I + 0: 9347 + 348: subview 'p1' + VIEW 1 rows = p2:I + 0: 9348 + 349: subview 'p1' + VIEW 1 rows = p2:I + 0: 9349 + 350: subview 'p1' + VIEW 1 rows = p2:I + 0: 9350 + 351: subview 'p1' + VIEW 1 rows = p2:I + 0: 9351 + 352: subview 'p1' + VIEW 1 rows = p2:I + 0: 9352 + 353: subview 'p1' + VIEW 1 rows = p2:I + 0: 9353 + 354: subview 'p1' + VIEW 1 rows = p2:I + 0: 9354 + 355: subview 'p1' + VIEW 1 rows = p2:I + 0: 9355 + 356: subview 'p1' + VIEW 1 rows = p2:I + 0: 9356 + 357: subview 'p1' + VIEW 1 rows = p2:I + 0: 9357 + 358: subview 'p1' + VIEW 1 rows = p2:I + 0: 9358 + 359: subview 'p1' + VIEW 1 rows = p2:I + 0: 9359 + 360: subview 'p1' + VIEW 1 rows = p2:I + 0: 9360 + 361: subview 'p1' + VIEW 1 rows = p2:I + 0: 9361 + 362: subview 'p1' + VIEW 1 rows = p2:I + 0: 9362 + 363: subview 'p1' + VIEW 1 rows = p2:I + 0: 9363 + 364: subview 'p1' + VIEW 1 rows = p2:I + 0: 9364 + 365: subview 'p1' + VIEW 1 rows = p2:I + 0: 9365 + 366: subview 'p1' + VIEW 1 rows = p2:I + 0: 9366 + 367: subview 'p1' + VIEW 1 rows = p2:I + 0: 9367 + 368: subview 'p1' + VIEW 1 rows = p2:I + 0: 9368 + 369: subview 'p1' + VIEW 1 rows = p2:I + 0: 9369 + 370: subview 'p1' + VIEW 1 rows = p2:I + 0: 9370 + 371: subview 'p1' + VIEW 1 rows = p2:I + 0: 9371 + 372: subview 'p1' + VIEW 1 rows = p2:I + 0: 9372 + 373: subview 'p1' + VIEW 1 rows = p2:I + 0: 9373 + 374: subview 'p1' + VIEW 1 rows = p2:I + 0: 9374 + 375: subview 'p1' + VIEW 1 rows = p2:I + 0: 9375 + 376: subview 'p1' + VIEW 1 rows = p2:I + 0: 9376 + 377: subview 'p1' + VIEW 1 rows = p2:I + 0: 9377 + 378: subview 'p1' + VIEW 1 rows = p2:I + 0: 9378 + 379: subview 'p1' + VIEW 1 rows = p2:I + 0: 9379 + 380: subview 'p1' + VIEW 1 rows = p2:I + 0: 9380 + 381: subview 'p1' + VIEW 1 rows = p2:I + 0: 9381 + 382: subview 'p1' + VIEW 1 rows = p2:I + 0: 9382 + 383: subview 'p1' + VIEW 1 rows = p2:I + 0: 9383 + 384: subview 'p1' + VIEW 1 rows = p2:I + 0: 9384 + 385: subview 'p1' + VIEW 1 rows = p2:I + 0: 9385 + 386: subview 'p1' + VIEW 1 rows = p2:I + 0: 9386 + 387: subview 'p1' + VIEW 1 rows = p2:I + 0: 9387 + 388: subview 'p1' + VIEW 1 rows = p2:I + 0: 9388 + 389: subview 'p1' + VIEW 1 rows = p2:I + 0: 9389 + 390: subview 'p1' + VIEW 1 rows = p2:I + 0: 9390 + 391: subview 'p1' + VIEW 1 rows = p2:I + 0: 9391 + 392: subview 'p1' + VIEW 1 rows = p2:I + 0: 9392 + 393: subview 'p1' + VIEW 1 rows = p2:I + 0: 9393 + 394: subview 'p1' + VIEW 1 rows = p2:I + 0: 9394 + 395: subview 'p1' + VIEW 1 rows = p2:I + 0: 9395 + 396: subview 'p1' + VIEW 1 rows = p2:I + 0: 9396 + 397: subview 'p1' + VIEW 1 rows = p2:I + 0: 9397 + 398: subview 'p1' + VIEW 1 rows = p2:I + 0: 9398 + 399: subview 'p1' + VIEW 1 rows = p2:I + 0: 9399 + 400: subview 'p1' + VIEW 1 rows = p2:I + 0: 9400 + 401: subview 'p1' + VIEW 1 rows = p2:I + 0: 9401 + 402: subview 'p1' + VIEW 1 rows = p2:I + 0: 9402 + 403: subview 'p1' + VIEW 1 rows = p2:I + 0: 9403 + 404: subview 'p1' + VIEW 1 rows = p2:I + 0: 9404 + 405: subview 'p1' + VIEW 1 rows = p2:I + 0: 9405 + 406: subview 'p1' + VIEW 1 rows = p2:I + 0: 9406 + 407: subview 'p1' + VIEW 1 rows = p2:I + 0: 9407 + 408: subview 'p1' + VIEW 1 rows = p2:I + 0: 9408 + 409: subview 'p1' + VIEW 1 rows = p2:I + 0: 9409 + 410: subview 'p1' + VIEW 1 rows = p2:I + 0: 9410 + 411: subview 'p1' + VIEW 1 rows = p2:I + 0: 9411 + 412: subview 'p1' + VIEW 1 rows = p2:I + 0: 9412 + 413: subview 'p1' + VIEW 1 rows = p2:I + 0: 9413 + 414: subview 'p1' + VIEW 1 rows = p2:I + 0: 9414 + 415: subview 'p1' + VIEW 1 rows = p2:I + 0: 9415 + 416: subview 'p1' + VIEW 1 rows = p2:I + 0: 9416 + 417: subview 'p1' + VIEW 1 rows = p2:I + 0: 9417 + 418: subview 'p1' + VIEW 1 rows = p2:I + 0: 9418 + 419: subview 'p1' + VIEW 1 rows = p2:I + 0: 9419 + 420: subview 'p1' + VIEW 1 rows = p2:I + 0: 9420 + 421: subview 'p1' + VIEW 1 rows = p2:I + 0: 9421 + 422: subview 'p1' + VIEW 1 rows = p2:I + 0: 9422 + 423: subview 'p1' + VIEW 1 rows = p2:I + 0: 9423 + 424: subview 'p1' + VIEW 1 rows = p2:I + 0: 9424 + 425: subview 'p1' + VIEW 1 rows = p2:I + 0: 9425 + 426: subview 'p1' + VIEW 1 rows = p2:I + 0: 9426 + 427: subview 'p1' + VIEW 1 rows = p2:I + 0: 9427 + 428: subview 'p1' + VIEW 1 rows = p2:I + 0: 9428 + 429: subview 'p1' + VIEW 1 rows = p2:I + 0: 9429 + 430: subview 'p1' + VIEW 1 rows = p2:I + 0: 9430 + 431: subview 'p1' + VIEW 1 rows = p2:I + 0: 9431 + 432: subview 'p1' + VIEW 1 rows = p2:I + 0: 9432 + 433: subview 'p1' + VIEW 1 rows = p2:I + 0: 9433 + 434: subview 'p1' + VIEW 1 rows = p2:I + 0: 9434 + 435: subview 'p1' + VIEW 1 rows = p2:I + 0: 9435 + 436: subview 'p1' + VIEW 1 rows = p2:I + 0: 9436 + 437: subview 'p1' + VIEW 1 rows = p2:I + 0: 9437 + 438: subview 'p1' + VIEW 1 rows = p2:I + 0: 9438 + 439: subview 'p1' + VIEW 1 rows = p2:I + 0: 9439 + 440: subview 'p1' + VIEW 1 rows = p2:I + 0: 9440 + 441: subview 'p1' + VIEW 1 rows = p2:I + 0: 9441 + 442: subview 'p1' + VIEW 1 rows = p2:I + 0: 9442 + 443: subview 'p1' + VIEW 1 rows = p2:I + 0: 9443 + 444: subview 'p1' + VIEW 1 rows = p2:I + 0: 9444 + 445: subview 'p1' + VIEW 1 rows = p2:I + 0: 9445 + 446: subview 'p1' + VIEW 1 rows = p2:I + 0: 9446 + 447: subview 'p1' + VIEW 1 rows = p2:I + 0: 9447 + 448: subview 'p1' + VIEW 1 rows = p2:I + 0: 9448 + 449: subview 'p1' + VIEW 1 rows = p2:I + 0: 9449 + 450: subview 'p1' + VIEW 1 rows = p2:I + 0: 9450 + 451: subview 'p1' + VIEW 1 rows = p2:I + 0: 9451 + 452: subview 'p1' + VIEW 1 rows = p2:I + 0: 9452 + 453: subview 'p1' + VIEW 1 rows = p2:I + 0: 9453 + 454: subview 'p1' + VIEW 1 rows = p2:I + 0: 9454 + 455: subview 'p1' + VIEW 1 rows = p2:I + 0: 9455 + 456: subview 'p1' + VIEW 1 rows = p2:I + 0: 9456 + 457: subview 'p1' + VIEW 1 rows = p2:I + 0: 9457 + 458: subview 'p1' + VIEW 1 rows = p2:I + 0: 9458 + 459: subview 'p1' + VIEW 1 rows = p2:I + 0: 9459 + 460: subview 'p1' + VIEW 1 rows = p2:I + 0: 9460 + 461: subview 'p1' + VIEW 1 rows = p2:I + 0: 9461 + 462: subview 'p1' + VIEW 1 rows = p2:I + 0: 9462 + 463: subview 'p1' + VIEW 1 rows = p2:I + 0: 9463 + 464: subview 'p1' + VIEW 1 rows = p2:I + 0: 9464 + 465: subview 'p1' + VIEW 1 rows = p2:I + 0: 9465 + 466: subview 'p1' + VIEW 1 rows = p2:I + 0: 9466 + 467: subview 'p1' + VIEW 1 rows = p2:I + 0: 9467 + 468: subview 'p1' + VIEW 1 rows = p2:I + 0: 9468 + 469: subview 'p1' + VIEW 1 rows = p2:I + 0: 9469 + 470: subview 'p1' + VIEW 1 rows = p2:I + 0: 9470 + 471: subview 'p1' + VIEW 1 rows = p2:I + 0: 9471 + 472: subview 'p1' + VIEW 1 rows = p2:I + 0: 9472 + 473: subview 'p1' + VIEW 1 rows = p2:I + 0: 9473 + 474: subview 'p1' + VIEW 1 rows = p2:I + 0: 9474 + 475: subview 'p1' + VIEW 1 rows = p2:I + 0: 9475 + 476: subview 'p1' + VIEW 1 rows = p2:I + 0: 9476 + 477: subview 'p1' + VIEW 1 rows = p2:I + 0: 9477 + 478: subview 'p1' + VIEW 1 rows = p2:I + 0: 9478 + 479: subview 'p1' + VIEW 1 rows = p2:I + 0: 9479 + 480: subview 'p1' + VIEW 1 rows = p2:I + 0: 9480 + 481: subview 'p1' + VIEW 1 rows = p2:I + 0: 9481 + 482: subview 'p1' + VIEW 1 rows = p2:I + 0: 9482 + 483: subview 'p1' + VIEW 1 rows = p2:I + 0: 9483 + 484: subview 'p1' + VIEW 1 rows = p2:I + 0: 9484 + 485: subview 'p1' + VIEW 1 rows = p2:I + 0: 9485 + 486: subview 'p1' + VIEW 1 rows = p2:I + 0: 9486 + 487: subview 'p1' + VIEW 1 rows = p2:I + 0: 9487 + 488: subview 'p1' + VIEW 1 rows = p2:I + 0: 9488 + 489: subview 'p1' + VIEW 1 rows = p2:I + 0: 9489 + 490: subview 'p1' + VIEW 1 rows = p2:I + 0: 9490 + 491: subview 'p1' + VIEW 1 rows = p2:I + 0: 9491 + 492: subview 'p1' + VIEW 1 rows = p2:I + 0: 9492 + 493: subview 'p1' + VIEW 1 rows = p2:I + 0: 9493 + 494: subview 'p1' + VIEW 1 rows = p2:I + 0: 9494 + 495: subview 'p1' + VIEW 1 rows = p2:I + 0: 9495 + 496: subview 'p1' + VIEW 1 rows = p2:I + 0: 9496 + 497: subview 'p1' + VIEW 1 rows = p2:I + 0: 9497 + 498: subview 'p1' + VIEW 1 rows = p2:I + 0: 9498 + 499: subview 'p1' + VIEW 1 rows = p2:I + 0: 9499 diff --git a/akregator/src/mk4storage/metakit/tests/ok/l03b.txt b/akregator/src/mk4storage/metakit/tests/ok/l03b.txt new file mode 100644 index 000000000..daff458fa --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l03b.txt @@ -0,0 +1,1503 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 500 rows = p1:V + 0: subview 'p1' + VIEW 1 rows = p2:I + 0: 9000 + 1: subview 'p1' + VIEW 1 rows = p2:I + 0: 9001 + 2: subview 'p1' + VIEW 1 rows = p2:I + 0: 9002 + 3: subview 'p1' + VIEW 1 rows = p2:I + 0: 9003 + 4: subview 'p1' + VIEW 1 rows = p2:I + 0: 9004 + 5: subview 'p1' + VIEW 1 rows = p2:I + 0: 9005 + 6: subview 'p1' + VIEW 1 rows = p2:I + 0: 9006 + 7: subview 'p1' + VIEW 1 rows = p2:I + 0: 9007 + 8: subview 'p1' + VIEW 1 rows = p2:I + 0: 9008 + 9: subview 'p1' + VIEW 1 rows = p2:I + 0: 9009 + 10: subview 'p1' + VIEW 1 rows = p2:I + 0: 9010 + 11: subview 'p1' + VIEW 1 rows = p2:I + 0: 9011 + 12: subview 'p1' + VIEW 1 rows = p2:I + 0: 9012 + 13: subview 'p1' + VIEW 1 rows = p2:I + 0: 9013 + 14: subview 'p1' + VIEW 1 rows = p2:I + 0: 9014 + 15: subview 'p1' + VIEW 1 rows = p2:I + 0: 9015 + 16: subview 'p1' + VIEW 1 rows = p2:I + 0: 9016 + 17: subview 'p1' + VIEW 1 rows = p2:I + 0: 9017 + 18: subview 'p1' + VIEW 1 rows = p2:I + 0: 9018 + 19: subview 'p1' + VIEW 1 rows = p2:I + 0: 9019 + 20: subview 'p1' + VIEW 1 rows = p2:I + 0: 9020 + 21: subview 'p1' + VIEW 1 rows = p2:I + 0: 9021 + 22: subview 'p1' + VIEW 1 rows = p2:I + 0: 9022 + 23: subview 'p1' + VIEW 1 rows = p2:I + 0: 9023 + 24: subview 'p1' + VIEW 1 rows = p2:I + 0: 9024 + 25: subview 'p1' + VIEW 1 rows = p2:I + 0: 9025 + 26: subview 'p1' + VIEW 1 rows = p2:I + 0: 9026 + 27: subview 'p1' + VIEW 1 rows = p2:I + 0: 9027 + 28: subview 'p1' + VIEW 1 rows = p2:I + 0: 9028 + 29: subview 'p1' + VIEW 1 rows = p2:I + 0: 9029 + 30: subview 'p1' + VIEW 1 rows = p2:I + 0: 9030 + 31: subview 'p1' + VIEW 1 rows = p2:I + 0: 9031 + 32: subview 'p1' + VIEW 1 rows = p2:I + 0: 9032 + 33: subview 'p1' + VIEW 1 rows = p2:I + 0: 9033 + 34: subview 'p1' + VIEW 1 rows = p2:I + 0: 9034 + 35: subview 'p1' + VIEW 1 rows = p2:I + 0: 9035 + 36: subview 'p1' + VIEW 1 rows = p2:I + 0: 9036 + 37: subview 'p1' + VIEW 1 rows = p2:I + 0: 9037 + 38: subview 'p1' + VIEW 1 rows = p2:I + 0: 9038 + 39: subview 'p1' + VIEW 1 rows = p2:I + 0: 9039 + 40: subview 'p1' + VIEW 1 rows = p2:I + 0: 9040 + 41: subview 'p1' + VIEW 1 rows = p2:I + 0: 9041 + 42: subview 'p1' + VIEW 1 rows = p2:I + 0: 9042 + 43: subview 'p1' + VIEW 1 rows = p2:I + 0: 9043 + 44: subview 'p1' + VIEW 1 rows = p2:I + 0: 9044 + 45: subview 'p1' + VIEW 1 rows = p2:I + 0: 9045 + 46: subview 'p1' + VIEW 1 rows = p2:I + 0: 9046 + 47: subview 'p1' + VIEW 1 rows = p2:I + 0: 9047 + 48: subview 'p1' + VIEW 1 rows = p2:I + 0: 9048 + 49: subview 'p1' + VIEW 1 rows = p2:I + 0: 9049 + 50: subview 'p1' + VIEW 1 rows = p2:I + 0: 9050 + 51: subview 'p1' + VIEW 1 rows = p2:I + 0: 9051 + 52: subview 'p1' + VIEW 1 rows = p2:I + 0: 9052 + 53: subview 'p1' + VIEW 1 rows = p2:I + 0: 9053 + 54: subview 'p1' + VIEW 1 rows = p2:I + 0: 9054 + 55: subview 'p1' + VIEW 1 rows = p2:I + 0: 9055 + 56: subview 'p1' + VIEW 1 rows = p2:I + 0: 9056 + 57: subview 'p1' + VIEW 1 rows = p2:I + 0: 9057 + 58: subview 'p1' + VIEW 1 rows = p2:I + 0: 9058 + 59: subview 'p1' + VIEW 1 rows = p2:I + 0: 9059 + 60: subview 'p1' + VIEW 1 rows = p2:I + 0: 9060 + 61: subview 'p1' + VIEW 1 rows = p2:I + 0: 9061 + 62: subview 'p1' + VIEW 1 rows = p2:I + 0: 9062 + 63: subview 'p1' + VIEW 1 rows = p2:I + 0: 9063 + 64: subview 'p1' + VIEW 1 rows = p2:I + 0: 9064 + 65: subview 'p1' + VIEW 1 rows = p2:I + 0: 9065 + 66: subview 'p1' + VIEW 1 rows = p2:I + 0: 9066 + 67: subview 'p1' + VIEW 1 rows = p2:I + 0: 9067 + 68: subview 'p1' + VIEW 1 rows = p2:I + 0: 9068 + 69: subview 'p1' + VIEW 1 rows = p2:I + 0: 9069 + 70: subview 'p1' + VIEW 1 rows = p2:I + 0: 9070 + 71: subview 'p1' + VIEW 1 rows = p2:I + 0: 9071 + 72: subview 'p1' + VIEW 1 rows = p2:I + 0: 9072 + 73: subview 'p1' + VIEW 1 rows = p2:I + 0: 9073 + 74: subview 'p1' + VIEW 1 rows = p2:I + 0: 9074 + 75: subview 'p1' + VIEW 1 rows = p2:I + 0: 9075 + 76: subview 'p1' + VIEW 1 rows = p2:I + 0: 9076 + 77: subview 'p1' + VIEW 1 rows = p2:I + 0: 9077 + 78: subview 'p1' + VIEW 1 rows = p2:I + 0: 9078 + 79: subview 'p1' + VIEW 1 rows = p2:I + 0: 9079 + 80: subview 'p1' + VIEW 1 rows = p2:I + 0: 9080 + 81: subview 'p1' + VIEW 1 rows = p2:I + 0: 9081 + 82: subview 'p1' + VIEW 1 rows = p2:I + 0: 9082 + 83: subview 'p1' + VIEW 1 rows = p2:I + 0: 9083 + 84: subview 'p1' + VIEW 1 rows = p2:I + 0: 9084 + 85: subview 'p1' + VIEW 1 rows = p2:I + 0: 9085 + 86: subview 'p1' + VIEW 1 rows = p2:I + 0: 9086 + 87: subview 'p1' + VIEW 1 rows = p2:I + 0: 9087 + 88: subview 'p1' + VIEW 1 rows = p2:I + 0: 9088 + 89: subview 'p1' + VIEW 1 rows = p2:I + 0: 9089 + 90: subview 'p1' + VIEW 1 rows = p2:I + 0: 9090 + 91: subview 'p1' + VIEW 1 rows = p2:I + 0: 9091 + 92: subview 'p1' + VIEW 1 rows = p2:I + 0: 9092 + 93: subview 'p1' + VIEW 1 rows = p2:I + 0: 9093 + 94: subview 'p1' + VIEW 1 rows = p2:I + 0: 9094 + 95: subview 'p1' + VIEW 1 rows = p2:I + 0: 9095 + 96: subview 'p1' + VIEW 1 rows = p2:I + 0: 9096 + 97: subview 'p1' + VIEW 1 rows = p2:I + 0: 9097 + 98: subview 'p1' + VIEW 1 rows = p2:I + 0: 9098 + 99: subview 'p1' + VIEW 1 rows = p2:I + 0: 9099 + 100: subview 'p1' + VIEW 1 rows = p2:I + 0: 9100 + 101: subview 'p1' + VIEW 1 rows = p2:I + 0: 9101 + 102: subview 'p1' + VIEW 1 rows = p2:I + 0: 9102 + 103: subview 'p1' + VIEW 1 rows = p2:I + 0: 9103 + 104: subview 'p1' + VIEW 1 rows = p2:I + 0: 9104 + 105: subview 'p1' + VIEW 1 rows = p2:I + 0: 9105 + 106: subview 'p1' + VIEW 1 rows = p2:I + 0: 9106 + 107: subview 'p1' + VIEW 1 rows = p2:I + 0: 9107 + 108: subview 'p1' + VIEW 1 rows = p2:I + 0: 9108 + 109: subview 'p1' + VIEW 1 rows = p2:I + 0: 9109 + 110: subview 'p1' + VIEW 1 rows = p2:I + 0: 9110 + 111: subview 'p1' + VIEW 1 rows = p2:I + 0: 9111 + 112: subview 'p1' + VIEW 1 rows = p2:I + 0: 9112 + 113: subview 'p1' + VIEW 1 rows = p2:I + 0: 9113 + 114: subview 'p1' + VIEW 1 rows = p2:I + 0: 9114 + 115: subview 'p1' + VIEW 1 rows = p2:I + 0: 9115 + 116: subview 'p1' + VIEW 1 rows = p2:I + 0: 9116 + 117: subview 'p1' + VIEW 1 rows = p2:I + 0: 9117 + 118: subview 'p1' + VIEW 1 rows = p2:I + 0: 9118 + 119: subview 'p1' + VIEW 1 rows = p2:I + 0: 9119 + 120: subview 'p1' + VIEW 1 rows = p2:I + 0: 9120 + 121: subview 'p1' + VIEW 1 rows = p2:I + 0: 9121 + 122: subview 'p1' + VIEW 1 rows = p2:I + 0: 9122 + 123: subview 'p1' + VIEW 1 rows = p2:I + 0: 9123 + 124: subview 'p1' + VIEW 1 rows = p2:I + 0: 9124 + 125: subview 'p1' + VIEW 1 rows = p2:I + 0: 9125 + 126: subview 'p1' + VIEW 1 rows = p2:I + 0: 9126 + 127: subview 'p1' + VIEW 1 rows = p2:I + 0: 9127 + 128: subview 'p1' + VIEW 1 rows = p2:I + 0: 9128 + 129: subview 'p1' + VIEW 1 rows = p2:I + 0: 9129 + 130: subview 'p1' + VIEW 1 rows = p2:I + 0: 9130 + 131: subview 'p1' + VIEW 1 rows = p2:I + 0: 9131 + 132: subview 'p1' + VIEW 1 rows = p2:I + 0: 9132 + 133: subview 'p1' + VIEW 1 rows = p2:I + 0: 9133 + 134: subview 'p1' + VIEW 1 rows = p2:I + 0: 9134 + 135: subview 'p1' + VIEW 1 rows = p2:I + 0: 9135 + 136: subview 'p1' + VIEW 1 rows = p2:I + 0: 9136 + 137: subview 'p1' + VIEW 1 rows = p2:I + 0: 9137 + 138: subview 'p1' + VIEW 1 rows = p2:I + 0: 9138 + 139: subview 'p1' + VIEW 1 rows = p2:I + 0: 9139 + 140: subview 'p1' + VIEW 1 rows = p2:I + 0: 9140 + 141: subview 'p1' + VIEW 1 rows = p2:I + 0: 9141 + 142: subview 'p1' + VIEW 1 rows = p2:I + 0: 9142 + 143: subview 'p1' + VIEW 1 rows = p2:I + 0: 9143 + 144: subview 'p1' + VIEW 1 rows = p2:I + 0: 9144 + 145: subview 'p1' + VIEW 1 rows = p2:I + 0: 9145 + 146: subview 'p1' + VIEW 1 rows = p2:I + 0: 9146 + 147: subview 'p1' + VIEW 1 rows = p2:I + 0: 9147 + 148: subview 'p1' + VIEW 1 rows = p2:I + 0: 9148 + 149: subview 'p1' + VIEW 1 rows = p2:I + 0: 9149 + 150: subview 'p1' + VIEW 1 rows = p2:I + 0: 9150 + 151: subview 'p1' + VIEW 1 rows = p2:I + 0: 9151 + 152: subview 'p1' + VIEW 1 rows = p2:I + 0: 9152 + 153: subview 'p1' + VIEW 1 rows = p2:I + 0: 9153 + 154: subview 'p1' + VIEW 1 rows = p2:I + 0: 9154 + 155: subview 'p1' + VIEW 1 rows = p2:I + 0: 9155 + 156: subview 'p1' + VIEW 1 rows = p2:I + 0: 9156 + 157: subview 'p1' + VIEW 1 rows = p2:I + 0: 9157 + 158: subview 'p1' + VIEW 1 rows = p2:I + 0: 9158 + 159: subview 'p1' + VIEW 1 rows = p2:I + 0: 9159 + 160: subview 'p1' + VIEW 1 rows = p2:I + 0: 9160 + 161: subview 'p1' + VIEW 1 rows = p2:I + 0: 9161 + 162: subview 'p1' + VIEW 1 rows = p2:I + 0: 9162 + 163: subview 'p1' + VIEW 1 rows = p2:I + 0: 9163 + 164: subview 'p1' + VIEW 1 rows = p2:I + 0: 9164 + 165: subview 'p1' + VIEW 1 rows = p2:I + 0: 9165 + 166: subview 'p1' + VIEW 1 rows = p2:I + 0: 9166 + 167: subview 'p1' + VIEW 1 rows = p2:I + 0: 9167 + 168: subview 'p1' + VIEW 1 rows = p2:I + 0: 9168 + 169: subview 'p1' + VIEW 1 rows = p2:I + 0: 9169 + 170: subview 'p1' + VIEW 1 rows = p2:I + 0: 9170 + 171: subview 'p1' + VIEW 1 rows = p2:I + 0: 9171 + 172: subview 'p1' + VIEW 1 rows = p2:I + 0: 9172 + 173: subview 'p1' + VIEW 1 rows = p2:I + 0: 9173 + 174: subview 'p1' + VIEW 1 rows = p2:I + 0: 9174 + 175: subview 'p1' + VIEW 1 rows = p2:I + 0: 9175 + 176: subview 'p1' + VIEW 1 rows = p2:I + 0: 9176 + 177: subview 'p1' + VIEW 1 rows = p2:I + 0: 9177 + 178: subview 'p1' + VIEW 1 rows = p2:I + 0: 9178 + 179: subview 'p1' + VIEW 1 rows = p2:I + 0: 9179 + 180: subview 'p1' + VIEW 1 rows = p2:I + 0: 9180 + 181: subview 'p1' + VIEW 1 rows = p2:I + 0: 9181 + 182: subview 'p1' + VIEW 1 rows = p2:I + 0: 9182 + 183: subview 'p1' + VIEW 1 rows = p2:I + 0: 9183 + 184: subview 'p1' + VIEW 1 rows = p2:I + 0: 9184 + 185: subview 'p1' + VIEW 1 rows = p2:I + 0: 9185 + 186: subview 'p1' + VIEW 1 rows = p2:I + 0: 9186 + 187: subview 'p1' + VIEW 1 rows = p2:I + 0: 9187 + 188: subview 'p1' + VIEW 1 rows = p2:I + 0: 9188 + 189: subview 'p1' + VIEW 1 rows = p2:I + 0: 9189 + 190: subview 'p1' + VIEW 1 rows = p2:I + 0: 9190 + 191: subview 'p1' + VIEW 1 rows = p2:I + 0: 9191 + 192: subview 'p1' + VIEW 1 rows = p2:I + 0: 9192 + 193: subview 'p1' + VIEW 1 rows = p2:I + 0: 9193 + 194: subview 'p1' + VIEW 1 rows = p2:I + 0: 9194 + 195: subview 'p1' + VIEW 1 rows = p2:I + 0: 9195 + 196: subview 'p1' + VIEW 1 rows = p2:I + 0: 9196 + 197: subview 'p1' + VIEW 1 rows = p2:I + 0: 9197 + 198: subview 'p1' + VIEW 1 rows = p2:I + 0: 9198 + 199: subview 'p1' + VIEW 1 rows = p2:I + 0: 9199 + 200: subview 'p1' + VIEW 1 rows = p2:I + 0: 9200 + 201: subview 'p1' + VIEW 1 rows = p2:I + 0: 9201 + 202: subview 'p1' + VIEW 1 rows = p2:I + 0: 9202 + 203: subview 'p1' + VIEW 1 rows = p2:I + 0: 9203 + 204: subview 'p1' + VIEW 1 rows = p2:I + 0: 9204 + 205: subview 'p1' + VIEW 1 rows = p2:I + 0: 9205 + 206: subview 'p1' + VIEW 1 rows = p2:I + 0: 9206 + 207: subview 'p1' + VIEW 1 rows = p2:I + 0: 9207 + 208: subview 'p1' + VIEW 1 rows = p2:I + 0: 9208 + 209: subview 'p1' + VIEW 1 rows = p2:I + 0: 9209 + 210: subview 'p1' + VIEW 1 rows = p2:I + 0: 9210 + 211: subview 'p1' + VIEW 1 rows = p2:I + 0: 9211 + 212: subview 'p1' + VIEW 1 rows = p2:I + 0: 9212 + 213: subview 'p1' + VIEW 1 rows = p2:I + 0: 9213 + 214: subview 'p1' + VIEW 1 rows = p2:I + 0: 9214 + 215: subview 'p1' + VIEW 1 rows = p2:I + 0: 9215 + 216: subview 'p1' + VIEW 1 rows = p2:I + 0: 9216 + 217: subview 'p1' + VIEW 1 rows = p2:I + 0: 9217 + 218: subview 'p1' + VIEW 1 rows = p2:I + 0: 9218 + 219: subview 'p1' + VIEW 1 rows = p2:I + 0: 9219 + 220: subview 'p1' + VIEW 1 rows = p2:I + 0: 9220 + 221: subview 'p1' + VIEW 1 rows = p2:I + 0: 9221 + 222: subview 'p1' + VIEW 1 rows = p2:I + 0: 9222 + 223: subview 'p1' + VIEW 1 rows = p2:I + 0: 9223 + 224: subview 'p1' + VIEW 1 rows = p2:I + 0: 9224 + 225: subview 'p1' + VIEW 1 rows = p2:I + 0: 9225 + 226: subview 'p1' + VIEW 1 rows = p2:I + 0: 9226 + 227: subview 'p1' + VIEW 1 rows = p2:I + 0: 9227 + 228: subview 'p1' + VIEW 1 rows = p2:I + 0: 9228 + 229: subview 'p1' + VIEW 1 rows = p2:I + 0: 9229 + 230: subview 'p1' + VIEW 1 rows = p2:I + 0: 9230 + 231: subview 'p1' + VIEW 1 rows = p2:I + 0: 9231 + 232: subview 'p1' + VIEW 1 rows = p2:I + 0: 9232 + 233: subview 'p1' + VIEW 1 rows = p2:I + 0: 9233 + 234: subview 'p1' + VIEW 1 rows = p2:I + 0: 9234 + 235: subview 'p1' + VIEW 1 rows = p2:I + 0: 9235 + 236: subview 'p1' + VIEW 1 rows = p2:I + 0: 9236 + 237: subview 'p1' + VIEW 1 rows = p2:I + 0: 9237 + 238: subview 'p1' + VIEW 1 rows = p2:I + 0: 9238 + 239: subview 'p1' + VIEW 1 rows = p2:I + 0: 9239 + 240: subview 'p1' + VIEW 1 rows = p2:I + 0: 9240 + 241: subview 'p1' + VIEW 1 rows = p2:I + 0: 9241 + 242: subview 'p1' + VIEW 1 rows = p2:I + 0: 9242 + 243: subview 'p1' + VIEW 1 rows = p2:I + 0: 9243 + 244: subview 'p1' + VIEW 1 rows = p2:I + 0: 9244 + 245: subview 'p1' + VIEW 1 rows = p2:I + 0: 9245 + 246: subview 'p1' + VIEW 1 rows = p2:I + 0: 9246 + 247: subview 'p1' + VIEW 1 rows = p2:I + 0: 9247 + 248: subview 'p1' + VIEW 1 rows = p2:I + 0: 9248 + 249: subview 'p1' + VIEW 1 rows = p2:I + 0: 9249 + 250: subview 'p1' + VIEW 1 rows = p2:I + 0: 9250 + 251: subview 'p1' + VIEW 1 rows = p2:I + 0: 9251 + 252: subview 'p1' + VIEW 1 rows = p2:I + 0: 9252 + 253: subview 'p1' + VIEW 1 rows = p2:I + 0: 9253 + 254: subview 'p1' + VIEW 1 rows = p2:I + 0: 9254 + 255: subview 'p1' + VIEW 1 rows = p2:I + 0: 9255 + 256: subview 'p1' + VIEW 1 rows = p2:I + 0: 9256 + 257: subview 'p1' + VIEW 1 rows = p2:I + 0: 9257 + 258: subview 'p1' + VIEW 1 rows = p2:I + 0: 9258 + 259: subview 'p1' + VIEW 1 rows = p2:I + 0: 9259 + 260: subview 'p1' + VIEW 1 rows = p2:I + 0: 9260 + 261: subview 'p1' + VIEW 1 rows = p2:I + 0: 9261 + 262: subview 'p1' + VIEW 1 rows = p2:I + 0: 9262 + 263: subview 'p1' + VIEW 1 rows = p2:I + 0: 9263 + 264: subview 'p1' + VIEW 1 rows = p2:I + 0: 9264 + 265: subview 'p1' + VIEW 1 rows = p2:I + 0: 9265 + 266: subview 'p1' + VIEW 1 rows = p2:I + 0: 9266 + 267: subview 'p1' + VIEW 1 rows = p2:I + 0: 9267 + 268: subview 'p1' + VIEW 1 rows = p2:I + 0: 9268 + 269: subview 'p1' + VIEW 1 rows = p2:I + 0: 9269 + 270: subview 'p1' + VIEW 1 rows = p2:I + 0: 9270 + 271: subview 'p1' + VIEW 1 rows = p2:I + 0: 9271 + 272: subview 'p1' + VIEW 1 rows = p2:I + 0: 9272 + 273: subview 'p1' + VIEW 1 rows = p2:I + 0: 9273 + 274: subview 'p1' + VIEW 1 rows = p2:I + 0: 9274 + 275: subview 'p1' + VIEW 1 rows = p2:I + 0: 9275 + 276: subview 'p1' + VIEW 1 rows = p2:I + 0: 9276 + 277: subview 'p1' + VIEW 1 rows = p2:I + 0: 9277 + 278: subview 'p1' + VIEW 1 rows = p2:I + 0: 9278 + 279: subview 'p1' + VIEW 1 rows = p2:I + 0: 9279 + 280: subview 'p1' + VIEW 1 rows = p2:I + 0: 9280 + 281: subview 'p1' + VIEW 1 rows = p2:I + 0: 9281 + 282: subview 'p1' + VIEW 1 rows = p2:I + 0: 9282 + 283: subview 'p1' + VIEW 1 rows = p2:I + 0: 9283 + 284: subview 'p1' + VIEW 1 rows = p2:I + 0: 9284 + 285: subview 'p1' + VIEW 1 rows = p2:I + 0: 9285 + 286: subview 'p1' + VIEW 1 rows = p2:I + 0: 9286 + 287: subview 'p1' + VIEW 1 rows = p2:I + 0: 9287 + 288: subview 'p1' + VIEW 1 rows = p2:I + 0: 9288 + 289: subview 'p1' + VIEW 1 rows = p2:I + 0: 9289 + 290: subview 'p1' + VIEW 1 rows = p2:I + 0: 9290 + 291: subview 'p1' + VIEW 1 rows = p2:I + 0: 9291 + 292: subview 'p1' + VIEW 1 rows = p2:I + 0: 9292 + 293: subview 'p1' + VIEW 1 rows = p2:I + 0: 9293 + 294: subview 'p1' + VIEW 1 rows = p2:I + 0: 9294 + 295: subview 'p1' + VIEW 1 rows = p2:I + 0: 9295 + 296: subview 'p1' + VIEW 1 rows = p2:I + 0: 9296 + 297: subview 'p1' + VIEW 1 rows = p2:I + 0: 9297 + 298: subview 'p1' + VIEW 1 rows = p2:I + 0: 9298 + 299: subview 'p1' + VIEW 1 rows = p2:I + 0: 9299 + 300: subview 'p1' + VIEW 1 rows = p2:I + 0: 9300 + 301: subview 'p1' + VIEW 1 rows = p2:I + 0: 9301 + 302: subview 'p1' + VIEW 1 rows = p2:I + 0: 9302 + 303: subview 'p1' + VIEW 1 rows = p2:I + 0: 9303 + 304: subview 'p1' + VIEW 1 rows = p2:I + 0: 9304 + 305: subview 'p1' + VIEW 1 rows = p2:I + 0: 9305 + 306: subview 'p1' + VIEW 1 rows = p2:I + 0: 9306 + 307: subview 'p1' + VIEW 1 rows = p2:I + 0: 9307 + 308: subview 'p1' + VIEW 1 rows = p2:I + 0: 9308 + 309: subview 'p1' + VIEW 1 rows = p2:I + 0: 9309 + 310: subview 'p1' + VIEW 1 rows = p2:I + 0: 9310 + 311: subview 'p1' + VIEW 1 rows = p2:I + 0: 9311 + 312: subview 'p1' + VIEW 1 rows = p2:I + 0: 9312 + 313: subview 'p1' + VIEW 1 rows = p2:I + 0: 9313 + 314: subview 'p1' + VIEW 1 rows = p2:I + 0: 9314 + 315: subview 'p1' + VIEW 1 rows = p2:I + 0: 9315 + 316: subview 'p1' + VIEW 1 rows = p2:I + 0: 9316 + 317: subview 'p1' + VIEW 1 rows = p2:I + 0: 9317 + 318: subview 'p1' + VIEW 1 rows = p2:I + 0: 9318 + 319: subview 'p1' + VIEW 1 rows = p2:I + 0: 9319 + 320: subview 'p1' + VIEW 1 rows = p2:I + 0: 9320 + 321: subview 'p1' + VIEW 1 rows = p2:I + 0: 9321 + 322: subview 'p1' + VIEW 1 rows = p2:I + 0: 9322 + 323: subview 'p1' + VIEW 1 rows = p2:I + 0: 9323 + 324: subview 'p1' + VIEW 1 rows = p2:I + 0: 9324 + 325: subview 'p1' + VIEW 1 rows = p2:I + 0: 9325 + 326: subview 'p1' + VIEW 1 rows = p2:I + 0: 9326 + 327: subview 'p1' + VIEW 1 rows = p2:I + 0: 9327 + 328: subview 'p1' + VIEW 1 rows = p2:I + 0: 9328 + 329: subview 'p1' + VIEW 1 rows = p2:I + 0: 9329 + 330: subview 'p1' + VIEW 1 rows = p2:I + 0: 9330 + 331: subview 'p1' + VIEW 1 rows = p2:I + 0: 9331 + 332: subview 'p1' + VIEW 1 rows = p2:I + 0: 9332 + 333: subview 'p1' + VIEW 1 rows = p2:I + 0: 9333 + 334: subview 'p1' + VIEW 1 rows = p2:I + 0: 9334 + 335: subview 'p1' + VIEW 1 rows = p2:I + 0: 9335 + 336: subview 'p1' + VIEW 1 rows = p2:I + 0: 9336 + 337: subview 'p1' + VIEW 1 rows = p2:I + 0: 9337 + 338: subview 'p1' + VIEW 1 rows = p2:I + 0: 9338 + 339: subview 'p1' + VIEW 1 rows = p2:I + 0: 9339 + 340: subview 'p1' + VIEW 1 rows = p2:I + 0: 9340 + 341: subview 'p1' + VIEW 1 rows = p2:I + 0: 9341 + 342: subview 'p1' + VIEW 1 rows = p2:I + 0: 9342 + 343: subview 'p1' + VIEW 1 rows = p2:I + 0: 9343 + 344: subview 'p1' + VIEW 1 rows = p2:I + 0: 9344 + 345: subview 'p1' + VIEW 1 rows = p2:I + 0: 9345 + 346: subview 'p1' + VIEW 1 rows = p2:I + 0: 9346 + 347: subview 'p1' + VIEW 1 rows = p2:I + 0: 9347 + 348: subview 'p1' + VIEW 1 rows = p2:I + 0: 9348 + 349: subview 'p1' + VIEW 1 rows = p2:I + 0: 9349 + 350: subview 'p1' + VIEW 1 rows = p2:I + 0: 9350 + 351: subview 'p1' + VIEW 1 rows = p2:I + 0: 9351 + 352: subview 'p1' + VIEW 1 rows = p2:I + 0: 9352 + 353: subview 'p1' + VIEW 1 rows = p2:I + 0: 9353 + 354: subview 'p1' + VIEW 1 rows = p2:I + 0: 9354 + 355: subview 'p1' + VIEW 1 rows = p2:I + 0: 9355 + 356: subview 'p1' + VIEW 1 rows = p2:I + 0: 9356 + 357: subview 'p1' + VIEW 1 rows = p2:I + 0: 9357 + 358: subview 'p1' + VIEW 1 rows = p2:I + 0: 9358 + 359: subview 'p1' + VIEW 1 rows = p2:I + 0: 9359 + 360: subview 'p1' + VIEW 1 rows = p2:I + 0: 9360 + 361: subview 'p1' + VIEW 1 rows = p2:I + 0: 9361 + 362: subview 'p1' + VIEW 1 rows = p2:I + 0: 9362 + 363: subview 'p1' + VIEW 1 rows = p2:I + 0: 9363 + 364: subview 'p1' + VIEW 1 rows = p2:I + 0: 9364 + 365: subview 'p1' + VIEW 1 rows = p2:I + 0: 9365 + 366: subview 'p1' + VIEW 1 rows = p2:I + 0: 9366 + 367: subview 'p1' + VIEW 1 rows = p2:I + 0: 9367 + 368: subview 'p1' + VIEW 1 rows = p2:I + 0: 9368 + 369: subview 'p1' + VIEW 1 rows = p2:I + 0: 9369 + 370: subview 'p1' + VIEW 1 rows = p2:I + 0: 9370 + 371: subview 'p1' + VIEW 1 rows = p2:I + 0: 9371 + 372: subview 'p1' + VIEW 1 rows = p2:I + 0: 9372 + 373: subview 'p1' + VIEW 1 rows = p2:I + 0: 9373 + 374: subview 'p1' + VIEW 1 rows = p2:I + 0: 9374 + 375: subview 'p1' + VIEW 1 rows = p2:I + 0: 9375 + 376: subview 'p1' + VIEW 1 rows = p2:I + 0: 9376 + 377: subview 'p1' + VIEW 1 rows = p2:I + 0: 9377 + 378: subview 'p1' + VIEW 1 rows = p2:I + 0: 9378 + 379: subview 'p1' + VIEW 1 rows = p2:I + 0: 9379 + 380: subview 'p1' + VIEW 1 rows = p2:I + 0: 9380 + 381: subview 'p1' + VIEW 1 rows = p2:I + 0: 9381 + 382: subview 'p1' + VIEW 1 rows = p2:I + 0: 9382 + 383: subview 'p1' + VIEW 1 rows = p2:I + 0: 9383 + 384: subview 'p1' + VIEW 1 rows = p2:I + 0: 9384 + 385: subview 'p1' + VIEW 1 rows = p2:I + 0: 9385 + 386: subview 'p1' + VIEW 1 rows = p2:I + 0: 9386 + 387: subview 'p1' + VIEW 1 rows = p2:I + 0: 9387 + 388: subview 'p1' + VIEW 1 rows = p2:I + 0: 9388 + 389: subview 'p1' + VIEW 1 rows = p2:I + 0: 9389 + 390: subview 'p1' + VIEW 1 rows = p2:I + 0: 9390 + 391: subview 'p1' + VIEW 1 rows = p2:I + 0: 9391 + 392: subview 'p1' + VIEW 1 rows = p2:I + 0: 9392 + 393: subview 'p1' + VIEW 1 rows = p2:I + 0: 9393 + 394: subview 'p1' + VIEW 1 rows = p2:I + 0: 9394 + 395: subview 'p1' + VIEW 1 rows = p2:I + 0: 9395 + 396: subview 'p1' + VIEW 1 rows = p2:I + 0: 9396 + 397: subview 'p1' + VIEW 1 rows = p2:I + 0: 9397 + 398: subview 'p1' + VIEW 1 rows = p2:I + 0: 9398 + 399: subview 'p1' + VIEW 1 rows = p2:I + 0: 9399 + 400: subview 'p1' + VIEW 1 rows = p2:I + 0: 9400 + 401: subview 'p1' + VIEW 1 rows = p2:I + 0: 9401 + 402: subview 'p1' + VIEW 1 rows = p2:I + 0: 9402 + 403: subview 'p1' + VIEW 1 rows = p2:I + 0: 9403 + 404: subview 'p1' + VIEW 1 rows = p2:I + 0: 9404 + 405: subview 'p1' + VIEW 1 rows = p2:I + 0: 9405 + 406: subview 'p1' + VIEW 1 rows = p2:I + 0: 9406 + 407: subview 'p1' + VIEW 1 rows = p2:I + 0: 9407 + 408: subview 'p1' + VIEW 1 rows = p2:I + 0: 9408 + 409: subview 'p1' + VIEW 1 rows = p2:I + 0: 9409 + 410: subview 'p1' + VIEW 1 rows = p2:I + 0: 9410 + 411: subview 'p1' + VIEW 1 rows = p2:I + 0: 9411 + 412: subview 'p1' + VIEW 1 rows = p2:I + 0: 9412 + 413: subview 'p1' + VIEW 1 rows = p2:I + 0: 9413 + 414: subview 'p1' + VIEW 1 rows = p2:I + 0: 9414 + 415: subview 'p1' + VIEW 1 rows = p2:I + 0: 9415 + 416: subview 'p1' + VIEW 1 rows = p2:I + 0: 9416 + 417: subview 'p1' + VIEW 1 rows = p2:I + 0: 9417 + 418: subview 'p1' + VIEW 1 rows = p2:I + 0: 9418 + 419: subview 'p1' + VIEW 1 rows = p2:I + 0: 9419 + 420: subview 'p1' + VIEW 1 rows = p2:I + 0: 9420 + 421: subview 'p1' + VIEW 1 rows = p2:I + 0: 9421 + 422: subview 'p1' + VIEW 1 rows = p2:I + 0: 9422 + 423: subview 'p1' + VIEW 1 rows = p2:I + 0: 9423 + 424: subview 'p1' + VIEW 1 rows = p2:I + 0: 9424 + 425: subview 'p1' + VIEW 1 rows = p2:I + 0: 9425 + 426: subview 'p1' + VIEW 1 rows = p2:I + 0: 9426 + 427: subview 'p1' + VIEW 1 rows = p2:I + 0: 9427 + 428: subview 'p1' + VIEW 1 rows = p2:I + 0: 9428 + 429: subview 'p1' + VIEW 1 rows = p2:I + 0: 9429 + 430: subview 'p1' + VIEW 1 rows = p2:I + 0: 9430 + 431: subview 'p1' + VIEW 1 rows = p2:I + 0: 9431 + 432: subview 'p1' + VIEW 1 rows = p2:I + 0: 9432 + 433: subview 'p1' + VIEW 1 rows = p2:I + 0: 9433 + 434: subview 'p1' + VIEW 1 rows = p2:I + 0: 9434 + 435: subview 'p1' + VIEW 1 rows = p2:I + 0: 9435 + 436: subview 'p1' + VIEW 1 rows = p2:I + 0: 9436 + 437: subview 'p1' + VIEW 1 rows = p2:I + 0: 9437 + 438: subview 'p1' + VIEW 1 rows = p2:I + 0: 9438 + 439: subview 'p1' + VIEW 1 rows = p2:I + 0: 9439 + 440: subview 'p1' + VIEW 1 rows = p2:I + 0: 9440 + 441: subview 'p1' + VIEW 1 rows = p2:I + 0: 9441 + 442: subview 'p1' + VIEW 1 rows = p2:I + 0: 9442 + 443: subview 'p1' + VIEW 1 rows = p2:I + 0: 9443 + 444: subview 'p1' + VIEW 1 rows = p2:I + 0: 9444 + 445: subview 'p1' + VIEW 1 rows = p2:I + 0: 9445 + 446: subview 'p1' + VIEW 1 rows = p2:I + 0: 9446 + 447: subview 'p1' + VIEW 1 rows = p2:I + 0: 9447 + 448: subview 'p1' + VIEW 1 rows = p2:I + 0: 9448 + 449: subview 'p1' + VIEW 1 rows = p2:I + 0: 9449 + 450: subview 'p1' + VIEW 1 rows = p2:I + 0: 9450 + 451: subview 'p1' + VIEW 1 rows = p2:I + 0: 9451 + 452: subview 'p1' + VIEW 1 rows = p2:I + 0: 9452 + 453: subview 'p1' + VIEW 1 rows = p2:I + 0: 9453 + 454: subview 'p1' + VIEW 1 rows = p2:I + 0: 9454 + 455: subview 'p1' + VIEW 1 rows = p2:I + 0: 9455 + 456: subview 'p1' + VIEW 1 rows = p2:I + 0: 9456 + 457: subview 'p1' + VIEW 1 rows = p2:I + 0: 9457 + 458: subview 'p1' + VIEW 1 rows = p2:I + 0: 9458 + 459: subview 'p1' + VIEW 1 rows = p2:I + 0: 9459 + 460: subview 'p1' + VIEW 1 rows = p2:I + 0: 9460 + 461: subview 'p1' + VIEW 1 rows = p2:I + 0: 9461 + 462: subview 'p1' + VIEW 1 rows = p2:I + 0: 9462 + 463: subview 'p1' + VIEW 1 rows = p2:I + 0: 9463 + 464: subview 'p1' + VIEW 1 rows = p2:I + 0: 9464 + 465: subview 'p1' + VIEW 1 rows = p2:I + 0: 9465 + 466: subview 'p1' + VIEW 1 rows = p2:I + 0: 9466 + 467: subview 'p1' + VIEW 1 rows = p2:I + 0: 9467 + 468: subview 'p1' + VIEW 1 rows = p2:I + 0: 9468 + 469: subview 'p1' + VIEW 1 rows = p2:I + 0: 9469 + 470: subview 'p1' + VIEW 1 rows = p2:I + 0: 9470 + 471: subview 'p1' + VIEW 1 rows = p2:I + 0: 9471 + 472: subview 'p1' + VIEW 1 rows = p2:I + 0: 9472 + 473: subview 'p1' + VIEW 1 rows = p2:I + 0: 9473 + 474: subview 'p1' + VIEW 1 rows = p2:I + 0: 9474 + 475: subview 'p1' + VIEW 1 rows = p2:I + 0: 9475 + 476: subview 'p1' + VIEW 1 rows = p2:I + 0: 9476 + 477: subview 'p1' + VIEW 1 rows = p2:I + 0: 9477 + 478: subview 'p1' + VIEW 1 rows = p2:I + 0: 9478 + 479: subview 'p1' + VIEW 1 rows = p2:I + 0: 9479 + 480: subview 'p1' + VIEW 1 rows = p2:I + 0: 9480 + 481: subview 'p1' + VIEW 1 rows = p2:I + 0: 9481 + 482: subview 'p1' + VIEW 1 rows = p2:I + 0: 9482 + 483: subview 'p1' + VIEW 1 rows = p2:I + 0: 9483 + 484: subview 'p1' + VIEW 1 rows = p2:I + 0: 9484 + 485: subview 'p1' + VIEW 1 rows = p2:I + 0: 9485 + 486: subview 'p1' + VIEW 1 rows = p2:I + 0: 9486 + 487: subview 'p1' + VIEW 1 rows = p2:I + 0: 9487 + 488: subview 'p1' + VIEW 1 rows = p2:I + 0: 9488 + 489: subview 'p1' + VIEW 1 rows = p2:I + 0: 9489 + 490: subview 'p1' + VIEW 1 rows = p2:I + 0: 9490 + 491: subview 'p1' + VIEW 1 rows = p2:I + 0: 9491 + 492: subview 'p1' + VIEW 1 rows = p2:I + 0: 9492 + 493: subview 'p1' + VIEW 1 rows = p2:I + 0: 9493 + 494: subview 'p1' + VIEW 1 rows = p2:I + 0: 9494 + 495: subview 'p1' + VIEW 1 rows = p2:I + 0: 9495 + 496: subview 'p1' + VIEW 1 rows = p2:I + 0: 9496 + 497: subview 'p1' + VIEW 1 rows = p2:I + 0: 9497 + 498: subview 'p1' + VIEW 1 rows = p2:I + 0: 9498 + 499: subview 'p1' + VIEW 1 rows = p2:I + 0: 9499 diff --git a/akregator/src/mk4storage/metakit/tests/ok/l04.txt b/akregator/src/mk4storage/metakit/tests/ok/l04.txt new file mode 100644 index 000000000..23920007e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l04.txt @@ -0,0 +1,2 @@ +>>> Modify sections in storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/l04a.txt b/akregator/src/mk4storage/metakit/tests/ok/l04a.txt new file mode 100644 index 000000000..2eed1fc28 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l04a.txt @@ -0,0 +1,1503 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 500 rows = p1:V + 0: subview 'p1' + VIEW 1 rows = p2:I + 0: 1 + 1: subview 'p1' + VIEW 1 rows = p2:I + 0: 9001 + 2: subview 'p1' + VIEW 1 rows = p2:I + 0: 9002 + 3: subview 'p1' + VIEW 1 rows = p2:I + 0: 9003 + 4: subview 'p1' + VIEW 1 rows = p2:I + 0: 9004 + 5: subview 'p1' + VIEW 1 rows = p2:I + 0: 9005 + 6: subview 'p1' + VIEW 1 rows = p2:I + 0: 9006 + 7: subview 'p1' + VIEW 1 rows = p2:I + 0: 9007 + 8: subview 'p1' + VIEW 1 rows = p2:I + 0: 9008 + 9: subview 'p1' + VIEW 1 rows = p2:I + 0: 9009 + 10: subview 'p1' + VIEW 1 rows = p2:I + 0: 9010 + 11: subview 'p1' + VIEW 1 rows = p2:I + 0: 9011 + 12: subview 'p1' + VIEW 1 rows = p2:I + 0: 9012 + 13: subview 'p1' + VIEW 1 rows = p2:I + 0: 9013 + 14: subview 'p1' + VIEW 1 rows = p2:I + 0: 9014 + 15: subview 'p1' + VIEW 1 rows = p2:I + 0: 9015 + 16: subview 'p1' + VIEW 1 rows = p2:I + 0: 9016 + 17: subview 'p1' + VIEW 1 rows = p2:I + 0: 9017 + 18: subview 'p1' + VIEW 1 rows = p2:I + 0: 9018 + 19: subview 'p1' + VIEW 1 rows = p2:I + 0: 9019 + 20: subview 'p1' + VIEW 1 rows = p2:I + 0: 9020 + 21: subview 'p1' + VIEW 1 rows = p2:I + 0: 9021 + 22: subview 'p1' + VIEW 1 rows = p2:I + 0: 9022 + 23: subview 'p1' + VIEW 1 rows = p2:I + 0: 9023 + 24: subview 'p1' + VIEW 1 rows = p2:I + 0: 9024 + 25: subview 'p1' + VIEW 1 rows = p2:I + 0: 9025 + 26: subview 'p1' + VIEW 1 rows = p2:I + 0: 9026 + 27: subview 'p1' + VIEW 1 rows = p2:I + 0: 9027 + 28: subview 'p1' + VIEW 1 rows = p2:I + 0: 9028 + 29: subview 'p1' + VIEW 1 rows = p2:I + 0: 9029 + 30: subview 'p1' + VIEW 1 rows = p2:I + 0: 9030 + 31: subview 'p1' + VIEW 1 rows = p2:I + 0: 9031 + 32: subview 'p1' + VIEW 1 rows = p2:I + 0: 9032 + 33: subview 'p1' + VIEW 1 rows = p2:I + 0: 9033 + 34: subview 'p1' + VIEW 1 rows = p2:I + 0: 9034 + 35: subview 'p1' + VIEW 1 rows = p2:I + 0: 9035 + 36: subview 'p1' + VIEW 1 rows = p2:I + 0: 9036 + 37: subview 'p1' + VIEW 1 rows = p2:I + 0: 9037 + 38: subview 'p1' + VIEW 1 rows = p2:I + 0: 9038 + 39: subview 'p1' + VIEW 1 rows = p2:I + 0: 9039 + 40: subview 'p1' + VIEW 1 rows = p2:I + 0: 9040 + 41: subview 'p1' + VIEW 1 rows = p2:I + 0: 9041 + 42: subview 'p1' + VIEW 1 rows = p2:I + 0: 9042 + 43: subview 'p1' + VIEW 1 rows = p2:I + 0: 9043 + 44: subview 'p1' + VIEW 1 rows = p2:I + 0: 9044 + 45: subview 'p1' + VIEW 1 rows = p2:I + 0: 9045 + 46: subview 'p1' + VIEW 1 rows = p2:I + 0: 9046 + 47: subview 'p1' + VIEW 1 rows = p2:I + 0: 9047 + 48: subview 'p1' + VIEW 1 rows = p2:I + 0: 9048 + 49: subview 'p1' + VIEW 1 rows = p2:I + 0: 9049 + 50: subview 'p1' + VIEW 1 rows = p2:I + 0: 9050 + 51: subview 'p1' + VIEW 1 rows = p2:I + 0: 9051 + 52: subview 'p1' + VIEW 1 rows = p2:I + 0: 9052 + 53: subview 'p1' + VIEW 1 rows = p2:I + 0: 9053 + 54: subview 'p1' + VIEW 1 rows = p2:I + 0: 9054 + 55: subview 'p1' + VIEW 1 rows = p2:I + 0: 9055 + 56: subview 'p1' + VIEW 1 rows = p2:I + 0: 9056 + 57: subview 'p1' + VIEW 1 rows = p2:I + 0: 9057 + 58: subview 'p1' + VIEW 1 rows = p2:I + 0: 9058 + 59: subview 'p1' + VIEW 1 rows = p2:I + 0: 9059 + 60: subview 'p1' + VIEW 1 rows = p2:I + 0: 9060 + 61: subview 'p1' + VIEW 1 rows = p2:I + 0: 9061 + 62: subview 'p1' + VIEW 1 rows = p2:I + 0: 9062 + 63: subview 'p1' + VIEW 1 rows = p2:I + 0: 9063 + 64: subview 'p1' + VIEW 1 rows = p2:I + 0: 9064 + 65: subview 'p1' + VIEW 1 rows = p2:I + 0: 9065 + 66: subview 'p1' + VIEW 1 rows = p2:I + 0: 9066 + 67: subview 'p1' + VIEW 1 rows = p2:I + 0: 9067 + 68: subview 'p1' + VIEW 1 rows = p2:I + 0: 9068 + 69: subview 'p1' + VIEW 1 rows = p2:I + 0: 9069 + 70: subview 'p1' + VIEW 1 rows = p2:I + 0: 9070 + 71: subview 'p1' + VIEW 1 rows = p2:I + 0: 9071 + 72: subview 'p1' + VIEW 1 rows = p2:I + 0: 9072 + 73: subview 'p1' + VIEW 1 rows = p2:I + 0: 9073 + 74: subview 'p1' + VIEW 1 rows = p2:I + 0: 9074 + 75: subview 'p1' + VIEW 1 rows = p2:I + 0: 9075 + 76: subview 'p1' + VIEW 1 rows = p2:I + 0: 9076 + 77: subview 'p1' + VIEW 1 rows = p2:I + 0: 9077 + 78: subview 'p1' + VIEW 1 rows = p2:I + 0: 9078 + 79: subview 'p1' + VIEW 1 rows = p2:I + 0: 9079 + 80: subview 'p1' + VIEW 1 rows = p2:I + 0: 9080 + 81: subview 'p1' + VIEW 1 rows = p2:I + 0: 9081 + 82: subview 'p1' + VIEW 1 rows = p2:I + 0: 9082 + 83: subview 'p1' + VIEW 1 rows = p2:I + 0: 9083 + 84: subview 'p1' + VIEW 1 rows = p2:I + 0: 9084 + 85: subview 'p1' + VIEW 1 rows = p2:I + 0: 9085 + 86: subview 'p1' + VIEW 1 rows = p2:I + 0: 9086 + 87: subview 'p1' + VIEW 1 rows = p2:I + 0: 9087 + 88: subview 'p1' + VIEW 1 rows = p2:I + 0: 9088 + 89: subview 'p1' + VIEW 1 rows = p2:I + 0: 9089 + 90: subview 'p1' + VIEW 1 rows = p2:I + 0: 9090 + 91: subview 'p1' + VIEW 1 rows = p2:I + 0: 9091 + 92: subview 'p1' + VIEW 1 rows = p2:I + 0: 9092 + 93: subview 'p1' + VIEW 1 rows = p2:I + 0: 9093 + 94: subview 'p1' + VIEW 1 rows = p2:I + 0: 9094 + 95: subview 'p1' + VIEW 1 rows = p2:I + 0: 9095 + 96: subview 'p1' + VIEW 1 rows = p2:I + 0: 9096 + 97: subview 'p1' + VIEW 1 rows = p2:I + 0: 9097 + 98: subview 'p1' + VIEW 1 rows = p2:I + 0: 9098 + 99: subview 'p1' + VIEW 1 rows = p2:I + 0: 9099 + 100: subview 'p1' + VIEW 1 rows = p2:I + 0: 9100 + 101: subview 'p1' + VIEW 1 rows = p2:I + 0: 9101 + 102: subview 'p1' + VIEW 1 rows = p2:I + 0: 9102 + 103: subview 'p1' + VIEW 1 rows = p2:I + 0: 9103 + 104: subview 'p1' + VIEW 1 rows = p2:I + 0: 9104 + 105: subview 'p1' + VIEW 1 rows = p2:I + 0: 9105 + 106: subview 'p1' + VIEW 1 rows = p2:I + 0: 9106 + 107: subview 'p1' + VIEW 1 rows = p2:I + 0: 9107 + 108: subview 'p1' + VIEW 1 rows = p2:I + 0: 9108 + 109: subview 'p1' + VIEW 1 rows = p2:I + 0: 9109 + 110: subview 'p1' + VIEW 1 rows = p2:I + 0: 9110 + 111: subview 'p1' + VIEW 1 rows = p2:I + 0: 9111 + 112: subview 'p1' + VIEW 1 rows = p2:I + 0: 9112 + 113: subview 'p1' + VIEW 1 rows = p2:I + 0: 9113 + 114: subview 'p1' + VIEW 1 rows = p2:I + 0: 9114 + 115: subview 'p1' + VIEW 1 rows = p2:I + 0: 9115 + 116: subview 'p1' + VIEW 1 rows = p2:I + 0: 9116 + 117: subview 'p1' + VIEW 1 rows = p2:I + 0: 9117 + 118: subview 'p1' + VIEW 1 rows = p2:I + 0: 9118 + 119: subview 'p1' + VIEW 1 rows = p2:I + 0: 9119 + 120: subview 'p1' + VIEW 1 rows = p2:I + 0: 9120 + 121: subview 'p1' + VIEW 1 rows = p2:I + 0: 9121 + 122: subview 'p1' + VIEW 1 rows = p2:I + 0: 9122 + 123: subview 'p1' + VIEW 1 rows = p2:I + 0: 9123 + 124: subview 'p1' + VIEW 1 rows = p2:I + 0: 9124 + 125: subview 'p1' + VIEW 1 rows = p2:I + 0: 9125 + 126: subview 'p1' + VIEW 1 rows = p2:I + 0: 9126 + 127: subview 'p1' + VIEW 1 rows = p2:I + 0: 9127 + 128: subview 'p1' + VIEW 1 rows = p2:I + 0: 9128 + 129: subview 'p1' + VIEW 1 rows = p2:I + 0: 9129 + 130: subview 'p1' + VIEW 1 rows = p2:I + 0: 9130 + 131: subview 'p1' + VIEW 1 rows = p2:I + 0: 9131 + 132: subview 'p1' + VIEW 1 rows = p2:I + 0: 9132 + 133: subview 'p1' + VIEW 1 rows = p2:I + 0: 9133 + 134: subview 'p1' + VIEW 1 rows = p2:I + 0: 9134 + 135: subview 'p1' + VIEW 1 rows = p2:I + 0: 9135 + 136: subview 'p1' + VIEW 1 rows = p2:I + 0: 9136 + 137: subview 'p1' + VIEW 1 rows = p2:I + 0: 9137 + 138: subview 'p1' + VIEW 1 rows = p2:I + 0: 9138 + 139: subview 'p1' + VIEW 1 rows = p2:I + 0: 9139 + 140: subview 'p1' + VIEW 1 rows = p2:I + 0: 9140 + 141: subview 'p1' + VIEW 1 rows = p2:I + 0: 9141 + 142: subview 'p1' + VIEW 1 rows = p2:I + 0: 9142 + 143: subview 'p1' + VIEW 1 rows = p2:I + 0: 9143 + 144: subview 'p1' + VIEW 1 rows = p2:I + 0: 9144 + 145: subview 'p1' + VIEW 1 rows = p2:I + 0: 9145 + 146: subview 'p1' + VIEW 1 rows = p2:I + 0: 9146 + 147: subview 'p1' + VIEW 1 rows = p2:I + 0: 9147 + 148: subview 'p1' + VIEW 1 rows = p2:I + 0: 9148 + 149: subview 'p1' + VIEW 1 rows = p2:I + 0: 9149 + 150: subview 'p1' + VIEW 1 rows = p2:I + 0: 9150 + 151: subview 'p1' + VIEW 1 rows = p2:I + 0: 9151 + 152: subview 'p1' + VIEW 1 rows = p2:I + 0: 9152 + 153: subview 'p1' + VIEW 1 rows = p2:I + 0: 9153 + 154: subview 'p1' + VIEW 1 rows = p2:I + 0: 9154 + 155: subview 'p1' + VIEW 1 rows = p2:I + 0: 9155 + 156: subview 'p1' + VIEW 1 rows = p2:I + 0: 9156 + 157: subview 'p1' + VIEW 1 rows = p2:I + 0: 9157 + 158: subview 'p1' + VIEW 1 rows = p2:I + 0: 9158 + 159: subview 'p1' + VIEW 1 rows = p2:I + 0: 9159 + 160: subview 'p1' + VIEW 1 rows = p2:I + 0: 9160 + 161: subview 'p1' + VIEW 1 rows = p2:I + 0: 9161 + 162: subview 'p1' + VIEW 1 rows = p2:I + 0: 9162 + 163: subview 'p1' + VIEW 1 rows = p2:I + 0: 9163 + 164: subview 'p1' + VIEW 1 rows = p2:I + 0: 9164 + 165: subview 'p1' + VIEW 1 rows = p2:I + 0: 9165 + 166: subview 'p1' + VIEW 1 rows = p2:I + 0: 9166 + 167: subview 'p1' + VIEW 1 rows = p2:I + 0: 9167 + 168: subview 'p1' + VIEW 1 rows = p2:I + 0: 9168 + 169: subview 'p1' + VIEW 1 rows = p2:I + 0: 9169 + 170: subview 'p1' + VIEW 1 rows = p2:I + 0: 9170 + 171: subview 'p1' + VIEW 1 rows = p2:I + 0: 9171 + 172: subview 'p1' + VIEW 1 rows = p2:I + 0: 9172 + 173: subview 'p1' + VIEW 1 rows = p2:I + 0: 9173 + 174: subview 'p1' + VIEW 1 rows = p2:I + 0: 9174 + 175: subview 'p1' + VIEW 1 rows = p2:I + 0: 9175 + 176: subview 'p1' + VIEW 1 rows = p2:I + 0: 9176 + 177: subview 'p1' + VIEW 1 rows = p2:I + 0: 9177 + 178: subview 'p1' + VIEW 1 rows = p2:I + 0: 9178 + 179: subview 'p1' + VIEW 1 rows = p2:I + 0: 9179 + 180: subview 'p1' + VIEW 1 rows = p2:I + 0: 9180 + 181: subview 'p1' + VIEW 1 rows = p2:I + 0: 9181 + 182: subview 'p1' + VIEW 1 rows = p2:I + 0: 9182 + 183: subview 'p1' + VIEW 1 rows = p2:I + 0: 9183 + 184: subview 'p1' + VIEW 1 rows = p2:I + 0: 9184 + 185: subview 'p1' + VIEW 1 rows = p2:I + 0: 9185 + 186: subview 'p1' + VIEW 1 rows = p2:I + 0: 9186 + 187: subview 'p1' + VIEW 1 rows = p2:I + 0: 9187 + 188: subview 'p1' + VIEW 1 rows = p2:I + 0: 9188 + 189: subview 'p1' + VIEW 1 rows = p2:I + 0: 9189 + 190: subview 'p1' + VIEW 1 rows = p2:I + 0: 9190 + 191: subview 'p1' + VIEW 1 rows = p2:I + 0: 9191 + 192: subview 'p1' + VIEW 1 rows = p2:I + 0: 9192 + 193: subview 'p1' + VIEW 1 rows = p2:I + 0: 9193 + 194: subview 'p1' + VIEW 1 rows = p2:I + 0: 9194 + 195: subview 'p1' + VIEW 1 rows = p2:I + 0: 9195 + 196: subview 'p1' + VIEW 1 rows = p2:I + 0: 9196 + 197: subview 'p1' + VIEW 1 rows = p2:I + 0: 9197 + 198: subview 'p1' + VIEW 1 rows = p2:I + 0: 9198 + 199: subview 'p1' + VIEW 1 rows = p2:I + 0: 9199 + 200: subview 'p1' + VIEW 1 rows = p2:I + 0: 9200 + 201: subview 'p1' + VIEW 1 rows = p2:I + 0: 9201 + 202: subview 'p1' + VIEW 1 rows = p2:I + 0: 9202 + 203: subview 'p1' + VIEW 1 rows = p2:I + 0: 9203 + 204: subview 'p1' + VIEW 1 rows = p2:I + 0: 9204 + 205: subview 'p1' + VIEW 1 rows = p2:I + 0: 9205 + 206: subview 'p1' + VIEW 1 rows = p2:I + 0: 9206 + 207: subview 'p1' + VIEW 1 rows = p2:I + 0: 9207 + 208: subview 'p1' + VIEW 1 rows = p2:I + 0: 9208 + 209: subview 'p1' + VIEW 1 rows = p2:I + 0: 9209 + 210: subview 'p1' + VIEW 1 rows = p2:I + 0: 9210 + 211: subview 'p1' + VIEW 1 rows = p2:I + 0: 9211 + 212: subview 'p1' + VIEW 1 rows = p2:I + 0: 9212 + 213: subview 'p1' + VIEW 1 rows = p2:I + 0: 9213 + 214: subview 'p1' + VIEW 1 rows = p2:I + 0: 9214 + 215: subview 'p1' + VIEW 1 rows = p2:I + 0: 9215 + 216: subview 'p1' + VIEW 1 rows = p2:I + 0: 9216 + 217: subview 'p1' + VIEW 1 rows = p2:I + 0: 9217 + 218: subview 'p1' + VIEW 1 rows = p2:I + 0: 9218 + 219: subview 'p1' + VIEW 1 rows = p2:I + 0: 9219 + 220: subview 'p1' + VIEW 1 rows = p2:I + 0: 9220 + 221: subview 'p1' + VIEW 1 rows = p2:I + 0: 9221 + 222: subview 'p1' + VIEW 1 rows = p2:I + 0: 9222 + 223: subview 'p1' + VIEW 1 rows = p2:I + 0: 9223 + 224: subview 'p1' + VIEW 1 rows = p2:I + 0: 9224 + 225: subview 'p1' + VIEW 1 rows = p2:I + 0: 9225 + 226: subview 'p1' + VIEW 1 rows = p2:I + 0: 9226 + 227: subview 'p1' + VIEW 1 rows = p2:I + 0: 9227 + 228: subview 'p1' + VIEW 1 rows = p2:I + 0: 9228 + 229: subview 'p1' + VIEW 1 rows = p2:I + 0: 9229 + 230: subview 'p1' + VIEW 1 rows = p2:I + 0: 9230 + 231: subview 'p1' + VIEW 1 rows = p2:I + 0: 9231 + 232: subview 'p1' + VIEW 1 rows = p2:I + 0: 9232 + 233: subview 'p1' + VIEW 1 rows = p2:I + 0: 9233 + 234: subview 'p1' + VIEW 1 rows = p2:I + 0: 9234 + 235: subview 'p1' + VIEW 1 rows = p2:I + 0: 9235 + 236: subview 'p1' + VIEW 1 rows = p2:I + 0: 9236 + 237: subview 'p1' + VIEW 1 rows = p2:I + 0: 9237 + 238: subview 'p1' + VIEW 1 rows = p2:I + 0: 9238 + 239: subview 'p1' + VIEW 1 rows = p2:I + 0: 9239 + 240: subview 'p1' + VIEW 1 rows = p2:I + 0: 9240 + 241: subview 'p1' + VIEW 1 rows = p2:I + 0: 9241 + 242: subview 'p1' + VIEW 1 rows = p2:I + 0: 9242 + 243: subview 'p1' + VIEW 1 rows = p2:I + 0: 9243 + 244: subview 'p1' + VIEW 1 rows = p2:I + 0: 9244 + 245: subview 'p1' + VIEW 1 rows = p2:I + 0: 9245 + 246: subview 'p1' + VIEW 1 rows = p2:I + 0: 9246 + 247: subview 'p1' + VIEW 1 rows = p2:I + 0: 9247 + 248: subview 'p1' + VIEW 1 rows = p2:I + 0: 9248 + 249: subview 'p1' + VIEW 1 rows = p2:I + 0: 9249 + 250: subview 'p1' + VIEW 1 rows = p2:I + 0: 9250 + 251: subview 'p1' + VIEW 1 rows = p2:I + 0: 9251 + 252: subview 'p1' + VIEW 1 rows = p2:I + 0: 9252 + 253: subview 'p1' + VIEW 1 rows = p2:I + 0: 9253 + 254: subview 'p1' + VIEW 1 rows = p2:I + 0: 9254 + 255: subview 'p1' + VIEW 1 rows = p2:I + 0: 9255 + 256: subview 'p1' + VIEW 1 rows = p2:I + 0: 9256 + 257: subview 'p1' + VIEW 1 rows = p2:I + 0: 9257 + 258: subview 'p1' + VIEW 1 rows = p2:I + 0: 9258 + 259: subview 'p1' + VIEW 1 rows = p2:I + 0: 9259 + 260: subview 'p1' + VIEW 1 rows = p2:I + 0: 9260 + 261: subview 'p1' + VIEW 1 rows = p2:I + 0: 9261 + 262: subview 'p1' + VIEW 1 rows = p2:I + 0: 9262 + 263: subview 'p1' + VIEW 1 rows = p2:I + 0: 9263 + 264: subview 'p1' + VIEW 1 rows = p2:I + 0: 9264 + 265: subview 'p1' + VIEW 1 rows = p2:I + 0: 9265 + 266: subview 'p1' + VIEW 1 rows = p2:I + 0: 9266 + 267: subview 'p1' + VIEW 1 rows = p2:I + 0: 9267 + 268: subview 'p1' + VIEW 1 rows = p2:I + 0: 9268 + 269: subview 'p1' + VIEW 1 rows = p2:I + 0: 9269 + 270: subview 'p1' + VIEW 1 rows = p2:I + 0: 9270 + 271: subview 'p1' + VIEW 1 rows = p2:I + 0: 9271 + 272: subview 'p1' + VIEW 1 rows = p2:I + 0: 9272 + 273: subview 'p1' + VIEW 1 rows = p2:I + 0: 9273 + 274: subview 'p1' + VIEW 1 rows = p2:I + 0: 9274 + 275: subview 'p1' + VIEW 1 rows = p2:I + 0: 9275 + 276: subview 'p1' + VIEW 1 rows = p2:I + 0: 9276 + 277: subview 'p1' + VIEW 1 rows = p2:I + 0: 9277 + 278: subview 'p1' + VIEW 1 rows = p2:I + 0: 9278 + 279: subview 'p1' + VIEW 1 rows = p2:I + 0: 9279 + 280: subview 'p1' + VIEW 1 rows = p2:I + 0: 9280 + 281: subview 'p1' + VIEW 1 rows = p2:I + 0: 9281 + 282: subview 'p1' + VIEW 1 rows = p2:I + 0: 9282 + 283: subview 'p1' + VIEW 1 rows = p2:I + 0: 9283 + 284: subview 'p1' + VIEW 1 rows = p2:I + 0: 9284 + 285: subview 'p1' + VIEW 1 rows = p2:I + 0: 9285 + 286: subview 'p1' + VIEW 1 rows = p2:I + 0: 9286 + 287: subview 'p1' + VIEW 1 rows = p2:I + 0: 9287 + 288: subview 'p1' + VIEW 1 rows = p2:I + 0: 9288 + 289: subview 'p1' + VIEW 1 rows = p2:I + 0: 9289 + 290: subview 'p1' + VIEW 1 rows = p2:I + 0: 9290 + 291: subview 'p1' + VIEW 1 rows = p2:I + 0: 9291 + 292: subview 'p1' + VIEW 1 rows = p2:I + 0: 9292 + 293: subview 'p1' + VIEW 1 rows = p2:I + 0: 9293 + 294: subview 'p1' + VIEW 1 rows = p2:I + 0: 9294 + 295: subview 'p1' + VIEW 1 rows = p2:I + 0: 9295 + 296: subview 'p1' + VIEW 1 rows = p2:I + 0: 9296 + 297: subview 'p1' + VIEW 1 rows = p2:I + 0: 9297 + 298: subview 'p1' + VIEW 1 rows = p2:I + 0: 9298 + 299: subview 'p1' + VIEW 1 rows = p2:I + 0: 9299 + 300: subview 'p1' + VIEW 1 rows = p2:I + 0: 9300 + 301: subview 'p1' + VIEW 1 rows = p2:I + 0: 9301 + 302: subview 'p1' + VIEW 1 rows = p2:I + 0: 9302 + 303: subview 'p1' + VIEW 1 rows = p2:I + 0: 9303 + 304: subview 'p1' + VIEW 1 rows = p2:I + 0: 9304 + 305: subview 'p1' + VIEW 1 rows = p2:I + 0: 9305 + 306: subview 'p1' + VIEW 1 rows = p2:I + 0: 9306 + 307: subview 'p1' + VIEW 1 rows = p2:I + 0: 9307 + 308: subview 'p1' + VIEW 1 rows = p2:I + 0: 9308 + 309: subview 'p1' + VIEW 1 rows = p2:I + 0: 9309 + 310: subview 'p1' + VIEW 1 rows = p2:I + 0: 9310 + 311: subview 'p1' + VIEW 1 rows = p2:I + 0: 9311 + 312: subview 'p1' + VIEW 1 rows = p2:I + 0: 9312 + 313: subview 'p1' + VIEW 1 rows = p2:I + 0: 9313 + 314: subview 'p1' + VIEW 1 rows = p2:I + 0: 9314 + 315: subview 'p1' + VIEW 1 rows = p2:I + 0: 9315 + 316: subview 'p1' + VIEW 1 rows = p2:I + 0: 9316 + 317: subview 'p1' + VIEW 1 rows = p2:I + 0: 9317 + 318: subview 'p1' + VIEW 1 rows = p2:I + 0: 9318 + 319: subview 'p1' + VIEW 1 rows = p2:I + 0: 9319 + 320: subview 'p1' + VIEW 1 rows = p2:I + 0: 9320 + 321: subview 'p1' + VIEW 1 rows = p2:I + 0: 9321 + 322: subview 'p1' + VIEW 1 rows = p2:I + 0: 9322 + 323: subview 'p1' + VIEW 1 rows = p2:I + 0: 9323 + 324: subview 'p1' + VIEW 1 rows = p2:I + 0: 9324 + 325: subview 'p1' + VIEW 1 rows = p2:I + 0: 9325 + 326: subview 'p1' + VIEW 1 rows = p2:I + 0: 9326 + 327: subview 'p1' + VIEW 1 rows = p2:I + 0: 9327 + 328: subview 'p1' + VIEW 1 rows = p2:I + 0: 9328 + 329: subview 'p1' + VIEW 1 rows = p2:I + 0: 9329 + 330: subview 'p1' + VIEW 1 rows = p2:I + 0: 9330 + 331: subview 'p1' + VIEW 1 rows = p2:I + 0: 9331 + 332: subview 'p1' + VIEW 1 rows = p2:I + 0: 9332 + 333: subview 'p1' + VIEW 1 rows = p2:I + 0: 9333 + 334: subview 'p1' + VIEW 1 rows = p2:I + 0: 9334 + 335: subview 'p1' + VIEW 1 rows = p2:I + 0: 9335 + 336: subview 'p1' + VIEW 1 rows = p2:I + 0: 9336 + 337: subview 'p1' + VIEW 1 rows = p2:I + 0: 9337 + 338: subview 'p1' + VIEW 1 rows = p2:I + 0: 9338 + 339: subview 'p1' + VIEW 1 rows = p2:I + 0: 9339 + 340: subview 'p1' + VIEW 1 rows = p2:I + 0: 9340 + 341: subview 'p1' + VIEW 1 rows = p2:I + 0: 9341 + 342: subview 'p1' + VIEW 1 rows = p2:I + 0: 9342 + 343: subview 'p1' + VIEW 1 rows = p2:I + 0: 9343 + 344: subview 'p1' + VIEW 1 rows = p2:I + 0: 9344 + 345: subview 'p1' + VIEW 1 rows = p2:I + 0: 9345 + 346: subview 'p1' + VIEW 1 rows = p2:I + 0: 9346 + 347: subview 'p1' + VIEW 1 rows = p2:I + 0: 9347 + 348: subview 'p1' + VIEW 1 rows = p2:I + 0: 9348 + 349: subview 'p1' + VIEW 1 rows = p2:I + 0: 9349 + 350: subview 'p1' + VIEW 1 rows = p2:I + 0: 9350 + 351: subview 'p1' + VIEW 1 rows = p2:I + 0: 9351 + 352: subview 'p1' + VIEW 1 rows = p2:I + 0: 9352 + 353: subview 'p1' + VIEW 1 rows = p2:I + 0: 9353 + 354: subview 'p1' + VIEW 1 rows = p2:I + 0: 9354 + 355: subview 'p1' + VIEW 1 rows = p2:I + 0: 9355 + 356: subview 'p1' + VIEW 1 rows = p2:I + 0: 9356 + 357: subview 'p1' + VIEW 1 rows = p2:I + 0: 9357 + 358: subview 'p1' + VIEW 1 rows = p2:I + 0: 9358 + 359: subview 'p1' + VIEW 1 rows = p2:I + 0: 9359 + 360: subview 'p1' + VIEW 1 rows = p2:I + 0: 9360 + 361: subview 'p1' + VIEW 1 rows = p2:I + 0: 9361 + 362: subview 'p1' + VIEW 1 rows = p2:I + 0: 9362 + 363: subview 'p1' + VIEW 1 rows = p2:I + 0: 9363 + 364: subview 'p1' + VIEW 1 rows = p2:I + 0: 9364 + 365: subview 'p1' + VIEW 1 rows = p2:I + 0: 9365 + 366: subview 'p1' + VIEW 1 rows = p2:I + 0: 9366 + 367: subview 'p1' + VIEW 1 rows = p2:I + 0: 9367 + 368: subview 'p1' + VIEW 1 rows = p2:I + 0: 9368 + 369: subview 'p1' + VIEW 1 rows = p2:I + 0: 9369 + 370: subview 'p1' + VIEW 1 rows = p2:I + 0: 9370 + 371: subview 'p1' + VIEW 1 rows = p2:I + 0: 9371 + 372: subview 'p1' + VIEW 1 rows = p2:I + 0: 9372 + 373: subview 'p1' + VIEW 1 rows = p2:I + 0: 9373 + 374: subview 'p1' + VIEW 1 rows = p2:I + 0: 9374 + 375: subview 'p1' + VIEW 1 rows = p2:I + 0: 9375 + 376: subview 'p1' + VIEW 1 rows = p2:I + 0: 9376 + 377: subview 'p1' + VIEW 1 rows = p2:I + 0: 9377 + 378: subview 'p1' + VIEW 1 rows = p2:I + 0: 9378 + 379: subview 'p1' + VIEW 1 rows = p2:I + 0: 9379 + 380: subview 'p1' + VIEW 1 rows = p2:I + 0: 9380 + 381: subview 'p1' + VIEW 1 rows = p2:I + 0: 9381 + 382: subview 'p1' + VIEW 1 rows = p2:I + 0: 9382 + 383: subview 'p1' + VIEW 1 rows = p2:I + 0: 9383 + 384: subview 'p1' + VIEW 1 rows = p2:I + 0: 9384 + 385: subview 'p1' + VIEW 1 rows = p2:I + 0: 9385 + 386: subview 'p1' + VIEW 1 rows = p2:I + 0: 9386 + 387: subview 'p1' + VIEW 1 rows = p2:I + 0: 9387 + 388: subview 'p1' + VIEW 1 rows = p2:I + 0: 9388 + 389: subview 'p1' + VIEW 1 rows = p2:I + 0: 9389 + 390: subview 'p1' + VIEW 1 rows = p2:I + 0: 9390 + 391: subview 'p1' + VIEW 1 rows = p2:I + 0: 9391 + 392: subview 'p1' + VIEW 1 rows = p2:I + 0: 9392 + 393: subview 'p1' + VIEW 1 rows = p2:I + 0: 9393 + 394: subview 'p1' + VIEW 1 rows = p2:I + 0: 9394 + 395: subview 'p1' + VIEW 1 rows = p2:I + 0: 9395 + 396: subview 'p1' + VIEW 1 rows = p2:I + 0: 9396 + 397: subview 'p1' + VIEW 1 rows = p2:I + 0: 9397 + 398: subview 'p1' + VIEW 1 rows = p2:I + 0: 9398 + 399: subview 'p1' + VIEW 1 rows = p2:I + 0: 9399 + 400: subview 'p1' + VIEW 1 rows = p2:I + 0: 9400 + 401: subview 'p1' + VIEW 1 rows = p2:I + 0: 9401 + 402: subview 'p1' + VIEW 1 rows = p2:I + 0: 9402 + 403: subview 'p1' + VIEW 1 rows = p2:I + 0: 9403 + 404: subview 'p1' + VIEW 1 rows = p2:I + 0: 9404 + 405: subview 'p1' + VIEW 1 rows = p2:I + 0: 9405 + 406: subview 'p1' + VIEW 1 rows = p2:I + 0: 9406 + 407: subview 'p1' + VIEW 1 rows = p2:I + 0: 9407 + 408: subview 'p1' + VIEW 1 rows = p2:I + 0: 9408 + 409: subview 'p1' + VIEW 1 rows = p2:I + 0: 9409 + 410: subview 'p1' + VIEW 1 rows = p2:I + 0: 9410 + 411: subview 'p1' + VIEW 1 rows = p2:I + 0: 9411 + 412: subview 'p1' + VIEW 1 rows = p2:I + 0: 9412 + 413: subview 'p1' + VIEW 1 rows = p2:I + 0: 9413 + 414: subview 'p1' + VIEW 1 rows = p2:I + 0: 9414 + 415: subview 'p1' + VIEW 1 rows = p2:I + 0: 9415 + 416: subview 'p1' + VIEW 1 rows = p2:I + 0: 9416 + 417: subview 'p1' + VIEW 1 rows = p2:I + 0: 9417 + 418: subview 'p1' + VIEW 1 rows = p2:I + 0: 9418 + 419: subview 'p1' + VIEW 1 rows = p2:I + 0: 9419 + 420: subview 'p1' + VIEW 1 rows = p2:I + 0: 9420 + 421: subview 'p1' + VIEW 1 rows = p2:I + 0: 9421 + 422: subview 'p1' + VIEW 1 rows = p2:I + 0: 9422 + 423: subview 'p1' + VIEW 1 rows = p2:I + 0: 9423 + 424: subview 'p1' + VIEW 1 rows = p2:I + 0: 9424 + 425: subview 'p1' + VIEW 1 rows = p2:I + 0: 9425 + 426: subview 'p1' + VIEW 1 rows = p2:I + 0: 9426 + 427: subview 'p1' + VIEW 1 rows = p2:I + 0: 9427 + 428: subview 'p1' + VIEW 1 rows = p2:I + 0: 9428 + 429: subview 'p1' + VIEW 1 rows = p2:I + 0: 9429 + 430: subview 'p1' + VIEW 1 rows = p2:I + 0: 9430 + 431: subview 'p1' + VIEW 1 rows = p2:I + 0: 9431 + 432: subview 'p1' + VIEW 1 rows = p2:I + 0: 9432 + 433: subview 'p1' + VIEW 1 rows = p2:I + 0: 9433 + 434: subview 'p1' + VIEW 1 rows = p2:I + 0: 9434 + 435: subview 'p1' + VIEW 1 rows = p2:I + 0: 9435 + 436: subview 'p1' + VIEW 1 rows = p2:I + 0: 9436 + 437: subview 'p1' + VIEW 1 rows = p2:I + 0: 9437 + 438: subview 'p1' + VIEW 1 rows = p2:I + 0: 9438 + 439: subview 'p1' + VIEW 1 rows = p2:I + 0: 9439 + 440: subview 'p1' + VIEW 1 rows = p2:I + 0: 9440 + 441: subview 'p1' + VIEW 1 rows = p2:I + 0: 9441 + 442: subview 'p1' + VIEW 1 rows = p2:I + 0: 9442 + 443: subview 'p1' + VIEW 1 rows = p2:I + 0: 9443 + 444: subview 'p1' + VIEW 1 rows = p2:I + 0: 9444 + 445: subview 'p1' + VIEW 1 rows = p2:I + 0: 9445 + 446: subview 'p1' + VIEW 1 rows = p2:I + 0: 9446 + 447: subview 'p1' + VIEW 1 rows = p2:I + 0: 9447 + 448: subview 'p1' + VIEW 1 rows = p2:I + 0: 9448 + 449: subview 'p1' + VIEW 1 rows = p2:I + 0: 9449 + 450: subview 'p1' + VIEW 1 rows = p2:I + 0: 9450 + 451: subview 'p1' + VIEW 1 rows = p2:I + 0: 9451 + 452: subview 'p1' + VIEW 1 rows = p2:I + 0: 9452 + 453: subview 'p1' + VIEW 1 rows = p2:I + 0: 9453 + 454: subview 'p1' + VIEW 1 rows = p2:I + 0: 9454 + 455: subview 'p1' + VIEW 1 rows = p2:I + 0: 9455 + 456: subview 'p1' + VIEW 1 rows = p2:I + 0: 9456 + 457: subview 'p1' + VIEW 1 rows = p2:I + 0: 9457 + 458: subview 'p1' + VIEW 1 rows = p2:I + 0: 9458 + 459: subview 'p1' + VIEW 1 rows = p2:I + 0: 9459 + 460: subview 'p1' + VIEW 1 rows = p2:I + 0: 9460 + 461: subview 'p1' + VIEW 1 rows = p2:I + 0: 9461 + 462: subview 'p1' + VIEW 1 rows = p2:I + 0: 9462 + 463: subview 'p1' + VIEW 1 rows = p2:I + 0: 9463 + 464: subview 'p1' + VIEW 1 rows = p2:I + 0: 9464 + 465: subview 'p1' + VIEW 1 rows = p2:I + 0: 9465 + 466: subview 'p1' + VIEW 1 rows = p2:I + 0: 9466 + 467: subview 'p1' + VIEW 1 rows = p2:I + 0: 9467 + 468: subview 'p1' + VIEW 1 rows = p2:I + 0: 9468 + 469: subview 'p1' + VIEW 1 rows = p2:I + 0: 9469 + 470: subview 'p1' + VIEW 1 rows = p2:I + 0: 9470 + 471: subview 'p1' + VIEW 1 rows = p2:I + 0: 9471 + 472: subview 'p1' + VIEW 1 rows = p2:I + 0: 9472 + 473: subview 'p1' + VIEW 1 rows = p2:I + 0: 9473 + 474: subview 'p1' + VIEW 1 rows = p2:I + 0: 9474 + 475: subview 'p1' + VIEW 1 rows = p2:I + 0: 9475 + 476: subview 'p1' + VIEW 1 rows = p2:I + 0: 9476 + 477: subview 'p1' + VIEW 1 rows = p2:I + 0: 9477 + 478: subview 'p1' + VIEW 1 rows = p2:I + 0: 9478 + 479: subview 'p1' + VIEW 1 rows = p2:I + 0: 9479 + 480: subview 'p1' + VIEW 1 rows = p2:I + 0: 9480 + 481: subview 'p1' + VIEW 1 rows = p2:I + 0: 9481 + 482: subview 'p1' + VIEW 1 rows = p2:I + 0: 9482 + 483: subview 'p1' + VIEW 1 rows = p2:I + 0: 9483 + 484: subview 'p1' + VIEW 1 rows = p2:I + 0: 9484 + 485: subview 'p1' + VIEW 1 rows = p2:I + 0: 9485 + 486: subview 'p1' + VIEW 1 rows = p2:I + 0: 9486 + 487: subview 'p1' + VIEW 1 rows = p2:I + 0: 9487 + 488: subview 'p1' + VIEW 1 rows = p2:I + 0: 9488 + 489: subview 'p1' + VIEW 1 rows = p2:I + 0: 9489 + 490: subview 'p1' + VIEW 1 rows = p2:I + 0: 9490 + 491: subview 'p1' + VIEW 1 rows = p2:I + 0: 9491 + 492: subview 'p1' + VIEW 1 rows = p2:I + 0: 9492 + 493: subview 'p1' + VIEW 1 rows = p2:I + 0: 9493 + 494: subview 'p1' + VIEW 1 rows = p2:I + 0: 9494 + 495: subview 'p1' + VIEW 1 rows = p2:I + 0: 9495 + 496: subview 'p1' + VIEW 1 rows = p2:I + 0: 9496 + 497: subview 'p1' + VIEW 1 rows = p2:I + 0: 9497 + 498: subview 'p1' + VIEW 1 rows = p2:I + 0: 9498 + 499: subview 'p1' + VIEW 1 rows = p2:I + 0: 9499 diff --git a/akregator/src/mk4storage/metakit/tests/ok/l05.txt b/akregator/src/mk4storage/metakit/tests/ok/l05.txt new file mode 100644 index 000000000..64d8af7ad --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l05.txt @@ -0,0 +1,2 @@ +>>> Delete from 32 Kb of strings +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/l05a.txt b/akregator/src/mk4storage/metakit/tests/ok/l05a.txt new file mode 100644 index 000000000..d01cb2dc6 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l05a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I p2:S p3:S + 0: 1747 'The wizard of Oz' 'The wizard of Oz' diff --git a/akregator/src/mk4storage/metakit/tests/ok/l06.txt b/akregator/src/mk4storage/metakit/tests/ok/l06.txt new file mode 100644 index 000000000..d5e421d0d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l06.txt @@ -0,0 +1,2 @@ +>>> Bit field manipulations +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/l06a.txt b/akregator/src/mk4storage/metakit/tests/ok/l06a.txt new file mode 100644 index 000000000..05757a48e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l06a.txt @@ -0,0 +1,1371 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1368 rows = p1:I + 0: 0 + 1: 1 + 2: 2 + 3: 3 + 4: 4 + 5: 5 + 6: 6 + 7: 7 + 8: 8 + 9: 9 + 10: 10 + 11: 11 + 12: 12 + 13: 13 + 14: 14 + 15: 15 + 16: 16 + 17: 17 + 18: 17 + 19: 17 + 20: 17 + 21: 17 + 22: 17 + 23: 17 + 24: 17 + 25: 17 + 26: 17 + 27: 17 + 28: 17 + 29: 17 + 30: 17 + 31: 17 + 32: 17 + 33: 17 + 34: 17 + 35: 16 + 36: 16 + 37: 16 + 38: 16 + 39: 16 + 40: 16 + 41: 16 + 42: 16 + 43: 16 + 44: 16 + 45: 16 + 46: 16 + 47: 16 + 48: 16 + 49: 16 + 50: 16 + 51: 15 + 52: 15 + 53: 15 + 54: 15 + 55: 15 + 56: 15 + 57: 15 + 58: 15 + 59: 15 + 60: 15 + 61: 15 + 62: 15 + 63: 15 + 64: 15 + 65: 15 + 66: 14 + 67: 14 + 68: 14 + 69: 14 + 70: 14 + 71: 14 + 72: 14 + 73: 14 + 74: 14 + 75: 14 + 76: 14 + 77: 14 + 78: 14 + 79: 14 + 80: 13 + 81: 13 + 82: 13 + 83: 13 + 84: 13 + 85: 13 + 86: 13 + 87: 13 + 88: 13 + 89: 13 + 90: 13 + 91: 13 + 92: 13 + 93: 12 + 94: 12 + 95: 12 + 96: 12 + 97: 12 + 98: 12 + 99: 12 + 100: 12 + 101: 12 + 102: 12 + 103: 12 + 104: 12 + 105: 11 + 106: 11 + 107: 11 + 108: 11 + 109: 11 + 110: 11 + 111: 11 + 112: 11 + 113: 11 + 114: 11 + 115: 11 + 116: 10 + 117: 10 + 118: 10 + 119: 10 + 120: 10 + 121: 10 + 122: 10 + 123: 10 + 124: 10 + 125: 10 + 126: 9 + 127: 9 + 128: 9 + 129: 9 + 130: 9 + 131: 9 + 132: 9 + 133: 9 + 134: 9 + 135: 8 + 136: 8 + 137: 8 + 138: 8 + 139: 8 + 140: 8 + 141: 8 + 142: 8 + 143: 7 + 144: 7 + 145: 7 + 146: 7 + 147: 7 + 148: 7 + 149: 7 + 150: 6 + 151: 6 + 152: 6 + 153: 6 + 154: 6 + 155: 6 + 156: 5 + 157: 5 + 158: 5 + 159: 5 + 160: 5 + 161: 4 + 162: 4 + 163: 4 + 164: 4 + 165: 3 + 166: 3 + 167: 3 + 168: 2 + 169: 2 + 170: 1 + 171: 0 + 172: 1 + 173: 2 + 174: 3 + 175: 4 + 176: 5 + 177: 6 + 178: 7 + 179: 8 + 180: 9 + 181: 10 + 182: 11 + 183: 12 + 184: 13 + 185: 14 + 186: 15 + 187: 16 + 188: 17 + 189: 17 + 190: 17 + 191: 17 + 192: 17 + 193: 17 + 194: 17 + 195: 17 + 196: 17 + 197: 17 + 198: 17 + 199: 17 + 200: 17 + 201: 17 + 202: 17 + 203: 17 + 204: 17 + 205: 17 + 206: 16 + 207: 16 + 208: 16 + 209: 16 + 210: 16 + 211: 16 + 212: 16 + 213: 16 + 214: 16 + 215: 16 + 216: 16 + 217: 16 + 218: 16 + 219: 16 + 220: 16 + 221: 16 + 222: 15 + 223: 15 + 224: 15 + 225: 15 + 226: 15 + 227: 15 + 228: 15 + 229: 15 + 230: 15 + 231: 15 + 232: 15 + 233: 15 + 234: 15 + 235: 15 + 236: 15 + 237: 14 + 238: 14 + 239: 14 + 240: 14 + 241: 14 + 242: 14 + 243: 14 + 244: 14 + 245: 14 + 246: 14 + 247: 14 + 248: 14 + 249: 14 + 250: 14 + 251: 13 + 252: 13 + 253: 13 + 254: 13 + 255: 13 + 256: 13 + 257: 13 + 258: 13 + 259: 13 + 260: 13 + 261: 13 + 262: 13 + 263: 13 + 264: 12 + 265: 12 + 266: 12 + 267: 12 + 268: 12 + 269: 12 + 270: 12 + 271: 12 + 272: 12 + 273: 12 + 274: 12 + 275: 12 + 276: 11 + 277: 11 + 278: 11 + 279: 11 + 280: 11 + 281: 11 + 282: 11 + 283: 11 + 284: 11 + 285: 11 + 286: 11 + 287: 10 + 288: 10 + 289: 10 + 290: 10 + 291: 10 + 292: 10 + 293: 10 + 294: 10 + 295: 10 + 296: 10 + 297: 9 + 298: 9 + 299: 9 + 300: 9 + 301: 9 + 302: 9 + 303: 9 + 304: 9 + 305: 9 + 306: 8 + 307: 8 + 308: 8 + 309: 8 + 310: 8 + 311: 8 + 312: 8 + 313: 8 + 314: 7 + 315: 7 + 316: 7 + 317: 7 + 318: 7 + 319: 7 + 320: 7 + 321: 6 + 322: 6 + 323: 6 + 324: 6 + 325: 6 + 326: 6 + 327: 5 + 328: 5 + 329: 5 + 330: 5 + 331: 5 + 332: 4 + 333: 4 + 334: 4 + 335: 4 + 336: 3 + 337: 3 + 338: 3 + 339: 2 + 340: 2 + 341: 1 + 342: 0 + 343: 1 + 344: 2 + 345: 3 + 346: 4 + 347: 5 + 348: 6 + 349: 7 + 350: 8 + 351: 9 + 352: 10 + 353: 11 + 354: 12 + 355: 13 + 356: 14 + 357: 15 + 358: 16 + 359: 17 + 360: 17 + 361: 17 + 362: 17 + 363: 17 + 364: 17 + 365: 17 + 366: 17 + 367: 17 + 368: 17 + 369: 17 + 370: 17 + 371: 17 + 372: 17 + 373: 17 + 374: 17 + 375: 17 + 376: 17 + 377: 16 + 378: 16 + 379: 16 + 380: 16 + 381: 16 + 382: 16 + 383: 16 + 384: 16 + 385: 16 + 386: 16 + 387: 16 + 388: 16 + 389: 16 + 390: 16 + 391: 16 + 392: 16 + 393: 15 + 394: 15 + 395: 15 + 396: 15 + 397: 15 + 398: 15 + 399: 15 + 400: 15 + 401: 15 + 402: 15 + 403: 15 + 404: 15 + 405: 15 + 406: 15 + 407: 15 + 408: 14 + 409: 14 + 410: 14 + 411: 14 + 412: 14 + 413: 14 + 414: 14 + 415: 14 + 416: 14 + 417: 14 + 418: 14 + 419: 14 + 420: 14 + 421: 14 + 422: 13 + 423: 13 + 424: 13 + 425: 13 + 426: 13 + 427: 13 + 428: 13 + 429: 13 + 430: 13 + 431: 13 + 432: 13 + 433: 13 + 434: 13 + 435: 12 + 436: 12 + 437: 12 + 438: 12 + 439: 12 + 440: 12 + 441: 12 + 442: 12 + 443: 12 + 444: 12 + 445: 12 + 446: 12 + 447: 11 + 448: 11 + 449: 11 + 450: 11 + 451: 11 + 452: 11 + 453: 11 + 454: 11 + 455: 11 + 456: 11 + 457: 11 + 458: 10 + 459: 10 + 460: 10 + 461: 10 + 462: 10 + 463: 10 + 464: 10 + 465: 10 + 466: 10 + 467: 10 + 468: 9 + 469: 9 + 470: 9 + 471: 9 + 472: 9 + 473: 9 + 474: 9 + 475: 9 + 476: 9 + 477: 8 + 478: 8 + 479: 8 + 480: 8 + 481: 8 + 482: 8 + 483: 8 + 484: 8 + 485: 7 + 486: 7 + 487: 7 + 488: 7 + 489: 7 + 490: 7 + 491: 7 + 492: 6 + 493: 6 + 494: 6 + 495: 6 + 496: 6 + 497: 6 + 498: 5 + 499: 5 + 500: 5 + 501: 5 + 502: 5 + 503: 4 + 504: 4 + 505: 4 + 506: 4 + 507: 3 + 508: 3 + 509: 3 + 510: 2 + 511: 2 + 512: 1 + 513: 0 + 514: 1 + 515: 2 + 516: 3 + 517: 4 + 518: 5 + 519: 6 + 520: 7 + 521: 8 + 522: 9 + 523: 10 + 524: 11 + 525: 12 + 526: 13 + 527: 14 + 528: 15 + 529: 16 + 530: 17 + 531: 17 + 532: 17 + 533: 17 + 534: 17 + 535: 17 + 536: 17 + 537: 17 + 538: 17 + 539: 17 + 540: 17 + 541: 17 + 542: 17 + 543: 17 + 544: 17 + 545: 17 + 546: 17 + 547: 17 + 548: 16 + 549: 16 + 550: 16 + 551: 16 + 552: 16 + 553: 16 + 554: 16 + 555: 16 + 556: 16 + 557: 16 + 558: 16 + 559: 16 + 560: 16 + 561: 16 + 562: 16 + 563: 16 + 564: 15 + 565: 15 + 566: 15 + 567: 15 + 568: 15 + 569: 15 + 570: 15 + 571: 15 + 572: 15 + 573: 15 + 574: 15 + 575: 15 + 576: 15 + 577: 15 + 578: 15 + 579: 14 + 580: 14 + 581: 14 + 582: 14 + 583: 14 + 584: 14 + 585: 14 + 586: 14 + 587: 14 + 588: 14 + 589: 14 + 590: 14 + 591: 14 + 592: 14 + 593: 13 + 594: 13 + 595: 13 + 596: 13 + 597: 13 + 598: 13 + 599: 13 + 600: 13 + 601: 13 + 602: 13 + 603: 13 + 604: 13 + 605: 13 + 606: 12 + 607: 12 + 608: 12 + 609: 12 + 610: 12 + 611: 12 + 612: 12 + 613: 12 + 614: 12 + 615: 12 + 616: 12 + 617: 12 + 618: 11 + 619: 11 + 620: 11 + 621: 11 + 622: 11 + 623: 11 + 624: 11 + 625: 11 + 626: 11 + 627: 11 + 628: 11 + 629: 10 + 630: 10 + 631: 10 + 632: 10 + 633: 10 + 634: 10 + 635: 10 + 636: 10 + 637: 10 + 638: 10 + 639: 9 + 640: 9 + 641: 9 + 642: 9 + 643: 9 + 644: 9 + 645: 9 + 646: 9 + 647: 9 + 648: 8 + 649: 8 + 650: 8 + 651: 8 + 652: 8 + 653: 8 + 654: 8 + 655: 8 + 656: 7 + 657: 7 + 658: 7 + 659: 7 + 660: 7 + 661: 7 + 662: 7 + 663: 6 + 664: 6 + 665: 6 + 666: 6 + 667: 6 + 668: 6 + 669: 5 + 670: 5 + 671: 5 + 672: 5 + 673: 5 + 674: 4 + 675: 4 + 676: 4 + 677: 4 + 678: 3 + 679: 3 + 680: 3 + 681: 2 + 682: 2 + 683: 1 + 684: 0 + 685: 1 + 686: 2 + 687: 3 + 688: 4 + 689: 5 + 690: 6 + 691: 7 + 692: 8 + 693: 9 + 694: 10 + 695: 11 + 696: 12 + 697: 13 + 698: 14 + 699: 15 + 700: 0 + 701: 1 + 702: 1 + 703: 1 + 704: 1 + 705: 1 + 706: 1 + 707: 1 + 708: 1 + 709: 1 + 710: 1 + 711: 1 + 712: 1 + 713: 1 + 714: 1 + 715: 1 + 716: 1 + 717: 1 + 718: 1 + 719: 0 + 720: 0 + 721: 0 + 722: 0 + 723: 0 + 724: 0 + 725: 0 + 726: 0 + 727: 0 + 728: 0 + 729: 0 + 730: 0 + 731: 0 + 732: 0 + 733: 0 + 734: 0 + 735: 15 + 736: 15 + 737: 15 + 738: 15 + 739: 15 + 740: 15 + 741: 15 + 742: 15 + 743: 15 + 744: 15 + 745: 15 + 746: 15 + 747: 15 + 748: 15 + 749: 15 + 750: 14 + 751: 14 + 752: 14 + 753: 14 + 754: 14 + 755: 14 + 756: 14 + 757: 14 + 758: 14 + 759: 14 + 760: 14 + 761: 14 + 762: 14 + 763: 14 + 764: 13 + 765: 13 + 766: 13 + 767: 13 + 768: 13 + 769: 13 + 770: 13 + 771: 13 + 772: 13 + 773: 13 + 774: 13 + 775: 13 + 776: 13 + 777: 12 + 778: 12 + 779: 12 + 780: 12 + 781: 12 + 782: 12 + 783: 12 + 784: 12 + 785: 12 + 786: 12 + 787: 12 + 788: 12 + 789: 11 + 790: 11 + 791: 11 + 792: 11 + 793: 11 + 794: 11 + 795: 11 + 796: 11 + 797: 11 + 798: 11 + 799: 11 + 800: 10 + 801: 10 + 802: 10 + 803: 10 + 804: 10 + 805: 10 + 806: 10 + 807: 10 + 808: 10 + 809: 10 + 810: 9 + 811: 9 + 812: 9 + 813: 9 + 814: 9 + 815: 9 + 816: 9 + 817: 9 + 818: 9 + 819: 8 + 820: 8 + 821: 8 + 822: 8 + 823: 8 + 824: 8 + 825: 8 + 826: 8 + 827: 7 + 828: 7 + 829: 7 + 830: 7 + 831: 7 + 832: 7 + 833: 7 + 834: 6 + 835: 6 + 836: 6 + 837: 6 + 838: 6 + 839: 6 + 840: 5 + 841: 5 + 842: 5 + 843: 5 + 844: 5 + 845: 4 + 846: 4 + 847: 4 + 848: 4 + 849: 3 + 850: 3 + 851: 3 + 852: 2 + 853: 2 + 854: 1 + 855: 0 + 856: 1 + 857: 2 + 858: 3 + 859: 4 + 860: 5 + 861: 6 + 862: 7 + 863: 0 + 864: 1 + 865: 2 + 866: 3 + 867: 4 + 868: 5 + 869: 6 + 870: 7 + 871: 0 + 872: 1 + 873: 1 + 874: 1 + 875: 1 + 876: 1 + 877: 1 + 878: 1 + 879: 1 + 880: 1 + 881: 1 + 882: 1 + 883: 1 + 884: 1 + 885: 1 + 886: 1 + 887: 1 + 888: 1 + 889: 1 + 890: 0 + 891: 0 + 892: 0 + 893: 0 + 894: 0 + 895: 0 + 896: 0 + 897: 0 + 898: 0 + 899: 0 + 900: 0 + 901: 0 + 902: 0 + 903: 0 + 904: 0 + 905: 0 + 906: 7 + 907: 7 + 908: 7 + 909: 7 + 910: 7 + 911: 7 + 912: 7 + 913: 7 + 914: 7 + 915: 7 + 916: 7 + 917: 7 + 918: 7 + 919: 7 + 920: 7 + 921: 6 + 922: 6 + 923: 6 + 924: 6 + 925: 6 + 926: 6 + 927: 6 + 928: 6 + 929: 6 + 930: 6 + 931: 6 + 932: 6 + 933: 6 + 934: 6 + 935: 5 + 936: 5 + 937: 5 + 938: 5 + 939: 5 + 940: 5 + 941: 5 + 942: 5 + 943: 5 + 944: 5 + 945: 5 + 946: 5 + 947: 5 + 948: 4 + 949: 4 + 950: 4 + 951: 4 + 952: 4 + 953: 4 + 954: 4 + 955: 4 + 956: 4 + 957: 4 + 958: 4 + 959: 4 + 960: 3 + 961: 3 + 962: 3 + 963: 3 + 964: 3 + 965: 3 + 966: 3 + 967: 3 + 968: 3 + 969: 3 + 970: 3 + 971: 2 + 972: 2 + 973: 2 + 974: 2 + 975: 2 + 976: 2 + 977: 2 + 978: 2 + 979: 2 + 980: 2 + 981: 1 + 982: 1 + 983: 1 + 984: 1 + 985: 1 + 986: 1 + 987: 1 + 988: 1 + 989: 1 + 990: 0 + 991: 0 + 992: 0 + 993: 0 + 994: 0 + 995: 0 + 996: 0 + 997: 0 + 998: 7 + 999: 7 + 1000: 7 + 1001: 7 + 1002: 7 + 1003: 7 + 1004: 7 + 1005: 6 + 1006: 6 + 1007: 6 + 1008: 6 + 1009: 6 + 1010: 6 + 1011: 5 + 1012: 5 + 1013: 5 + 1014: 5 + 1015: 5 + 1016: 4 + 1017: 4 + 1018: 4 + 1019: 4 + 1020: 3 + 1021: 3 + 1022: 3 + 1023: 2 + 1024: 2 + 1025: 1 + 1026: 0 + 1027: 1 + 1028: 2 + 1029: 3 + 1030: 0 + 1031: 1 + 1032: 2 + 1033: 3 + 1034: 0 + 1035: 1 + 1036: 2 + 1037: 3 + 1038: 0 + 1039: 1 + 1040: 2 + 1041: 3 + 1042: 0 + 1043: 1 + 1044: 1 + 1045: 1 + 1046: 1 + 1047: 1 + 1048: 1 + 1049: 1 + 1050: 1 + 1051: 1 + 1052: 1 + 1053: 1 + 1054: 1 + 1055: 1 + 1056: 1 + 1057: 1 + 1058: 1 + 1059: 1 + 1060: 1 + 1061: 0 + 1062: 0 + 1063: 0 + 1064: 0 + 1065: 0 + 1066: 0 + 1067: 0 + 1068: 0 + 1069: 0 + 1070: 0 + 1071: 0 + 1072: 0 + 1073: 0 + 1074: 0 + 1075: 0 + 1076: 0 + 1077: 3 + 1078: 3 + 1079: 3 + 1080: 3 + 1081: 3 + 1082: 3 + 1083: 3 + 1084: 3 + 1085: 3 + 1086: 3 + 1087: 3 + 1088: 3 + 1089: 3 + 1090: 3 + 1091: 3 + 1092: 2 + 1093: 2 + 1094: 2 + 1095: 2 + 1096: 2 + 1097: 2 + 1098: 2 + 1099: 2 + 1100: 2 + 1101: 2 + 1102: 2 + 1103: 2 + 1104: 2 + 1105: 2 + 1106: 1 + 1107: 1 + 1108: 1 + 1109: 1 + 1110: 1 + 1111: 1 + 1112: 1 + 1113: 1 + 1114: 1 + 1115: 1 + 1116: 1 + 1117: 1 + 1118: 1 + 1119: 0 + 1120: 0 + 1121: 0 + 1122: 0 + 1123: 0 + 1124: 0 + 1125: 0 + 1126: 0 + 1127: 0 + 1128: 0 + 1129: 0 + 1130: 0 + 1131: 3 + 1132: 3 + 1133: 3 + 1134: 3 + 1135: 3 + 1136: 3 + 1137: 3 + 1138: 3 + 1139: 3 + 1140: 3 + 1141: 3 + 1142: 2 + 1143: 2 + 1144: 2 + 1145: 2 + 1146: 2 + 1147: 2 + 1148: 2 + 1149: 2 + 1150: 2 + 1151: 2 + 1152: 1 + 1153: 1 + 1154: 1 + 1155: 1 + 1156: 1 + 1157: 1 + 1158: 1 + 1159: 1 + 1160: 1 + 1161: 0 + 1162: 0 + 1163: 0 + 1164: 0 + 1165: 0 + 1166: 0 + 1167: 0 + 1168: 0 + 1169: 3 + 1170: 3 + 1171: 3 + 1172: 3 + 1173: 3 + 1174: 3 + 1175: 3 + 1176: 2 + 1177: 2 + 1178: 2 + 1179: 2 + 1180: 2 + 1181: 2 + 1182: 1 + 1183: 1 + 1184: 1 + 1185: 1 + 1186: 1 + 1187: 0 + 1188: 0 + 1189: 0 + 1190: 0 + 1191: 3 + 1192: 3 + 1193: 3 + 1194: 2 + 1195: 2 + 1196: 1 + 1197: 0 + 1198: 1 + 1199: 0 + 1200: 1 + 1201: 0 + 1202: 1 + 1203: 0 + 1204: 1 + 1205: 0 + 1206: 1 + 1207: 0 + 1208: 1 + 1209: 0 + 1210: 1 + 1211: 0 + 1212: 1 + 1213: 0 + 1214: 1 + 1215: 1 + 1216: 1 + 1217: 1 + 1218: 1 + 1219: 1 + 1220: 1 + 1221: 1 + 1222: 1 + 1223: 1 + 1224: 1 + 1225: 1 + 1226: 1 + 1227: 1 + 1228: 1 + 1229: 1 + 1230: 1 + 1231: 1 + 1232: 0 + 1233: 0 + 1234: 0 + 1235: 0 + 1236: 0 + 1237: 0 + 1238: 0 + 1239: 0 + 1240: 0 + 1241: 0 + 1242: 0 + 1243: 0 + 1244: 0 + 1245: 0 + 1246: 0 + 1247: 0 + 1248: 1 + 1249: 1 + 1250: 1 + 1251: 1 + 1252: 1 + 1253: 1 + 1254: 1 + 1255: 1 + 1256: 1 + 1257: 1 + 1258: 1 + 1259: 1 + 1260: 1 + 1261: 1 + 1262: 1 + 1263: 0 + 1264: 0 + 1265: 0 + 1266: 0 + 1267: 0 + 1268: 0 + 1269: 0 + 1270: 0 + 1271: 0 + 1272: 0 + 1273: 0 + 1274: 0 + 1275: 0 + 1276: 0 + 1277: 1 + 1278: 1 + 1279: 1 + 1280: 1 + 1281: 1 + 1282: 1 + 1283: 1 + 1284: 1 + 1285: 1 + 1286: 1 + 1287: 1 + 1288: 1 + 1289: 1 + 1290: 0 + 1291: 0 + 1292: 0 + 1293: 0 + 1294: 0 + 1295: 0 + 1296: 0 + 1297: 0 + 1298: 0 + 1299: 0 + 1300: 0 + 1301: 0 + 1302: 1 + 1303: 1 + 1304: 1 + 1305: 1 + 1306: 1 + 1307: 1 + 1308: 1 + 1309: 1 + 1310: 1 + 1311: 1 + 1312: 1 + 1313: 0 + 1314: 0 + 1315: 0 + 1316: 0 + 1317: 0 + 1318: 0 + 1319: 0 + 1320: 0 + 1321: 0 + 1322: 0 + 1323: 1 + 1324: 1 + 1325: 1 + 1326: 1 + 1327: 1 + 1328: 1 + 1329: 1 + 1330: 1 + 1331: 1 + 1332: 0 + 1333: 0 + 1334: 0 + 1335: 0 + 1336: 0 + 1337: 0 + 1338: 0 + 1339: 0 + 1340: 1 + 1341: 1 + 1342: 1 + 1343: 1 + 1344: 1 + 1345: 1 + 1346: 1 + 1347: 0 + 1348: 0 + 1349: 0 + 1350: 0 + 1351: 0 + 1352: 0 + 1353: 1 + 1354: 1 + 1355: 1 + 1356: 1 + 1357: 1 + 1358: 0 + 1359: 0 + 1360: 0 + 1361: 0 + 1362: 1 + 1363: 1 + 1364: 1 + 1365: 0 + 1366: 0 + 1367: 1 diff --git a/akregator/src/mk4storage/metakit/tests/ok/l07.txt b/akregator/src/mk4storage/metakit/tests/ok/l07.txt new file mode 100644 index 000000000..fa6b10cfc --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l07.txt @@ -0,0 +1,2 @@ +>>> Huge description +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/l07a.txt b/akregator/src/mk4storage/metakit/tests/ok/l07a.txt new file mode 100644 index 000000000..11c013725 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/l07a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = a123456789a123456789a123456789p1:I a123456789a123456789a123456789p2:I a123456789a123456789a123456789p3:I a123456789a123456789a123456789p4:I a123456789a123456789a123456789p5:I a123456789a123456789a123456789p6:I a123456789a123456789a123456789p7:I a123456789a123456789a123456789p8:I a123456789a123456789a123456789p9:I a123456789a123456789a123456789p10:I a123456789a123456789a123456789p11:I a123456789a123456789a123456789p12:I a123456789a123456789a123456789p13:I a123456789a123456789a123456789p14:I a123456789a123456789a123456789p15:I a123456789a123456789a123456789p16:I a123456789a123456789a123456789p17:I a123456789a123456789a123456789p18:I a123456789a123456789a123456789p19:I a123456789a123456789a123456789p20:I a123456789a123456789a123456789p21:I a123456789a123456789a123456789p22:I a123456789a123456789a123456789p23:I a123456789a123456789a123456789p24:I a123456789a123456789a123456789p25:I a123456789a123456789a123456789p26:I a123456789a123456789a123456789p27:I a123456789a123456789a123456789p28:I a123456789a123456789a123456789p29:I a123456789a123456789a123456789p30:I a123456789a123456789a123456789p31:I a123456789a123456789a123456789p32:I a123456789a123456789a123456789p33:I a123456789a123456789a123456789p34:I a123456789a123456789a123456789p35:I a123456789a123456789a123456789p36:I a123456789a123456789a123456789p37:I a123456789a123456789a123456789p38:I a123456789a123456789a123456789p39:I a123456789a123456789a123456789p40:I a123456789a123456789a123456789p41:I a123456789a123456789a123456789p42:I a123456789a123456789a123456789p43:I a123456789a123456789a123456789p44:I a123456789a123456789a123456789p45:I a123456789a123456789a123456789p46:I a123456789a123456789a123456789p47:I a123456789a123456789a123456789p48:I a123456789a123456789a123456789p49:I a123456789a123456789a123456789p50:I a123456789a123456789a123456789p51:I a123456789a123456789a123456789p52:I a123456789a123456789a123456789p53:I a123456789a123456789a123456789p54:I a123456789a123456789a123456789p55:I a123456789a123456789a123456789p56:I a123456789a123456789a123456789p57:I a123456789a123456789a123456789p58:I a123456789a123456789a123456789p59:I a123456789a123456789a123456789p60:I a123456789a123456789a123456789p61:I a123456789a123456789a123456789p62:I a123456789a123456789a123456789p63:I a123456789a123456789a123456789p64:I a123456789a123456789a123456789p65:I a123456789a123456789a123456789p66:I a123456789a123456789a123456789p67:I a123456789a123456789a123456789p68:I a123456789a123456789a123456789p69:I a123456789a123456789a123456789p70:I a123456789a123456789a123456789p71:I a123456789a123456789a123456789p72:I a123456789a123456789a123456789p73:I a123456789a123456789a123456789p74:I a123456789a123456789a123456789p75:I a123456789a123456789a123456789p76:I a123456789a123456789a123456789p77:I a123456789a123456789a123456789p78:I a123456789a123456789a123456789p79:I a123456789a123456789a123456789p80:I a123456789a123456789a123456789p81:I a123456789a123456789a123456789p82:I a123456789a123456789a123456789p83:I a123456789a123456789a123456789p84:I a123456789a123456789a123456789p85:I a123456789a123456789a123456789p86:I a123456789a123456789a123456789p87:I a123456789a123456789a123456789p88:I a123456789a123456789a123456789p89:I a123456789a123456789a123456789p90:I a123456789a123456789a123456789p91:I a123456789a123456789a123456789p92:I a123456789a123456789a123456789p93:I a123456789a123456789a123456789p94:I a123456789a123456789a123456789p95:I a123456789a123456789a123456789p96:I a123456789a123456789a123456789p97:I a123456789a123456789a123456789p98:I a123456789a123456789a123456789p99:I a123456789a123456789a123456789p100:I a123456789a123456789a123456789p101:I a123456789a123456789a123456789p102:I a123456789a123456789a123456789p103:I a123456789a123456789a123456789p104:I a123456789a123456789a123456789p105:I a123456789a123456789a123456789p106:I a123456789a123456789a123456789p107:I a123456789a123456789a123456789p108:I a123456789a123456789a123456789p109:I a123456789a123456789a123456789p110:I a123456789a123456789a123456789p111:I a123456789a123456789a123456789p112:I a123456789a123456789a123456789p113:I a123456789a123456789a123456789p114:I a123456789a123456789a123456789p115:I a123456789a123456789a123456789p116:I a123456789a123456789a123456789p117:I a123456789a123456789a123456789p118:I a123456789a123456789a123456789p119:I a123456789a123456789a123456789p120:I a123456789a123456789a123456789p121:I a123456789a123456789a123456789p122:I a123456789a123456789a123456789p123:I a123456789a123456789a123456789p124:I a123456789a123456789a123456789p125:I a123456789a123456789a123456789p126:I a123456789a123456789a123456789p127:I a123456789a123456789a123456789p128:I a123456789a123456789a123456789p129:I a123456789a123456789a123456789p130:I a123456789a123456789a123456789p131:I a123456789a123456789a123456789p132:I a123456789a123456789a123456789p133:I a123456789a123456789a123456789p134:I a123456789a123456789a123456789p135:I a123456789a123456789a123456789p136:I a123456789a123456789a123456789p137:I a123456789a123456789a123456789p138:I a123456789a123456789a123456789p139:I a123456789a123456789a123456789p140:I a123456789a123456789a123456789p141:I a123456789a123456789a123456789p142:I a123456789a123456789a123456789p143:I a123456789a123456789a123456789p144:I a123456789a123456789a123456789p145:I a123456789a123456789a123456789p146:I a123456789a123456789a123456789p147:I a123456789a123456789a123456789p148:I a123456789a123456789a123456789p149:I + 0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/akregator/src/mk4storage/metakit/tests/ok/m01.txt b/akregator/src/mk4storage/metakit/tests/ok/m01.txt new file mode 100644 index 000000000..0c3bb84be --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m01.txt @@ -0,0 +1,2 @@ +>>> Hash mapping +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/m02.txt b/akregator/src/mk4storage/metakit/tests/ok/m02.txt new file mode 100644 index 000000000..703e30b2d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m02.txt @@ -0,0 +1,2 @@ +>>> Blocked view bug +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/m02a.txt b/akregator/src/mk4storage/metakit/tests/ok/m02a.txt new file mode 100644 index 000000000..c51c6f2a6 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m02a.txt @@ -0,0 +1,22 @@ + VIEW 1 rows = v1:V + 0: subview 'v1' + VIEW 2 rows = _B:V + 0: subview '_B' + VIEW 15 rows = p1:B + 0: (3490b) + 1: (3491b) + 2: (3492b) + 3: (3493b) + 4: (3494b) + 5: (3495b) + 6: (3496b) + 7: (3497b) + 8: (3498b) + 9: (3499b) + 10: (3500b) + 11: (3501b) + 12: (3502b) + 13: (3503b) + 14: (3504b) + 1: subview '_B' + VIEW 0 rows = p1:B diff --git a/akregator/src/mk4storage/metakit/tests/ok/m03.txt b/akregator/src/mk4storage/metakit/tests/ok/m03.txt new file mode 100644 index 000000000..f80527b3c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m03.txt @@ -0,0 +1,2 @@ +>>> Hash adds +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/m03a.txt b/akregator/src/mk4storage/metakit/tests/ok/m03a.txt new file mode 100644 index 000000000..dc96ffa34 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m03a.txt @@ -0,0 +1,55 @@ + VIEW 1 rows = d1:V m1:V d2:V m2:V d3:V m3:V d4:V m4:V + 0: subview 'd1' + VIEW 4 rows = p1:S + 0: 'one' + 1: 'two' + 2: 'three' + 3: 'four' + 0: subview 'm1' + VIEW 9 rows = _H:I _R:I + 0: 0 -1 + 1: -1413211378 1 + 2: -153687682 2 + 3: 0 -1 + 4: 0 -1 + 5: 0 -1 + 6: -1614533319 3 + 7: -245760992 0 + 8: 11 0 + 0: subview 'd2' + VIEW 3 rows = p1:S + 0: 'two' + 1: 'three' + 2: 'four' + 0: subview 'm2' + VIEW 9 rows = _H:I _R:I + 0: 0 -1 + 1: -1413211378 0 + 2: -153687682 1 + 3: 0 -1 + 4: 0 -1 + 5: 0 -1 + 6: -1614533319 2 + 7: 0 -1 + 8: 11 0 + 0: subview 'd3' + VIEW 2 rows = p1:S + 0: 'three' + 1: 'four' + 0: subview 'm3' + VIEW 5 rows = _H:I _R:I + 0: 0 -1 + 1: -153687682 0 + 2: -1614533319 1 + 3: 0 -1 + 4: 7 0 + 0: subview 'd4' + VIEW 1 rows = p1:S + 0: 'four' + 0: subview 'm4' + VIEW 5 rows = _H:I _R:I + 0: 0 -1 + 1: 0 -1 + 2: -1614533319 0 + 3: 0 -1 + 4: 7 0 diff --git a/akregator/src/mk4storage/metakit/tests/ok/m04.txt b/akregator/src/mk4storage/metakit/tests/ok/m04.txt new file mode 100644 index 000000000..036ca9951 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m04.txt @@ -0,0 +1,2 @@ +>>> Locate bug +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/m04a.txt b/akregator/src/mk4storage/metakit/tests/ok/m04a.txt new file mode 100644 index 000000000..fb38c3971 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m04a.txt @@ -0,0 +1,9 @@ + VIEW 1 rows = v1:V + 0: subview 'v1' + VIEW 6 rows = p1:I p2:S + 0: 1 'one' + 1: 2 'two' + 2: 3 'three' + 3: 4 'four' + 4: 5 'five' + 5: 6 'six' diff --git a/akregator/src/mk4storage/metakit/tests/ok/m05.txt b/akregator/src/mk4storage/metakit/tests/ok/m05.txt new file mode 100644 index 000000000..7b4e60c7d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m05.txt @@ -0,0 +1,2 @@ +>>> Blocked view with subviews +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/m05a.txt b/akregator/src/mk4storage/metakit/tests/ok/m05a.txt new file mode 100644 index 000000000..a9f34115d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m05a.txt @@ -0,0 +1,4012 @@ + VIEW 1 rows = v1:V + 0: subview 'v1' + VIEW 3 rows = _B:V + 0: subview '_B' + VIEW 500 rows = p1:S sv:V + 0: 'id-0' + 0: subview 'sv' + VIEW 1 rows = p2:I + 0: 0 + 1: 'id-1' + 1: subview 'sv' + VIEW 1 rows = p2:I + 0: 1 + 2: 'id-2' + 2: subview 'sv' + VIEW 1 rows = p2:I + 0: 2 + 3: 'id-3' + 3: subview 'sv' + VIEW 1 rows = p2:I + 0: 3 + 4: 'id-4' + 4: subview 'sv' + VIEW 1 rows = p2:I + 0: 4 + 5: 'id-5' + 5: subview 'sv' + VIEW 1 rows = p2:I + 0: 5 + 6: 'id-6' + 6: subview 'sv' + VIEW 1 rows = p2:I + 0: 6 + 7: 'id-7' + 7: subview 'sv' + VIEW 1 rows = p2:I + 0: 7 + 8: 'id-8' + 8: subview 'sv' + VIEW 1 rows = p2:I + 0: 8 + 9: 'id-9' + 9: subview 'sv' + VIEW 1 rows = p2:I + 0: 9 + 10: 'id-10' + 10: subview 'sv' + VIEW 1 rows = p2:I + 0: 10 + 11: 'id-11' + 11: subview 'sv' + VIEW 1 rows = p2:I + 0: 11 + 12: 'id-12' + 12: subview 'sv' + VIEW 1 rows = p2:I + 0: 12 + 13: 'id-13' + 13: subview 'sv' + VIEW 1 rows = p2:I + 0: 13 + 14: 'id-14' + 14: subview 'sv' + VIEW 1 rows = p2:I + 0: 14 + 15: 'id-15' + 15: subview 'sv' + VIEW 1 rows = p2:I + 0: 15 + 16: 'id-16' + 16: subview 'sv' + VIEW 1 rows = p2:I + 0: 16 + 17: 'id-17' + 17: subview 'sv' + VIEW 1 rows = p2:I + 0: 17 + 18: 'id-18' + 18: subview 'sv' + VIEW 1 rows = p2:I + 0: 18 + 19: 'id-19' + 19: subview 'sv' + VIEW 1 rows = p2:I + 0: 19 + 20: 'id-20' + 20: subview 'sv' + VIEW 1 rows = p2:I + 0: 20 + 21: 'id-21' + 21: subview 'sv' + VIEW 1 rows = p2:I + 0: 21 + 22: 'id-22' + 22: subview 'sv' + VIEW 1 rows = p2:I + 0: 22 + 23: 'id-23' + 23: subview 'sv' + VIEW 1 rows = p2:I + 0: 23 + 24: 'id-24' + 24: subview 'sv' + VIEW 1 rows = p2:I + 0: 24 + 25: 'id-25' + 25: subview 'sv' + VIEW 1 rows = p2:I + 0: 25 + 26: 'id-26' + 26: subview 'sv' + VIEW 1 rows = p2:I + 0: 26 + 27: 'id-27' + 27: subview 'sv' + VIEW 1 rows = p2:I + 0: 27 + 28: 'id-28' + 28: subview 'sv' + VIEW 1 rows = p2:I + 0: 28 + 29: 'id-29' + 29: subview 'sv' + VIEW 1 rows = p2:I + 0: 29 + 30: 'id-30' + 30: subview 'sv' + VIEW 1 rows = p2:I + 0: 30 + 31: 'id-31' + 31: subview 'sv' + VIEW 1 rows = p2:I + 0: 31 + 32: 'id-32' + 32: subview 'sv' + VIEW 1 rows = p2:I + 0: 32 + 33: 'id-33' + 33: subview 'sv' + VIEW 1 rows = p2:I + 0: 33 + 34: 'id-34' + 34: subview 'sv' + VIEW 1 rows = p2:I + 0: 34 + 35: 'id-35' + 35: subview 'sv' + VIEW 1 rows = p2:I + 0: 35 + 36: 'id-36' + 36: subview 'sv' + VIEW 1 rows = p2:I + 0: 36 + 37: 'id-37' + 37: subview 'sv' + VIEW 1 rows = p2:I + 0: 37 + 38: 'id-38' + 38: subview 'sv' + VIEW 1 rows = p2:I + 0: 38 + 39: 'id-39' + 39: subview 'sv' + VIEW 1 rows = p2:I + 0: 39 + 40: 'id-40' + 40: subview 'sv' + VIEW 1 rows = p2:I + 0: 40 + 41: 'id-41' + 41: subview 'sv' + VIEW 1 rows = p2:I + 0: 41 + 42: 'id-42' + 42: subview 'sv' + VIEW 1 rows = p2:I + 0: 42 + 43: 'id-43' + 43: subview 'sv' + VIEW 1 rows = p2:I + 0: 43 + 44: 'id-44' + 44: subview 'sv' + VIEW 1 rows = p2:I + 0: 44 + 45: 'id-45' + 45: subview 'sv' + VIEW 1 rows = p2:I + 0: 45 + 46: 'id-46' + 46: subview 'sv' + VIEW 1 rows = p2:I + 0: 46 + 47: 'id-47' + 47: subview 'sv' + VIEW 1 rows = p2:I + 0: 47 + 48: 'id-48' + 48: subview 'sv' + VIEW 1 rows = p2:I + 0: 48 + 49: 'id-49' + 49: subview 'sv' + VIEW 1 rows = p2:I + 0: 49 + 50: 'id-50' + 50: subview 'sv' + VIEW 1 rows = p2:I + 0: 50 + 51: 'id-51' + 51: subview 'sv' + VIEW 1 rows = p2:I + 0: 51 + 52: 'id-52' + 52: subview 'sv' + VIEW 1 rows = p2:I + 0: 52 + 53: 'id-53' + 53: subview 'sv' + VIEW 1 rows = p2:I + 0: 53 + 54: 'id-54' + 54: subview 'sv' + VIEW 1 rows = p2:I + 0: 54 + 55: 'id-55' + 55: subview 'sv' + VIEW 1 rows = p2:I + 0: 55 + 56: 'id-56' + 56: subview 'sv' + VIEW 1 rows = p2:I + 0: 56 + 57: 'id-57' + 57: subview 'sv' + VIEW 1 rows = p2:I + 0: 57 + 58: 'id-58' + 58: subview 'sv' + VIEW 1 rows = p2:I + 0: 58 + 59: 'id-59' + 59: subview 'sv' + VIEW 1 rows = p2:I + 0: 59 + 60: 'id-60' + 60: subview 'sv' + VIEW 1 rows = p2:I + 0: 60 + 61: 'id-61' + 61: subview 'sv' + VIEW 1 rows = p2:I + 0: 61 + 62: 'id-62' + 62: subview 'sv' + VIEW 1 rows = p2:I + 0: 62 + 63: 'id-63' + 63: subview 'sv' + VIEW 1 rows = p2:I + 0: 63 + 64: 'id-64' + 64: subview 'sv' + VIEW 1 rows = p2:I + 0: 64 + 65: 'id-65' + 65: subview 'sv' + VIEW 1 rows = p2:I + 0: 65 + 66: 'id-66' + 66: subview 'sv' + VIEW 1 rows = p2:I + 0: 66 + 67: 'id-67' + 67: subview 'sv' + VIEW 1 rows = p2:I + 0: 67 + 68: 'id-68' + 68: subview 'sv' + VIEW 1 rows = p2:I + 0: 68 + 69: 'id-69' + 69: subview 'sv' + VIEW 1 rows = p2:I + 0: 69 + 70: 'id-70' + 70: subview 'sv' + VIEW 1 rows = p2:I + 0: 70 + 71: 'id-71' + 71: subview 'sv' + VIEW 1 rows = p2:I + 0: 71 + 72: 'id-72' + 72: subview 'sv' + VIEW 1 rows = p2:I + 0: 72 + 73: 'id-73' + 73: subview 'sv' + VIEW 1 rows = p2:I + 0: 73 + 74: 'id-74' + 74: subview 'sv' + VIEW 1 rows = p2:I + 0: 74 + 75: 'id-75' + 75: subview 'sv' + VIEW 1 rows = p2:I + 0: 75 + 76: 'id-76' + 76: subview 'sv' + VIEW 1 rows = p2:I + 0: 76 + 77: 'id-77' + 77: subview 'sv' + VIEW 1 rows = p2:I + 0: 77 + 78: 'id-78' + 78: subview 'sv' + VIEW 1 rows = p2:I + 0: 78 + 79: 'id-79' + 79: subview 'sv' + VIEW 1 rows = p2:I + 0: 79 + 80: 'id-80' + 80: subview 'sv' + VIEW 1 rows = p2:I + 0: 80 + 81: 'id-81' + 81: subview 'sv' + VIEW 1 rows = p2:I + 0: 81 + 82: 'id-82' + 82: subview 'sv' + VIEW 1 rows = p2:I + 0: 82 + 83: 'id-83' + 83: subview 'sv' + VIEW 1 rows = p2:I + 0: 83 + 84: 'id-84' + 84: subview 'sv' + VIEW 1 rows = p2:I + 0: 84 + 85: 'id-85' + 85: subview 'sv' + VIEW 1 rows = p2:I + 0: 85 + 86: 'id-86' + 86: subview 'sv' + VIEW 1 rows = p2:I + 0: 86 + 87: 'id-87' + 87: subview 'sv' + VIEW 1 rows = p2:I + 0: 87 + 88: 'id-88' + 88: subview 'sv' + VIEW 1 rows = p2:I + 0: 88 + 89: 'id-89' + 89: subview 'sv' + VIEW 1 rows = p2:I + 0: 89 + 90: 'id-90' + 90: subview 'sv' + VIEW 1 rows = p2:I + 0: 90 + 91: 'id-91' + 91: subview 'sv' + VIEW 1 rows = p2:I + 0: 91 + 92: 'id-92' + 92: subview 'sv' + VIEW 1 rows = p2:I + 0: 92 + 93: 'id-93' + 93: subview 'sv' + VIEW 1 rows = p2:I + 0: 93 + 94: 'id-94' + 94: subview 'sv' + VIEW 1 rows = p2:I + 0: 94 + 95: 'id-95' + 95: subview 'sv' + VIEW 1 rows = p2:I + 0: 95 + 96: 'id-96' + 96: subview 'sv' + VIEW 1 rows = p2:I + 0: 96 + 97: 'id-97' + 97: subview 'sv' + VIEW 1 rows = p2:I + 0: 97 + 98: 'id-98' + 98: subview 'sv' + VIEW 1 rows = p2:I + 0: 98 + 99: 'id-99' + 99: subview 'sv' + VIEW 1 rows = p2:I + 0: 99 + 100: 'id-100' + 100: subview 'sv' + VIEW 1 rows = p2:I + 0: 100 + 101: 'id-101' + 101: subview 'sv' + VIEW 1 rows = p2:I + 0: 101 + 102: 'id-102' + 102: subview 'sv' + VIEW 1 rows = p2:I + 0: 102 + 103: 'id-103' + 103: subview 'sv' + VIEW 1 rows = p2:I + 0: 103 + 104: 'id-104' + 104: subview 'sv' + VIEW 1 rows = p2:I + 0: 104 + 105: 'id-105' + 105: subview 'sv' + VIEW 1 rows = p2:I + 0: 105 + 106: 'id-106' + 106: subview 'sv' + VIEW 1 rows = p2:I + 0: 106 + 107: 'id-107' + 107: subview 'sv' + VIEW 1 rows = p2:I + 0: 107 + 108: 'id-108' + 108: subview 'sv' + VIEW 1 rows = p2:I + 0: 108 + 109: 'id-109' + 109: subview 'sv' + VIEW 1 rows = p2:I + 0: 109 + 110: 'id-110' + 110: subview 'sv' + VIEW 1 rows = p2:I + 0: 110 + 111: 'id-111' + 111: subview 'sv' + VIEW 1 rows = p2:I + 0: 111 + 112: 'id-112' + 112: subview 'sv' + VIEW 1 rows = p2:I + 0: 112 + 113: 'id-113' + 113: subview 'sv' + VIEW 1 rows = p2:I + 0: 113 + 114: 'id-114' + 114: subview 'sv' + VIEW 1 rows = p2:I + 0: 114 + 115: 'id-115' + 115: subview 'sv' + VIEW 1 rows = p2:I + 0: 115 + 116: 'id-116' + 116: subview 'sv' + VIEW 1 rows = p2:I + 0: 116 + 117: 'id-117' + 117: subview 'sv' + VIEW 1 rows = p2:I + 0: 117 + 118: 'id-118' + 118: subview 'sv' + VIEW 1 rows = p2:I + 0: 118 + 119: 'id-119' + 119: subview 'sv' + VIEW 1 rows = p2:I + 0: 119 + 120: 'id-120' + 120: subview 'sv' + VIEW 1 rows = p2:I + 0: 120 + 121: 'id-121' + 121: subview 'sv' + VIEW 1 rows = p2:I + 0: 121 + 122: 'id-122' + 122: subview 'sv' + VIEW 1 rows = p2:I + 0: 122 + 123: 'id-123' + 123: subview 'sv' + VIEW 1 rows = p2:I + 0: 123 + 124: 'id-124' + 124: subview 'sv' + VIEW 1 rows = p2:I + 0: 124 + 125: 'id-125' + 125: subview 'sv' + VIEW 1 rows = p2:I + 0: 125 + 126: 'id-126' + 126: subview 'sv' + VIEW 1 rows = p2:I + 0: 126 + 127: 'id-127' + 127: subview 'sv' + VIEW 1 rows = p2:I + 0: 127 + 128: 'id-128' + 128: subview 'sv' + VIEW 1 rows = p2:I + 0: 128 + 129: 'id-129' + 129: subview 'sv' + VIEW 1 rows = p2:I + 0: 129 + 130: 'id-130' + 130: subview 'sv' + VIEW 1 rows = p2:I + 0: 130 + 131: 'id-131' + 131: subview 'sv' + VIEW 1 rows = p2:I + 0: 131 + 132: 'id-132' + 132: subview 'sv' + VIEW 1 rows = p2:I + 0: 132 + 133: 'id-133' + 133: subview 'sv' + VIEW 1 rows = p2:I + 0: 133 + 134: 'id-134' + 134: subview 'sv' + VIEW 1 rows = p2:I + 0: 134 + 135: 'id-135' + 135: subview 'sv' + VIEW 1 rows = p2:I + 0: 135 + 136: 'id-136' + 136: subview 'sv' + VIEW 1 rows = p2:I + 0: 136 + 137: 'id-137' + 137: subview 'sv' + VIEW 1 rows = p2:I + 0: 137 + 138: 'id-138' + 138: subview 'sv' + VIEW 1 rows = p2:I + 0: 138 + 139: 'id-139' + 139: subview 'sv' + VIEW 1 rows = p2:I + 0: 139 + 140: 'id-140' + 140: subview 'sv' + VIEW 1 rows = p2:I + 0: 140 + 141: 'id-141' + 141: subview 'sv' + VIEW 1 rows = p2:I + 0: 141 + 142: 'id-142' + 142: subview 'sv' + VIEW 1 rows = p2:I + 0: 142 + 143: 'id-143' + 143: subview 'sv' + VIEW 1 rows = p2:I + 0: 143 + 144: 'id-144' + 144: subview 'sv' + VIEW 1 rows = p2:I + 0: 144 + 145: 'id-145' + 145: subview 'sv' + VIEW 1 rows = p2:I + 0: 145 + 146: 'id-146' + 146: subview 'sv' + VIEW 1 rows = p2:I + 0: 146 + 147: 'id-147' + 147: subview 'sv' + VIEW 1 rows = p2:I + 0: 147 + 148: 'id-148' + 148: subview 'sv' + VIEW 1 rows = p2:I + 0: 148 + 149: 'id-149' + 149: subview 'sv' + VIEW 1 rows = p2:I + 0: 149 + 150: 'id-150' + 150: subview 'sv' + VIEW 1 rows = p2:I + 0: 150 + 151: 'id-151' + 151: subview 'sv' + VIEW 1 rows = p2:I + 0: 151 + 152: 'id-152' + 152: subview 'sv' + VIEW 1 rows = p2:I + 0: 152 + 153: 'id-153' + 153: subview 'sv' + VIEW 1 rows = p2:I + 0: 153 + 154: 'id-154' + 154: subview 'sv' + VIEW 1 rows = p2:I + 0: 154 + 155: 'id-155' + 155: subview 'sv' + VIEW 1 rows = p2:I + 0: 155 + 156: 'id-156' + 156: subview 'sv' + VIEW 1 rows = p2:I + 0: 156 + 157: 'id-157' + 157: subview 'sv' + VIEW 1 rows = p2:I + 0: 157 + 158: 'id-158' + 158: subview 'sv' + VIEW 1 rows = p2:I + 0: 158 + 159: 'id-159' + 159: subview 'sv' + VIEW 1 rows = p2:I + 0: 159 + 160: 'id-160' + 160: subview 'sv' + VIEW 1 rows = p2:I + 0: 160 + 161: 'id-161' + 161: subview 'sv' + VIEW 1 rows = p2:I + 0: 161 + 162: 'id-162' + 162: subview 'sv' + VIEW 1 rows = p2:I + 0: 162 + 163: 'id-163' + 163: subview 'sv' + VIEW 1 rows = p2:I + 0: 163 + 164: 'id-164' + 164: subview 'sv' + VIEW 1 rows = p2:I + 0: 164 + 165: 'id-165' + 165: subview 'sv' + VIEW 1 rows = p2:I + 0: 165 + 166: 'id-166' + 166: subview 'sv' + VIEW 1 rows = p2:I + 0: 166 + 167: 'id-167' + 167: subview 'sv' + VIEW 1 rows = p2:I + 0: 167 + 168: 'id-168' + 168: subview 'sv' + VIEW 1 rows = p2:I + 0: 168 + 169: 'id-169' + 169: subview 'sv' + VIEW 1 rows = p2:I + 0: 169 + 170: 'id-170' + 170: subview 'sv' + VIEW 1 rows = p2:I + 0: 170 + 171: 'id-171' + 171: subview 'sv' + VIEW 1 rows = p2:I + 0: 171 + 172: 'id-172' + 172: subview 'sv' + VIEW 1 rows = p2:I + 0: 172 + 173: 'id-173' + 173: subview 'sv' + VIEW 1 rows = p2:I + 0: 173 + 174: 'id-174' + 174: subview 'sv' + VIEW 1 rows = p2:I + 0: 174 + 175: 'id-175' + 175: subview 'sv' + VIEW 1 rows = p2:I + 0: 175 + 176: 'id-176' + 176: subview 'sv' + VIEW 1 rows = p2:I + 0: 176 + 177: 'id-177' + 177: subview 'sv' + VIEW 1 rows = p2:I + 0: 177 + 178: 'id-178' + 178: subview 'sv' + VIEW 1 rows = p2:I + 0: 178 + 179: 'id-179' + 179: subview 'sv' + VIEW 1 rows = p2:I + 0: 179 + 180: 'id-180' + 180: subview 'sv' + VIEW 1 rows = p2:I + 0: 180 + 181: 'id-181' + 181: subview 'sv' + VIEW 1 rows = p2:I + 0: 181 + 182: 'id-182' + 182: subview 'sv' + VIEW 1 rows = p2:I + 0: 182 + 183: 'id-183' + 183: subview 'sv' + VIEW 1 rows = p2:I + 0: 183 + 184: 'id-184' + 184: subview 'sv' + VIEW 1 rows = p2:I + 0: 184 + 185: 'id-185' + 185: subview 'sv' + VIEW 1 rows = p2:I + 0: 185 + 186: 'id-186' + 186: subview 'sv' + VIEW 1 rows = p2:I + 0: 186 + 187: 'id-187' + 187: subview 'sv' + VIEW 1 rows = p2:I + 0: 187 + 188: 'id-188' + 188: subview 'sv' + VIEW 1 rows = p2:I + 0: 188 + 189: 'id-189' + 189: subview 'sv' + VIEW 1 rows = p2:I + 0: 189 + 190: 'id-190' + 190: subview 'sv' + VIEW 1 rows = p2:I + 0: 190 + 191: 'id-191' + 191: subview 'sv' + VIEW 1 rows = p2:I + 0: 191 + 192: 'id-192' + 192: subview 'sv' + VIEW 1 rows = p2:I + 0: 192 + 193: 'id-193' + 193: subview 'sv' + VIEW 1 rows = p2:I + 0: 193 + 194: 'id-194' + 194: subview 'sv' + VIEW 1 rows = p2:I + 0: 194 + 195: 'id-195' + 195: subview 'sv' + VIEW 1 rows = p2:I + 0: 195 + 196: 'id-196' + 196: subview 'sv' + VIEW 1 rows = p2:I + 0: 196 + 197: 'id-197' + 197: subview 'sv' + VIEW 1 rows = p2:I + 0: 197 + 198: 'id-198' + 198: subview 'sv' + VIEW 1 rows = p2:I + 0: 198 + 199: 'id-199' + 199: subview 'sv' + VIEW 1 rows = p2:I + 0: 199 + 200: 'id-200' + 200: subview 'sv' + VIEW 1 rows = p2:I + 0: 200 + 201: 'id-201' + 201: subview 'sv' + VIEW 1 rows = p2:I + 0: 201 + 202: 'id-202' + 202: subview 'sv' + VIEW 1 rows = p2:I + 0: 202 + 203: 'id-203' + 203: subview 'sv' + VIEW 1 rows = p2:I + 0: 203 + 204: 'id-204' + 204: subview 'sv' + VIEW 1 rows = p2:I + 0: 204 + 205: 'id-205' + 205: subview 'sv' + VIEW 1 rows = p2:I + 0: 205 + 206: 'id-206' + 206: subview 'sv' + VIEW 1 rows = p2:I + 0: 206 + 207: 'id-207' + 207: subview 'sv' + VIEW 1 rows = p2:I + 0: 207 + 208: 'id-208' + 208: subview 'sv' + VIEW 1 rows = p2:I + 0: 208 + 209: 'id-209' + 209: subview 'sv' + VIEW 1 rows = p2:I + 0: 209 + 210: 'id-210' + 210: subview 'sv' + VIEW 1 rows = p2:I + 0: 210 + 211: 'id-211' + 211: subview 'sv' + VIEW 1 rows = p2:I + 0: 211 + 212: 'id-212' + 212: subview 'sv' + VIEW 1 rows = p2:I + 0: 212 + 213: 'id-213' + 213: subview 'sv' + VIEW 1 rows = p2:I + 0: 213 + 214: 'id-214' + 214: subview 'sv' + VIEW 1 rows = p2:I + 0: 214 + 215: 'id-215' + 215: subview 'sv' + VIEW 1 rows = p2:I + 0: 215 + 216: 'id-216' + 216: subview 'sv' + VIEW 1 rows = p2:I + 0: 216 + 217: 'id-217' + 217: subview 'sv' + VIEW 1 rows = p2:I + 0: 217 + 218: 'id-218' + 218: subview 'sv' + VIEW 1 rows = p2:I + 0: 218 + 219: 'id-219' + 219: subview 'sv' + VIEW 1 rows = p2:I + 0: 219 + 220: 'id-220' + 220: subview 'sv' + VIEW 1 rows = p2:I + 0: 220 + 221: 'id-221' + 221: subview 'sv' + VIEW 1 rows = p2:I + 0: 221 + 222: 'id-222' + 222: subview 'sv' + VIEW 1 rows = p2:I + 0: 222 + 223: 'id-223' + 223: subview 'sv' + VIEW 1 rows = p2:I + 0: 223 + 224: 'id-224' + 224: subview 'sv' + VIEW 1 rows = p2:I + 0: 224 + 225: 'id-225' + 225: subview 'sv' + VIEW 1 rows = p2:I + 0: 225 + 226: 'id-226' + 226: subview 'sv' + VIEW 1 rows = p2:I + 0: 226 + 227: 'id-227' + 227: subview 'sv' + VIEW 1 rows = p2:I + 0: 227 + 228: 'id-228' + 228: subview 'sv' + VIEW 1 rows = p2:I + 0: 228 + 229: 'id-229' + 229: subview 'sv' + VIEW 1 rows = p2:I + 0: 229 + 230: 'id-230' + 230: subview 'sv' + VIEW 1 rows = p2:I + 0: 230 + 231: 'id-231' + 231: subview 'sv' + VIEW 1 rows = p2:I + 0: 231 + 232: 'id-232' + 232: subview 'sv' + VIEW 1 rows = p2:I + 0: 232 + 233: 'id-233' + 233: subview 'sv' + VIEW 1 rows = p2:I + 0: 233 + 234: 'id-234' + 234: subview 'sv' + VIEW 1 rows = p2:I + 0: 234 + 235: 'id-235' + 235: subview 'sv' + VIEW 1 rows = p2:I + 0: 235 + 236: 'id-236' + 236: subview 'sv' + VIEW 1 rows = p2:I + 0: 236 + 237: 'id-237' + 237: subview 'sv' + VIEW 1 rows = p2:I + 0: 237 + 238: 'id-238' + 238: subview 'sv' + VIEW 1 rows = p2:I + 0: 238 + 239: 'id-239' + 239: subview 'sv' + VIEW 1 rows = p2:I + 0: 239 + 240: 'id-240' + 240: subview 'sv' + VIEW 1 rows = p2:I + 0: 240 + 241: 'id-241' + 241: subview 'sv' + VIEW 1 rows = p2:I + 0: 241 + 242: 'id-242' + 242: subview 'sv' + VIEW 1 rows = p2:I + 0: 242 + 243: 'id-243' + 243: subview 'sv' + VIEW 1 rows = p2:I + 0: 243 + 244: 'id-244' + 244: subview 'sv' + VIEW 1 rows = p2:I + 0: 244 + 245: 'id-245' + 245: subview 'sv' + VIEW 1 rows = p2:I + 0: 245 + 246: 'id-246' + 246: subview 'sv' + VIEW 1 rows = p2:I + 0: 246 + 247: 'id-247' + 247: subview 'sv' + VIEW 1 rows = p2:I + 0: 247 + 248: 'id-248' + 248: subview 'sv' + VIEW 1 rows = p2:I + 0: 248 + 249: 'id-249' + 249: subview 'sv' + VIEW 1 rows = p2:I + 0: 249 + 250: 'id-250' + 250: subview 'sv' + VIEW 1 rows = p2:I + 0: 250 + 251: 'id-251' + 251: subview 'sv' + VIEW 1 rows = p2:I + 0: 251 + 252: 'id-252' + 252: subview 'sv' + VIEW 1 rows = p2:I + 0: 252 + 253: 'id-253' + 253: subview 'sv' + VIEW 1 rows = p2:I + 0: 253 + 254: 'id-254' + 254: subview 'sv' + VIEW 1 rows = p2:I + 0: 254 + 255: 'id-255' + 255: subview 'sv' + VIEW 1 rows = p2:I + 0: 255 + 256: 'id-256' + 256: subview 'sv' + VIEW 1 rows = p2:I + 0: 256 + 257: 'id-257' + 257: subview 'sv' + VIEW 1 rows = p2:I + 0: 257 + 258: 'id-258' + 258: subview 'sv' + VIEW 1 rows = p2:I + 0: 258 + 259: 'id-259' + 259: subview 'sv' + VIEW 1 rows = p2:I + 0: 259 + 260: 'id-260' + 260: subview 'sv' + VIEW 1 rows = p2:I + 0: 260 + 261: 'id-261' + 261: subview 'sv' + VIEW 1 rows = p2:I + 0: 261 + 262: 'id-262' + 262: subview 'sv' + VIEW 1 rows = p2:I + 0: 262 + 263: 'id-263' + 263: subview 'sv' + VIEW 1 rows = p2:I + 0: 263 + 264: 'id-264' + 264: subview 'sv' + VIEW 1 rows = p2:I + 0: 264 + 265: 'id-265' + 265: subview 'sv' + VIEW 1 rows = p2:I + 0: 265 + 266: 'id-266' + 266: subview 'sv' + VIEW 1 rows = p2:I + 0: 266 + 267: 'id-267' + 267: subview 'sv' + VIEW 1 rows = p2:I + 0: 267 + 268: 'id-268' + 268: subview 'sv' + VIEW 1 rows = p2:I + 0: 268 + 269: 'id-269' + 269: subview 'sv' + VIEW 1 rows = p2:I + 0: 269 + 270: 'id-270' + 270: subview 'sv' + VIEW 1 rows = p2:I + 0: 270 + 271: 'id-271' + 271: subview 'sv' + VIEW 1 rows = p2:I + 0: 271 + 272: 'id-272' + 272: subview 'sv' + VIEW 1 rows = p2:I + 0: 272 + 273: 'id-273' + 273: subview 'sv' + VIEW 1 rows = p2:I + 0: 273 + 274: 'id-274' + 274: subview 'sv' + VIEW 1 rows = p2:I + 0: 274 + 275: 'id-275' + 275: subview 'sv' + VIEW 1 rows = p2:I + 0: 275 + 276: 'id-276' + 276: subview 'sv' + VIEW 1 rows = p2:I + 0: 276 + 277: 'id-277' + 277: subview 'sv' + VIEW 1 rows = p2:I + 0: 277 + 278: 'id-278' + 278: subview 'sv' + VIEW 1 rows = p2:I + 0: 278 + 279: 'id-279' + 279: subview 'sv' + VIEW 1 rows = p2:I + 0: 279 + 280: 'id-280' + 280: subview 'sv' + VIEW 1 rows = p2:I + 0: 280 + 281: 'id-281' + 281: subview 'sv' + VIEW 1 rows = p2:I + 0: 281 + 282: 'id-282' + 282: subview 'sv' + VIEW 1 rows = p2:I + 0: 282 + 283: 'id-283' + 283: subview 'sv' + VIEW 1 rows = p2:I + 0: 283 + 284: 'id-284' + 284: subview 'sv' + VIEW 1 rows = p2:I + 0: 284 + 285: 'id-285' + 285: subview 'sv' + VIEW 1 rows = p2:I + 0: 285 + 286: 'id-286' + 286: subview 'sv' + VIEW 1 rows = p2:I + 0: 286 + 287: 'id-287' + 287: subview 'sv' + VIEW 1 rows = p2:I + 0: 287 + 288: 'id-288' + 288: subview 'sv' + VIEW 1 rows = p2:I + 0: 288 + 289: 'id-289' + 289: subview 'sv' + VIEW 1 rows = p2:I + 0: 289 + 290: 'id-290' + 290: subview 'sv' + VIEW 1 rows = p2:I + 0: 290 + 291: 'id-291' + 291: subview 'sv' + VIEW 1 rows = p2:I + 0: 291 + 292: 'id-292' + 292: subview 'sv' + VIEW 1 rows = p2:I + 0: 292 + 293: 'id-293' + 293: subview 'sv' + VIEW 1 rows = p2:I + 0: 293 + 294: 'id-294' + 294: subview 'sv' + VIEW 1 rows = p2:I + 0: 294 + 295: 'id-295' + 295: subview 'sv' + VIEW 1 rows = p2:I + 0: 295 + 296: 'id-296' + 296: subview 'sv' + VIEW 1 rows = p2:I + 0: 296 + 297: 'id-297' + 297: subview 'sv' + VIEW 1 rows = p2:I + 0: 297 + 298: 'id-298' + 298: subview 'sv' + VIEW 1 rows = p2:I + 0: 298 + 299: 'id-299' + 299: subview 'sv' + VIEW 1 rows = p2:I + 0: 299 + 300: 'id-300' + 300: subview 'sv' + VIEW 1 rows = p2:I + 0: 300 + 301: 'id-301' + 301: subview 'sv' + VIEW 1 rows = p2:I + 0: 301 + 302: 'id-302' + 302: subview 'sv' + VIEW 1 rows = p2:I + 0: 302 + 303: 'id-303' + 303: subview 'sv' + VIEW 1 rows = p2:I + 0: 303 + 304: 'id-304' + 304: subview 'sv' + VIEW 1 rows = p2:I + 0: 304 + 305: 'id-305' + 305: subview 'sv' + VIEW 1 rows = p2:I + 0: 305 + 306: 'id-306' + 306: subview 'sv' + VIEW 1 rows = p2:I + 0: 306 + 307: 'id-307' + 307: subview 'sv' + VIEW 1 rows = p2:I + 0: 307 + 308: 'id-308' + 308: subview 'sv' + VIEW 1 rows = p2:I + 0: 308 + 309: 'id-309' + 309: subview 'sv' + VIEW 1 rows = p2:I + 0: 309 + 310: 'id-310' + 310: subview 'sv' + VIEW 1 rows = p2:I + 0: 310 + 311: 'id-311' + 311: subview 'sv' + VIEW 1 rows = p2:I + 0: 311 + 312: 'id-312' + 312: subview 'sv' + VIEW 1 rows = p2:I + 0: 312 + 313: 'id-313' + 313: subview 'sv' + VIEW 1 rows = p2:I + 0: 313 + 314: 'id-314' + 314: subview 'sv' + VIEW 1 rows = p2:I + 0: 314 + 315: 'id-315' + 315: subview 'sv' + VIEW 1 rows = p2:I + 0: 315 + 316: 'id-316' + 316: subview 'sv' + VIEW 1 rows = p2:I + 0: 316 + 317: 'id-317' + 317: subview 'sv' + VIEW 1 rows = p2:I + 0: 317 + 318: 'id-318' + 318: subview 'sv' + VIEW 1 rows = p2:I + 0: 318 + 319: 'id-319' + 319: subview 'sv' + VIEW 1 rows = p2:I + 0: 319 + 320: 'id-320' + 320: subview 'sv' + VIEW 1 rows = p2:I + 0: 320 + 321: 'id-321' + 321: subview 'sv' + VIEW 1 rows = p2:I + 0: 321 + 322: 'id-322' + 322: subview 'sv' + VIEW 1 rows = p2:I + 0: 322 + 323: 'id-323' + 323: subview 'sv' + VIEW 1 rows = p2:I + 0: 323 + 324: 'id-324' + 324: subview 'sv' + VIEW 1 rows = p2:I + 0: 324 + 325: 'id-325' + 325: subview 'sv' + VIEW 1 rows = p2:I + 0: 325 + 326: 'id-326' + 326: subview 'sv' + VIEW 1 rows = p2:I + 0: 326 + 327: 'id-327' + 327: subview 'sv' + VIEW 1 rows = p2:I + 0: 327 + 328: 'id-328' + 328: subview 'sv' + VIEW 1 rows = p2:I + 0: 328 + 329: 'id-329' + 329: subview 'sv' + VIEW 1 rows = p2:I + 0: 329 + 330: 'id-330' + 330: subview 'sv' + VIEW 1 rows = p2:I + 0: 330 + 331: 'id-331' + 331: subview 'sv' + VIEW 1 rows = p2:I + 0: 331 + 332: 'id-332' + 332: subview 'sv' + VIEW 1 rows = p2:I + 0: 332 + 333: 'id-333' + 333: subview 'sv' + VIEW 1 rows = p2:I + 0: 333 + 334: 'id-334' + 334: subview 'sv' + VIEW 1 rows = p2:I + 0: 334 + 335: 'id-335' + 335: subview 'sv' + VIEW 1 rows = p2:I + 0: 335 + 336: 'id-336' + 336: subview 'sv' + VIEW 1 rows = p2:I + 0: 336 + 337: 'id-337' + 337: subview 'sv' + VIEW 1 rows = p2:I + 0: 337 + 338: 'id-338' + 338: subview 'sv' + VIEW 1 rows = p2:I + 0: 338 + 339: 'id-339' + 339: subview 'sv' + VIEW 1 rows = p2:I + 0: 339 + 340: 'id-340' + 340: subview 'sv' + VIEW 1 rows = p2:I + 0: 340 + 341: 'id-341' + 341: subview 'sv' + VIEW 1 rows = p2:I + 0: 341 + 342: 'id-342' + 342: subview 'sv' + VIEW 1 rows = p2:I + 0: 342 + 343: 'id-343' + 343: subview 'sv' + VIEW 1 rows = p2:I + 0: 343 + 344: 'id-344' + 344: subview 'sv' + VIEW 1 rows = p2:I + 0: 344 + 345: 'id-345' + 345: subview 'sv' + VIEW 1 rows = p2:I + 0: 345 + 346: 'id-346' + 346: subview 'sv' + VIEW 1 rows = p2:I + 0: 346 + 347: 'id-347' + 347: subview 'sv' + VIEW 1 rows = p2:I + 0: 347 + 348: 'id-348' + 348: subview 'sv' + VIEW 1 rows = p2:I + 0: 348 + 349: 'id-349' + 349: subview 'sv' + VIEW 1 rows = p2:I + 0: 349 + 350: 'id-350' + 350: subview 'sv' + VIEW 1 rows = p2:I + 0: 350 + 351: 'id-351' + 351: subview 'sv' + VIEW 1 rows = p2:I + 0: 351 + 352: 'id-352' + 352: subview 'sv' + VIEW 1 rows = p2:I + 0: 352 + 353: 'id-353' + 353: subview 'sv' + VIEW 1 rows = p2:I + 0: 353 + 354: 'id-354' + 354: subview 'sv' + VIEW 1 rows = p2:I + 0: 354 + 355: 'id-355' + 355: subview 'sv' + VIEW 1 rows = p2:I + 0: 355 + 356: 'id-356' + 356: subview 'sv' + VIEW 1 rows = p2:I + 0: 356 + 357: 'id-357' + 357: subview 'sv' + VIEW 1 rows = p2:I + 0: 357 + 358: 'id-358' + 358: subview 'sv' + VIEW 1 rows = p2:I + 0: 358 + 359: 'id-359' + 359: subview 'sv' + VIEW 1 rows = p2:I + 0: 359 + 360: 'id-360' + 360: subview 'sv' + VIEW 1 rows = p2:I + 0: 360 + 361: 'id-361' + 361: subview 'sv' + VIEW 1 rows = p2:I + 0: 361 + 362: 'id-362' + 362: subview 'sv' + VIEW 1 rows = p2:I + 0: 362 + 363: 'id-363' + 363: subview 'sv' + VIEW 1 rows = p2:I + 0: 363 + 364: 'id-364' + 364: subview 'sv' + VIEW 1 rows = p2:I + 0: 364 + 365: 'id-365' + 365: subview 'sv' + VIEW 1 rows = p2:I + 0: 365 + 366: 'id-366' + 366: subview 'sv' + VIEW 1 rows = p2:I + 0: 366 + 367: 'id-367' + 367: subview 'sv' + VIEW 1 rows = p2:I + 0: 367 + 368: 'id-368' + 368: subview 'sv' + VIEW 1 rows = p2:I + 0: 368 + 369: 'id-369' + 369: subview 'sv' + VIEW 1 rows = p2:I + 0: 369 + 370: 'id-370' + 370: subview 'sv' + VIEW 1 rows = p2:I + 0: 370 + 371: 'id-371' + 371: subview 'sv' + VIEW 1 rows = p2:I + 0: 371 + 372: 'id-372' + 372: subview 'sv' + VIEW 1 rows = p2:I + 0: 372 + 373: 'id-373' + 373: subview 'sv' + VIEW 1 rows = p2:I + 0: 373 + 374: 'id-374' + 374: subview 'sv' + VIEW 1 rows = p2:I + 0: 374 + 375: 'id-375' + 375: subview 'sv' + VIEW 1 rows = p2:I + 0: 375 + 376: 'id-376' + 376: subview 'sv' + VIEW 1 rows = p2:I + 0: 376 + 377: 'id-377' + 377: subview 'sv' + VIEW 1 rows = p2:I + 0: 377 + 378: 'id-378' + 378: subview 'sv' + VIEW 1 rows = p2:I + 0: 378 + 379: 'id-379' + 379: subview 'sv' + VIEW 1 rows = p2:I + 0: 379 + 380: 'id-380' + 380: subview 'sv' + VIEW 1 rows = p2:I + 0: 380 + 381: 'id-381' + 381: subview 'sv' + VIEW 1 rows = p2:I + 0: 381 + 382: 'id-382' + 382: subview 'sv' + VIEW 1 rows = p2:I + 0: 382 + 383: 'id-383' + 383: subview 'sv' + VIEW 1 rows = p2:I + 0: 383 + 384: 'id-384' + 384: subview 'sv' + VIEW 1 rows = p2:I + 0: 384 + 385: 'id-385' + 385: subview 'sv' + VIEW 1 rows = p2:I + 0: 385 + 386: 'id-386' + 386: subview 'sv' + VIEW 1 rows = p2:I + 0: 386 + 387: 'id-387' + 387: subview 'sv' + VIEW 1 rows = p2:I + 0: 387 + 388: 'id-388' + 388: subview 'sv' + VIEW 1 rows = p2:I + 0: 388 + 389: 'id-389' + 389: subview 'sv' + VIEW 1 rows = p2:I + 0: 389 + 390: 'id-390' + 390: subview 'sv' + VIEW 1 rows = p2:I + 0: 390 + 391: 'id-391' + 391: subview 'sv' + VIEW 1 rows = p2:I + 0: 391 + 392: 'id-392' + 392: subview 'sv' + VIEW 1 rows = p2:I + 0: 392 + 393: 'id-393' + 393: subview 'sv' + VIEW 1 rows = p2:I + 0: 393 + 394: 'id-394' + 394: subview 'sv' + VIEW 1 rows = p2:I + 0: 394 + 395: 'id-395' + 395: subview 'sv' + VIEW 1 rows = p2:I + 0: 395 + 396: 'id-396' + 396: subview 'sv' + VIEW 1 rows = p2:I + 0: 396 + 397: 'id-397' + 397: subview 'sv' + VIEW 1 rows = p2:I + 0: 397 + 398: 'id-398' + 398: subview 'sv' + VIEW 1 rows = p2:I + 0: 398 + 399: 'id-399' + 399: subview 'sv' + VIEW 1 rows = p2:I + 0: 399 + 400: 'id-400' + 400: subview 'sv' + VIEW 1 rows = p2:I + 0: 400 + 401: 'id-401' + 401: subview 'sv' + VIEW 1 rows = p2:I + 0: 401 + 402: 'id-402' + 402: subview 'sv' + VIEW 1 rows = p2:I + 0: 402 + 403: 'id-403' + 403: subview 'sv' + VIEW 1 rows = p2:I + 0: 403 + 404: 'id-404' + 404: subview 'sv' + VIEW 1 rows = p2:I + 0: 404 + 405: 'id-405' + 405: subview 'sv' + VIEW 1 rows = p2:I + 0: 405 + 406: 'id-406' + 406: subview 'sv' + VIEW 1 rows = p2:I + 0: 406 + 407: 'id-407' + 407: subview 'sv' + VIEW 1 rows = p2:I + 0: 407 + 408: 'id-408' + 408: subview 'sv' + VIEW 1 rows = p2:I + 0: 408 + 409: 'id-409' + 409: subview 'sv' + VIEW 1 rows = p2:I + 0: 409 + 410: 'id-410' + 410: subview 'sv' + VIEW 1 rows = p2:I + 0: 410 + 411: 'id-411' + 411: subview 'sv' + VIEW 1 rows = p2:I + 0: 411 + 412: 'id-412' + 412: subview 'sv' + VIEW 1 rows = p2:I + 0: 412 + 413: 'id-413' + 413: subview 'sv' + VIEW 1 rows = p2:I + 0: 413 + 414: 'id-414' + 414: subview 'sv' + VIEW 1 rows = p2:I + 0: 414 + 415: 'id-415' + 415: subview 'sv' + VIEW 1 rows = p2:I + 0: 415 + 416: 'id-416' + 416: subview 'sv' + VIEW 1 rows = p2:I + 0: 416 + 417: 'id-417' + 417: subview 'sv' + VIEW 1 rows = p2:I + 0: 417 + 418: 'id-418' + 418: subview 'sv' + VIEW 1 rows = p2:I + 0: 418 + 419: 'id-419' + 419: subview 'sv' + VIEW 1 rows = p2:I + 0: 419 + 420: 'id-420' + 420: subview 'sv' + VIEW 1 rows = p2:I + 0: 420 + 421: 'id-421' + 421: subview 'sv' + VIEW 1 rows = p2:I + 0: 421 + 422: 'id-422' + 422: subview 'sv' + VIEW 1 rows = p2:I + 0: 422 + 423: 'id-423' + 423: subview 'sv' + VIEW 1 rows = p2:I + 0: 423 + 424: 'id-424' + 424: subview 'sv' + VIEW 1 rows = p2:I + 0: 424 + 425: 'id-425' + 425: subview 'sv' + VIEW 1 rows = p2:I + 0: 425 + 426: 'id-426' + 426: subview 'sv' + VIEW 1 rows = p2:I + 0: 426 + 427: 'id-427' + 427: subview 'sv' + VIEW 1 rows = p2:I + 0: 427 + 428: 'id-428' + 428: subview 'sv' + VIEW 1 rows = p2:I + 0: 428 + 429: 'id-429' + 429: subview 'sv' + VIEW 1 rows = p2:I + 0: 429 + 430: 'id-430' + 430: subview 'sv' + VIEW 1 rows = p2:I + 0: 430 + 431: 'id-431' + 431: subview 'sv' + VIEW 1 rows = p2:I + 0: 431 + 432: 'id-432' + 432: subview 'sv' + VIEW 1 rows = p2:I + 0: 432 + 433: 'id-433' + 433: subview 'sv' + VIEW 1 rows = p2:I + 0: 433 + 434: 'id-434' + 434: subview 'sv' + VIEW 1 rows = p2:I + 0: 434 + 435: 'id-435' + 435: subview 'sv' + VIEW 1 rows = p2:I + 0: 435 + 436: 'id-436' + 436: subview 'sv' + VIEW 1 rows = p2:I + 0: 436 + 437: 'id-437' + 437: subview 'sv' + VIEW 1 rows = p2:I + 0: 437 + 438: 'id-438' + 438: subview 'sv' + VIEW 1 rows = p2:I + 0: 438 + 439: 'id-439' + 439: subview 'sv' + VIEW 1 rows = p2:I + 0: 439 + 440: 'id-440' + 440: subview 'sv' + VIEW 1 rows = p2:I + 0: 440 + 441: 'id-441' + 441: subview 'sv' + VIEW 1 rows = p2:I + 0: 441 + 442: 'id-442' + 442: subview 'sv' + VIEW 1 rows = p2:I + 0: 442 + 443: 'id-443' + 443: subview 'sv' + VIEW 1 rows = p2:I + 0: 443 + 444: 'id-444' + 444: subview 'sv' + VIEW 1 rows = p2:I + 0: 444 + 445: 'id-445' + 445: subview 'sv' + VIEW 1 rows = p2:I + 0: 445 + 446: 'id-446' + 446: subview 'sv' + VIEW 1 rows = p2:I + 0: 446 + 447: 'id-447' + 447: subview 'sv' + VIEW 1 rows = p2:I + 0: 447 + 448: 'id-448' + 448: subview 'sv' + VIEW 1 rows = p2:I + 0: 448 + 449: 'id-449' + 449: subview 'sv' + VIEW 1 rows = p2:I + 0: 449 + 450: 'id-450' + 450: subview 'sv' + VIEW 1 rows = p2:I + 0: 450 + 451: 'id-451' + 451: subview 'sv' + VIEW 1 rows = p2:I + 0: 451 + 452: 'id-452' + 452: subview 'sv' + VIEW 1 rows = p2:I + 0: 452 + 453: 'id-453' + 453: subview 'sv' + VIEW 1 rows = p2:I + 0: 453 + 454: 'id-454' + 454: subview 'sv' + VIEW 1 rows = p2:I + 0: 454 + 455: 'id-455' + 455: subview 'sv' + VIEW 1 rows = p2:I + 0: 455 + 456: 'id-456' + 456: subview 'sv' + VIEW 1 rows = p2:I + 0: 456 + 457: 'id-457' + 457: subview 'sv' + VIEW 1 rows = p2:I + 0: 457 + 458: 'id-458' + 458: subview 'sv' + VIEW 1 rows = p2:I + 0: 458 + 459: 'id-459' + 459: subview 'sv' + VIEW 1 rows = p2:I + 0: 459 + 460: 'id-460' + 460: subview 'sv' + VIEW 1 rows = p2:I + 0: 460 + 461: 'id-461' + 461: subview 'sv' + VIEW 1 rows = p2:I + 0: 461 + 462: 'id-462' + 462: subview 'sv' + VIEW 1 rows = p2:I + 0: 462 + 463: 'id-463' + 463: subview 'sv' + VIEW 1 rows = p2:I + 0: 463 + 464: 'id-464' + 464: subview 'sv' + VIEW 1 rows = p2:I + 0: 464 + 465: 'id-465' + 465: subview 'sv' + VIEW 1 rows = p2:I + 0: 465 + 466: 'id-466' + 466: subview 'sv' + VIEW 1 rows = p2:I + 0: 466 + 467: 'id-467' + 467: subview 'sv' + VIEW 1 rows = p2:I + 0: 467 + 468: 'id-468' + 468: subview 'sv' + VIEW 1 rows = p2:I + 0: 468 + 469: 'id-469' + 469: subview 'sv' + VIEW 1 rows = p2:I + 0: 469 + 470: 'id-470' + 470: subview 'sv' + VIEW 1 rows = p2:I + 0: 470 + 471: 'id-471' + 471: subview 'sv' + VIEW 1 rows = p2:I + 0: 471 + 472: 'id-472' + 472: subview 'sv' + VIEW 1 rows = p2:I + 0: 472 + 473: 'id-473' + 473: subview 'sv' + VIEW 1 rows = p2:I + 0: 473 + 474: 'id-474' + 474: subview 'sv' + VIEW 1 rows = p2:I + 0: 474 + 475: 'id-475' + 475: subview 'sv' + VIEW 1 rows = p2:I + 0: 475 + 476: 'id-476' + 476: subview 'sv' + VIEW 1 rows = p2:I + 0: 476 + 477: 'id-477' + 477: subview 'sv' + VIEW 1 rows = p2:I + 0: 477 + 478: 'id-478' + 478: subview 'sv' + VIEW 1 rows = p2:I + 0: 478 + 479: 'id-479' + 479: subview 'sv' + VIEW 1 rows = p2:I + 0: 479 + 480: 'id-480' + 480: subview 'sv' + VIEW 1 rows = p2:I + 0: 480 + 481: 'id-481' + 481: subview 'sv' + VIEW 1 rows = p2:I + 0: 481 + 482: 'id-482' + 482: subview 'sv' + VIEW 1 rows = p2:I + 0: 482 + 483: 'id-483' + 483: subview 'sv' + VIEW 1 rows = p2:I + 0: 483 + 484: 'id-484' + 484: subview 'sv' + VIEW 1 rows = p2:I + 0: 484 + 485: 'id-485' + 485: subview 'sv' + VIEW 1 rows = p2:I + 0: 485 + 486: 'id-486' + 486: subview 'sv' + VIEW 1 rows = p2:I + 0: 486 + 487: 'id-487' + 487: subview 'sv' + VIEW 1 rows = p2:I + 0: 487 + 488: 'id-488' + 488: subview 'sv' + VIEW 1 rows = p2:I + 0: 488 + 489: 'id-489' + 489: subview 'sv' + VIEW 1 rows = p2:I + 0: 489 + 490: 'id-490' + 490: subview 'sv' + VIEW 1 rows = p2:I + 0: 490 + 491: 'id-491' + 491: subview 'sv' + VIEW 1 rows = p2:I + 0: 491 + 492: 'id-492' + 492: subview 'sv' + VIEW 1 rows = p2:I + 0: 492 + 493: 'id-493' + 493: subview 'sv' + VIEW 1 rows = p2:I + 0: 493 + 494: 'id-494' + 494: subview 'sv' + VIEW 1 rows = p2:I + 0: 494 + 495: 'id-495' + 495: subview 'sv' + VIEW 1 rows = p2:I + 0: 495 + 496: 'id-496' + 496: subview 'sv' + VIEW 1 rows = p2:I + 0: 496 + 497: 'id-497' + 497: subview 'sv' + VIEW 1 rows = p2:I + 0: 497 + 498: 'id-498' + 498: subview 'sv' + VIEW 1 rows = p2:I + 0: 498 + 499: 'id-499' + 499: subview 'sv' + VIEW 1 rows = p2:I + 0: 499 + 1: subview '_B' + VIEW 500 rows = p1:S sv:V + 0: 'id-500' + 0: subview 'sv' + VIEW 1 rows = p2:I + 0: 500 + 1: 'id-501' + 1: subview 'sv' + VIEW 1 rows = p2:I + 0: 501 + 2: 'id-502' + 2: subview 'sv' + VIEW 1 rows = p2:I + 0: 502 + 3: 'id-503' + 3: subview 'sv' + VIEW 1 rows = p2:I + 0: 503 + 4: 'id-504' + 4: subview 'sv' + VIEW 1 rows = p2:I + 0: 504 + 5: 'id-505' + 5: subview 'sv' + VIEW 1 rows = p2:I + 0: 505 + 6: 'id-506' + 6: subview 'sv' + VIEW 1 rows = p2:I + 0: 506 + 7: 'id-507' + 7: subview 'sv' + VIEW 1 rows = p2:I + 0: 507 + 8: 'id-508' + 8: subview 'sv' + VIEW 1 rows = p2:I + 0: 508 + 9: 'id-509' + 9: subview 'sv' + VIEW 1 rows = p2:I + 0: 509 + 10: 'id-510' + 10: subview 'sv' + VIEW 1 rows = p2:I + 0: 510 + 11: 'id-511' + 11: subview 'sv' + VIEW 1 rows = p2:I + 0: 511 + 12: 'id-512' + 12: subview 'sv' + VIEW 1 rows = p2:I + 0: 512 + 13: 'id-513' + 13: subview 'sv' + VIEW 1 rows = p2:I + 0: 513 + 14: 'id-514' + 14: subview 'sv' + VIEW 1 rows = p2:I + 0: 514 + 15: 'id-515' + 15: subview 'sv' + VIEW 1 rows = p2:I + 0: 515 + 16: 'id-516' + 16: subview 'sv' + VIEW 1 rows = p2:I + 0: 516 + 17: 'id-517' + 17: subview 'sv' + VIEW 1 rows = p2:I + 0: 517 + 18: 'id-518' + 18: subview 'sv' + VIEW 1 rows = p2:I + 0: 518 + 19: 'id-519' + 19: subview 'sv' + VIEW 1 rows = p2:I + 0: 519 + 20: 'id-520' + 20: subview 'sv' + VIEW 1 rows = p2:I + 0: 520 + 21: 'id-521' + 21: subview 'sv' + VIEW 1 rows = p2:I + 0: 521 + 22: 'id-522' + 22: subview 'sv' + VIEW 1 rows = p2:I + 0: 522 + 23: 'id-523' + 23: subview 'sv' + VIEW 1 rows = p2:I + 0: 523 + 24: 'id-524' + 24: subview 'sv' + VIEW 1 rows = p2:I + 0: 524 + 25: 'id-525' + 25: subview 'sv' + VIEW 1 rows = p2:I + 0: 525 + 26: 'id-526' + 26: subview 'sv' + VIEW 1 rows = p2:I + 0: 526 + 27: 'id-527' + 27: subview 'sv' + VIEW 1 rows = p2:I + 0: 527 + 28: 'id-528' + 28: subview 'sv' + VIEW 1 rows = p2:I + 0: 528 + 29: 'id-529' + 29: subview 'sv' + VIEW 1 rows = p2:I + 0: 529 + 30: 'id-530' + 30: subview 'sv' + VIEW 1 rows = p2:I + 0: 530 + 31: 'id-531' + 31: subview 'sv' + VIEW 1 rows = p2:I + 0: 531 + 32: 'id-532' + 32: subview 'sv' + VIEW 1 rows = p2:I + 0: 532 + 33: 'id-533' + 33: subview 'sv' + VIEW 1 rows = p2:I + 0: 533 + 34: 'id-534' + 34: subview 'sv' + VIEW 1 rows = p2:I + 0: 534 + 35: 'id-535' + 35: subview 'sv' + VIEW 1 rows = p2:I + 0: 535 + 36: 'id-536' + 36: subview 'sv' + VIEW 1 rows = p2:I + 0: 536 + 37: 'id-537' + 37: subview 'sv' + VIEW 1 rows = p2:I + 0: 537 + 38: 'id-538' + 38: subview 'sv' + VIEW 1 rows = p2:I + 0: 538 + 39: 'id-539' + 39: subview 'sv' + VIEW 1 rows = p2:I + 0: 539 + 40: 'id-540' + 40: subview 'sv' + VIEW 1 rows = p2:I + 0: 540 + 41: 'id-541' + 41: subview 'sv' + VIEW 1 rows = p2:I + 0: 541 + 42: 'id-542' + 42: subview 'sv' + VIEW 1 rows = p2:I + 0: 542 + 43: 'id-543' + 43: subview 'sv' + VIEW 1 rows = p2:I + 0: 543 + 44: 'id-544' + 44: subview 'sv' + VIEW 1 rows = p2:I + 0: 544 + 45: 'id-545' + 45: subview 'sv' + VIEW 1 rows = p2:I + 0: 545 + 46: 'id-546' + 46: subview 'sv' + VIEW 1 rows = p2:I + 0: 546 + 47: 'id-547' + 47: subview 'sv' + VIEW 1 rows = p2:I + 0: 547 + 48: 'id-548' + 48: subview 'sv' + VIEW 1 rows = p2:I + 0: 548 + 49: 'id-549' + 49: subview 'sv' + VIEW 1 rows = p2:I + 0: 549 + 50: 'id-550' + 50: subview 'sv' + VIEW 1 rows = p2:I + 0: 550 + 51: 'id-551' + 51: subview 'sv' + VIEW 1 rows = p2:I + 0: 551 + 52: 'id-552' + 52: subview 'sv' + VIEW 1 rows = p2:I + 0: 552 + 53: 'id-553' + 53: subview 'sv' + VIEW 1 rows = p2:I + 0: 553 + 54: 'id-554' + 54: subview 'sv' + VIEW 1 rows = p2:I + 0: 554 + 55: 'id-555' + 55: subview 'sv' + VIEW 1 rows = p2:I + 0: 555 + 56: 'id-556' + 56: subview 'sv' + VIEW 1 rows = p2:I + 0: 556 + 57: 'id-557' + 57: subview 'sv' + VIEW 1 rows = p2:I + 0: 557 + 58: 'id-558' + 58: subview 'sv' + VIEW 1 rows = p2:I + 0: 558 + 59: 'id-559' + 59: subview 'sv' + VIEW 1 rows = p2:I + 0: 559 + 60: 'id-560' + 60: subview 'sv' + VIEW 1 rows = p2:I + 0: 560 + 61: 'id-561' + 61: subview 'sv' + VIEW 1 rows = p2:I + 0: 561 + 62: 'id-562' + 62: subview 'sv' + VIEW 1 rows = p2:I + 0: 562 + 63: 'id-563' + 63: subview 'sv' + VIEW 1 rows = p2:I + 0: 563 + 64: 'id-564' + 64: subview 'sv' + VIEW 1 rows = p2:I + 0: 564 + 65: 'id-565' + 65: subview 'sv' + VIEW 1 rows = p2:I + 0: 565 + 66: 'id-566' + 66: subview 'sv' + VIEW 1 rows = p2:I + 0: 566 + 67: 'id-567' + 67: subview 'sv' + VIEW 1 rows = p2:I + 0: 567 + 68: 'id-568' + 68: subview 'sv' + VIEW 1 rows = p2:I + 0: 568 + 69: 'id-569' + 69: subview 'sv' + VIEW 1 rows = p2:I + 0: 569 + 70: 'id-570' + 70: subview 'sv' + VIEW 1 rows = p2:I + 0: 570 + 71: 'id-571' + 71: subview 'sv' + VIEW 1 rows = p2:I + 0: 571 + 72: 'id-572' + 72: subview 'sv' + VIEW 1 rows = p2:I + 0: 572 + 73: 'id-573' + 73: subview 'sv' + VIEW 1 rows = p2:I + 0: 573 + 74: 'id-574' + 74: subview 'sv' + VIEW 1 rows = p2:I + 0: 574 + 75: 'id-575' + 75: subview 'sv' + VIEW 1 rows = p2:I + 0: 575 + 76: 'id-576' + 76: subview 'sv' + VIEW 1 rows = p2:I + 0: 576 + 77: 'id-577' + 77: subview 'sv' + VIEW 1 rows = p2:I + 0: 577 + 78: 'id-578' + 78: subview 'sv' + VIEW 1 rows = p2:I + 0: 578 + 79: 'id-579' + 79: subview 'sv' + VIEW 1 rows = p2:I + 0: 579 + 80: 'id-580' + 80: subview 'sv' + VIEW 1 rows = p2:I + 0: 580 + 81: 'id-581' + 81: subview 'sv' + VIEW 1 rows = p2:I + 0: 581 + 82: 'id-582' + 82: subview 'sv' + VIEW 1 rows = p2:I + 0: 582 + 83: 'id-583' + 83: subview 'sv' + VIEW 1 rows = p2:I + 0: 583 + 84: 'id-584' + 84: subview 'sv' + VIEW 1 rows = p2:I + 0: 584 + 85: 'id-585' + 85: subview 'sv' + VIEW 1 rows = p2:I + 0: 585 + 86: 'id-586' + 86: subview 'sv' + VIEW 1 rows = p2:I + 0: 586 + 87: 'id-587' + 87: subview 'sv' + VIEW 1 rows = p2:I + 0: 587 + 88: 'id-588' + 88: subview 'sv' + VIEW 1 rows = p2:I + 0: 588 + 89: 'id-589' + 89: subview 'sv' + VIEW 1 rows = p2:I + 0: 589 + 90: 'id-590' + 90: subview 'sv' + VIEW 1 rows = p2:I + 0: 590 + 91: 'id-591' + 91: subview 'sv' + VIEW 1 rows = p2:I + 0: 591 + 92: 'id-592' + 92: subview 'sv' + VIEW 1 rows = p2:I + 0: 592 + 93: 'id-593' + 93: subview 'sv' + VIEW 1 rows = p2:I + 0: 593 + 94: 'id-594' + 94: subview 'sv' + VIEW 1 rows = p2:I + 0: 594 + 95: 'id-595' + 95: subview 'sv' + VIEW 1 rows = p2:I + 0: 595 + 96: 'id-596' + 96: subview 'sv' + VIEW 1 rows = p2:I + 0: 596 + 97: 'id-597' + 97: subview 'sv' + VIEW 1 rows = p2:I + 0: 597 + 98: 'id-598' + 98: subview 'sv' + VIEW 1 rows = p2:I + 0: 598 + 99: 'id-599' + 99: subview 'sv' + VIEW 1 rows = p2:I + 0: 599 + 100: 'id-600' + 100: subview 'sv' + VIEW 1 rows = p2:I + 0: 600 + 101: 'id-601' + 101: subview 'sv' + VIEW 1 rows = p2:I + 0: 601 + 102: 'id-602' + 102: subview 'sv' + VIEW 1 rows = p2:I + 0: 602 + 103: 'id-603' + 103: subview 'sv' + VIEW 1 rows = p2:I + 0: 603 + 104: 'id-604' + 104: subview 'sv' + VIEW 1 rows = p2:I + 0: 604 + 105: 'id-605' + 105: subview 'sv' + VIEW 1 rows = p2:I + 0: 605 + 106: 'id-606' + 106: subview 'sv' + VIEW 1 rows = p2:I + 0: 606 + 107: 'id-607' + 107: subview 'sv' + VIEW 1 rows = p2:I + 0: 607 + 108: 'id-608' + 108: subview 'sv' + VIEW 1 rows = p2:I + 0: 608 + 109: 'id-609' + 109: subview 'sv' + VIEW 1 rows = p2:I + 0: 609 + 110: 'id-610' + 110: subview 'sv' + VIEW 1 rows = p2:I + 0: 610 + 111: 'id-611' + 111: subview 'sv' + VIEW 1 rows = p2:I + 0: 611 + 112: 'id-612' + 112: subview 'sv' + VIEW 1 rows = p2:I + 0: 612 + 113: 'id-613' + 113: subview 'sv' + VIEW 1 rows = p2:I + 0: 613 + 114: 'id-614' + 114: subview 'sv' + VIEW 1 rows = p2:I + 0: 614 + 115: 'id-615' + 115: subview 'sv' + VIEW 1 rows = p2:I + 0: 615 + 116: 'id-616' + 116: subview 'sv' + VIEW 1 rows = p2:I + 0: 616 + 117: 'id-617' + 117: subview 'sv' + VIEW 1 rows = p2:I + 0: 617 + 118: 'id-618' + 118: subview 'sv' + VIEW 1 rows = p2:I + 0: 618 + 119: 'id-619' + 119: subview 'sv' + VIEW 1 rows = p2:I + 0: 619 + 120: 'id-620' + 120: subview 'sv' + VIEW 1 rows = p2:I + 0: 620 + 121: 'id-621' + 121: subview 'sv' + VIEW 1 rows = p2:I + 0: 621 + 122: 'id-622' + 122: subview 'sv' + VIEW 1 rows = p2:I + 0: 622 + 123: 'id-623' + 123: subview 'sv' + VIEW 1 rows = p2:I + 0: 623 + 124: 'id-624' + 124: subview 'sv' + VIEW 1 rows = p2:I + 0: 624 + 125: 'id-625' + 125: subview 'sv' + VIEW 1 rows = p2:I + 0: 625 + 126: 'id-626' + 126: subview 'sv' + VIEW 1 rows = p2:I + 0: 626 + 127: 'id-627' + 127: subview 'sv' + VIEW 1 rows = p2:I + 0: 627 + 128: 'id-628' + 128: subview 'sv' + VIEW 1 rows = p2:I + 0: 628 + 129: 'id-629' + 129: subview 'sv' + VIEW 1 rows = p2:I + 0: 629 + 130: 'id-630' + 130: subview 'sv' + VIEW 1 rows = p2:I + 0: 630 + 131: 'id-631' + 131: subview 'sv' + VIEW 1 rows = p2:I + 0: 631 + 132: 'id-632' + 132: subview 'sv' + VIEW 1 rows = p2:I + 0: 632 + 133: 'id-633' + 133: subview 'sv' + VIEW 1 rows = p2:I + 0: 633 + 134: 'id-634' + 134: subview 'sv' + VIEW 1 rows = p2:I + 0: 634 + 135: 'id-635' + 135: subview 'sv' + VIEW 1 rows = p2:I + 0: 635 + 136: 'id-636' + 136: subview 'sv' + VIEW 1 rows = p2:I + 0: 636 + 137: 'id-637' + 137: subview 'sv' + VIEW 1 rows = p2:I + 0: 637 + 138: 'id-638' + 138: subview 'sv' + VIEW 1 rows = p2:I + 0: 638 + 139: 'id-639' + 139: subview 'sv' + VIEW 1 rows = p2:I + 0: 639 + 140: 'id-640' + 140: subview 'sv' + VIEW 1 rows = p2:I + 0: 640 + 141: 'id-641' + 141: subview 'sv' + VIEW 1 rows = p2:I + 0: 641 + 142: 'id-642' + 142: subview 'sv' + VIEW 1 rows = p2:I + 0: 642 + 143: 'id-643' + 143: subview 'sv' + VIEW 1 rows = p2:I + 0: 643 + 144: 'id-644' + 144: subview 'sv' + VIEW 1 rows = p2:I + 0: 644 + 145: 'id-645' + 145: subview 'sv' + VIEW 1 rows = p2:I + 0: 645 + 146: 'id-646' + 146: subview 'sv' + VIEW 1 rows = p2:I + 0: 646 + 147: 'id-647' + 147: subview 'sv' + VIEW 1 rows = p2:I + 0: 647 + 148: 'id-648' + 148: subview 'sv' + VIEW 1 rows = p2:I + 0: 648 + 149: 'id-649' + 149: subview 'sv' + VIEW 1 rows = p2:I + 0: 649 + 150: 'id-650' + 150: subview 'sv' + VIEW 1 rows = p2:I + 0: 650 + 151: 'id-651' + 151: subview 'sv' + VIEW 1 rows = p2:I + 0: 651 + 152: 'id-652' + 152: subview 'sv' + VIEW 1 rows = p2:I + 0: 652 + 153: 'id-653' + 153: subview 'sv' + VIEW 1 rows = p2:I + 0: 653 + 154: 'id-654' + 154: subview 'sv' + VIEW 1 rows = p2:I + 0: 654 + 155: 'id-655' + 155: subview 'sv' + VIEW 1 rows = p2:I + 0: 655 + 156: 'id-656' + 156: subview 'sv' + VIEW 1 rows = p2:I + 0: 656 + 157: 'id-657' + 157: subview 'sv' + VIEW 1 rows = p2:I + 0: 657 + 158: 'id-658' + 158: subview 'sv' + VIEW 1 rows = p2:I + 0: 658 + 159: 'id-659' + 159: subview 'sv' + VIEW 1 rows = p2:I + 0: 659 + 160: 'id-660' + 160: subview 'sv' + VIEW 1 rows = p2:I + 0: 660 + 161: 'id-661' + 161: subview 'sv' + VIEW 1 rows = p2:I + 0: 661 + 162: 'id-662' + 162: subview 'sv' + VIEW 1 rows = p2:I + 0: 662 + 163: 'id-663' + 163: subview 'sv' + VIEW 1 rows = p2:I + 0: 663 + 164: 'id-664' + 164: subview 'sv' + VIEW 1 rows = p2:I + 0: 664 + 165: 'id-665' + 165: subview 'sv' + VIEW 1 rows = p2:I + 0: 665 + 166: 'id-666' + 166: subview 'sv' + VIEW 1 rows = p2:I + 0: 666 + 167: 'id-667' + 167: subview 'sv' + VIEW 1 rows = p2:I + 0: 667 + 168: 'id-668' + 168: subview 'sv' + VIEW 1 rows = p2:I + 0: 668 + 169: 'id-669' + 169: subview 'sv' + VIEW 1 rows = p2:I + 0: 669 + 170: 'id-670' + 170: subview 'sv' + VIEW 1 rows = p2:I + 0: 670 + 171: 'id-671' + 171: subview 'sv' + VIEW 1 rows = p2:I + 0: 671 + 172: 'id-672' + 172: subview 'sv' + VIEW 1 rows = p2:I + 0: 672 + 173: 'id-673' + 173: subview 'sv' + VIEW 1 rows = p2:I + 0: 673 + 174: 'id-674' + 174: subview 'sv' + VIEW 1 rows = p2:I + 0: 674 + 175: 'id-675' + 175: subview 'sv' + VIEW 1 rows = p2:I + 0: 675 + 176: 'id-676' + 176: subview 'sv' + VIEW 1 rows = p2:I + 0: 676 + 177: 'id-677' + 177: subview 'sv' + VIEW 1 rows = p2:I + 0: 677 + 178: 'id-678' + 178: subview 'sv' + VIEW 1 rows = p2:I + 0: 678 + 179: 'id-679' + 179: subview 'sv' + VIEW 1 rows = p2:I + 0: 679 + 180: 'id-680' + 180: subview 'sv' + VIEW 1 rows = p2:I + 0: 680 + 181: 'id-681' + 181: subview 'sv' + VIEW 1 rows = p2:I + 0: 681 + 182: 'id-682' + 182: subview 'sv' + VIEW 1 rows = p2:I + 0: 682 + 183: 'id-683' + 183: subview 'sv' + VIEW 1 rows = p2:I + 0: 683 + 184: 'id-684' + 184: subview 'sv' + VIEW 1 rows = p2:I + 0: 684 + 185: 'id-685' + 185: subview 'sv' + VIEW 1 rows = p2:I + 0: 685 + 186: 'id-686' + 186: subview 'sv' + VIEW 1 rows = p2:I + 0: 686 + 187: 'id-687' + 187: subview 'sv' + VIEW 1 rows = p2:I + 0: 687 + 188: 'id-688' + 188: subview 'sv' + VIEW 1 rows = p2:I + 0: 688 + 189: 'id-689' + 189: subview 'sv' + VIEW 1 rows = p2:I + 0: 689 + 190: 'id-690' + 190: subview 'sv' + VIEW 1 rows = p2:I + 0: 690 + 191: 'id-691' + 191: subview 'sv' + VIEW 1 rows = p2:I + 0: 691 + 192: 'id-692' + 192: subview 'sv' + VIEW 1 rows = p2:I + 0: 692 + 193: 'id-693' + 193: subview 'sv' + VIEW 1 rows = p2:I + 0: 693 + 194: 'id-694' + 194: subview 'sv' + VIEW 1 rows = p2:I + 0: 694 + 195: 'id-695' + 195: subview 'sv' + VIEW 1 rows = p2:I + 0: 695 + 196: 'id-696' + 196: subview 'sv' + VIEW 1 rows = p2:I + 0: 696 + 197: 'id-697' + 197: subview 'sv' + VIEW 1 rows = p2:I + 0: 697 + 198: 'id-698' + 198: subview 'sv' + VIEW 1 rows = p2:I + 0: 698 + 199: 'id-699' + 199: subview 'sv' + VIEW 1 rows = p2:I + 0: 699 + 200: 'id-700' + 200: subview 'sv' + VIEW 1 rows = p2:I + 0: 700 + 201: 'id-701' + 201: subview 'sv' + VIEW 1 rows = p2:I + 0: 701 + 202: 'id-702' + 202: subview 'sv' + VIEW 1 rows = p2:I + 0: 702 + 203: 'id-703' + 203: subview 'sv' + VIEW 1 rows = p2:I + 0: 703 + 204: 'id-704' + 204: subview 'sv' + VIEW 1 rows = p2:I + 0: 704 + 205: 'id-705' + 205: subview 'sv' + VIEW 1 rows = p2:I + 0: 705 + 206: 'id-706' + 206: subview 'sv' + VIEW 1 rows = p2:I + 0: 706 + 207: 'id-707' + 207: subview 'sv' + VIEW 1 rows = p2:I + 0: 707 + 208: 'id-708' + 208: subview 'sv' + VIEW 1 rows = p2:I + 0: 708 + 209: 'id-709' + 209: subview 'sv' + VIEW 1 rows = p2:I + 0: 709 + 210: 'id-710' + 210: subview 'sv' + VIEW 1 rows = p2:I + 0: 710 + 211: 'id-711' + 211: subview 'sv' + VIEW 1 rows = p2:I + 0: 711 + 212: 'id-712' + 212: subview 'sv' + VIEW 1 rows = p2:I + 0: 712 + 213: 'id-713' + 213: subview 'sv' + VIEW 1 rows = p2:I + 0: 713 + 214: 'id-714' + 214: subview 'sv' + VIEW 1 rows = p2:I + 0: 714 + 215: 'id-715' + 215: subview 'sv' + VIEW 1 rows = p2:I + 0: 715 + 216: 'id-716' + 216: subview 'sv' + VIEW 1 rows = p2:I + 0: 716 + 217: 'id-717' + 217: subview 'sv' + VIEW 1 rows = p2:I + 0: 717 + 218: 'id-718' + 218: subview 'sv' + VIEW 1 rows = p2:I + 0: 718 + 219: 'id-719' + 219: subview 'sv' + VIEW 1 rows = p2:I + 0: 719 + 220: 'id-720' + 220: subview 'sv' + VIEW 1 rows = p2:I + 0: 720 + 221: 'id-721' + 221: subview 'sv' + VIEW 1 rows = p2:I + 0: 721 + 222: 'id-722' + 222: subview 'sv' + VIEW 1 rows = p2:I + 0: 722 + 223: 'id-723' + 223: subview 'sv' + VIEW 1 rows = p2:I + 0: 723 + 224: 'id-724' + 224: subview 'sv' + VIEW 1 rows = p2:I + 0: 724 + 225: 'id-725' + 225: subview 'sv' + VIEW 1 rows = p2:I + 0: 725 + 226: 'id-726' + 226: subview 'sv' + VIEW 1 rows = p2:I + 0: 726 + 227: 'id-727' + 227: subview 'sv' + VIEW 1 rows = p2:I + 0: 727 + 228: 'id-728' + 228: subview 'sv' + VIEW 1 rows = p2:I + 0: 728 + 229: 'id-729' + 229: subview 'sv' + VIEW 1 rows = p2:I + 0: 729 + 230: 'id-730' + 230: subview 'sv' + VIEW 1 rows = p2:I + 0: 730 + 231: 'id-731' + 231: subview 'sv' + VIEW 1 rows = p2:I + 0: 731 + 232: 'id-732' + 232: subview 'sv' + VIEW 1 rows = p2:I + 0: 732 + 233: 'id-733' + 233: subview 'sv' + VIEW 1 rows = p2:I + 0: 733 + 234: 'id-734' + 234: subview 'sv' + VIEW 1 rows = p2:I + 0: 734 + 235: 'id-735' + 235: subview 'sv' + VIEW 1 rows = p2:I + 0: 735 + 236: 'id-736' + 236: subview 'sv' + VIEW 1 rows = p2:I + 0: 736 + 237: 'id-737' + 237: subview 'sv' + VIEW 1 rows = p2:I + 0: 737 + 238: 'id-738' + 238: subview 'sv' + VIEW 1 rows = p2:I + 0: 738 + 239: 'id-739' + 239: subview 'sv' + VIEW 1 rows = p2:I + 0: 739 + 240: 'id-740' + 240: subview 'sv' + VIEW 1 rows = p2:I + 0: 740 + 241: 'id-741' + 241: subview 'sv' + VIEW 1 rows = p2:I + 0: 741 + 242: 'id-742' + 242: subview 'sv' + VIEW 1 rows = p2:I + 0: 742 + 243: 'id-743' + 243: subview 'sv' + VIEW 1 rows = p2:I + 0: 743 + 244: 'id-744' + 244: subview 'sv' + VIEW 1 rows = p2:I + 0: 744 + 245: 'id-745' + 245: subview 'sv' + VIEW 1 rows = p2:I + 0: 745 + 246: 'id-746' + 246: subview 'sv' + VIEW 1 rows = p2:I + 0: 746 + 247: 'id-747' + 247: subview 'sv' + VIEW 1 rows = p2:I + 0: 747 + 248: 'id-748' + 248: subview 'sv' + VIEW 1 rows = p2:I + 0: 748 + 249: 'id-749' + 249: subview 'sv' + VIEW 1 rows = p2:I + 0: 749 + 250: 'id-750' + 250: subview 'sv' + VIEW 1 rows = p2:I + 0: 750 + 251: 'id-751' + 251: subview 'sv' + VIEW 1 rows = p2:I + 0: 751 + 252: 'id-752' + 252: subview 'sv' + VIEW 1 rows = p2:I + 0: 752 + 253: 'id-753' + 253: subview 'sv' + VIEW 1 rows = p2:I + 0: 753 + 254: 'id-754' + 254: subview 'sv' + VIEW 1 rows = p2:I + 0: 754 + 255: 'id-755' + 255: subview 'sv' + VIEW 1 rows = p2:I + 0: 755 + 256: 'id-756' + 256: subview 'sv' + VIEW 1 rows = p2:I + 0: 756 + 257: 'id-757' + 257: subview 'sv' + VIEW 1 rows = p2:I + 0: 757 + 258: 'id-758' + 258: subview 'sv' + VIEW 1 rows = p2:I + 0: 758 + 259: 'id-759' + 259: subview 'sv' + VIEW 1 rows = p2:I + 0: 759 + 260: 'id-760' + 260: subview 'sv' + VIEW 1 rows = p2:I + 0: 760 + 261: 'id-761' + 261: subview 'sv' + VIEW 1 rows = p2:I + 0: 761 + 262: 'id-762' + 262: subview 'sv' + VIEW 1 rows = p2:I + 0: 762 + 263: 'id-763' + 263: subview 'sv' + VIEW 1 rows = p2:I + 0: 763 + 264: 'id-764' + 264: subview 'sv' + VIEW 1 rows = p2:I + 0: 764 + 265: 'id-765' + 265: subview 'sv' + VIEW 1 rows = p2:I + 0: 765 + 266: 'id-766' + 266: subview 'sv' + VIEW 1 rows = p2:I + 0: 766 + 267: 'id-767' + 267: subview 'sv' + VIEW 1 rows = p2:I + 0: 767 + 268: 'id-768' + 268: subview 'sv' + VIEW 1 rows = p2:I + 0: 768 + 269: 'id-769' + 269: subview 'sv' + VIEW 1 rows = p2:I + 0: 769 + 270: 'id-770' + 270: subview 'sv' + VIEW 1 rows = p2:I + 0: 770 + 271: 'id-771' + 271: subview 'sv' + VIEW 1 rows = p2:I + 0: 771 + 272: 'id-772' + 272: subview 'sv' + VIEW 1 rows = p2:I + 0: 772 + 273: 'id-773' + 273: subview 'sv' + VIEW 1 rows = p2:I + 0: 773 + 274: 'id-774' + 274: subview 'sv' + VIEW 1 rows = p2:I + 0: 774 + 275: 'id-775' + 275: subview 'sv' + VIEW 1 rows = p2:I + 0: 775 + 276: 'id-776' + 276: subview 'sv' + VIEW 1 rows = p2:I + 0: 776 + 277: 'id-777' + 277: subview 'sv' + VIEW 1 rows = p2:I + 0: 777 + 278: 'id-778' + 278: subview 'sv' + VIEW 1 rows = p2:I + 0: 778 + 279: 'id-779' + 279: subview 'sv' + VIEW 1 rows = p2:I + 0: 779 + 280: 'id-780' + 280: subview 'sv' + VIEW 1 rows = p2:I + 0: 780 + 281: 'id-781' + 281: subview 'sv' + VIEW 1 rows = p2:I + 0: 781 + 282: 'id-782' + 282: subview 'sv' + VIEW 1 rows = p2:I + 0: 782 + 283: 'id-783' + 283: subview 'sv' + VIEW 1 rows = p2:I + 0: 783 + 284: 'id-784' + 284: subview 'sv' + VIEW 1 rows = p2:I + 0: 784 + 285: 'id-785' + 285: subview 'sv' + VIEW 1 rows = p2:I + 0: 785 + 286: 'id-786' + 286: subview 'sv' + VIEW 1 rows = p2:I + 0: 786 + 287: 'id-787' + 287: subview 'sv' + VIEW 1 rows = p2:I + 0: 787 + 288: 'id-788' + 288: subview 'sv' + VIEW 1 rows = p2:I + 0: 788 + 289: 'id-789' + 289: subview 'sv' + VIEW 1 rows = p2:I + 0: 789 + 290: 'id-790' + 290: subview 'sv' + VIEW 1 rows = p2:I + 0: 790 + 291: 'id-791' + 291: subview 'sv' + VIEW 1 rows = p2:I + 0: 791 + 292: 'id-792' + 292: subview 'sv' + VIEW 1 rows = p2:I + 0: 792 + 293: 'id-793' + 293: subview 'sv' + VIEW 1 rows = p2:I + 0: 793 + 294: 'id-794' + 294: subview 'sv' + VIEW 1 rows = p2:I + 0: 794 + 295: 'id-795' + 295: subview 'sv' + VIEW 1 rows = p2:I + 0: 795 + 296: 'id-796' + 296: subview 'sv' + VIEW 1 rows = p2:I + 0: 796 + 297: 'id-797' + 297: subview 'sv' + VIEW 1 rows = p2:I + 0: 797 + 298: 'id-798' + 298: subview 'sv' + VIEW 1 rows = p2:I + 0: 798 + 299: 'id-799' + 299: subview 'sv' + VIEW 1 rows = p2:I + 0: 799 + 300: 'id-800' + 300: subview 'sv' + VIEW 1 rows = p2:I + 0: 800 + 301: 'id-801' + 301: subview 'sv' + VIEW 1 rows = p2:I + 0: 801 + 302: 'id-802' + 302: subview 'sv' + VIEW 1 rows = p2:I + 0: 802 + 303: 'id-803' + 303: subview 'sv' + VIEW 1 rows = p2:I + 0: 803 + 304: 'id-804' + 304: subview 'sv' + VIEW 1 rows = p2:I + 0: 804 + 305: 'id-805' + 305: subview 'sv' + VIEW 1 rows = p2:I + 0: 805 + 306: 'id-806' + 306: subview 'sv' + VIEW 1 rows = p2:I + 0: 806 + 307: 'id-807' + 307: subview 'sv' + VIEW 1 rows = p2:I + 0: 807 + 308: 'id-808' + 308: subview 'sv' + VIEW 1 rows = p2:I + 0: 808 + 309: 'id-809' + 309: subview 'sv' + VIEW 1 rows = p2:I + 0: 809 + 310: 'id-810' + 310: subview 'sv' + VIEW 1 rows = p2:I + 0: 810 + 311: 'id-811' + 311: subview 'sv' + VIEW 1 rows = p2:I + 0: 811 + 312: 'id-812' + 312: subview 'sv' + VIEW 1 rows = p2:I + 0: 812 + 313: 'id-813' + 313: subview 'sv' + VIEW 1 rows = p2:I + 0: 813 + 314: 'id-814' + 314: subview 'sv' + VIEW 1 rows = p2:I + 0: 814 + 315: 'id-815' + 315: subview 'sv' + VIEW 1 rows = p2:I + 0: 815 + 316: 'id-816' + 316: subview 'sv' + VIEW 1 rows = p2:I + 0: 816 + 317: 'id-817' + 317: subview 'sv' + VIEW 1 rows = p2:I + 0: 817 + 318: 'id-818' + 318: subview 'sv' + VIEW 1 rows = p2:I + 0: 818 + 319: 'id-819' + 319: subview 'sv' + VIEW 1 rows = p2:I + 0: 819 + 320: 'id-820' + 320: subview 'sv' + VIEW 1 rows = p2:I + 0: 820 + 321: 'id-821' + 321: subview 'sv' + VIEW 1 rows = p2:I + 0: 821 + 322: 'id-822' + 322: subview 'sv' + VIEW 1 rows = p2:I + 0: 822 + 323: 'id-823' + 323: subview 'sv' + VIEW 1 rows = p2:I + 0: 823 + 324: 'id-824' + 324: subview 'sv' + VIEW 1 rows = p2:I + 0: 824 + 325: 'id-825' + 325: subview 'sv' + VIEW 1 rows = p2:I + 0: 825 + 326: 'id-826' + 326: subview 'sv' + VIEW 1 rows = p2:I + 0: 826 + 327: 'id-827' + 327: subview 'sv' + VIEW 1 rows = p2:I + 0: 827 + 328: 'id-828' + 328: subview 'sv' + VIEW 1 rows = p2:I + 0: 828 + 329: 'id-829' + 329: subview 'sv' + VIEW 1 rows = p2:I + 0: 829 + 330: 'id-830' + 330: subview 'sv' + VIEW 1 rows = p2:I + 0: 830 + 331: 'id-831' + 331: subview 'sv' + VIEW 1 rows = p2:I + 0: 831 + 332: 'id-832' + 332: subview 'sv' + VIEW 1 rows = p2:I + 0: 832 + 333: 'id-833' + 333: subview 'sv' + VIEW 1 rows = p2:I + 0: 833 + 334: 'id-834' + 334: subview 'sv' + VIEW 1 rows = p2:I + 0: 834 + 335: 'id-835' + 335: subview 'sv' + VIEW 1 rows = p2:I + 0: 835 + 336: 'id-836' + 336: subview 'sv' + VIEW 1 rows = p2:I + 0: 836 + 337: 'id-837' + 337: subview 'sv' + VIEW 1 rows = p2:I + 0: 837 + 338: 'id-838' + 338: subview 'sv' + VIEW 1 rows = p2:I + 0: 838 + 339: 'id-839' + 339: subview 'sv' + VIEW 1 rows = p2:I + 0: 839 + 340: 'id-840' + 340: subview 'sv' + VIEW 1 rows = p2:I + 0: 840 + 341: 'id-841' + 341: subview 'sv' + VIEW 1 rows = p2:I + 0: 841 + 342: 'id-842' + 342: subview 'sv' + VIEW 1 rows = p2:I + 0: 842 + 343: 'id-843' + 343: subview 'sv' + VIEW 1 rows = p2:I + 0: 843 + 344: 'id-844' + 344: subview 'sv' + VIEW 1 rows = p2:I + 0: 844 + 345: 'id-845' + 345: subview 'sv' + VIEW 1 rows = p2:I + 0: 845 + 346: 'id-846' + 346: subview 'sv' + VIEW 1 rows = p2:I + 0: 846 + 347: 'id-847' + 347: subview 'sv' + VIEW 1 rows = p2:I + 0: 847 + 348: 'id-848' + 348: subview 'sv' + VIEW 1 rows = p2:I + 0: 848 + 349: 'id-849' + 349: subview 'sv' + VIEW 1 rows = p2:I + 0: 849 + 350: 'id-850' + 350: subview 'sv' + VIEW 1 rows = p2:I + 0: 850 + 351: 'id-851' + 351: subview 'sv' + VIEW 1 rows = p2:I + 0: 851 + 352: 'id-852' + 352: subview 'sv' + VIEW 1 rows = p2:I + 0: 852 + 353: 'id-853' + 353: subview 'sv' + VIEW 1 rows = p2:I + 0: 853 + 354: 'id-854' + 354: subview 'sv' + VIEW 1 rows = p2:I + 0: 854 + 355: 'id-855' + 355: subview 'sv' + VIEW 1 rows = p2:I + 0: 855 + 356: 'id-856' + 356: subview 'sv' + VIEW 1 rows = p2:I + 0: 856 + 357: 'id-857' + 357: subview 'sv' + VIEW 1 rows = p2:I + 0: 857 + 358: 'id-858' + 358: subview 'sv' + VIEW 1 rows = p2:I + 0: 858 + 359: 'id-859' + 359: subview 'sv' + VIEW 1 rows = p2:I + 0: 859 + 360: 'id-860' + 360: subview 'sv' + VIEW 1 rows = p2:I + 0: 860 + 361: 'id-861' + 361: subview 'sv' + VIEW 1 rows = p2:I + 0: 861 + 362: 'id-862' + 362: subview 'sv' + VIEW 1 rows = p2:I + 0: 862 + 363: 'id-863' + 363: subview 'sv' + VIEW 1 rows = p2:I + 0: 863 + 364: 'id-864' + 364: subview 'sv' + VIEW 1 rows = p2:I + 0: 864 + 365: 'id-865' + 365: subview 'sv' + VIEW 1 rows = p2:I + 0: 865 + 366: 'id-866' + 366: subview 'sv' + VIEW 1 rows = p2:I + 0: 866 + 367: 'id-867' + 367: subview 'sv' + VIEW 1 rows = p2:I + 0: 867 + 368: 'id-868' + 368: subview 'sv' + VIEW 1 rows = p2:I + 0: 868 + 369: 'id-869' + 369: subview 'sv' + VIEW 1 rows = p2:I + 0: 869 + 370: 'id-870' + 370: subview 'sv' + VIEW 1 rows = p2:I + 0: 870 + 371: 'id-871' + 371: subview 'sv' + VIEW 1 rows = p2:I + 0: 871 + 372: 'id-872' + 372: subview 'sv' + VIEW 1 rows = p2:I + 0: 872 + 373: 'id-873' + 373: subview 'sv' + VIEW 1 rows = p2:I + 0: 873 + 374: 'id-874' + 374: subview 'sv' + VIEW 1 rows = p2:I + 0: 874 + 375: 'id-875' + 375: subview 'sv' + VIEW 1 rows = p2:I + 0: 875 + 376: 'id-876' + 376: subview 'sv' + VIEW 1 rows = p2:I + 0: 876 + 377: 'id-877' + 377: subview 'sv' + VIEW 1 rows = p2:I + 0: 877 + 378: 'id-878' + 378: subview 'sv' + VIEW 1 rows = p2:I + 0: 878 + 379: 'id-879' + 379: subview 'sv' + VIEW 1 rows = p2:I + 0: 879 + 380: 'id-880' + 380: subview 'sv' + VIEW 1 rows = p2:I + 0: 880 + 381: 'id-881' + 381: subview 'sv' + VIEW 1 rows = p2:I + 0: 881 + 382: 'id-882' + 382: subview 'sv' + VIEW 1 rows = p2:I + 0: 882 + 383: 'id-883' + 383: subview 'sv' + VIEW 1 rows = p2:I + 0: 883 + 384: 'id-884' + 384: subview 'sv' + VIEW 1 rows = p2:I + 0: 884 + 385: 'id-885' + 385: subview 'sv' + VIEW 1 rows = p2:I + 0: 885 + 386: 'id-886' + 386: subview 'sv' + VIEW 1 rows = p2:I + 0: 886 + 387: 'id-887' + 387: subview 'sv' + VIEW 1 rows = p2:I + 0: 887 + 388: 'id-888' + 388: subview 'sv' + VIEW 1 rows = p2:I + 0: 888 + 389: 'id-889' + 389: subview 'sv' + VIEW 1 rows = p2:I + 0: 889 + 390: 'id-890' + 390: subview 'sv' + VIEW 1 rows = p2:I + 0: 890 + 391: 'id-891' + 391: subview 'sv' + VIEW 1 rows = p2:I + 0: 891 + 392: 'id-892' + 392: subview 'sv' + VIEW 1 rows = p2:I + 0: 892 + 393: 'id-893' + 393: subview 'sv' + VIEW 1 rows = p2:I + 0: 893 + 394: 'id-894' + 394: subview 'sv' + VIEW 1 rows = p2:I + 0: 894 + 395: 'id-895' + 395: subview 'sv' + VIEW 1 rows = p2:I + 0: 895 + 396: 'id-896' + 396: subview 'sv' + VIEW 1 rows = p2:I + 0: 896 + 397: 'id-897' + 397: subview 'sv' + VIEW 1 rows = p2:I + 0: 897 + 398: 'id-898' + 398: subview 'sv' + VIEW 1 rows = p2:I + 0: 898 + 399: 'id-899' + 399: subview 'sv' + VIEW 1 rows = p2:I + 0: 899 + 400: 'id-900' + 400: subview 'sv' + VIEW 1 rows = p2:I + 0: 900 + 401: 'id-901' + 401: subview 'sv' + VIEW 1 rows = p2:I + 0: 901 + 402: 'id-902' + 402: subview 'sv' + VIEW 1 rows = p2:I + 0: 902 + 403: 'id-903' + 403: subview 'sv' + VIEW 1 rows = p2:I + 0: 903 + 404: 'id-904' + 404: subview 'sv' + VIEW 1 rows = p2:I + 0: 904 + 405: 'id-905' + 405: subview 'sv' + VIEW 1 rows = p2:I + 0: 905 + 406: 'id-906' + 406: subview 'sv' + VIEW 1 rows = p2:I + 0: 906 + 407: 'id-907' + 407: subview 'sv' + VIEW 1 rows = p2:I + 0: 907 + 408: 'id-908' + 408: subview 'sv' + VIEW 1 rows = p2:I + 0: 908 + 409: 'id-909' + 409: subview 'sv' + VIEW 1 rows = p2:I + 0: 909 + 410: 'id-910' + 410: subview 'sv' + VIEW 1 rows = p2:I + 0: 910 + 411: 'id-911' + 411: subview 'sv' + VIEW 1 rows = p2:I + 0: 911 + 412: 'id-912' + 412: subview 'sv' + VIEW 1 rows = p2:I + 0: 912 + 413: 'id-913' + 413: subview 'sv' + VIEW 1 rows = p2:I + 0: 913 + 414: 'id-914' + 414: subview 'sv' + VIEW 1 rows = p2:I + 0: 914 + 415: 'id-915' + 415: subview 'sv' + VIEW 1 rows = p2:I + 0: 915 + 416: 'id-916' + 416: subview 'sv' + VIEW 1 rows = p2:I + 0: 916 + 417: 'id-917' + 417: subview 'sv' + VIEW 1 rows = p2:I + 0: 917 + 418: 'id-918' + 418: subview 'sv' + VIEW 1 rows = p2:I + 0: 918 + 419: 'id-919' + 419: subview 'sv' + VIEW 1 rows = p2:I + 0: 919 + 420: 'id-920' + 420: subview 'sv' + VIEW 1 rows = p2:I + 0: 920 + 421: 'id-921' + 421: subview 'sv' + VIEW 1 rows = p2:I + 0: 921 + 422: 'id-922' + 422: subview 'sv' + VIEW 1 rows = p2:I + 0: 922 + 423: 'id-923' + 423: subview 'sv' + VIEW 1 rows = p2:I + 0: 923 + 424: 'id-924' + 424: subview 'sv' + VIEW 1 rows = p2:I + 0: 924 + 425: 'id-925' + 425: subview 'sv' + VIEW 1 rows = p2:I + 0: 925 + 426: 'id-926' + 426: subview 'sv' + VIEW 1 rows = p2:I + 0: 926 + 427: 'id-927' + 427: subview 'sv' + VIEW 1 rows = p2:I + 0: 927 + 428: 'id-928' + 428: subview 'sv' + VIEW 1 rows = p2:I + 0: 928 + 429: 'id-929' + 429: subview 'sv' + VIEW 1 rows = p2:I + 0: 929 + 430: 'id-930' + 430: subview 'sv' + VIEW 1 rows = p2:I + 0: 930 + 431: 'id-931' + 431: subview 'sv' + VIEW 1 rows = p2:I + 0: 931 + 432: 'id-932' + 432: subview 'sv' + VIEW 1 rows = p2:I + 0: 932 + 433: 'id-933' + 433: subview 'sv' + VIEW 1 rows = p2:I + 0: 933 + 434: 'id-934' + 434: subview 'sv' + VIEW 1 rows = p2:I + 0: 934 + 435: 'id-935' + 435: subview 'sv' + VIEW 1 rows = p2:I + 0: 935 + 436: 'id-936' + 436: subview 'sv' + VIEW 1 rows = p2:I + 0: 936 + 437: 'id-937' + 437: subview 'sv' + VIEW 1 rows = p2:I + 0: 937 + 438: 'id-938' + 438: subview 'sv' + VIEW 1 rows = p2:I + 0: 938 + 439: 'id-939' + 439: subview 'sv' + VIEW 1 rows = p2:I + 0: 939 + 440: 'id-940' + 440: subview 'sv' + VIEW 1 rows = p2:I + 0: 940 + 441: 'id-941' + 441: subview 'sv' + VIEW 1 rows = p2:I + 0: 941 + 442: 'id-942' + 442: subview 'sv' + VIEW 1 rows = p2:I + 0: 942 + 443: 'id-943' + 443: subview 'sv' + VIEW 1 rows = p2:I + 0: 943 + 444: 'id-944' + 444: subview 'sv' + VIEW 1 rows = p2:I + 0: 944 + 445: 'id-945' + 445: subview 'sv' + VIEW 1 rows = p2:I + 0: 945 + 446: 'id-946' + 446: subview 'sv' + VIEW 1 rows = p2:I + 0: 946 + 447: 'id-947' + 447: subview 'sv' + VIEW 1 rows = p2:I + 0: 947 + 448: 'id-948' + 448: subview 'sv' + VIEW 1 rows = p2:I + 0: 948 + 449: 'id-949' + 449: subview 'sv' + VIEW 1 rows = p2:I + 0: 949 + 450: 'id-950' + 450: subview 'sv' + VIEW 1 rows = p2:I + 0: 950 + 451: 'id-951' + 451: subview 'sv' + VIEW 1 rows = p2:I + 0: 951 + 452: 'id-952' + 452: subview 'sv' + VIEW 1 rows = p2:I + 0: 952 + 453: 'id-953' + 453: subview 'sv' + VIEW 1 rows = p2:I + 0: 953 + 454: 'id-954' + 454: subview 'sv' + VIEW 1 rows = p2:I + 0: 954 + 455: 'id-955' + 455: subview 'sv' + VIEW 1 rows = p2:I + 0: 955 + 456: 'id-956' + 456: subview 'sv' + VIEW 1 rows = p2:I + 0: 956 + 457: 'id-957' + 457: subview 'sv' + VIEW 1 rows = p2:I + 0: 957 + 458: 'id-958' + 458: subview 'sv' + VIEW 1 rows = p2:I + 0: 958 + 459: 'id-959' + 459: subview 'sv' + VIEW 1 rows = p2:I + 0: 959 + 460: 'id-960' + 460: subview 'sv' + VIEW 1 rows = p2:I + 0: 960 + 461: 'id-961' + 461: subview 'sv' + VIEW 1 rows = p2:I + 0: 961 + 462: 'id-962' + 462: subview 'sv' + VIEW 1 rows = p2:I + 0: 962 + 463: 'id-963' + 463: subview 'sv' + VIEW 1 rows = p2:I + 0: 963 + 464: 'id-964' + 464: subview 'sv' + VIEW 1 rows = p2:I + 0: 964 + 465: 'id-965' + 465: subview 'sv' + VIEW 1 rows = p2:I + 0: 965 + 466: 'id-966' + 466: subview 'sv' + VIEW 1 rows = p2:I + 0: 966 + 467: 'id-967' + 467: subview 'sv' + VIEW 1 rows = p2:I + 0: 967 + 468: 'id-968' + 468: subview 'sv' + VIEW 1 rows = p2:I + 0: 968 + 469: 'id-969' + 469: subview 'sv' + VIEW 1 rows = p2:I + 0: 969 + 470: 'id-970' + 470: subview 'sv' + VIEW 1 rows = p2:I + 0: 970 + 471: 'id-971' + 471: subview 'sv' + VIEW 1 rows = p2:I + 0: 971 + 472: 'id-972' + 472: subview 'sv' + VIEW 1 rows = p2:I + 0: 972 + 473: 'id-973' + 473: subview 'sv' + VIEW 1 rows = p2:I + 0: 973 + 474: 'id-974' + 474: subview 'sv' + VIEW 1 rows = p2:I + 0: 974 + 475: 'id-975' + 475: subview 'sv' + VIEW 1 rows = p2:I + 0: 975 + 476: 'id-976' + 476: subview 'sv' + VIEW 1 rows = p2:I + 0: 976 + 477: 'id-977' + 477: subview 'sv' + VIEW 1 rows = p2:I + 0: 977 + 478: 'id-978' + 478: subview 'sv' + VIEW 1 rows = p2:I + 0: 978 + 479: 'id-979' + 479: subview 'sv' + VIEW 1 rows = p2:I + 0: 979 + 480: 'id-980' + 480: subview 'sv' + VIEW 1 rows = p2:I + 0: 980 + 481: 'id-981' + 481: subview 'sv' + VIEW 1 rows = p2:I + 0: 981 + 482: 'id-982' + 482: subview 'sv' + VIEW 1 rows = p2:I + 0: 982 + 483: 'id-983' + 483: subview 'sv' + VIEW 1 rows = p2:I + 0: 983 + 484: 'id-984' + 484: subview 'sv' + VIEW 1 rows = p2:I + 0: 984 + 485: 'id-985' + 485: subview 'sv' + VIEW 1 rows = p2:I + 0: 985 + 486: 'id-986' + 486: subview 'sv' + VIEW 1 rows = p2:I + 0: 986 + 487: 'id-987' + 487: subview 'sv' + VIEW 1 rows = p2:I + 0: 987 + 488: 'id-988' + 488: subview 'sv' + VIEW 1 rows = p2:I + 0: 988 + 489: 'id-989' + 489: subview 'sv' + VIEW 1 rows = p2:I + 0: 989 + 490: 'id-990' + 490: subview 'sv' + VIEW 1 rows = p2:I + 0: 990 + 491: 'id-991' + 491: subview 'sv' + VIEW 1 rows = p2:I + 0: 991 + 492: 'id-992' + 492: subview 'sv' + VIEW 1 rows = p2:I + 0: 992 + 493: 'id-993' + 493: subview 'sv' + VIEW 1 rows = p2:I + 0: 993 + 494: 'id-994' + 494: subview 'sv' + VIEW 1 rows = p2:I + 0: 994 + 495: 'id-995' + 495: subview 'sv' + VIEW 1 rows = p2:I + 0: 995 + 496: 'id-996' + 496: subview 'sv' + VIEW 1 rows = p2:I + 0: 996 + 497: 'id-997' + 497: subview 'sv' + VIEW 1 rows = p2:I + 0: 997 + 498: 'id-998' + 498: subview 'sv' + VIEW 1 rows = p2:I + 0: 998 + 499: 'id-999' + 499: subview 'sv' + VIEW 1 rows = p2:I + 0: 999 + 2: subview '_B' + VIEW 1 rows = p1:S sv:V + 0: 'insert-0' + 0: subview 'sv' + VIEW 0 rows = p2:I diff --git a/akregator/src/mk4storage/metakit/tests/ok/m06.txt b/akregator/src/mk4storage/metakit/tests/ok/m06.txt new file mode 100644 index 000000000..ef0cb4640 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m06.txt @@ -0,0 +1,2 @@ +>>> Blocked view multi-row deletion +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/m06a.txt b/akregator/src/mk4storage/metakit/tests/ok/m06a.txt new file mode 100644 index 000000000..d72b2e671 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m06a.txt @@ -0,0 +1,2963 @@ + VIEW 1 rows = v1:V v2:V + 0: subview 'v1' + VIEW 901 rows = p1:I + 0: 1 + 1: 100 + 2: 101 + 3: 102 + 4: 103 + 5: 104 + 6: 105 + 7: 106 + 8: 107 + 9: 108 + 10: 109 + 11: 110 + 12: 111 + 13: 112 + 14: 113 + 15: 114 + 16: 115 + 17: 116 + 18: 117 + 19: 118 + 20: 119 + 21: 120 + 22: 121 + 23: 122 + 24: 123 + 25: 124 + 26: 125 + 27: 126 + 28: 127 + 29: 128 + 30: 129 + 31: 130 + 32: 131 + 33: 132 + 34: 133 + 35: 134 + 36: 135 + 37: 136 + 38: 137 + 39: 138 + 40: 139 + 41: 140 + 42: 141 + 43: 142 + 44: 143 + 45: 144 + 46: 145 + 47: 146 + 48: 147 + 49: 148 + 50: 149 + 51: 150 + 52: 151 + 53: 152 + 54: 153 + 55: 154 + 56: 155 + 57: 156 + 58: 157 + 59: 158 + 60: 159 + 61: 160 + 62: 161 + 63: 162 + 64: 163 + 65: 164 + 66: 165 + 67: 166 + 68: 167 + 69: 168 + 70: 169 + 71: 170 + 72: 171 + 73: 172 + 74: 173 + 75: 174 + 76: 175 + 77: 176 + 78: 177 + 79: 178 + 80: 179 + 81: 180 + 82: 181 + 83: 182 + 84: 183 + 85: 184 + 86: 185 + 87: 186 + 88: 187 + 89: 188 + 90: 189 + 91: 190 + 92: 191 + 93: 192 + 94: 193 + 95: 194 + 96: 195 + 97: 196 + 98: 197 + 99: 198 + 100: 199 + 101: 200 + 102: 201 + 103: 202 + 104: 203 + 105: 204 + 106: 205 + 107: 206 + 108: 207 + 109: 208 + 110: 209 + 111: 210 + 112: 211 + 113: 212 + 114: 213 + 115: 214 + 116: 215 + 117: 216 + 118: 217 + 119: 218 + 120: 219 + 121: 220 + 122: 221 + 123: 222 + 124: 223 + 125: 224 + 126: 225 + 127: 226 + 128: 227 + 129: 228 + 130: 229 + 131: 230 + 132: 231 + 133: 232 + 134: 233 + 135: 234 + 136: 235 + 137: 236 + 138: 237 + 139: 238 + 140: 239 + 141: 240 + 142: 241 + 143: 242 + 144: 243 + 145: 244 + 146: 245 + 147: 246 + 148: 247 + 149: 248 + 150: 249 + 151: 250 + 152: 251 + 153: 252 + 154: 253 + 155: 254 + 156: 255 + 157: 256 + 158: 257 + 159: 258 + 160: 259 + 161: 260 + 162: 261 + 163: 262 + 164: 263 + 165: 264 + 166: 265 + 167: 266 + 168: 267 + 169: 268 + 170: 269 + 171: 270 + 172: 271 + 173: 272 + 174: 273 + 175: 274 + 176: 275 + 177: 276 + 178: 277 + 179: 278 + 180: 279 + 181: 280 + 182: 281 + 183: 282 + 184: 283 + 185: 284 + 186: 285 + 187: 286 + 188: 287 + 189: 288 + 190: 289 + 191: 290 + 192: 291 + 193: 292 + 194: 293 + 195: 294 + 196: 295 + 197: 296 + 198: 297 + 199: 298 + 200: 299 + 201: 300 + 202: 301 + 203: 302 + 204: 303 + 205: 304 + 206: 305 + 207: 306 + 208: 307 + 209: 308 + 210: 309 + 211: 310 + 212: 311 + 213: 312 + 214: 313 + 215: 314 + 216: 315 + 217: 316 + 218: 317 + 219: 318 + 220: 319 + 221: 320 + 222: 321 + 223: 322 + 224: 323 + 225: 324 + 226: 325 + 227: 326 + 228: 327 + 229: 328 + 230: 329 + 231: 330 + 232: 331 + 233: 332 + 234: 333 + 235: 334 + 236: 335 + 237: 336 + 238: 337 + 239: 338 + 240: 339 + 241: 340 + 242: 341 + 243: 342 + 244: 343 + 245: 344 + 246: 345 + 247: 346 + 248: 347 + 249: 348 + 250: 349 + 251: 350 + 252: 351 + 253: 352 + 254: 353 + 255: 354 + 256: 355 + 257: 356 + 258: 357 + 259: 358 + 260: 359 + 261: 360 + 262: 361 + 263: 362 + 264: 363 + 265: 364 + 266: 365 + 267: 366 + 268: 367 + 269: 368 + 270: 369 + 271: 370 + 272: 371 + 273: 372 + 274: 373 + 275: 374 + 276: 375 + 277: 376 + 278: 377 + 279: 378 + 280: 379 + 281: 380 + 282: 381 + 283: 382 + 284: 383 + 285: 384 + 286: 385 + 287: 386 + 288: 387 + 289: 388 + 290: 389 + 291: 390 + 292: 391 + 293: 392 + 294: 393 + 295: 394 + 296: 395 + 297: 396 + 298: 397 + 299: 398 + 300: 399 + 301: 400 + 302: 401 + 303: 402 + 304: 403 + 305: 404 + 306: 405 + 307: 406 + 308: 407 + 309: 408 + 310: 409 + 311: 410 + 312: 411 + 313: 412 + 314: 413 + 315: 414 + 316: 415 + 317: 416 + 318: 417 + 319: 418 + 320: 419 + 321: 420 + 322: 421 + 323: 422 + 324: 423 + 325: 424 + 326: 425 + 327: 426 + 328: 427 + 329: 428 + 330: 429 + 331: 430 + 332: 431 + 333: 432 + 334: 433 + 335: 434 + 336: 435 + 337: 436 + 338: 437 + 339: 438 + 340: 439 + 341: 440 + 342: 441 + 343: 442 + 344: 443 + 345: 444 + 346: 445 + 347: 446 + 348: 447 + 349: 448 + 350: 449 + 351: 450 + 352: 451 + 353: 452 + 354: 453 + 355: 454 + 356: 455 + 357: 456 + 358: 457 + 359: 458 + 360: 459 + 361: 460 + 362: 461 + 363: 462 + 364: 463 + 365: 464 + 366: 465 + 367: 466 + 368: 467 + 369: 468 + 370: 469 + 371: 470 + 372: 471 + 373: 472 + 374: 473 + 375: 474 + 376: 475 + 377: 476 + 378: 477 + 379: 478 + 380: 479 + 381: 480 + 382: 481 + 383: 482 + 384: 483 + 385: 484 + 386: 485 + 387: 486 + 388: 487 + 389: 488 + 390: 489 + 391: 490 + 392: 491 + 393: 492 + 394: 493 + 395: 494 + 396: 495 + 397: 496 + 398: 497 + 399: 498 + 400: 499 + 401: 500 + 402: 501 + 403: 502 + 404: 503 + 405: 504 + 406: 505 + 407: 506 + 408: 507 + 409: 508 + 410: 509 + 411: 510 + 412: 511 + 413: 512 + 414: 513 + 415: 514 + 416: 515 + 417: 516 + 418: 517 + 419: 518 + 420: 519 + 421: 520 + 422: 521 + 423: 522 + 424: 523 + 425: 524 + 426: 525 + 427: 526 + 428: 527 + 429: 528 + 430: 529 + 431: 530 + 432: 531 + 433: 532 + 434: 533 + 435: 534 + 436: 535 + 437: 536 + 438: 537 + 439: 538 + 440: 539 + 441: 540 + 442: 541 + 443: 542 + 444: 543 + 445: 544 + 446: 545 + 447: 546 + 448: 547 + 449: 548 + 450: 549 + 451: 550 + 452: 551 + 453: 552 + 454: 553 + 455: 554 + 456: 555 + 457: 556 + 458: 557 + 459: 558 + 460: 559 + 461: 560 + 462: 561 + 463: 562 + 464: 563 + 465: 564 + 466: 565 + 467: 566 + 468: 567 + 469: 568 + 470: 569 + 471: 570 + 472: 571 + 473: 572 + 474: 573 + 475: 574 + 476: 575 + 477: 576 + 478: 577 + 479: 578 + 480: 579 + 481: 580 + 482: 581 + 483: 582 + 484: 583 + 485: 584 + 486: 585 + 487: 586 + 488: 587 + 489: 588 + 490: 589 + 491: 590 + 492: 591 + 493: 592 + 494: 593 + 495: 594 + 496: 595 + 497: 596 + 498: 597 + 499: 598 + 500: 599 + 501: 600 + 502: 601 + 503: 602 + 504: 603 + 505: 604 + 506: 605 + 507: 606 + 508: 607 + 509: 608 + 510: 609 + 511: 610 + 512: 611 + 513: 612 + 514: 613 + 515: 614 + 516: 615 + 517: 616 + 518: 617 + 519: 618 + 520: 619 + 521: 620 + 522: 621 + 523: 622 + 524: 623 + 525: 624 + 526: 625 + 527: 626 + 528: 627 + 529: 628 + 530: 629 + 531: 630 + 532: 631 + 533: 632 + 534: 633 + 535: 634 + 536: 635 + 537: 636 + 538: 637 + 539: 638 + 540: 639 + 541: 640 + 542: 641 + 543: 642 + 544: 643 + 545: 644 + 546: 645 + 547: 646 + 548: 647 + 549: 648 + 550: 649 + 551: 650 + 552: 651 + 553: 652 + 554: 653 + 555: 654 + 556: 655 + 557: 656 + 558: 657 + 559: 658 + 560: 659 + 561: 660 + 562: 661 + 563: 662 + 564: 663 + 565: 664 + 566: 665 + 567: 666 + 568: 667 + 569: 668 + 570: 669 + 571: 670 + 572: 671 + 573: 672 + 574: 673 + 575: 674 + 576: 675 + 577: 676 + 578: 677 + 579: 678 + 580: 679 + 581: 680 + 582: 681 + 583: 682 + 584: 683 + 585: 684 + 586: 685 + 587: 686 + 588: 687 + 589: 688 + 590: 689 + 591: 690 + 592: 691 + 593: 692 + 594: 693 + 595: 694 + 596: 695 + 597: 696 + 598: 697 + 599: 698 + 600: 699 + 601: 700 + 602: 701 + 603: 702 + 604: 703 + 605: 704 + 606: 705 + 607: 706 + 608: 707 + 609: 708 + 610: 709 + 611: 710 + 612: 711 + 613: 712 + 614: 713 + 615: 714 + 616: 715 + 617: 716 + 618: 717 + 619: 718 + 620: 719 + 621: 720 + 622: 721 + 623: 722 + 624: 723 + 625: 724 + 626: 725 + 627: 726 + 628: 727 + 629: 728 + 630: 729 + 631: 730 + 632: 731 + 633: 732 + 634: 733 + 635: 734 + 636: 735 + 637: 736 + 638: 737 + 639: 738 + 640: 739 + 641: 740 + 642: 741 + 643: 742 + 644: 743 + 645: 744 + 646: 745 + 647: 746 + 648: 747 + 649: 748 + 650: 749 + 651: 750 + 652: 751 + 653: 752 + 654: 753 + 655: 754 + 656: 755 + 657: 756 + 658: 757 + 659: 758 + 660: 759 + 661: 760 + 662: 761 + 663: 762 + 664: 763 + 665: 764 + 666: 765 + 667: 766 + 668: 767 + 669: 768 + 670: 769 + 671: 770 + 672: 771 + 673: 772 + 674: 773 + 675: 774 + 676: 775 + 677: 776 + 678: 777 + 679: 778 + 680: 779 + 681: 780 + 682: 781 + 683: 782 + 684: 783 + 685: 784 + 686: 785 + 687: 786 + 688: 787 + 689: 788 + 690: 789 + 691: 790 + 692: 791 + 693: 792 + 694: 793 + 695: 794 + 696: 795 + 697: 796 + 698: 797 + 699: 798 + 700: 799 + 701: 800 + 702: 801 + 703: 802 + 704: 803 + 705: 804 + 706: 805 + 707: 806 + 708: 807 + 709: 808 + 710: 809 + 711: 810 + 712: 811 + 713: 812 + 714: 813 + 715: 814 + 716: 815 + 717: 816 + 718: 817 + 719: 818 + 720: 819 + 721: 820 + 722: 821 + 723: 822 + 724: 823 + 725: 824 + 726: 825 + 727: 826 + 728: 827 + 729: 828 + 730: 829 + 731: 830 + 732: 831 + 733: 832 + 734: 833 + 735: 834 + 736: 835 + 737: 836 + 738: 837 + 739: 838 + 740: 839 + 741: 840 + 742: 841 + 743: 842 + 744: 843 + 745: 844 + 746: 845 + 747: 846 + 748: 847 + 749: 848 + 750: 849 + 751: 850 + 752: 851 + 753: 852 + 754: 853 + 755: 854 + 756: 855 + 757: 856 + 758: 857 + 759: 858 + 760: 859 + 761: 860 + 762: 861 + 763: 862 + 764: 863 + 765: 864 + 766: 865 + 767: 866 + 768: 867 + 769: 868 + 770: 869 + 771: 870 + 772: 871 + 773: 872 + 774: 873 + 775: 874 + 776: 875 + 777: 876 + 778: 877 + 779: 878 + 780: 879 + 781: 880 + 782: 881 + 783: 882 + 784: 883 + 785: 884 + 786: 885 + 787: 886 + 788: 887 + 789: 888 + 790: 889 + 791: 890 + 792: 891 + 793: 892 + 794: 893 + 795: 894 + 796: 895 + 797: 896 + 798: 897 + 799: 898 + 800: 899 + 801: 900 + 802: 901 + 803: 902 + 804: 903 + 805: 904 + 806: 905 + 807: 906 + 808: 907 + 809: 908 + 810: 909 + 811: 910 + 812: 911 + 813: 912 + 814: 913 + 815: 914 + 816: 915 + 817: 916 + 818: 917 + 819: 918 + 820: 919 + 821: 920 + 822: 921 + 823: 922 + 824: 923 + 825: 924 + 826: 925 + 827: 926 + 828: 927 + 829: 928 + 830: 929 + 831: 930 + 832: 931 + 833: 932 + 834: 933 + 835: 934 + 836: 935 + 837: 936 + 838: 937 + 839: 938 + 840: 939 + 841: 940 + 842: 941 + 843: 942 + 844: 943 + 845: 944 + 846: 945 + 847: 946 + 848: 947 + 849: 948 + 850: 949 + 851: 950 + 852: 951 + 853: 952 + 854: 953 + 855: 954 + 856: 955 + 857: 956 + 858: 957 + 859: 958 + 860: 959 + 861: 960 + 862: 961 + 863: 962 + 864: 963 + 865: 964 + 866: 965 + 867: 966 + 868: 967 + 869: 968 + 870: 969 + 871: 970 + 872: 971 + 873: 972 + 874: 973 + 875: 974 + 876: 975 + 877: 976 + 878: 977 + 879: 978 + 880: 979 + 881: 980 + 882: 981 + 883: 982 + 884: 983 + 885: 984 + 886: 985 + 887: 986 + 888: 987 + 889: 988 + 890: 989 + 891: 990 + 892: 991 + 893: 992 + 894: 993 + 895: 994 + 896: 995 + 897: 996 + 898: 997 + 899: 998 + 900: 999 + 0: subview 'v2' + VIEW 4 rows = _B:V + 0: subview '_B' + VIEW 999 rows = _H:I _R:I + 0: 0 -1 + 1: 0 -1 + 2: -1461104643 430 + 3: 0 -1 + 4: 0 -1 + 5: 1034993658 780 + 6: 777013241 36 + 7: 608274424 551 + 8: 0 -1 + 9: -1460496394 19 + 10: 0 -1 + 11: 0 -1 + 12: 1035601907 881 + 13: 0 -1 + 14: 0 -1 + 15: 1799477232 164 + 16: 0 -1 + 17: 0 -1 + 18: 0 -1 + 19: -696012820 427 + 20: -683483157 154 + 21: 0 -1 + 22: 1800085481 265 + 23: 0 -1 + 24: -268685337 757 + 25: 0 -1 + 26: -695404571 16 + 27: -953384988 296 + 28: 0 -1 + 29: 338980834 282 + 30: 81000417 562 + 31: 1373974496 137 + 32: -1987770401 30 + 33: -694796322 629 + 34: 0 -1 + 35: 0 -1 + 36: 339589083 383 + 37: 0 -1 + 38: 0 -1 + 39: 1103464408 690 + 40: 0 -1 + 41: -965306410 158 + 42: 0 -1 + 43: 69687252 13 + 44: 1530791891 508 + 45: 0 -1 + 46: 1104072657 791 + 47: 0 -1 + 48: -964698161 259 + 49: 0 -1 + 50: 0 -1 + 51: -1649397812 822 + 52: 0 -1 + 53: 0 -1 + 54: 846700489 148 + 55: 677961672 663 + 56: -1222070329 640 + 57: -1390809146 131 + 58: 0 -1 + 59: 0 -1 + 60: 0 -1 + 61: -1999083582 505 + 62: 0 -1 + 63: 1869164480 276 + 64: 0 -1 + 65: -199606338 768 + 66: 0 -1 + 67: -626325572 539 + 68: 834779067 10 + 69: 576798650 290 + 70: 1869772729 377 + 71: 0 -1 + 72: -198998089 869 + 73: 0 -1 + 74: 0 -1 + 75: -883697740 408 + 76: 0 -1 + 77: 0 -1 + 78: 1599262641 418 + 79: 0 -1 + 80: -1918083153 142 + 81: 0 -1 + 82: 565485485 253 + 83: 0 -1 + 84: 0 -1 + 85: 1599870890 7 + 86: 0 -1 + 87: 0 -1 + 88: 0 -1 + 89: -895619162 270 + 90: -1153599579 550 + 91: 139374500 125 + 92: 0 -1 + 93: 1342498722 900 + 94: 0 -1 + 95: -1930612832 415 + 96: -895010913 371 + 97: 0 -1 + 98: 0 -1 + 99: -131135588 678 + 100: -1503285349 745 + 101: 0 -1 + 102: -1930004583 4 + 103: 0 -1 + 104: 296191895 496 + 105: 0 -1 + 106: -130527339 779 + 107: 0 -1 + 108: 0 -1 + 109: -1929396334 617 + 110: 0 -1 + 111: 0 -1 + 112: 0 -1 + 113: 0 -1 + 114: -387899507 136 + 115: -556638324 651 + 116: 0 -1 + 117: 646485898 402 + 118: 0 -1 + 119: -1164912760 1 + 120: 0 -1 + 121: 1061283718 493 + 122: 0 -1 + 123: 634564484 264 + 124: 2095669123 247 + 125: 0 -1 + 126: 1668949889 530 + 127: 1410969472 810 + 128: 0 -1 + 129: 0 -1 + 130: 635172733 365 + 131: 0 -1 + 132: 1838296955 628 + 133: 1669558138 119 + 134: 0 -1 + 135: 0 -1 + 136: 0 -1 + 137: 0 -1 + 138: -1083912331 662 + 139: 0 -1 + 140: 0 -1 + 141: -1434206350 756 + 142: 0 -1 + 143: -1860925584 527 + 144: 0 -1 + 145: 0 -1 + 146: 0 -1 + 147: -61448340 790 + 148: -1433598101 857 + 149: 0 -1 + 150: 0 -1 + 151: -2118297752 396 + 152: 0 -1 + 153: 107898726 888 + 154: -60840091 891 + 155: 0 -1 + 156: 1142284131 130 + 157: 0 -1 + 158: -669114527 241 + 159: 0 -1 + 160: 1557081951 733 + 161: 0 -1 + 162: 0 -1 + 163: 0 -1 + 164: 0 -1 + 165: -2130219174 258 + 166: 0 -1 + 167: -1095225512 113 + 168: 0 -1 + 169: 1130970966 605 + 170: 0 -1 + 171: 0 -1 + 172: -2129610925 359 + 173: 0 -1 + 174: 0 -1 + 175: 0 -1 + 176: 0 -1 + 177: -588114098 390 + 178: 0 -1 + 179: 0 -1 + 180: -938408117 484 + 181: 0 -1 + 182: -1365127351 767 + 183: 0 -1 + 184: 861069127 235 + 185: 0 -1 + 186: 434349893 518 + 187: 176369476 798 + 188: 0 -1 + 189: 0 -1 + 190: -1622499519 124 + 191: -1791238336 639 + 192: 603696959 616 + 193: 434958142 107 + 194: 0 -1 + 195: 0 -1 + 196: 0 -1 + 197: -173316294 481 + 198: 0 -1 + 199: -600035528 252 + 200: 0 -1 + 201: 1626160950 744 + 202: 0 -1 + 203: 1199441716 515 + 204: 0 -1 + 205: 0 -1 + 206: -599427279 353 + 207: 0 -1 + 208: 1626769199 845 + 209: 0 -1 + 210: 0 -1 + 211: 942069548 384 + 212: 0 -1 + 213: 0 -1 + 214: 1976454953 650 + 215: 0 -1 + 216: -92315865 118 + 217: 0 -1 + 218: -1903714523 229 + 219: 0 -1 + 220: 0 -1 + 221: 0 -1 + 222: 0 -1 + 223: -1296048352 778 + 224: 0 -1 + 225: 930148126 246 + 226: 0 -1 + 227: 1965141788 101 + 228: 0 -1 + 229: -1126701286 876 + 230: -1295440103 879 + 231: 0 -1 + 232: 930756375 347 + 233: 0 -1 + 234: 0 -1 + 235: 0 -1 + 236: 322481939 721 + 237: 0 -1 + 238: 0 -1 + 239: 0 -1 + 240: 2121959183 472 + 241: 0 -1 + 242: 1695239949 755 + 243: 0 -1 + 244: 0 -1 + 245: -103629046 593 + 246: 0 -1 + 247: 0 -1 + 248: 0 -1 + 249: 0 -1 + 250: 1437867781 112 + 251: 1269128964 627 + 252: 0 -1 + 253: -1822714110 378 + 254: 0 -1 + 255: 0 -1 + 256: 0 -1 + 257: -1407916290 469 + 258: 0 -1 + 259: -1834635524 240 + 260: -373530885 223 + 261: 0 -1 + 262: -800250119 506 + 263: 0 -1 + 264: 0 -1 + 265: 0 -1 + 266: -1834027275 341 + 267: 0 -1 + 268: -630903053 604 + 269: -799641870 95 + 270: 0 -1 + 271: 0 -1 + 272: 0 -1 + 273: 0 -1 + 274: 741854957 638 + 275: 0 -1 + 276: 0 -1 + 277: 391560938 732 + 278: 0 -1 + 279: -35158296 503 + 280: 0 -1 + 281: 0 -1 + 282: 0 -1 + 283: 1764318948 766 + 284: 392169187 833 + 285: 0 -1 + 286: 0 -1 + 287: -292530464 372 + 288: 0 -1 + 289: 1933666014 864 + 290: 1764927197 867 + 291: 0 -1 + 292: -1326915877 106 + 293: 0 -1 + 294: 1156652761 217 + 295: 0 -1 + 296: -912118057 709 + 297: 0 -1 + 298: 0 -1 + 299: 0 -1 + 300: 0 -1 + 301: -304451886 234 + 302: 0 -1 + 303: 730541776 89 + 304: 0 -1 + 305: -1338229042 581 + 306: 0 -1 + 307: 0 -1 + 308: -303843637 335 + 309: 0 -1 + 310: 0 -1 + 311: -988543288 898 + 312: 0 -1 + 313: 1237653190 366 + 314: 0 -1 + 315: 0 -1 + 316: 887359171 460 + 317: 0 -1 + 318: 460639937 743 + 319: 0 -1 + 320: -1608130881 211 + 321: 0 -1 + 322: -2034850115 494 + 323: 0 -1 + 324: 0 -1 + 325: 0 -1 + 326: 203267769 100 + 327: 34528952 615 + 328: -1865503049 592 + 329: -2034241866 83 + 330: 0 -1 + 331: 0 -1 + 332: 0 -1 + 333: 1652450994 457 + 334: 0 -1 + 335: 1225731760 228 + 336: 0 -1 + 337: -843039058 720 + 338: 0 -1 + 339: -1269758292 491 + 340: 0 -1 + 341: 0 -1 + 342: 1226340009 329 + 343: 0 -1 + 344: -842430809 821 + 345: 0 -1 + 346: 0 -1 + 347: -1527130460 360 + 348: 0 -1 + 349: 0 -1 + 350: -492745055 626 + 351: 0 -1 + 352: 1733451423 94 + 353: 0 -1 + 354: -77947235 205 + 355: 0 -1 + 356: 0 -1 + 357: 0 -1 + 358: 0 -1 + 359: 529718936 754 + 360: 0 -1 + 361: -1539051882 222 + 362: 0 -1 + 363: -504058220 77 + 364: 0 -1 + 365: 699066002 852 + 366: 530327185 855 + 367: 0 -1 + 368: -1538443633 323 + 369: 0 -1 + 370: 0 -1 + 371: 2071824012 886 + 372: -2146718069 697 + 373: 0 -1 + 374: 0 -1 + 375: 0 -1 + 376: -347240825 448 + 377: 0 -1 + 378: -773960059 731 + 379: 0 -1 + 380: 0 -1 + 381: 1722138242 569 + 382: 0 -1 + 383: 0 -1 + 384: 0 -1 + 385: 0 -1 + 386: -1031332227 88 + 387: -1200071044 603 + 388: 0 -1 + 389: 3053178 354 + 390: 0 -1 + 391: 0 -1 + 392: 0 -1 + 393: 417850998 445 + 394: 0 -1 + 395: -8868236 216 + 396: 1452236403 199 + 397: 0 -1 + 398: 1025517169 482 + 399: 0 -1 + 400: 0 -1 + 401: 0 -1 + 402: -8259987 317 + 403: 0 -1 + 404: 1194864235 580 + 405: 1026125418 71 + 406: 0 -1 + 407: 0 -1 + 408: 0 -1 + 409: 0 -1 + 410: -1727345051 614 + 411: 0 -1 + 412: 0 -1 + 413: -2077639070 708 + 414: 0 -1 + 415: 1790608992 479 + 416: 0 -1 + 417: 0 -1 + 418: 0 -1 + 419: -704881060 742 + 420: -2077030821 809 + 421: 0 -1 + 422: 0 -1 + 423: 1533236824 348 + 424: 0 -1 + 425: -535533994 840 + 426: -704272811 843 + 427: 0 -1 + 428: 498851411 82 + 429: 0 -1 + 430: -1312547247 193 + 431: 0 -1 + 432: 913649231 685 + 433: 0 -1 + 434: 0 -1 + 435: 0 -1 + 436: 0 -1 + 437: 1521315402 210 + 438: 0 -1 + 439: -1738658232 65 + 440: 0 -1 + 441: 487538246 557 + 442: 0 -1 + 443: 0 -1 + 444: 1521923651 311 + 445: 0 -1 + 446: 0 -1 + 447: 837224000 874 + 448: 0 -1 + 449: -1231546818 342 + 450: 0 -1 + 451: 0 -1 + 452: -1581840837 436 + 453: 0 -1 + 454: -2008560071 719 + 455: 0 -1 + 456: 217636407 187 + 457: 0 -1 + 458: -209082827 470 + 459: 0 -1 + 460: 0 -1 + 461: 0 -1 + 462: 2029035057 76 + 463: 1860296240 591 + 464: -39735761 568 + 465: -208474578 59 + 466: 0 -1 + 467: 0 -1 + 468: 0 -1 + 469: -816749014 433 + 470: 0 -1 + 471: -1243468248 204 + 472: 0 -1 + 473: 982728230 696 + 474: 0 -1 + 475: 556008996 467 + 476: 0 -1 + 477: 0 -1 + 478: -1242859999 305 + 479: 0 -1 + 480: 983336479 797 + 481: 0 -1 + 482: 0 -1 + 483: 298636828 336 + 484: 0 -1 + 485: 0 -1 + 486: 1333022233 602 + 487: 0 -1 + 488: -735748585 70 + 489: 0 -1 + 490: 1747820053 181 + 491: 0 -1 + 492: 0 -1 + 493: 0 -1 + 494: 0 -1 + 495: -1939481072 730 + 496: 0 -1 + 497: 286715406 198 + 498: 0 -1 + 499: 1321709068 53 + 500: 0 -1 + 501: -1770134006 828 + 502: -1938872823 831 + 503: 0 -1 + 504: 287323655 299 + 505: 0 -1 + 506: 0 -1 + 507: -397375996 862 + 508: -320950781 673 + 509: 0 -1 + 510: 0 -1 + 511: 0 -1 + 512: 1478526463 424 + 513: 0 -1 + 514: 1051807229 707 + 515: 0 -1 + 516: 0 -1 + 517: -747061766 545 + 518: 0 -1 + 519: 0 -1 + 520: 0 -1 + 521: 0 -1 + 522: 794435061 64 + 523: 625696244 579 + 524: 0 -1 + 525: 1828820466 330 + 526: 0 -1 + 527: 0 -1 + 528: 0 -1 + 529: -2051349010 421 + 530: 0 -1 + 531: 1816899052 192 + 532: -1016963605 175 + 533: 0 -1 + 534: -1443682839 458 + 535: 0 -1 + 536: 0 -1 + 537: 0 -1 + 538: 1817507301 293 + 539: 0 -1 + 540: -1274335773 556 + 541: -1443074590 47 + 542: 0 -1 + 543: 0 -1 + 544: 0 -1 + 545: 0 -1 + 546: 98422237 590 + 547: 0 -1 + 548: 0 -1 + 549: -251871782 684 + 550: 0 -1 + 551: -678591016 455 + 552: 357010903 411 + 553: 0 -1 + 554: 0 -1 + 555: 1120886228 718 + 556: -251263533 785 + 557: 0 -1 + 558: 0 -1 + 559: -935963184 324 + 560: 1548213711 536 + 561: 1290233294 816 + 562: 1121494477 819 + 563: 0 -1 + 564: -1970348597 58 + 565: -677374518 657 + 566: 513220041 169 + 567: 0 -1 + 568: 0 -1 + 569: 0 -1 + 570: 0 -1 + 571: 0 -1 + 572: 0 -1 + 573: -947884606 186 + 574: 0 -1 + 575: 87109056 41 + 576: 0 -1 + 577: -1981661762 533 + 578: 0 -1 + 579: 0 -1 + 580: -947276357 287 + 581: 0 -1 + 582: 0 -1 + 583: -1631976008 850 + 584: 0 -1 + 585: 594220470 318 + 586: 1887194549 405 + 587: 0 -1 + 588: -1204648525 668 + 589: 0 -1 + 590: -182792783 695 + 591: 0 -1 + 592: 2043403695 163 + 593: 0 -1 + 594: 1616684461 446 + 595: 0 -1 + 596: 0 -1 + 597: -182184534 796 + 598: -440164951 52 + 599: -608903768 567 + 600: 1786031527 544 + 601: 1617292710 35 + 602: 0 -1 + 603: 0 -1 + 604: -181576285 897 + 605: 0 -1 + 606: 0 -1 + 607: 582299040 180 + 608: 0 -1 + 609: -1486471778 672 + 610: 0 -1 + 611: -1913191012 443 + 612: 0 -1 + 613: 0 -1 + 614: 582907289 281 + 615: 0 -1 + 616: -1485863529 773 + 617: 0 -1 + 618: 0 -1 + 619: 2124404116 312 + 620: 0 -1 + 621: 0 -1 + 622: -1136177775 578 + 623: 156796304 153 + 624: 1090018703 46 + 625: -1911974514 645 + 626: -721379955 157 + 627: 0 -1 + 628: -877589109 399 + 629: 0 -1 + 630: 0 -1 + 631: -113713784 706 + 632: 0 -1 + 633: 2112482694 174 + 634: 0 -1 + 635: -1147490940 29 + 636: 313613699 524 + 637: 55633282 804 + 638: -113105535 807 + 639: 0 -1 + 640: 2113090943 275 + 641: 0 -1 + 642: 0 -1 + 643: 1428391292 838 + 644: 0 -1 + 645: 0 -1 + 646: 0 -1 + 647: 0 -1 + 648: 1855718775 656 + 649: 1686979958 147 + 650: -1417392779 683 + 651: 0 -1 + 652: 0 -1 + 653: 1078705522 521 + 654: 0 -1 + 655: 0 -1 + 656: 0 -1 + 657: -1416784530 784 + 658: -1674764947 40 + 659: -1843503764 555 + 660: -382399125 26 + 661: -640379542 306 + 662: 652594537 393 + 663: 0 -1 + 664: -1416176281 885 + 665: 0 -1 + 666: 0 -1 + 667: -652300956 168 + 668: 0 -1 + 669: 0 -1 + 670: 382084449 434 + 671: 0 -1 + 672: -1686686369 0 + 673: 0 -1 + 674: -651692707 269 + 675: 0 -1 + 676: 0 -1 + 677: 382692698 23 + 678: 0 -1 + 679: 0 -1 + 680: 0 -1 + 681: 0 -1 + 682: 1924189525 566 + 683: -1077803692 141 + 684: 0 -1 + 685: 0 -1 + 686: 0 -1 + 687: 1147176272 431 + 688: -2112189105 387 + 689: 0 -1 + 690: 0 -1 + 691: -1348313780 694 + 692: 1574503755 761 + 693: 0 -1 + 694: 1147784521 20 + 695: 889804104 300 + 696: -920986297 512 + 697: 0 -1 + 698: -1347705531 795 + 699: 0 -1 + 700: -144581309 34 + 701: 1148392770 633 + 702: 0 -1 + 703: 0 -1 + 704: 0 -1 + 705: 0 -1 + 706: -1605077699 152 + 707: -1773816516 667 + 708: 0 -1 + 709: 877882682 162 + 710: 0 -1 + 711: 1912876344 17 + 712: 0 -1 + 713: -155894474 509 + 714: 0 -1 + 715: -582613708 280 + 716: 878490931 263 + 717: 0 -1 + 718: 0 -1 + 719: 193791280 826 + 720: -1616999121 14 + 721: -1874979538 294 + 722: -582005459 381 + 723: 0 -1 + 724: 621118763 644 + 725: 452379946 135 + 726: 1642974505 671 + 727: 0 -1 + 728: 0 -1 + 729: 0 -1 + 730: -852515547 422 + 731: 0 -1 + 732: 0 -1 + 733: 1643582754 772 + 734: 0 -1 + 735: 1216863520 543 + 736: 0 -1 + 737: -851907298 11 + 738: 0 -1 + 739: 0 -1 + 740: 1644191003 873 + 741: 0 -1 + 742: 0 -1 + 743: 959491352 412 + 744: 0 -1 + 745: 0 -1 + 746: 0 -1 + 747: -87423724 419 + 748: -74894061 146 + 749: 0 -1 + 750: -1886292719 257 + 751: 0 -1 + 752: 339903759 749 + 753: 0 -1 + 754: -86815475 8 + 755: -344795892 288 + 756: 0 -1 + 757: 947569930 274 + 758: 689589513 554 + 759: 1982563592 129 + 760: 0 -1 + 761: -86207226 621 + 762: 0 -1 + 763: 0 -1 + 764: 948178179 375 + 765: 0 -1 + 766: 0 -1 + 767: 1712053504 682 + 768: 0 -1 + 769: -1805292290 406 + 770: 0 -1 + 771: 678276348 5 + 772: 2139380987 500 + 773: 0 -1 + 774: 1712661753 783 + 775: 0 -1 + 776: -356109065 251 + 777: 0 -1 + 778: -782828299 534 + 779: -1040808716 814 + 780: 0 -1 + 781: 0 -1 + 782: 1455289585 140 + 783: 1286550768 655 + 784: -613481233 632 + 785: -782220050 123 + 786: 0 -1 + 787: 0 -1 + 788: 0 -1 + 789: -1390494486 497 + 790: 0 -1 + 791: -1817213720 268 + 792: 0 -1 + 793: 408982758 760 + 794: 0 -1 + 795: -17736476 531 + 796: 1443368163 2 + 797: 0 -1 + 798: -1816605471 369 + 799: 0 -1 + 800: 409591007 861 + 801: 0 -1 + 802: 0 -1 + 803: -275108644 400 + 804: 0 -1 + 805: 0 -1 + 806: 759276761 666 + 807: 0 -1 + 808: -1309494057 134 + 809: 0 -1 + 810: 1174074581 245 + 811: 0 -1 + 812: 0 -1 + 813: 0 -1 + 814: 0 -1 + 815: 1781740752 794 + 816: 0 -1 + 817: -287030066 262 + 818: -545010483 542 + 819: 747963596 117 + 820: 0 -1 + 821: 1951087818 892 + 822: 1782349001 895 + 823: 0 -1 + 824: -286421817 363 + 825: 0 -1 + 826: 0 -1 + 827: 477453508 670 + 828: -894696253 737 + 829: 0 -1 + 830: 0 -1 + 831: 0 -1 + 832: 904780991 488 + 833: 0 -1 + 834: 478061757 771 + 835: 0 -1 + 836: 0 -1 + 837: -1320807238 609 + 838: 0 -1 + 839: 0 -1 + 840: 0 -1 + 841: 0 -1 + 842: 220689589 128 + 843: 51950772 643 + 844: 0 -1 + 845: 1255074994 394 + 846: 0 -1 + 847: 0 -1 + 848: 0 -1 + 849: 1669872814 485 + 850: 0 -1 + 851: 1243153580 256 + 852: -1590709077 239 + 853: 0 -1 + 854: -2017428311 522 + 855: 2019558568 802 + 856: 0 -1 + 857: 0 -1 + 858: 1243761829 357 + 859: 0 -1 + 860: -1848081245 620 + 861: -2016820062 111 + 862: 0 -1 + 863: 0 -1 + 864: 0 -1 + 865: 0 -1 + 866: -475323235 654 + 867: 0 -1 + 868: 0 -1 + 869: -825617254 748 + 870: 0 -1 + 871: -1252336488 519 + 872: 0 -1 + 873: 0 -1 + 874: 0 -1 + 875: 547140756 782 + 876: -825009005 849 + 877: 0 -1 + 878: 0 -1 + 879: -1509708656 388 + 880: 0 -1 + 881: 716487822 880 + 882: 547749005 883 + 883: 0 -1 + 884: 1750873227 122 + 885: 0 -1 + 886: -60525431 233 + 887: 0 -1 + 888: -2129296249 725 + 889: 0 -1 + 890: 0 -1 + 891: 0 -1 + 892: 0 -1 + 893: -1521630078 250 + 894: 0 -1 + 895: -486636416 105 + 896: 0 -1 + 897: 1739560062 597 + 898: 0 -1 + 899: 0 -1 + 900: -1521021829 351 + 901: 0 -1 + 902: 0 -1 + 903: 0 -1 + 904: 0 -1 + 905: 20474998 382 + 906: 0 -1 + 907: 0 -1 + 908: -329819021 476 + 909: 0 -1 + 910: -756538255 759 + 911: 0 -1 + 912: 1469658223 227 + 913: 0 -1 + 914: 1042938989 510 + 915: 0 -1 + 916: 0 -1 + 917: 0 -1 + 918: -1013910423 116 + 919: -1182649240 631 + 920: 1212286055 608 + 921: 1043547238 99 + 922: 0 -1 + 923: 0 -1 + 924: 0 -1 + 925: 435272802 473 + 926: 0 -1 + 927: 8553568 244 + 928: 0 -1 + 929: -2060217250 736 + 930: 0 -1 + 931: 1808030812 507 + 932: 0 -1 + 933: 0 -1 + 934: 9161817 345 + 935: 0 -1 + 936: -2059609001 837 + 937: 0 -1 + 938: 0 -1 + 939: 1550658644 376 + 940: 0 -1 + 941: 0 -1 + 942: -1709923247 642 + 943: 0 -1 + 944: 516273231 110 + 945: 0 -1 + 946: -1295125427 221 + 947: 0 -1 + 948: 0 -1 + 949: 0 -1 + 950: 0 -1 + 951: -687459256 770 + 952: 0 -1 + 953: 1538737222 238 + 954: 0 -1 + 955: -1721236412 93 + 956: 0 -1 + 957: -518112190 868 + 958: -686851007 871 + 959: 0 -1 + 960: 1539345471 339 + 961: 0 -1 + 962: 0 -1 + 963: 0 -1 + 964: 931071035 713 + 965: 0 -1 + 966: 0 -1 + 967: 0 -1 + 968: -1564419017 464 + 969: 0 -1 + 970: -1991138251 747 + 971: 0 -1 + 972: 0 -1 + 973: 504960050 585 + 974: 0 -1 + 975: 0 -1 + 976: 0 -1 + 977: 0 -1 + 978: 2046456877 104 + 979: 1877718060 619 + 980: 0 -1 + 981: -1214125014 370 + 982: 0 -1 + 983: 0 -1 + 984: 0 -1 + 985: -799327194 461 + 986: 0 -1 + 987: -1226046428 232 + 988: 235058211 215 + 989: 0 -1 + 990: -191661023 498 + 991: 0 -1 + 992: 0 -1 + 993: 0 -1 + 994: -1225438179 333 + 995: 0 -1 + 996: -22313957 596 + 997: -191052774 87 + 998: 0 -1 + 1: subview '_B' + VIEW 47 rows = _H:I _R:I + 0: 0 -1 + 1: 0 -1 + 2: 1350444053 630 + 3: 0 -1 + 4: 0 -1 + 5: 1000150034 724 + 6: 0 -1 + 7: 573430800 495 + 8: 0 -1 + 9: 0 -1 + 10: 0 -1 + 11: -1922059252 758 + 12: 1000758283 825 + 13: 0 -1 + 14: 0 -1 + 15: 316058632 364 + 16: 0 -1 + 17: -1752712186 856 + 18: -1921451003 859 + 19: 0 -1 + 20: -718326781 98 + 21: 0 -1 + 22: 1765241857 209 + 23: 0 -1 + 24: -303528961 701 + 25: 0 -1 + 26: 0 -1 + 27: 0 -1 + 28: 0 -1 + 29: 304137210 226 + 30: 0 -1 + 31: 1339130872 81 + 32: 0 -1 + 33: -729639946 573 + 34: 0 -1 + 35: 0 -1 + 36: 304745459 327 + 37: 0 -1 + 38: 0 -1 + 39: -379954192 890 + 40: 0 -1 + 41: 1846242286 358 + 42: 0 -1 + 43: 0 -1 + 44: 1495948267 452 + 45: 0 -1 + 46: 1069229033 735 + 2: subview '_B' + VIEW 1001 rows = _H:I _R:I + 0: -999541785 203 + 1: 0 -1 + 2: -1426261019 486 + 3: 0 -1 + 4: 0 -1 + 5: 0 -1 + 6: 811856865 92 + 7: 643118048 607 + 8: -1256913953 584 + 9: -1425652770 75 + 10: 0 -1 + 11: 0 -1 + 12: 0 -1 + 13: -2033927206 449 + 14: 0 -1 + 15: 1834320856 220 + 16: 0 -1 + 17: -234449962 712 + 18: 0 -1 + 19: -661169196 483 + 20: 0 -1 + 21: 0 -1 + 22: 1834929105 321 + 23: 0 -1 + 24: -233841713 813 + 25: 0 -1 + 26: 0 -1 + 27: -918541364 352 + 28: 0 -1 + 29: 0 -1 + 30: 115844041 618 + 31: 0 -1 + 32: -1952926777 86 + 33: 0 -1 + 34: 530641861 197 + 35: 0 -1 + 36: 0 -1 + 37: 0 -1 + 38: 0 -1 + 39: 1138308032 746 + 40: 0 -1 + 41: -930462786 214 + 42: 0 -1 + 43: 104530876 69 + 44: 0 -1 + 45: 1307655098 844 + 46: 1138916281 847 + 47: 0 -1 + 48: -929854537 315 + 49: 0 -1 + 50: 0 -1 + 51: -1614554188 878 + 52: -1538128973 689 + 53: 0 -1 + 54: 0 -1 + 55: 0 -1 + 56: 261348271 440 + 57: 0 -1 + 58: -165370963 723 + 59: 0 -1 + 60: 0 -1 + 61: -1964239958 561 + 62: 0 -1 + 63: 0 -1 + 64: 0 -1 + 65: 0 -1 + 66: -422743131 80 + 67: -591481948 595 + 68: 0 -1 + 69: 611642274 346 + 70: 0 -1 + 71: 0 -1 + 72: 0 -1 + 73: 1026440094 437 + 74: 0 -1 + 75: 599720860 208 + 76: 2060825499 191 + 77: 0 -1 + 78: 1634106265 474 + 79: 0 -1 + 80: 0 -1 + 81: 0 -1 + 82: 600329109 309 + 83: 0 -1 + 84: 1803453331 572 + 85: 1634714514 63 + 86: 0 -1 + 87: 0 -1 + 88: 0 -1 + 89: 0 -1 + 90: -1118755955 606 + 91: 0 -1 + 92: 0 -1 + 93: -1469049974 700 + 94: 0 -1 + 95: -1895769208 471 + 96: 0 -1 + 97: 0 -1 + 98: 0 -1 + 99: -96291964 734 + 100: -1468441725 801 + 101: 0 -1 + 102: 0 -1 + 103: 2141825920 340 + 104: 0 -1 + 105: 73055102 832 + 106: -95683715 835 + 107: 0 -1 + 108: 1107440507 74 + 109: 0 -1 + 110: -703958151 185 + 111: 0 -1 + 112: 1522238327 677 + 113: 0 -1 + 114: 0 -1 + 115: 0 -1 + 116: 0 -1 + 117: 2129904498 202 + 118: 0 -1 + 119: -1130069136 57 + 120: 0 -1 + 121: 1096127342 549 + 122: 0 -1 + 123: 0 -1 + 124: 2130512747 303 + 125: 0 -1 + 126: 0 -1 + 127: 1445813096 866 + 128: 0 -1 + 129: -622957722 334 + 130: 0 -1 + 131: 0 -1 + 132: -973251741 428 + 133: 0 -1 + 134: -1399970975 711 + 135: 0 -1 + 136: 826225503 179 + 137: 0 -1 + 138: 399506269 462 + 139: 0 -1 + 140: 0 -1 + 141: 0 -1 + 142: -1657343143 68 + 143: -1826081960 583 + 144: 568853335 560 + 145: 400114518 51 + 146: 0 -1 + 147: 0 -1 + 148: 0 -1 + 149: -208159918 425 + 150: 0 -1 + 151: -634879152 196 + 152: 0 -1 + 153: 1591317326 688 + 154: 0 -1 + 155: 1164598092 459 + 156: 0 -1 + 157: 0 -1 + 158: -634270903 297 + 159: 0 -1 + 160: 1591925575 789 + 161: 0 -1 + 162: 0 -1 + 163: 907225924 328 + 164: 0 -1 + 165: 0 -1 + 166: 1941611329 594 + 167: 0 -1 + 168: -127159489 62 + 169: 1165814590 661 + 170: -1938558147 173 + 171: 0 -1 + 172: 0 -1 + 173: 0 -1 + 174: 0 -1 + 175: -1330891976 722 + 176: 0 -1 + 177: 895304502 190 + 178: 0 -1 + 179: 1930298164 45 + 180: -903564493 540 + 181: -1161544910 820 + 182: -1330283727 823 + 183: 0 -1 + 184: 895912751 291 + 185: 0 -1 + 186: 0 -1 + 187: 211213100 854 + 188: 0 -1 + 189: 0 -1 + 190: 0 -1 + 191: 0 -1 + 192: 2087115559 416 + 193: 0 -1 + 194: 1660396325 699 + 195: 0 -1 + 196: 0 -1 + 197: -138472670 537 + 198: 0 -1 + 199: 0 -1 + 200: 0 -1 + 201: 0 -1 + 202: 1403024157 56 + 203: 1234285340 571 + 204: 0 -1 + 205: -1857557734 322 + 206: -564583655 409 + 207: 0 -1 + 208: 0 -1 + 209: -1442759914 413 + 210: 0 -1 + 211: -1869479148 184 + 212: -408374509 167 + 213: 0 -1 + 214: -835093743 450 + 215: 0 -1 + 216: 0 -1 + 217: 0 -1 + 218: -1868870899 285 + 219: 0 -1 + 220: -665746677 548 + 221: -834485494 39 + 222: 0 -1 + 223: 0 -1 + 224: 0 -1 + 225: 0 -1 + 226: 707011333 582 + 227: 0 -1 + 228: 0 -1 + 229: 356717314 676 + 230: 0 -1 + 231: -70001920 447 + 232: 965599999 403 + 233: 0 -1 + 234: 0 -1 + 235: 1729475324 710 + 236: 357325563 777 + 237: 0 -1 + 238: 0 -1 + 239: -327374088 316 + 240: -2138164489 528 + 241: 1898822390 808 + 242: 1730083573 811 + 243: 0 -1 + 244: -1361759501 50 + 245: -68785422 649 + 246: 1121809137 161 + 247: 0 -1 + 248: 0 -1 + 249: 0 -1 + 250: 0 -1 + 251: 0 -1 + 252: 0 -1 + 253: -339295510 178 + 254: 0 -1 + 255: 695698152 33 + 256: 0 -1 + 257: -1373072666 525 + 258: 0 -1 + 259: 0 -1 + 260: -338687261 279 + 261: 0 -1 + 262: 0 -1 + 263: -1023386912 842 + 264: 0 -1 + 265: 1202809566 310 + 266: -1799183651 397 + 267: 0 -1 + 268: -596059429 660 + 269: -764798246 151 + 270: 425796313 687 + 271: 0 -1 + 272: 0 -1 + 273: 0 -1 + 274: -2069693739 438 + 275: 0 -1 + 276: 0 -1 + 277: 426404562 788 + 278: 168424145 44 + 279: -314672 559 + 280: 0 -1 + 281: -2069085490 27 + 282: 0 -1 + 283: 0 -1 + 284: 427012811 889 + 285: 0 -1 + 286: 0 -1 + 287: 1190888136 172 + 288: 0 -1 + 289: 0 -1 + 290: 0 -1 + 291: -1304601916 435 + 292: 0 -1 + 293: 0 -1 + 294: 1191496385 273 + 295: 0 -1 + 296: -877274433 765 + 297: 0 -1 + 298: -1303993667 24 + 299: -1561974084 304 + 300: 0 -1 + 301: 0 -1 + 302: -527588679 570 + 303: 765385400 145 + 304: 1698607799 38 + 305: -1303385418 637 + 306: 0 -1 + 307: 0 -1 + 308: -269000013 391 + 309: 0 -1 + 310: 0 -1 + 311: 494875312 698 + 312: 0 -1 + 313: -1573895506 166 + 314: 0 -1 + 315: -538901844 21 + 316: 922202795 516 + 317: 0 -1 + 318: 495483561 799 + 319: 0 -1 + 320: -1573287257 267 + 321: 0 -1 + 322: 0 -1 + 323: 2036980388 830 + 324: 0 -1 + 325: 0 -1 + 326: 238111393 156 + 327: 0 -1 + 328: -1830659425 648 + 329: -1999398242 139 + 330: -808803683 675 + 331: 0 -1 + 332: 0 -1 + 333: 1687294618 513 + 334: 0 -1 + 335: 1260575384 284 + 336: 0 -1 + 337: -808195434 776 + 338: -1066175851 32 + 339: -1234914668 547 + 340: 226189971 18 + 341: -31790446 298 + 342: 1261183633 385 + 343: 0 -1 + 344: -807587185 877 + 345: 0 -1 + 346: 0 -1 + 347: -43711860 160 + 348: 0 -1 + 349: 0 -1 + 350: 990673545 426 + 351: 0 -1 + 352: 1768295047 150 + 353: 0 -1 + 354: -43103611 261 + 355: 0 -1 + 356: 0 -1 + 357: 991281794 15 + 358: 0 -1 + 359: 0 -1 + 360: 0 -1 + 361: -1504208258 278 + 362: -1762188675 558 + 363: -469214596 133 + 364: 0 -1 + 365: 0 -1 + 366: 0 -1 + 367: 1755765368 423 + 368: -1503600009 379 + 369: 0 -1 + 370: 0 -1 + 371: -739724684 686 + 372: -2111874445 753 + 373: 0 -1 + 374: 1756373617 12 + 375: 1498393200 292 + 376: -312397201 504 + 377: 0 -1 + 378: -739116435 787 + 379: 0 -1 + 380: 0 -1 + 381: 1756981866 625 + 382: 0 -1 + 383: 0 -1 + 384: 0 -1 + 385: 0 -1 + 386: -996488603 144 + 387: -1165227420 659 + 388: 0 -1 + 389: 37896802 410 + 390: 0 -1 + 391: -1773501856 9 + 392: 0 -1 + 393: 452694622 501 + 394: 0 -1 + 395: 25975388 272 + 396: 1487080027 255 + 397: 0 -1 + 398: 1060360793 538 + 399: 802380376 818 + 400: -1008410025 6 + 401: -1266390442 286 + 402: 26583637 373 + 403: 0 -1 + 404: 1229707859 636 + 405: 1060969042 127 + 406: 0 -1 + 407: 0 -1 + 408: 0 -1 + 409: 0 -1 + 410: -243926451 414 + 411: 0 -1 + 412: 0 -1 + 413: -2042795446 764 + 414: 0 -1 + 415: 1825452616 535 + 416: 0 -1 + 417: -243318202 3 + 418: 0 -1 + 419: 0 -1 + 420: -2042187197 865 + 421: 0 -1 + 422: 0 -1 + 423: 1568080448 404 + 424: 0 -1 + 425: -500690370 896 + 426: -669429187 899 + 427: 0 -1 + 428: 533695035 138 + 429: 0 -1 + 430: -1277703623 249 + 431: 0 -1 + 432: 948492855 741 + 433: 0 -1 + 434: 0 -1 + 435: 0 -1 + 436: 0 -1 + 437: 1556159026 266 + 438: 1298178609 546 + 439: -1703814608 121 + 440: 0 -1 + 441: 522381870 613 + 442: 0 -1 + 443: 0 -1 + 444: 1556767275 367 + 445: 0 -1 + 446: 0 -1 + 447: -1974324696 674 + 448: 0 -1 + 449: -1196703194 398 + 450: 0 -1 + 451: 0 -1 + 452: -1546997213 492 + 453: 0 -1 + 454: -1973716447 775 + 455: 0 -1 + 456: 252480031 243 + 457: 0 -1 + 458: -174239203 526 + 459: -432219620 806 + 460: 0 -1 + 461: 0 -1 + 462: 2063878681 132 + 463: 1895139864 647 + 464: -4892137 624 + 465: -173630954 115 + 466: 0 -1 + 467: 0 -1 + 468: 0 -1 + 469: -781905390 489 + 470: 0 -1 + 471: -1208624624 260 + 472: 0 -1 + 473: 1017571854 752 + 474: 0 -1 + 475: 590852620 523 + 476: 0 -1 + 477: 0 -1 + 478: -1208016375 361 + 479: 0 -1 + 480: 1018180103 853 + 481: 0 -1 + 482: 0 -1 + 483: 333480452 392 + 484: 0 -1 + 485: 0 -1 + 486: 1367865857 658 + 487: 0 -1 + 488: -700904961 126 + 489: 0 -1 + 490: 1782663677 237 + 491: 0 -1 + 492: 0 -1 + 493: 0 -1 + 494: 0 -1 + 495: -1904637448 786 + 496: 0 -1 + 497: 321559030 254 + 498: 0 -1 + 499: 1356552692 109 + 500: 0 -1 + 501: -1735290382 884 + 502: -1904029199 887 + 503: 0 -1 + 504: 322167279 355 + 505: 0 -1 + 506: 0 -1 + 507: 0 -1 + 508: -286107157 729 + 509: 0 -1 + 510: 0 -1 + 511: 0 -1 + 512: 1513370087 480 + 513: 0 -1 + 514: 1086650853 763 + 515: 0 -1 + 516: 0 -1 + 517: -712218142 601 + 518: 0 -1 + 519: 0 -1 + 520: 0 -1 + 521: 0 -1 + 522: 829278685 120 + 523: 660539868 635 + 524: 0 -1 + 525: 1863664090 386 + 526: 0 -1 + 527: 0 -1 + 528: 0 -1 + 529: -2016505386 477 + 530: 0 -1 + 531: 1851742676 248 + 532: -982119981 231 + 533: 0 -1 + 534: -1408839215 514 + 535: 0 -1 + 536: 0 -1 + 537: 0 -1 + 538: 1852350925 349 + 539: 0 -1 + 540: -1239492149 612 + 541: -1408230966 103 + 542: 0 -1 + 543: 0 -1 + 544: 0 -1 + 545: 0 -1 + 546: 133265861 646 + 547: 0 -1 + 548: 0 -1 + 549: -217028158 740 + 550: 0 -1 + 551: -643747392 511 + 552: 0 -1 + 553: 0 -1 + 554: 0 -1 + 555: 1155729852 774 + 556: -216419909 841 + 557: 0 -1 + 558: 0 -1 + 559: -901119560 380 + 560: 0 -1 + 561: 1325076918 872 + 562: 1156338101 875 + 563: 0 -1 + 564: -1935504973 114 + 565: 0 -1 + 566: 548063665 225 + 567: 0 -1 + 568: -1520707153 717 + 569: 0 -1 + 570: 0 -1 + 571: 0 -1 + 572: 0 -1 + 573: -913040982 242 + 574: 0 -1 + 575: 121952680 97 + 576: 0 -1 + 577: -1946818138 589 + 578: 0 -1 + 579: 0 -1 + 580: -912432733 343 + 581: 0 -1 + 582: 0 -1 + 583: 0 -1 + 584: 0 -1 + 585: 629064094 374 + 586: 0 -1 + 587: 0 -1 + 588: 278770075 468 + 589: 0 -1 + 590: -147949159 751 + 591: 0 -1 + 592: 2078247319 219 + 593: 0 -1 + 594: 1651528085 502 + 595: 0 -1 + 596: 0 -1 + 597: 0 -1 + 598: -405321327 108 + 599: -574060144 623 + 600: 1820875151 600 + 601: 1652136334 91 + 602: 0 -1 + 603: 0 -1 + 604: 0 -1 + 605: 1043861898 465 + 606: 0 -1 + 607: 617142664 236 + 608: 0 -1 + 609: -1451628154 728 + 610: 0 -1 + 611: -1878347388 499 + 612: 0 -1 + 613: 0 -1 + 614: 617750913 337 + 615: 0 -1 + 616: -1451019905 829 + 617: 0 -1 + 618: 0 -1 + 619: -2135719556 368 + 620: 0 -1 + 621: 0 -1 + 622: -1101334151 634 + 623: 0 -1 + 624: 1124862327 102 + 625: 0 -1 + 626: -686536331 213 + 627: 0 -1 + 628: 0 -1 + 629: 0 -1 + 630: 0 -1 + 631: -78870160 762 + 632: 0 -1 + 633: 2147326318 230 + 634: 0 -1 + 635: -1112647316 85 + 636: 0 -1 + 637: 90476906 860 + 638: -78261911 863 + 639: 0 -1 + 640: -2147032729 331 + 641: 0 -1 + 642: 0 -1 + 643: 1463234916 894 + 644: 1539660131 705 + 645: 0 -1 + 646: 0 -1 + 647: 0 -1 + 648: -955829921 456 + 649: 0 -1 + 650: -1382549155 739 + 651: 0 -1 + 652: 0 -1 + 653: 1113549146 577 + 654: 0 -1 + 655: 0 -1 + 656: 0 -1 + 657: 0 -1 + 658: -1639921323 96 + 659: -1808660140 611 + 660: 0 -1 + 661: -605535918 362 + 662: 0 -1 + 663: 0 -1 + 664: 0 -1 + 665: -190738098 453 + 666: 0 -1 + 667: -617457332 224 + 668: 843647307 207 + 669: 0 -1 + 670: 416928073 490 + 671: 0 -1 + 672: 0 -1 + 673: 0 -1 + 674: -616849083 325 + 675: 0 -1 + 676: 586275139 588 + 677: 417536322 79 + 678: 0 -1 + 679: 0 -1 + 680: 0 -1 + 681: 0 -1 + 682: 1959033149 622 + 683: 0 -1 + 684: 0 -1 + 685: 1608739130 716 + 686: 0 -1 + 687: 1182019896 487 + 688: 0 -1 + 689: 0 -1 + 690: 0 -1 + 691: -1313470156 750 + 692: 1609347379 817 + 693: 0 -1 + 694: 0 -1 + 695: 924647728 356 + 696: 0 -1 + 697: -1144123090 848 + 698: -1312861907 851 + 699: 0 -1 + 700: -109737685 90 + 701: 0 -1 + 702: -1921136343 201 + 703: 0 -1 + 704: 305060135 693 + 705: 0 -1 + 706: 0 -1 + 707: 0 -1 + 708: 0 -1 + 709: 912726306 218 + 710: 0 -1 + 711: 1947719968 73 + 712: 0 -1 + 713: -121050850 565 + 714: 0 -1 + 715: 0 -1 + 716: 913334555 319 + 717: 0 -1 + 718: 0 -1 + 719: 228634904 882 + 720: 0 -1 + 721: -1840135914 350 + 722: 0 -1 + 723: 0 -1 + 724: 2104537363 444 + 725: 0 -1 + 726: 1677818129 727 + 727: 0 -1 + 728: -390952689 195 + 729: 0 -1 + 730: -817671923 478 + 731: 0 -1 + 732: 0 -1 + 733: 0 -1 + 734: 1420445961 84 + 735: 1251707144 599 + 736: -648324857 576 + 737: -817063674 67 + 738: 0 -1 + 739: 0 -1 + 740: 0 -1 + 741: -1425338110 441 + 742: 0 -1 + 743: -1852057344 212 + 744: 0 -1 + 745: 374139134 704 + 746: 0 -1 + 747: -52580100 475 + 748: 0 -1 + 749: 0 -1 + 750: -1851449095 313 + 751: 0 -1 + 752: 374747383 805 + 753: 0 -1 + 754: 0 -1 + 755: -309952268 344 + 756: 0 -1 + 757: 0 -1 + 758: 724433137 610 + 759: 0 -1 + 760: -1344337681 78 + 761: 0 -1 + 762: 1139230957 189 + 763: 0 -1 + 764: 0 -1 + 765: 0 -1 + 766: 0 -1 + 767: 1746897128 738 + 768: 0 -1 + 769: -321873690 206 + 770: 0 -1 + 771: 713119972 61 + 772: 0 -1 + 773: 1916244194 836 + 774: 1747505377 839 + 775: 0 -1 + 776: -321265441 307 + 777: 0 -1 + 778: 0 -1 + 779: -1005965092 870 + 780: -929539877 681 + 781: 0 -1 + 782: 0 -1 + 783: 0 -1 + 784: 869937367 432 + 785: 0 -1 + 786: 443218133 715 + 787: 0 -1 + 788: 0 -1 + 789: -1355650862 553 + 790: 0 -1 + 791: 0 -1 + 792: 0 -1 + 793: 0 -1 + 794: 185845965 72 + 795: 17107148 587 + 796: 0 -1 + 797: 1220231370 338 + 798: 0 -1 + 799: 0 -1 + 800: 0 -1 + 801: 1635029190 429 + 802: 0 -1 + 803: 1208309956 200 + 804: -1625552701 183 + 805: 0 -1 + 806: -2052271935 466 + 807: 0 -1 + 808: 0 -1 + 809: 0 -1 + 810: 1208918205 301 + 811: 0 -1 + 812: -1882924869 564 + 813: -2051663686 55 + 814: 0 -1 + 815: 0 -1 + 816: 0 -1 + 817: 0 -1 + 818: -510166859 598 + 819: 0 -1 + 820: 0 -1 + 821: -860460878 692 + 822: 0 -1 + 823: -1287180112 463 + 824: 0 -1 + 825: 0 -1 + 826: 0 -1 + 827: 512297132 726 + 828: -859852629 793 + 829: 0 -1 + 830: 0 -1 + 831: -1544552280 332 + 832: 0 -1 + 833: 681644198 824 + 834: 512905381 827 + 835: 0 -1 + 836: 1716029603 66 + 837: -1285963614 665 + 838: -95369055 177 + 839: 0 -1 + 840: 2130827423 669 + 841: 0 -1 + 842: 0 -1 + 843: 0 -1 + 844: 0 -1 + 845: -1556473702 194 + 846: 0 -1 + 847: -521480040 49 + 848: 0 -1 + 849: 1704716438 541 + 850: 0 -1 + 851: 0 -1 + 852: -1555865453 295 + 853: 0 -1 + 854: 0 -1 + 855: 2054402192 858 + 856: 0 -1 + 857: -14368626 326 + 858: 0 -1 + 859: 0 -1 + 860: -364662645 420 + 861: 0 -1 + 862: -791381879 703 + 863: 0 -1 + 864: 1434814599 171 + 865: 0 -1 + 866: 1008095365 454 + 867: 0 -1 + 868: 0 -1 + 869: 0 -1 + 870: -1048754047 60 + 871: -1217492864 575 + 872: 1177442431 552 + 873: 1008703614 43 + 874: 0 -1 + 875: 0 -1 + 876: 0 -1 + 877: 400429178 417 + 878: 0 -1 + 879: -26290056 188 + 880: 0 -1 + 881: -2095060874 680 + 882: 0 -1 + 883: 1773187188 451 + 884: 0 -1 + 885: 0 -1 + 886: -25681807 289 + 887: 0 -1 + 888: -2094452625 781 + 889: 0 -1 + 890: 0 -1 + 891: 1515815020 320 + 892: 0 -1 + 893: 0 -1 + 894: -1744766871 586 + 895: 0 -1 + 896: 481429607 54 + 897: 1774403686 653 + 898: -1329969051 165 + 899: 0 -1 + 900: -1486178205 407 + 901: 0 -1 + 902: 0 -1 + 903: -722302880 714 + 904: 0 -1 + 905: 1503893598 182 + 906: 0 -1 + 907: -1756080036 37 + 908: -294975397 532 + 909: -552955814 812 + 910: -721694631 815 + 911: 0 -1 + 912: 1504501847 283 + 913: 0 -1 + 914: 0 -1 + 915: 819802196 846 + 916: 0 -1 + 917: 0 -1 + 918: 0 -1 + 919: 0 -1 + 920: 1247129679 664 + 921: 1078390862 155 + 922: -2025981875 691 + 923: 0 -1 + 924: 0 -1 + 925: 470116426 529 + 926: 0 -1 + 927: 0 -1 + 928: 0 -1 + 929: -2025373626 792 + 930: 2011613253 48 + 931: 1842874436 563 + 932: 0 -1 + 933: -1248968638 314 + 934: 44005441 401 + 935: 0 -1 + 936: -2024765377 893 + 937: 0 -1 + 938: 0 -1 + 939: -1260890052 176 + 940: 200214587 159 + 941: 0 -1 + 942: -226504647 442 + 943: 0 -1 + 944: 0 -1 + 945: 0 -1 + 946: -1260281803 277 + 947: 0 -1 + 948: 0 -1 + 949: -225896398 31 + 950: 0 -1 + 951: 0 -1 + 952: 0 -1 + 953: 0 -1 + 954: 1315600429 574 + 955: -1686392788 149 + 956: 0 -1 + 957: 0 -1 + 958: 0 -1 + 959: 538587176 439 + 960: 1574189095 395 + 961: 0 -1 + 962: 0 -1 + 963: -1956902876 702 + 964: 965914659 769 + 965: 0 -1 + 966: 539195425 28 + 967: 281215008 308 + 968: -1529575393 520 + 969: -1787555810 800 + 970: -1956294627 803 + 971: 0 -1 + 972: -753170405 42 + 973: 539803674 641 + 974: 0 -1 + 975: 0 -1 + 976: 0 -1 + 977: 0 -1 + 978: 0 -1 + 979: 0 -1 + 980: 0 -1 + 981: 269293586 170 + 982: 0 -1 + 983: 1304287248 25 + 984: 0 -1 + 985: -764483570 517 + 986: 0 -1 + 987: 0 -1 + 988: 269901835 271 + 989: 0 -1 + 990: 0 -1 + 991: -414797816 834 + 992: 2069379079 22 + 993: 1811398662 302 + 994: -1190594555 389 + 995: 0 -1 + 996: 12529667 652 + 997: -156209150 143 + 998: 1034385409 679 + 999: 0 -1 + 1000: 2053 0 + 3: subview '_B' + VIEW 2 rows = _H:I _R:I + 0: 0 -1 + 1: 0 -1 diff --git a/akregator/src/mk4storage/metakit/tests/ok/m07.txt b/akregator/src/mk4storage/metakit/tests/ok/m07.txt new file mode 100644 index 000000000..aac9208cf --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/m07.txt @@ -0,0 +1,63 @@ +>>> All blocked view multi-deletion cases +blockdel pos 0 len 1 +blockdel pos 0 len 2 +blockdel pos 0 len 3 +blockdel pos 0 len 998 +blockdel pos 0 len 999 +blockdel pos 0 len 1000 +blockdel pos 0 len 1001 +blockdel pos 0 len 1998 +blockdel pos 0 len 1999 +blockdel pos 0 len 2000 +blockdel pos 0 len 2001 +blockdel pos 1 len 1 +blockdel pos 1 len 2 +blockdel pos 1 len 3 +blockdel pos 1 len 998 +blockdel pos 1 len 999 +blockdel pos 1 len 1000 +blockdel pos 1 len 1001 +blockdel pos 1 len 1998 +blockdel pos 1 len 1999 +blockdel pos 1 len 2000 +blockdel pos 1 len 2001 +blockdel pos 998 len 1 +blockdel pos 998 len 2 +blockdel pos 998 len 3 +blockdel pos 998 len 998 +blockdel pos 998 len 999 +blockdel pos 998 len 1000 +blockdel pos 998 len 1001 +blockdel pos 999 len 1 +blockdel pos 999 len 2 +blockdel pos 999 len 3 +blockdel pos 999 len 998 +blockdel pos 999 len 999 +blockdel pos 999 len 1000 +blockdel pos 999 len 1001 +blockdel pos 1000 len 1 +blockdel pos 1000 len 2 +blockdel pos 1000 len 3 +blockdel pos 1000 len 998 +blockdel pos 1000 len 999 +blockdel pos 1000 len 1000 +blockdel pos 1000 len 1001 +blockdel pos 1001 len 1 +blockdel pos 1001 len 2 +blockdel pos 1001 len 3 +blockdel pos 1001 len 998 +blockdel pos 1001 len 999 +blockdel pos 1001 len 1000 +blockdel pos 1001 len 1001 +blockdel pos 2998 len 1 +blockdel pos 2997 len 2 +blockdel pos 2996 len 3 +blockdel pos 2001 len 998 +blockdel pos 2000 len 999 +blockdel pos 1999 len 1000 +blockdel pos 1998 len 1001 +blockdel pos 1001 len 1998 +blockdel pos 1000 len 1999 +blockdel pos 999 len 2000 +blockdel pos 998 len 2001 +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n01.txt b/akregator/src/mk4storage/metakit/tests/ok/n01.txt new file mode 100644 index 000000000..28b19811f --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n01.txt @@ -0,0 +1,2 @@ +>>> Add to selection +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n02.txt b/akregator/src/mk4storage/metakit/tests/ok/n02.txt new file mode 100644 index 000000000..a912aae04 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n02.txt @@ -0,0 +1,2 @@ +>>> Remove from selection +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n03.txt b/akregator/src/mk4storage/metakit/tests/ok/n03.txt new file mode 100644 index 000000000..5934324cc --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n03.txt @@ -0,0 +1,2 @@ +>>> Modify into selection +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n04.txt b/akregator/src/mk4storage/metakit/tests/ok/n04.txt new file mode 100644 index 000000000..efb96017d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n04.txt @@ -0,0 +1,2 @@ +>>> Modify out of selection +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n05.txt b/akregator/src/mk4storage/metakit/tests/ok/n05.txt new file mode 100644 index 000000000..bc40bea33 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n05.txt @@ -0,0 +1,2 @@ +>>> Add to sorted +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n06.txt b/akregator/src/mk4storage/metakit/tests/ok/n06.txt new file mode 100644 index 000000000..f8c499a53 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n06.txt @@ -0,0 +1,2 @@ +>>> Remove from sorted +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n07.txt b/akregator/src/mk4storage/metakit/tests/ok/n07.txt new file mode 100644 index 000000000..87ff41217 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n07.txt @@ -0,0 +1,2 @@ +>>> New property through sort +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n08.txt b/akregator/src/mk4storage/metakit/tests/ok/n08.txt new file mode 100644 index 000000000..0939301c6 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n08.txt @@ -0,0 +1,2 @@ +>>> Nested project and select +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n09.txt b/akregator/src/mk4storage/metakit/tests/ok/n09.txt new file mode 100644 index 000000000..0732f4208 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n09.txt @@ -0,0 +1,2 @@ +>>> Multiple dependencies +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n10.txt b/akregator/src/mk4storage/metakit/tests/ok/n10.txt new file mode 100644 index 000000000..8c1f92ded --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n10.txt @@ -0,0 +1,2 @@ +>>> Modify sorted duplicates +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n11.txt b/akregator/src/mk4storage/metakit/tests/ok/n11.txt new file mode 100644 index 000000000..07d6ebddf --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n11.txt @@ -0,0 +1,2 @@ +>>> Resize compound derived view +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n12.txt b/akregator/src/mk4storage/metakit/tests/ok/n12.txt new file mode 100644 index 000000000..fa194393d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n12.txt @@ -0,0 +1,2 @@ +>>> Alter multiply derived view +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n13.txt b/akregator/src/mk4storage/metakit/tests/ok/n13.txt new file mode 100644 index 000000000..e9ba290d1 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n13.txt @@ -0,0 +1,2 @@ +>>> Project without +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n14.txt b/akregator/src/mk4storage/metakit/tests/ok/n14.txt new file mode 100644 index 000000000..2522115e5 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n14.txt @@ -0,0 +1,2 @@ +>>> Insert in non-mapped position +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/n14a.txt b/akregator/src/mk4storage/metakit/tests/ok/n14a.txt new file mode 100644 index 000000000..ef5e47ac5 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/n14a.txt @@ -0,0 +1,15 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 12 rows = p1:I + 0: 0 + 1: 1 + 2: 2 + 3: 6 + 4: 0 + 5: 1 + 6: 2 + 7: 1 + 8: 0 + 9: 1 + 10: 2 + 11: 0 diff --git a/akregator/src/mk4storage/metakit/tests/ok/r00.txt b/akregator/src/mk4storage/metakit/tests/ok/r00.txt new file mode 100644 index 000000000..c2dd0e8c5 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r00.txt @@ -0,0 +1,2 @@ +>>> Simple insert +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/r00a.txt b/akregator/src/mk4storage/metakit/tests/ok/r00a.txt new file mode 100644 index 000000000..16475db59 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r00a.txt @@ -0,0 +1,253 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 250 rows = p1:I + 0: 1 + 1: 2 + 2: 3 + 3: 4 + 4: 5 + 5: 6 + 6: 7 + 7: 8 + 8: 9 + 9: 10 + 10: 11 + 11: 12 + 12: 13 + 13: 14 + 14: 15 + 15: 16 + 16: 17 + 17: 18 + 18: 19 + 19: 20 + 20: 21 + 21: 22 + 22: 23 + 23: 24 + 24: 25 + 25: 26 + 26: 27 + 27: 28 + 28: 29 + 29: 30 + 30: 31 + 31: 32 + 32: 33 + 33: 34 + 34: 35 + 35: 36 + 36: 37 + 37: 38 + 38: 39 + 39: 40 + 40: 41 + 41: 42 + 42: 43 + 43: 44 + 44: 45 + 45: 46 + 46: 47 + 47: 48 + 48: 49 + 49: 50 + 50: 51 + 51: 52 + 52: 53 + 53: 54 + 54: 55 + 55: 56 + 56: 57 + 57: 58 + 58: 59 + 59: 60 + 60: 61 + 61: 62 + 62: 63 + 63: 64 + 64: 65 + 65: 66 + 66: 67 + 67: 68 + 68: 69 + 69: 70 + 70: 71 + 71: 72 + 72: 73 + 73: 74 + 74: 75 + 75: 76 + 76: 77 + 77: 78 + 78: 79 + 79: 80 + 80: 81 + 81: 82 + 82: 83 + 83: 84 + 84: 85 + 85: 86 + 86: 87 + 87: 88 + 88: 89 + 89: 90 + 90: 91 + 91: 92 + 92: 93 + 93: 94 + 94: 95 + 95: 96 + 96: 97 + 97: 98 + 98: 99 + 99: 100 + 100: 101 + 101: 102 + 102: 103 + 103: 104 + 104: 105 + 105: 106 + 106: 107 + 107: 108 + 108: 109 + 109: 110 + 110: 111 + 111: 112 + 112: 113 + 113: 114 + 114: 115 + 115: 116 + 116: 117 + 117: 118 + 118: 119 + 119: 120 + 120: 121 + 121: 122 + 122: 123 + 123: 1 + 124: 2 + 125: 3 + 126: 4 + 127: 5 + 128: 6 + 129: 7 + 130: 8 + 131: 9 + 132: 10 + 133: 11 + 134: 12 + 135: 13 + 136: 14 + 137: 15 + 138: 16 + 139: 17 + 140: 18 + 141: 19 + 142: 20 + 143: 21 + 144: 22 + 145: 23 + 146: 24 + 147: 25 + 148: 26 + 149: 27 + 150: 28 + 151: 29 + 152: 30 + 153: 31 + 154: 32 + 155: 33 + 156: 34 + 157: 35 + 158: 36 + 159: 37 + 160: 38 + 161: 39 + 162: 40 + 163: 41 + 164: 42 + 165: 43 + 166: 44 + 167: 45 + 168: 46 + 169: 47 + 170: 48 + 171: 49 + 172: 50 + 173: 51 + 174: 52 + 175: 53 + 176: 54 + 177: 55 + 178: 56 + 179: 57 + 180: 58 + 181: 59 + 182: 60 + 183: 61 + 184: 62 + 185: 63 + 186: 64 + 187: 65 + 188: 66 + 189: 67 + 190: 68 + 191: 69 + 192: 70 + 193: 71 + 194: 72 + 195: 73 + 196: 74 + 197: 75 + 198: 76 + 199: 77 + 200: 78 + 201: 79 + 202: 80 + 203: 81 + 204: 82 + 205: 83 + 206: 84 + 207: 85 + 208: 86 + 209: 87 + 210: 88 + 211: 89 + 212: 90 + 213: 91 + 214: 92 + 215: 93 + 216: 94 + 217: 95 + 218: 96 + 219: 97 + 220: 98 + 221: 99 + 222: 100 + 223: 101 + 224: 102 + 225: 103 + 226: 104 + 227: 105 + 228: 106 + 229: 107 + 230: 108 + 231: 109 + 232: 110 + 233: 111 + 234: 112 + 235: 113 + 236: 114 + 237: 115 + 238: 116 + 239: 117 + 240: 118 + 241: 119 + 242: 120 + 243: 121 + 244: 122 + 245: 123 + 246: 1 + 247: 2 + 248: 3 + 249: 4 diff --git a/akregator/src/mk4storage/metakit/tests/ok/r01.txt b/akregator/src/mk4storage/metakit/tests/ok/r01.txt new file mode 100644 index 000000000..092f02ca2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r01.txt @@ -0,0 +1,2 @@ +>>> Simple removes +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/r01a.txt b/akregator/src/mk4storage/metakit/tests/ok/r01a.txt new file mode 100644 index 000000000..65a6851c8 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r01a.txt @@ -0,0 +1,18 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 15 rows = p1:I + 0: 9 + 1: 10 + 2: 11 + 3: 12 + 4: 13 + 5: 14 + 6: 15 + 7: 16 + 8: 17 + 9: 18 + 10: 19 + 11: 20 + 12: 21 + 13: 22 + 14: 23 diff --git a/akregator/src/mk4storage/metakit/tests/ok/r02.txt b/akregator/src/mk4storage/metakit/tests/ok/r02.txt new file mode 100644 index 000000000..9f5b549a9 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r02.txt @@ -0,0 +1,2 @@ +>>> Large inserts and removes +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/r02a.txt b/akregator/src/mk4storage/metakit/tests/ok/r02a.txt new file mode 100644 index 000000000..c86766a9c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r02a.txt @@ -0,0 +1,8 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 5 rows = p1:I + 0: 37 + 1: 38 + 2: 39 + 3: 95 + 4: 96 diff --git a/akregator/src/mk4storage/metakit/tests/ok/r03.txt b/akregator/src/mk4storage/metakit/tests/ok/r03.txt new file mode 100644 index 000000000..34f35e910 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r03.txt @@ -0,0 +1,2 @@ +>>> Binary property insertions +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/r03a.txt b/akregator/src/mk4storage/metakit/tests/ok/r03a.txt new file mode 100644 index 000000000..a99e46af8 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r03a.txt @@ -0,0 +1,8 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 5 rows = p1:B + 0: (1024b) + 1: (256b) + 2: (1024b) + 3: (1024b) + 4: (341b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/r04.txt b/akregator/src/mk4storage/metakit/tests/ok/r04.txt new file mode 100644 index 000000000..60404b776 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r04.txt @@ -0,0 +1,2 @@ +>>> Scripted string property tests +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/r04a.txt b/akregator/src/mk4storage/metakit/tests/ok/r04a.txt new file mode 100644 index 000000000..88ad82637 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/r04a.txt @@ -0,0 +1,3 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 0 rows = p1:S diff --git a/akregator/src/mk4storage/metakit/tests/ok/reversed.txt b/akregator/src/mk4storage/metakit/tests/ok/reversed.txt new file mode 100644 index 000000000..59ba292d4 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/reversed.txt @@ -0,0 +1,14 @@ + VIEW 1 rows = address:V info:V + 0: subview 'address' + VIEW 8 rows = name:S country:S age:I + 0: 'John Williams' 'UK' 0 + 1: 'Paco Pena' 'Spain' 44 + 2: 'Julian Bream' '' 50 + 3: 'Julian Bream' '' 0 + 4: 'Julien Coco' 'Netherlands' 0 + 5: 'John Williams' 'UK' 0 + 6: 'Paco Pena' 'Spain' 0 + 7: 'Julien Coco' 'Netherlands' 0 + 0: subview 'info' + VIEW 1 rows = version:I + 0: 100 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s00.txt b/akregator/src/mk4storage/metakit/tests/ok/s00.txt new file mode 100644 index 000000000..24df9e24a --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s00.txt @@ -0,0 +1,2 @@ +>>> Simple storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s00a.txt b/akregator/src/mk4storage/metakit/tests/ok/s00a.txt new file mode 100644 index 000000000..0872f9361 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s00a.txt @@ -0,0 +1,3 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 0 rows = p1:I diff --git a/akregator/src/mk4storage/metakit/tests/ok/s01.txt b/akregator/src/mk4storage/metakit/tests/ok/s01.txt new file mode 100644 index 000000000..b5d474170 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s01.txt @@ -0,0 +1,2 @@ +>>> Integer storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s01a.txt b/akregator/src/mk4storage/metakit/tests/ok/s01a.txt new file mode 100644 index 000000000..b393bf251 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s01a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:I + 0: 123 + 1: 789 + 2: 456 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s02.txt b/akregator/src/mk4storage/metakit/tests/ok/s02.txt new file mode 100644 index 000000000..7ec87fa82 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s02.txt @@ -0,0 +1,2 @@ +>>> Float storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s02a.txt b/akregator/src/mk4storage/metakit/tests/ok/s02a.txt new file mode 100644 index 000000000..6a561a53e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s02a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:F + 0: 12.3 + 1: 78.9 + 2: 45.6 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s03.txt b/akregator/src/mk4storage/metakit/tests/ok/s03.txt new file mode 100644 index 000000000..307fb2a61 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s03.txt @@ -0,0 +1,2 @@ +>>> String storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s03a.txt b/akregator/src/mk4storage/metakit/tests/ok/s03a.txt new file mode 100644 index 000000000..83b694645 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s03a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:S + 0: 'one' + 1: 'three' + 2: 'two' diff --git a/akregator/src/mk4storage/metakit/tests/ok/s04.txt b/akregator/src/mk4storage/metakit/tests/ok/s04.txt new file mode 100644 index 000000000..2a6472b6f --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s04.txt @@ -0,0 +1,2 @@ +>>> View storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s04a.txt b/akregator/src/mk4storage/metakit/tests/ok/s04a.txt new file mode 100644 index 000000000..2b6800f31 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s04a.txt @@ -0,0 +1,18 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:S p2:V + 0: 'one' + 0: subview 'p2' + VIEW 1 rows = p3:I + 0: 1 + 1: 'three' + 1: subview 'p2' + VIEW 3 rows = p3:I + 0: 111 + 1: 222 + 2: 333 + 2: 'two' + 2: subview 'p2' + VIEW 2 rows = p3:I + 0: 11 + 1: 22 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s05.txt b/akregator/src/mk4storage/metakit/tests/ok/s05.txt new file mode 100644 index 000000000..625769c15 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s05.txt @@ -0,0 +1,2 @@ +>>> Store and reload +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s05a.txt b/akregator/src/mk4storage/metakit/tests/ok/s05a.txt new file mode 100644 index 000000000..fb8a3f195 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s05a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s06.txt b/akregator/src/mk4storage/metakit/tests/ok/s06.txt new file mode 100644 index 000000000..6246a4721 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s06.txt @@ -0,0 +1,2 @@ +>>> Commit twice +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s06a.txt b/akregator/src/mk4storage/metakit/tests/ok/s06a.txt new file mode 100644 index 000000000..5688100e0 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s06a.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 2 rows = p1:I + 0: 123 + 1: 234 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s07.txt b/akregator/src/mk4storage/metakit/tests/ok/s07.txt new file mode 100644 index 000000000..93559f6fe --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s07.txt @@ -0,0 +1,2 @@ +>>> Commit modified +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s07a.txt b/akregator/src/mk4storage/metakit/tests/ok/s07a.txt new file mode 100644 index 000000000..80140cf7f --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s07a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 234 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s08.txt b/akregator/src/mk4storage/metakit/tests/ok/s08.txt new file mode 100644 index 000000000..cd8f89711 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s08.txt @@ -0,0 +1,2 @@ +>>> View after storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s08a.txt b/akregator/src/mk4storage/metakit/tests/ok/s08a.txt new file mode 100644 index 000000000..fb8a3f195 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s08a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s09.txt b/akregator/src/mk4storage/metakit/tests/ok/s09.txt new file mode 100644 index 000000000..9599ae19e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s09.txt @@ -0,0 +1,2 @@ +>>> Copy storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s09a.txt b/akregator/src/mk4storage/metakit/tests/ok/s09a.txt new file mode 100644 index 000000000..fb8a3f195 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s09a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s09b.txt b/akregator/src/mk4storage/metakit/tests/ok/s09b.txt new file mode 100644 index 000000000..fb8a3f195 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s09b.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s10.txt b/akregator/src/mk4storage/metakit/tests/ok/s10.txt new file mode 100644 index 000000000..03f9bed9b --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s10.txt @@ -0,0 +1,2 @@ +>>> Stream storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s10a.txt b/akregator/src/mk4storage/metakit/tests/ok/s10a.txt new file mode 100644 index 000000000..2b6800f31 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s10a.txt @@ -0,0 +1,18 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:S p2:V + 0: 'one' + 0: subview 'p2' + VIEW 1 rows = p3:I + 0: 1 + 1: 'three' + 1: subview 'p2' + VIEW 3 rows = p3:I + 0: 111 + 1: 222 + 2: 333 + 2: 'two' + 2: subview 'p2' + VIEW 2 rows = p3:I + 0: 11 + 1: 22 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s10b.txt b/akregator/src/mk4storage/metakit/tests/ok/s10b.txt new file mode 100644 index 000000000..2b6800f31 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s10b.txt @@ -0,0 +1,18 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:S p2:V + 0: 'one' + 0: subview 'p2' + VIEW 1 rows = p3:I + 0: 1 + 1: 'three' + 1: subview 'p2' + VIEW 3 rows = p3:I + 0: 111 + 1: 222 + 2: 333 + 2: 'two' + 2: subview 'p2' + VIEW 2 rows = p3:I + 0: 11 + 1: 22 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s10c.txt b/akregator/src/mk4storage/metakit/tests/ok/s10c.txt new file mode 100644 index 000000000..bb34ca011 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s10c.txt @@ -0,0 +1,21 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 4 rows = p1:S p2:V + 0: 'one' + 0: subview 'p2' + VIEW 1 rows = p3:I + 0: 1 + 1: 'three' + 1: subview 'p2' + VIEW 3 rows = p3:I + 0: 111 + 1: 222 + 2: 333 + 2: 'two' + 2: subview 'p2' + VIEW 2 rows = p3:I + 0: 11 + 1: 22 + 3: 'four' + 3: subview 'p2' + VIEW 0 rows = p3:I diff --git a/akregator/src/mk4storage/metakit/tests/ok/s11.txt b/akregator/src/mk4storage/metakit/tests/ok/s11.txt new file mode 100644 index 000000000..fd82a1603 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s11.txt @@ -0,0 +1,2 @@ +>>> Commit and rollback +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s11a.txt b/akregator/src/mk4storage/metakit/tests/ok/s11a.txt new file mode 100644 index 000000000..fb8a3f195 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s11a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s12.txt b/akregator/src/mk4storage/metakit/tests/ok/s12.txt new file mode 100644 index 000000000..be9ca7a36 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s12.txt @@ -0,0 +1,2 @@ +>>> Remove subview +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s12a.txt b/akregator/src/mk4storage/metakit/tests/ok/s12a.txt new file mode 100644 index 000000000..9b6e95f0a --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s12a.txt @@ -0,0 +1,3 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 0 rows = p1:I p2:V diff --git a/akregator/src/mk4storage/metakit/tests/ok/s13.txt b/akregator/src/mk4storage/metakit/tests/ok/s13.txt new file mode 100644 index 000000000..112c33c70 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s13.txt @@ -0,0 +1,2 @@ +>>> Remove middle subview +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s13a.txt b/akregator/src/mk4storage/metakit/tests/ok/s13a.txt new file mode 100644 index 000000000..2189bb0a0 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s13a.txt @@ -0,0 +1,13 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 2 rows = p1:I p2:V + 0: 123 + 0: subview 'p2' + VIEW 1 rows = p3:I + 0: 234 + 1: 125 + 1: subview 'p2' + VIEW 3 rows = p3:I + 0: 456 + 1: 457 + 2: 458 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s14.txt b/akregator/src/mk4storage/metakit/tests/ok/s14.txt new file mode 100644 index 000000000..0e9348b04 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s14.txt @@ -0,0 +1,2 @@ +>>> Replace attached subview +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s14a.txt b/akregator/src/mk4storage/metakit/tests/ok/s14a.txt new file mode 100644 index 000000000..e87913c05 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s14a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I p2:V + 0: 0 + 0: subview 'p2' + VIEW 0 rows = p3:I diff --git a/akregator/src/mk4storage/metakit/tests/ok/s15.txt b/akregator/src/mk4storage/metakit/tests/ok/s15.txt new file mode 100644 index 000000000..305baef1a --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s15.txt @@ -0,0 +1,2 @@ +>>> Add after removed subviews +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s15a.txt b/akregator/src/mk4storage/metakit/tests/ok/s15a.txt new file mode 100644 index 000000000..9e07c88fe --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s15a.txt @@ -0,0 +1,7 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I p2:V + 0: 111 + 0: subview 'p2' + VIEW 1 rows = p3:I + 0: 234 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s16.txt b/akregator/src/mk4storage/metakit/tests/ok/s16.txt new file mode 100644 index 000000000..27c69ca10 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s16.txt @@ -0,0 +1,2 @@ +>>> Add after removed ints +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s16a.txt b/akregator/src/mk4storage/metakit/tests/ok/s16a.txt new file mode 100644 index 000000000..fd274ae0d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s16a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I p2:V + 0: 4 + 0: subview 'p2' + VIEW 0 rows = p3:I diff --git a/akregator/src/mk4storage/metakit/tests/ok/s17.txt b/akregator/src/mk4storage/metakit/tests/ok/s17.txt new file mode 100644 index 000000000..979139531 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s17.txt @@ -0,0 +1,2 @@ +>>> Add after removed strings +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s17a.txt b/akregator/src/mk4storage/metakit/tests/ok/s17a.txt new file mode 100644 index 000000000..40720e9d5 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s17a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:S p2:V + 0: 'four' + 0: subview 'p2' + VIEW 0 rows = p3:I diff --git a/akregator/src/mk4storage/metakit/tests/ok/s18.txt b/akregator/src/mk4storage/metakit/tests/ok/s18.txt new file mode 100644 index 000000000..5ff2d8e73 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s18.txt @@ -0,0 +1,2 @@ +>>> Empty storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s18a.txt b/akregator/src/mk4storage/metakit/tests/ok/s18a.txt new file mode 100644 index 000000000..a28a7cae2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s18a.txt @@ -0,0 +1 @@ + VIEW 1 rows = diff --git a/akregator/src/mk4storage/metakit/tests/ok/s19.txt b/akregator/src/mk4storage/metakit/tests/ok/s19.txt new file mode 100644 index 000000000..0a9ff3a17 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s19.txt @@ -0,0 +1,2 @@ +>>> Empty view outlives storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s19a.txt b/akregator/src/mk4storage/metakit/tests/ok/s19a.txt new file mode 100644 index 000000000..a28a7cae2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s19a.txt @@ -0,0 +1 @@ + VIEW 1 rows = diff --git a/akregator/src/mk4storage/metakit/tests/ok/s20.txt b/akregator/src/mk4storage/metakit/tests/ok/s20.txt new file mode 100644 index 000000000..5124a59e3 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s20.txt @@ -0,0 +1,2 @@ +>>> View outlives storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s20a.txt b/akregator/src/mk4storage/metakit/tests/ok/s20a.txt new file mode 100644 index 000000000..a28a7cae2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s20a.txt @@ -0,0 +1 @@ + VIEW 1 rows = diff --git a/akregator/src/mk4storage/metakit/tests/ok/s21.txt b/akregator/src/mk4storage/metakit/tests/ok/s21.txt new file mode 100644 index 000000000..4b944bf03 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s21.txt @@ -0,0 +1,2 @@ +>>> Test demo scenario +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s21a.txt b/akregator/src/mk4storage/metakit/tests/ok/s21a.txt new file mode 100644 index 000000000..2da5bab8b --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s21a.txt @@ -0,0 +1,10 @@ + VIEW 1 rows = a:V b:V + 0: subview 'a' + VIEW 4 rows = p1:S p2:S p3:I + 0: 'One' 'Un' 0 + 1: 'Two' 'Deux' 123 + 2: 'Four' '' 0 + 3: 'Three' 'Trois' 0 + 0: subview 'b' + VIEW 1 rows = p4:I + 0: 234 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s22.txt b/akregator/src/mk4storage/metakit/tests/ok/s22.txt new file mode 100644 index 000000000..8d5c2bc75 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s22.txt @@ -0,0 +1,2 @@ +>>> Double storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s22a.txt b/akregator/src/mk4storage/metakit/tests/ok/s22a.txt new file mode 100644 index 000000000..03d83cf6f --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s22a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:D + 0: 1234.5678 + 1: 3456.789 + 2: 2345.6789 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s23.txt b/akregator/src/mk4storage/metakit/tests/ok/s23.txt new file mode 100644 index 000000000..7f921bcf3 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s23.txt @@ -0,0 +1,2 @@ +>>> Find absent record +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s23a.txt b/akregator/src/mk4storage/metakit/tests/ok/s23a.txt new file mode 100644 index 000000000..a28a7cae2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s23a.txt @@ -0,0 +1 @@ + VIEW 1 rows = diff --git a/akregator/src/mk4storage/metakit/tests/ok/s24.txt b/akregator/src/mk4storage/metakit/tests/ok/s24.txt new file mode 100644 index 000000000..91ef101b2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s24.txt @@ -0,0 +1,2 @@ +>>> Bitwise storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s24a.txt b/akregator/src/mk4storage/metakit/tests/ok/s24a.txt new file mode 100644 index 000000000..37fc08320 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s24a.txt @@ -0,0 +1,45 @@ + VIEW 1 rows = a1:V a2:V a3:V a4:V + 0: subview 'a1' + VIEW 9 rows = p1:I + 0: 1 + 1: 0 + 2: 1 + 3: 0 + 4: 1 + 5: 0 + 6: 1 + 7: 0 + 8: 1 + 0: subview 'a2' + VIEW 9 rows = p1:I + 0: 3 + 1: 0 + 2: 1 + 3: 2 + 4: 3 + 5: 0 + 6: 1 + 7: 2 + 8: 3 + 0: subview 'a3' + VIEW 9 rows = p1:I + 0: 7 + 1: 8 + 2: 9 + 3: 10 + 4: 11 + 5: 12 + 6: 13 + 7: 14 + 8: 15 + 0: subview 'a4' + VIEW 9 rows = p1:I + 0: 119 + 1: 120 + 2: 121 + 3: 122 + 4: 123 + 5: 124 + 6: 125 + 7: 126 + 8: 127 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s25.txt b/akregator/src/mk4storage/metakit/tests/ok/s25.txt new file mode 100644 index 000000000..a9f5a3686 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s25.txt @@ -0,0 +1,2 @@ +>>> Bytes storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s25a.txt b/akregator/src/mk4storage/metakit/tests/ok/s25a.txt new file mode 100644 index 000000000..ced17ab22 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s25a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:B + 0: (2b) + 1: (4b) + 2: (5b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s26.txt b/akregator/src/mk4storage/metakit/tests/ok/s26.txt new file mode 100644 index 000000000..4496d6ee5 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s26.txt @@ -0,0 +1,2 @@ +>>> Bitwise autosizing +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s26a.txt b/akregator/src/mk4storage/metakit/tests/ok/s26a.txt new file mode 100644 index 000000000..2b644a8e8 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s26a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I p2:I p3:I p4:I + 0: 100000 100000 100000 100000 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s27.txt b/akregator/src/mk4storage/metakit/tests/ok/s27.txt new file mode 100644 index 000000000..d35484ead --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s27.txt @@ -0,0 +1,2 @@ +>>> Bytes restructuring +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s27a.txt b/akregator/src/mk4storage/metakit/tests/ok/s27a.txt new file mode 100644 index 000000000..c39554b1e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s27a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:B + 0: (4b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s28.txt b/akregator/src/mk4storage/metakit/tests/ok/s28.txt new file mode 100644 index 000000000..4e7e1a167 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s28.txt @@ -0,0 +1,2 @@ +>>> Doubles added later +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s28a.txt b/akregator/src/mk4storage/metakit/tests/ok/s28a.txt new file mode 100644 index 000000000..a731a6a3c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s28a.txt @@ -0,0 +1,7 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:F p2:D p3:V + 0: 123 123 + 0: subview 'p3' + VIEW 1 rows = p1:F p2:D + 0: 234 234 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s29.txt b/akregator/src/mk4storage/metakit/tests/ok/s29.txt new file mode 100644 index 000000000..982807abc --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s29.txt @@ -0,0 +1,2 @@ +>>> Delete bytes property +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s29a.txt b/akregator/src/mk4storage/metakit/tests/ok/s29a.txt new file mode 100644 index 000000000..36e2113bd --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s29a.txt @@ -0,0 +1,3 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 0 rows = p1:B diff --git a/akregator/src/mk4storage/metakit/tests/ok/s30.txt b/akregator/src/mk4storage/metakit/tests/ok/s30.txt new file mode 100644 index 000000000..e86ceee7c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s30.txt @@ -0,0 +1,2 @@ +>>> Memo storage +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s30a.txt b/akregator/src/mk4storage/metakit/tests/ok/s30a.txt new file mode 100644 index 000000000..ced17ab22 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s30a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:B + 0: (2b) + 1: (4b) + 2: (5b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s31.txt b/akregator/src/mk4storage/metakit/tests/ok/s31.txt new file mode 100644 index 000000000..661077237 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s31.txt @@ -0,0 +1,2 @@ +>>> Check sort buffer use +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s31a.txt b/akregator/src/mk4storage/metakit/tests/ok/s31a.txt new file mode 100644 index 000000000..bb0beb13e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s31a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:I + 0: 3 + 1: 1 + 2: 2 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s32.txt b/akregator/src/mk4storage/metakit/tests/ok/s32.txt new file mode 100644 index 000000000..342f61ddb --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s32.txt @@ -0,0 +1,2 @@ +>>> Set memo empty or same size +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s32a.txt b/akregator/src/mk4storage/metakit/tests/ok/s32a.txt new file mode 100644 index 000000000..c39554b1e --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s32a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:B + 0: (4b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s33.txt b/akregator/src/mk4storage/metakit/tests/ok/s33.txt new file mode 100644 index 000000000..749e7d37c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s33.txt @@ -0,0 +1,2 @@ +>>> Serialize memo fields +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s33a.txt b/akregator/src/mk4storage/metakit/tests/ok/s33a.txt new file mode 100644 index 000000000..ced17ab22 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s33a.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:B + 0: (2b) + 1: (4b) + 2: (5b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s33b.txt b/akregator/src/mk4storage/metakit/tests/ok/s33b.txt new file mode 100644 index 000000000..ced17ab22 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s33b.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:B + 0: (2b) + 1: (4b) + 2: (5b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s33c.txt b/akregator/src/mk4storage/metakit/tests/ok/s33c.txt new file mode 100644 index 000000000..ced17ab22 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s33c.txt @@ -0,0 +1,6 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 3 rows = p1:B + 0: (2b) + 1: (4b) + 2: (5b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s34.txt b/akregator/src/mk4storage/metakit/tests/ok/s34.txt new file mode 100644 index 000000000..63a225ef2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s34.txt @@ -0,0 +1,2 @@ +>>> Smart and failed commits +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s34a.txt b/akregator/src/mk4storage/metakit/tests/ok/s34a.txt new file mode 100644 index 000000000..81e1847d2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s34a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 111 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s35.txt b/akregator/src/mk4storage/metakit/tests/ok/s35.txt new file mode 100644 index 000000000..18835d389 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s35.txt @@ -0,0 +1,2 @@ +>>> Datafile with preamble +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s35a.txt b/akregator/src/mk4storage/metakit/tests/ok/s35a.txt new file mode 100644 index 000000000..81e1847d2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s35a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 111 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s36.txt b/akregator/src/mk4storage/metakit/tests/ok/s36.txt new file mode 100644 index 000000000..63d15af21 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s36.txt @@ -0,0 +1,2 @@ +>>> Commit after load +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s36a.txt b/akregator/src/mk4storage/metakit/tests/ok/s36a.txt new file mode 100644 index 000000000..81e1847d2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s36a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 111 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s36b.txt b/akregator/src/mk4storage/metakit/tests/ok/s36b.txt new file mode 100644 index 000000000..81e1847d2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s36b.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 111 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s37.txt b/akregator/src/mk4storage/metakit/tests/ok/s37.txt new file mode 100644 index 000000000..8bf5f8b73 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s37.txt @@ -0,0 +1,2 @@ +>>> Change short partial fields +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s37a.txt b/akregator/src/mk4storage/metakit/tests/ok/s37a.txt new file mode 100644 index 000000000..21eab9c9d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s37a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = v1:V + 0: subview 'v1' + VIEW 1 rows = key:I p1:B + 0: 0 (6b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s38.txt b/akregator/src/mk4storage/metakit/tests/ok/s38.txt new file mode 100644 index 000000000..acd0b2019 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s38.txt @@ -0,0 +1,2 @@ +>>> Lots of empty subviews +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s38a.txt b/akregator/src/mk4storage/metakit/tests/ok/s38a.txt new file mode 100644 index 000000000..8ee8c3471 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s38a.txt @@ -0,0 +1,7 @@ + VIEW 1 rows = v:V + 0: subview 'v' + VIEW 2 rows = v1:V + 0: subview 'v1' + VIEW 0 rows = p1:S + 1: subview 'v1' + VIEW 0 rows = p1:S diff --git a/akregator/src/mk4storage/metakit/tests/ok/s39.txt b/akregator/src/mk4storage/metakit/tests/ok/s39.txt new file mode 100644 index 000000000..a907f11e6 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s39.txt @@ -0,0 +1,2 @@ +>>> Do not detach empty top-level views +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s39a.txt b/akregator/src/mk4storage/metakit/tests/ok/s39a.txt new file mode 100644 index 000000000..7799a2713 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s39a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = v1:V + 0: subview 'v1' + VIEW 1 rows = p1:I + 0: 123 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s40.txt b/akregator/src/mk4storage/metakit/tests/ok/s40.txt new file mode 100644 index 000000000..b799ff95c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s40.txt @@ -0,0 +1,2 @@ +>>> LoadFrom after commit +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s40a.txt b/akregator/src/mk4storage/metakit/tests/ok/s40a.txt new file mode 100644 index 000000000..d256fc735 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s40a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I + 0: 456 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s41.txt b/akregator/src/mk4storage/metakit/tests/ok/s41.txt new file mode 100644 index 000000000..419edbad8 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s41.txt @@ -0,0 +1,2 @@ +>>> Partial modify blocked +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s41a.txt b/akregator/src/mk4storage/metakit/tests/ok/s41a.txt new file mode 100644 index 000000000..51bc32d70 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s41a.txt @@ -0,0 +1,8 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 2 rows = _B:V + 0: subview '_B' + VIEW 1 rows = p1:B + 0: (8b) + 1: subview '_B' + VIEW 0 rows = p1:B diff --git a/akregator/src/mk4storage/metakit/tests/ok/s42.txt b/akregator/src/mk4storage/metakit/tests/ok/s42.txt new file mode 100644 index 000000000..61c83f2aa --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s42.txt @@ -0,0 +1,2 @@ +>>> Get descriptions +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s43.txt b/akregator/src/mk4storage/metakit/tests/ok/s43.txt new file mode 100644 index 000000000..af2b07123 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s43.txt @@ -0,0 +1,2 @@ +>>> View reuse after sub-byte ints +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s43a.txt b/akregator/src/mk4storage/metakit/tests/ok/s43a.txt new file mode 100644 index 000000000..df0a22ecb --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s43a.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 2 rows = p1:I + 0: 0 + 1: 12345 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s44.txt b/akregator/src/mk4storage/metakit/tests/ok/s44.txt new file mode 100644 index 000000000..640461805 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s44.txt @@ -0,0 +1,2 @@ +>>> Bad memo free space +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s44a.txt b/akregator/src/mk4storage/metakit/tests/ok/s44a.txt new file mode 100644 index 000000000..02b49b500 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s44a.txt @@ -0,0 +1,4 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I p2:B + 0: 0 (12345b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s45.txt b/akregator/src/mk4storage/metakit/tests/ok/s45.txt new file mode 100644 index 000000000..066826a49 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s45.txt @@ -0,0 +1,2 @@ +>>> Bad subview memo free space +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s45a.txt b/akregator/src/mk4storage/metakit/tests/ok/s45a.txt new file mode 100644 index 000000000..920e28eed --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s45a.txt @@ -0,0 +1,7 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 1 rows = p1:I p2:V + 0: 0 + 0: subview 'p2' + VIEW 1 rows = p3:B + 0: (12345b) diff --git a/akregator/src/mk4storage/metakit/tests/ok/s46.txt b/akregator/src/mk4storage/metakit/tests/ok/s46.txt new file mode 100644 index 000000000..b799ff95c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s46.txt @@ -0,0 +1,2 @@ +>>> LoadFrom after commit +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s46a.txt b/akregator/src/mk4storage/metakit/tests/ok/s46a.txt new file mode 100644 index 000000000..9fa04509b --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s46a.txt @@ -0,0 +1,15 @@ + VIEW 1 rows = a:V + 0: subview 'a' + VIEW 12 rows = p1:I + 0: 11 + 1: 22 + 2: 33 + 3: 44 + 4: 0 + 5: 55 + 6: 66 + 7: 77 + 8: 0 + 9: 88 + 10: 99 + 11: 1000 diff --git a/akregator/src/mk4storage/metakit/tests/ok/s47.txt b/akregator/src/mk4storage/metakit/tests/ok/s47.txt new file mode 100644 index 000000000..55827d04d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s47.txt @@ -0,0 +1,2 @@ +>>> Defining bad property type +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s48.txt b/akregator/src/mk4storage/metakit/tests/ok/s48.txt new file mode 100644 index 000000000..28fdd3a5c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s48.txt @@ -0,0 +1,2 @@ +>>> Resize subview to zero and back +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s48a.txt b/akregator/src/mk4storage/metakit/tests/ok/s48a.txt new file mode 100644 index 000000000..5e398789c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s48a.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = v1:V + 0: subview 'v1' + VIEW 1 rows = v2:V + 0: subview 'v2' + VIEW 0 rows = p1:I diff --git a/akregator/src/mk4storage/metakit/tests/ok/s48b.txt b/akregator/src/mk4storage/metakit/tests/ok/s48b.txt new file mode 100644 index 000000000..5e398789c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s48b.txt @@ -0,0 +1,5 @@ + VIEW 1 rows = v1:V + 0: subview 'v1' + VIEW 1 rows = v2:V + 0: subview 'v2' + VIEW 0 rows = p1:I diff --git a/akregator/src/mk4storage/metakit/tests/ok/s49.txt b/akregator/src/mk4storage/metakit/tests/ok/s49.txt new file mode 100644 index 000000000..b32d7ff00 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s49.txt @@ -0,0 +1,2 @@ +>>> Specify conflicting properties +<<< done. diff --git a/akregator/src/mk4storage/metakit/tests/ok/s49a.txt b/akregator/src/mk4storage/metakit/tests/ok/s49a.txt new file mode 100644 index 000000000..992724c50 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/ok/s49a.txt @@ -0,0 +1,7 @@ + VIEW 1 rows = v1:V v2:V v3:V + 0: subview 'v1' + VIEW 0 rows = p1:I + 0: subview 'v2' + VIEW 0 rows = p1:I + 0: subview 'v3' + VIEW 0 rows = v3:V diff --git a/akregator/src/mk4storage/metakit/tests/regress.cpp b/akregator/src/mk4storage/metakit/tests/regress.cpp new file mode 100644 index 000000000..0725f57f5 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/regress.cpp @@ -0,0 +1,269 @@ +// regress.cpp -- Regression test program, main code +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +#include "regress.h" + +#if defined (macintosh) + #include <SIOUX.h> + #ifdef DEBUG_NEW + #include <DebugNew.cp> + //#include "ZoneRanger.c" + #if DEBUG_NEW >= 2 && !defined (q4_MAC_LEAK_CHECK) + #define q4_MAC_LEAK_CHECK 1 + #endif + #endif +#endif + +#if __profile__ + #define q4_MWCW_PROFILER 1 + #include <profiler.h> +#endif + +#if q4_NOTHROW + const char* msg; +#endif + +#if _WIN32_WCE + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +int remove(const char* fn_) +{ + c4_Bytes buffer; + int n = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, fn_, -1, NULL, 0); + wchar_t* w = (wchar_t*) buffer.SetBufferClear((n+1) * sizeof (wchar_t)); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, fn_, -1, w, n); + return DeleteFile((wchar_t*) buffer.Contents()) ? 0 : -1; +} + +#endif + +int +#if _WIN32_WCE +_cdecl +#endif +main() +{ +// afxMemDF |= allocMemDF | checkAlwaysMemDF; + + // The M4STRING package sometimes keeps a spare empty string around. + // By allocating it here, we avoid a few bogus memory leak reports. + c4_String empty; + + #if q4_MAC_LEAK_CHECK + DebugNewForgetLeaks(); + #endif + +#if q4_MWCW_PROFILER + if (!ProfilerInit(collectDetailed, bestTimeBase, 20, 5)) + { +#endif + TestBasics1(); + TestBasics2(); + TestNotify(); + TestCustom1(); + TestCustom2(); + TestResize(); + TestStores1(); + TestStores2(); + TestStores3(); + TestStores4(); + TestStores5(); + TestDiffer(); + TestExtend(); + TestFormat(); + TestMapped(); + TestLimits(); + +#if q4_MWCW_PROFILER + ProfilerDump("\pRegress.prof"); + ProfilerTerm(); + } +#endif + + #if defined (_DEBUG) + fputs("\nPress return... ", stderr); + getchar(); + #endif + #if q4_MAC_LEAK_CHECK + if (DebugNewReportLeaks()) + fputs(" *** Memory leaks found ***\n", stderr); + #endif + #if defined (macintosh) + SIOUXSettings.asktosaveonclose = false; + #endif + + fputs("Done.\n", stderr); + return 0; +} + +// Recursively display the entire view contents. The results shown do not +// depend on file layout (free space, file positions, flat vs. on-demand). + +static void ViewDisplay(const c4_View& v_, FILE* fp, int l_ =0) +{ + c4_String types; + bool hasData = false, hasSubs = false; + + // display header info and collect all data types + fprintf(fp, "%*s VIEW %5d rows =", l_, "", v_.GetSize()); + for (int n = 0; n < v_.NumProperties(); ++n) + { + c4_Property prop = v_.NthProperty(n); + char t = prop.Type(); + + fprintf(fp, " %s:%c", (const char*) prop.Name(), t); + + types += t; + + if (t == 'V') + hasSubs = true; + else + hasData = true; + } + fprintf(fp, "\n"); + + for (int j = 0; j < v_.GetSize(); ++j) + { + if (hasData) // data properties are all shown on the same line + { + fprintf(fp, "%*s %4d:", l_, "", j); + c4_RowRef r = v_[j]; + + for (int k = 0; k < types.GetLength(); ++k) + { + c4_Property p = v_.NthProperty(k); + + switch (types[k]) + { + case 'I': + fprintf(fp, " %ld", (long) ((c4_IntProp&) p) (r)); + break; + +#if !q4_TINY + case 'F': + fprintf(fp, " %g", (double) ((c4_FloatProp&) p) (r)); + break; + + case 'D': + fprintf(fp, " %.12g", (double) ((c4_DoubleProp&) p) (r)); + break; +#endif + + case 'S': + fprintf(fp, " '%s'", (const char*) ((c4_StringProp&) p) (r)); + break; + + case 'M': // backward compatibility + case 'B': + fprintf(fp, " (%db)", (p (r)).GetSize()); + break; + + default: + if (types[k] != 'V') + fprintf(fp, " (%c?)", types[k]); + } + } + + fprintf(fp, "\n"); + } + + if (hasSubs) // subviews are then shown, each as a separate block + { + for (int k = 0; k < types.GetLength(); ++k) + { + if (types[k] == 'V') + { + c4_Property prop = v_.NthProperty(k); + + fprintf(fp, "%*s %4d: subview '%s'\n", l_, "", j, + (const char*) prop.Name()); + + c4_ViewProp& vp = (c4_ViewProp&) prop; + + ViewDisplay(vp (v_[j]), fp, l_ + 2); + } + } + } + } +} + +void DumpFile(const char* in_, const char* out_) +{ + FILE* fp = fopen(out_, TEXTOUT); + A(fp); + + c4_Storage store (in_, 0); + + ViewDisplay(store, fp); + + fclose(fp); +} + +void Fail(const char* msg) +{ + #if q4_NOTHROW + fprintf(stderr, "\t%s\n", msg); + printf("*** %s ***\n", msg); + #else + throw msg; + #endif +} + +void FailExpr(const char* expr) +{ + char buffer [100]; + sprintf(buffer, "Failed: A(%s)", expr); + Fail(buffer); +} + +int StartTest(int mask_, const char* name_, const char* desc_) +{ + if (mask_) + { + #if q4_MFC && defined(_DEBUG) + TRACE("%s - %-40s *** DISABLED ***\n", name_, desc_); + #endif + #if !q4_MWCW_PROFILER + fprintf(stderr, "%s - %-40s *** DISABLED ***\n", name_, desc_); + #endif + return false; + } + + #if q4_MFC && defined(_DEBUG) + TRACE("%s - %s\n", name_, desc_); + #endif + #if !q4_MWCW_PROFILER + fprintf(stderr, "%s - %s\n", name_, desc_); + #endif + + char buffer [50]; + sprintf(buffer, "%s%s.txt", TESTDIR, name_); + #if _WIN32_WCE + fclose(stdout); + fopen(buffer, TEXTOUT); + #else + freopen(buffer, TEXTOUT, stdout); + #endif + printf(">>> %s\n", desc_); + + return true; +} + +void CatchMsg(const char* msg) +{ + #if !q4_MWCW_PROFILER + fprintf(stderr, "\t%s\n", msg); + #endif + printf("*** %s ***\n", msg); +} + +void CatchOther() +{ + #if !q4_MWCW_PROFILER + fputs("\tException!\n", stderr); + #endif + printf("*** Exception ***\n"); +} diff --git a/akregator/src/mk4storage/metakit/tests/regress.h b/akregator/src/mk4storage/metakit/tests/regress.h new file mode 100644 index 000000000..f317bcb26 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/regress.h @@ -0,0 +1,145 @@ +// regress.h -- Regression test program, header file +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +#include "mk4.h" +#include "mk4io.h" +#include "mk4str.h" + +#define TraceAll false + + // default for dos and unix is to assume they don't support exceptions +#if defined (_DOS) || defined (unix) || defined (__unix__) || \ + defined (__GNUC__) || defined (_WIN32_WCE) +#if !defined (q4_NOTHROW) +#define q4_NOTHROW 1 +#endif +#endif + +#ifdef _WIN32_WCE +int remove(const char*); +#endif + +#if _MSC_VER == 800 +#pragma warning (disable: 4703) // function too large for global optimizations + +// also no exceptions in MSVC 1.52 when used with a QuickWin target +#if defined (_QWINVER) && !defined (q4_NOTHROW) +#define q4_NOTHROW 1 +#endif +#endif + +#if q4_NOTHROW +#define try +#define catch(x) if (0) + +extern const char* msg; +#endif + +#if defined (macintosh) +#define TESTDIR ":tests:" +#define TEXTOUT "wt" +#define LINESEP "\r" +#elif defined (__VMS) +#define TESTDIR "[.tests]" +#define TEXTOUT "w" +#define LINESEP "\r\n" // is this correct? +#elif defined (unix) || defined (__unix__) || defined (__GNUC__) +#define TESTDIR "tests/" +#define TEXTOUT "w" +#define LINESEP "\n" +#else +#define TESTDIR "tests\\" +#define TEXTOUT "wt" +#define LINESEP "\r\n" +#endif + +#include <stdio.h> + +#if q4_MFC && defined(_DEBUG) +#define B(n_,d_,c_) \ + if (StartTest(c_, #n_, #d_)) \ + { \ + CMemoryState oldState, newState, diffState; \ + oldState.Checkpoint(); \ + afxTraceEnabled = TraceAll; \ + try \ + { \ + { +#define E \ + } \ + puts("<<< done."); \ + } \ + catch (const char* msg) { CatchMsg(msg); } \ + catch (...) { CatchOther(); } \ + afxTraceEnabled = true; \ + fflush(stdout); \ + newState.Checkpoint(); \ + if (diffState.Difference(oldState, newState)) \ + { \ + fputs("\tMemory leaked!\n", stderr); \ + puts("*** Memory leaked ***"); \ + TRACE(" *** Memory leaked, "); \ + diffState.DumpAllObjectsSince(); \ + } \ + fflush(stdout); \ + } +#else +#define B(n_,d_,c_) \ + if (StartTest(c_, #n_, #d_)) \ + { \ + try \ + { \ + { +#define E \ + } \ + puts("<<< done."); \ + } \ + catch (const char* msg) { CatchMsg(msg); } \ + catch (...) { CatchOther(); } \ + fflush(stdout); \ + } +#endif + +#define A(e_) if (e_) ; else FailExpr(#e_) + +#define W(f_) remove(#f_) +#define R(f_) A(remove(#f_) == 0) +#define D(f_) DumpFile(#f_, TESTDIR #f_ ".txt") + +typedef c4_BytesProp c4_MemoProp; + +extern void DumpFile(const char* in_, const char* out_); +extern void Fail(const char* msg); +extern void FailExpr(const char* expr); +extern int StartTest(int, const char*, const char*); +extern void CatchMsg(const char* msg); +extern void CatchOther(); + +extern void TestBasics1(); +extern void TestBasics2(); +extern void TestCustom1(); +extern void TestCustom2(); +extern void TestDiffer(); +extern void TestExtend(); +extern void TestFormat(); +extern void TestLimits(); +extern void TestMapped(); +extern void TestNotify(); +extern void TestResize(); +extern void TestStores1(); +extern void TestStores2(); +extern void TestStores3(); +extern void TestStores4(); +extern void TestStores5(); + + // The Borland C++ RTL does not want file handle objects to cross + // DLL boundaries, so we use special fopen/fclose hooks in the DLL. + +#if defined (__BORLANDC__) // this assumes Metakit is in a DLL! +extern FILE* f4_FileOpenInDLL(const char*, const char*); +extern int f4_FileCloseInDLL(FILE*); + +#define fopen f4_FileOpenInDLL +#define fclose f4_FileCloseInDLL +#endif diff --git a/akregator/src/mk4storage/metakit/tests/tbasic1.cpp b/akregator/src/mk4storage/metakit/tests/tbasic1.cpp new file mode 100644 index 000000000..0c5742a25 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tbasic1.cpp @@ -0,0 +1,268 @@ +// tbasic1.cpp -- Regression test program, basic tests part 1 +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestBasics1() +{ + B(b00, Should fail, 0) + { + A(false); + } E; + + B(b01, Should succeed, 0) + { + A(sizeof (t4_byte) == 1); + A(sizeof (short) == 2); + A(sizeof (t4_i32) == 4); + A(sizeof (float) == 4); + A(sizeof (double) == 8); + } E; + + B(b02, Int property, 0) + { + c4_Row r1; + c4_IntProp p1 ("p1"); + p1 (r1) = 1234567890L; + long x1 = p1 (r1); + A(x1 == 1234567890L); + } E; + +#if !q4_TINY + B(b03, Float property, 0) + { + c4_Row r1; + c4_FloatProp p1 ("p1"); + p1 (r1) = 123.456; + double x1 = p1 (r1); + A((float) x1 == (float) 123.456); + } E; +#endif + + B(b04, String property, 0) + { + c4_Row r1; + c4_StringProp p1 ("p1"); + p1 (r1) = "abc"; + const char* x1 = p1 (r1); + A((c4_String) x1 == "abc"); + } E; + + B(b05, View property, 0) + { + c4_View v1; + c4_Row r1; + c4_ViewProp p1 ("p1"); + p1 (r1) = v1; + c4_View x1 = p1 (r1); + // compare cursors to make sure this is the same sequence + A(x1[0] == v1[0]); + } E; + + B(b06, View construction, 0) + { + c4_IntProp p1 ("p1"), p2 ("p2"), p3 ("p3"); + c4_View v1 = (p1, p3, p2); + A(v1.FindProperty(p1.GetId()) == 0); + A(v1.FindProperty(p2.GetId()) == 2); + A(v1.FindProperty(p3.GetId()) == 1); + } E; + + B(b07, Row manipulation, 0) + { + c4_StringProp p1 ("p1"), p2 ("p2"); + c4_IntProp p3 ("p3"); + c4_Row r1; + p1 (r1) = "look at this" ; + const char* x1 = p1 (r1); + A(x1 == (c4_String) "look at this"); + r1 = p1 [ "what's in a" ] + p2 [ "name..." ]; + c4_String t = (const char*) p2 (r1); + p1 (r1) = t + (const char*) (p1 (r1)); + p2 (r1) = p1 (r1); + c4_String x2 = (const char*) p1 (r1); // 2000-03-16, store as c4_String + A(x2 == "name...what's in a"); + // the above change avoids an evaluation order issue in assert below + A(x2 == p2 (r1)); + p3 (r1) = 12345; + p3 (r1) = p3 (r1) + 123; + int x3 = p3 (r1); + A(x3 == 12345 + 123); + } E; + + B(b08, Row expressions, 0) + { + c4_StringProp p1 ("p1"), p2 ("p2"); + c4_IntProp p3 ("p3"); + c4_Row r1; + c4_View v1 = (p1, p2, p3); + v1.SetSize(5); + r1 = v1[1]; + v1[2] = v1[1]; + v1[3] = r1; + v1[4] = v1[4]; + r1 = r1; + } E; + + B(b09, View manipulation, 0) + { + c4_StringProp p1 ("p1"), p2 ("p2"); + c4_Row r1 = p1 ["One"] + p2 ["Two"]; + c4_Row r2; + c4_View v1; + v1.Add(r1); + v1.Add(r2); + v1.Add(r1); + A(v1.GetSize() == 3); + A(v1[0] == r1); + A(v1[1] == r2); + A(v1[2] == r1); + v1.RemoveAt(1, 1); + A(v1.GetSize() == 2); + A(v1[0] == r1); + A(v1[0] == v1[1]); + } E; + + B(b10, View sorting, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + v1.Add(p1 [345]); + v1.Add(p1 [234]); + v1.Add(p1 [123]); + c4_View v2 = v1.Sort(); + A(v2.GetSize() == 6); + A(p1 (v2[0]) == 111); + A(p1 (v2[1]) == 123); + A(p1 (v2[2]) == 222); + A(p1 (v2[3]) == 234); + A(p1 (v2[4]) == 333); + A(p1 (v2[5]) == 345); + } E; + + B(b11, View selection, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + v1.Add(p1 [345]); + v1.Add(p1 [234]); + v1.Add(p1 [123]); + c4_View v2 = v1.SelectRange(p1 [200], p1 [333]); + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + } E; + + B(b12, Add after remove, 0) + { + c4_StringProp p1 ("p1"); + c4_View v1; + v1.Add(p1 ["abc"]); + A(v1.GetSize() == 1); + v1.RemoveAt(0); + A(v1.GetSize() == 0); + v1.Add(p1 ["def"]); + A(v1.GetSize() == 1); + } E; + + B(b13, Clear view entry, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + + v1.Add(p1 [123]); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + + v1[0] = c4_Row (); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 0); + } E; + + B(b14, Empty view outlives temp storage, 0) + { + c4_View v1; + c4_Storage s1; + v1 = s1.GetAs("a[p1:I,p2:S]"); + } E; + + B(b15, View outlives temp storage, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + + { + c4_Storage s1; + v1 = s1.GetAs("a[p1:I,p2:S]"); + v1.Add(p1 [123]); + } + + // 19990916 - semantics changed, view now 1 row, but 0 props + A(v1.GetSize() == 1); + A(v1.NumProperties() == 0); + //A(p1 (v1[0]) == 123); + } E; + + B(b16, View outlives cleared temp storage, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + + { + c4_Storage s1; + v1 = s1.GetAs("a[p1:I,p2:S]"); + v1.Add(p1 [123]); + v1.RemoveAll(); + } + + A(v1.GetSize() == 0); + v1.Add(p1 [123]); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + } E; + +#if !q4_TINY + B(b17, Double property, 0) + { + c4_Row r1; + c4_DoubleProp p1 ("p1"); + p1 (r1) = 1234.5678; + double x1 = p1 (r1); + A(x1 == (double) 1234.5678); + } E; +#endif + + B(b18, SetAtGrow usage, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + + v1.SetAtGrow(3, p1 [333]); + v1.SetAtGrow(1, p1 [111]); + v1.SetAtGrow(5, p1 [555]); + + A(v1.GetSize() == 6); + A(p1 (v1[1]) == 111); + A(p1 (v1[3]) == 333); + A(p1 (v1[5]) == 555); + } E; + + B(b19, Bytes property, 0) + { + c4_Row r1; + c4_BytesProp p1 ("p1"); + c4_Bytes x1 ("hi!", 3); + + p1 (r1) = x1; + c4_Bytes x2 = p1 (r1); + A(x1 == x2); + } E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tbasic2.cpp b/akregator/src/mk4storage/metakit/tests/tbasic2.cpp new file mode 100644 index 000000000..53c6b307f --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tbasic2.cpp @@ -0,0 +1,218 @@ +// tbasic2.cpp -- Regression test program, basic tests part 2 +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +#include "regress.h" + + static int ViewSize(c4_View v) + { + return v.GetSize(); + } + +void TestBasics2() +{ + B(b20, Search sorted view, 0) + { + c4_IntProp p1 ("p1"); + c4_StringProp p2 ("p2"); + c4_View v1; + v1.Add(p1 [111] + p2 ["one"]); + v1.Add(p1 [222] + p2 ["two"]); + v1.Add(p1 [333] + p2 ["three"]); + v1.Add(p1 [345] + p2 ["four"]); + v1.Add(p1 [234] + p2 ["five"]); + v1.Add(p1 [123] + p2 ["six"]); + c4_View v2 = v1.Sort(); + A(v2.GetSize() == 6); + A(p1 (v2[0]) == 111); + A(p1 (v2[1]) == 123); + A(p1 (v2[2]) == 222); + A(p1 (v2[3]) == 234); + A(p1 (v2[4]) == 333); + A(p1 (v2[5]) == 345); + A(v2.Search(p1 [123]) == 1); + A(v2.Search(p1 [100]) == 0); + A(v2.Search(p1 [200]) == 2); + A(v2.Search(p1 [400]) == 6); + c4_View v3 = v1.SortOn(p2); + A(v3.GetSize() == 6); + A(p1 (v3[0]) == 234); + A(p1 (v3[1]) == 345); + A(p1 (v3[2]) == 111); + A(p1 (v3[3]) == 123); + A(p1 (v3[4]) == 333); + A(p1 (v3[5]) == 222); + A(v3.Search(p2 ["six"]) == 3); + A(v3.Search(p2 ["aha"]) == 0); + A(v3.Search(p2 ["gee"]) == 2); + A(v3.Search(p2 ["wow"]) == 6); + c4_View v4 = v1.SortOnReverse(p2, p2); + A(v4.GetSize() == 6); + A(p1 (v4[0]) == 222); + A(p1 (v4[1]) == 333); + A(p1 (v4[2]) == 123); + A(p1 (v4[3]) == 111); + A(p1 (v4[4]) == 345); + A(p1 (v4[5]) == 234); + A(v4.Search(p2 ["six"]) == 2); + A(v4.Search(p2 ["aha"]) == 6); + A(v4.Search(p2 ["gee"]) == 4); + A(v4.Search(p2 ["wow"]) == 0); + } E; + + B(b21, Memo property, 0) + { + c4_Row r1; + c4_MemoProp p1 ("p1"); + c4_Bytes x1 ("hi!", 3); + + p1 (r1) = x1; + c4_Bytes x2 = p1 (r1); + A(x1 == x2); + } E; + + B(b22, Stored view references, 0) + { + c4_ViewProp p1 ("p1"); + c4_View v1; + + { + v1.Add(p1 [c4_View ()]); + } + + // this works + int n = ViewSize(p1.Get(v1[0])); + A(n == 0); + + // this fails in 1.8b2 using MSVC 1.52 (tq_wvus) + // + // The compiler destructs temp c4_View once too often, or + // what's more likely, fails to call the constructor once. + // + // So for MSVC 1.52: use prop.Get(rowref) for subviews, + // or immediately assign the result to a c4_View object, + // do not pass a "prop (rowref)" expression as argument. + +#if _MSC_VER != 800 + int m = ViewSize(p1 (v1[0])); + A(m == 0); +#endif + } E; + + B(b23, Sort comparison fix, 0) // 1.9e: compare buffering problem + { + c4_DoubleProp p1 ("p1"); + c4_View v1; + for (int i = 0; i < 100; ++i) + v1.Add(p1 [99-i]); + c4_View v2 = v1.Sort(); + A(v2.GetSize() == 100); + for (int j = 0; j < 100; ++j) + { + A(p1 (v1[j]) == (double) 99-j); + A(p1 (v2[j]) == (double) j); + } + } E; + + B(b24, Custom view comparisons, 0) // 1.9f: more compare cache problems + { + c4_IntProp p1 ("p1"); + c4_FloatProp p2 ("p2"); + c4_DoubleProp p3 ("p3"); + c4_IntProp p4 ("p4"); + c4_View v1; + v1.Add(p1 [2] + p2 [2] + p3 [2]); + v1.Add(p1 [1] + p2 [1] + p3 [1]); + v1.Add(p1 [3] + p2 [3] + p3 [3]); + A(v1.GetSize() == 3); + A((int) p1 (v1[0]) > (int) p1 (v1[1])); + A((float) p2 (v1[0]) > (float) p2 (v1[1])); + A((double) p3 (v1[0]) > (double) p3 (v1[1])); + A((int) p1 (v1[0]) < (int) p1 (v1[2])); + A((float) p2 (v1[0]) < (float) p2 (v1[2])); + A((double) p3 (v1[0]) < (double) p3 (v1[2])); + c4_View v2 = v1.Unique(); + A(v2.GetSize() == 3); + A((int) p1 (v2[0]) != (int) p1 (v2[1])); + A((float) p2 (v2[0]) != (float) p2 (v2[1])); + A((double) p3 (v2[0]) != (double) p3 (v2[1])); + A((int) p1 (v2[0]) != (int) p1 (v2[2])); + A((float) p2 (v2[0]) != (float) p2 (v2[2])); + A((double) p3 (v2[0]) != (double) p3 (v2[2])); + v1.Add(p1 [2] + p2 [2] + p3 [2]); + v1.Add(p1 [1] + p2 [1] + p3 [1]); + v1.Add(p1 [3] + p2 [3] + p3 [3]); + c4_View v3 = v1.Unique(); + A(v3.GetSize() == 3); + A((int) p1 (v3[0]) != (int) p1 (v3[1])); + A((float) p2 (v3[0]) != (float) p2 (v3[1])); + A((double) p3 (v3[0]) != (double) p3 (v3[1])); + A((int) p1 (v3[0]) != (int) p1 (v3[2])); + A((float) p2 (v3[0]) != (float) p2 (v3[2])); + A((double) p3 (v3[0]) != (double) p3 (v3[2])); + c4_View v4 = v1.Counts(p1, p4); + A(v4.GetSize() == 3); + c4_View v5 = v1.Counts(p2, p4); + A(v5.GetSize() == 3); // this failed in 1.9f + c4_View v6 = v1.Counts(p3, p4); + A(v6.GetSize() == 3); // this failed in 1.9f + } E; + + B(b25, Copy row from derived, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + c4_View v2 = v1.Select(p1 [222]); + A(v2.GetSize() == 1); + A(p1 (v2[0]) == 222); + c4_Row r = v2[0]; + A(p1 (r) == 222); // 1.9g: failed because SetAt did not remap + } E; + + B(b26, Partial memo field access, 0) + { + c4_BytesProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [c4_Bytes ("12345", 5)]); + A(v1.GetSize() == 1); + c4_Bytes buf = p1 (v1[0]); + A(buf.Size() == 5); + A(buf == c4_Bytes ("12345", 5)); + buf = p1(v1[0]).Access(1,3); + A(buf == c4_Bytes ("234", 3)); + p1 (v1[0]).Modify(c4_Bytes ("ab", 2), 2, 0); + buf = p1 (v1[0]); + A(buf == c4_Bytes ("12ab5", 5)); + p1 (v1[0]).Modify(c4_Bytes ("ABC", 3), 1, 2); + buf = p1 (v1[0]); + A(buf == c4_Bytes ("1ABCab5", 7)); + p1 (v1[0]).Modify(c4_Bytes ("xyz", 3), 2, -2); + buf = p1 (v1[0]); + A(buf == c4_Bytes ("1Axyz", 5)); + p1 (v1[0]).Modify(c4_Bytes ("3456", 4), 4, 0); + buf = p1 (v1[0]); + A(buf == c4_Bytes ("1Axy3456", 8)); + } E; + + B(b27, Copy value to another row, 0) + { + c4_StringProp p1 ("p1"); + c4_View v1; + v1.SetSize(2); + p1 (v1[1]) = "abc"; + // next assert fails in MacOS X 10.2.1 "Jaguar" with 2.4.7 + // seems bug in gcc 3.1, -O i.s.o. -O2 works [jcw 21oct02] + A((const char*) (p1 (v1[0])) == (c4_String) ""); + A((const char*) (p1 (v1[1])) == (c4_String) "abc"); + + // fails in 2.4.0, reported by Jerry McRae, August 2001 + p1 (v1[0]) = (const char*) p1 (v1[1]); + // MacOS 10.2.3 gcc 3.1 dec 2002 is still weird, inserting the + // following code (which should be a noop) *fixes* the assert! + //const char* q = p1 (v1[1]); + A((c4_String)(const char*) (p1 (v1[0])) == (c4_String) "abc"); + } E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tcusto1.cpp b/akregator/src/mk4storage/metakit/tests/tcusto1.cpp new file mode 100644 index 000000000..38161d5fc --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tcusto1.cpp @@ -0,0 +1,277 @@ +// tcusto1.cpp -- Regression test program, custom view tests +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestCustom1() +{ + B(c01, Slice forward, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1; + v1.Add(p1 [123]); + v1.Add(p1 [234]); + v1.Add(p1 [345]); + v1.Add(p1 [456]); + v1.Add(p1 [567]); + + c4_View v2 = v1.Slice(1, -1, 2); + A(v2.GetSize() == 2); + A(p1 (v2[0]) == 234); + A(p1 (v2[1]) == 456); + + v1.Add(p1 [678]); + A(v1.GetSize() == 6); + A(v2.GetSize() == 3); + A(p1 (v2[2]) == 678); + } E; + + B(c02, Slice backward, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1; + v1.Add(p1 [123]); + v1.Add(p1 [234]); + v1.Add(p1 [345]); + v1.Add(p1 [456]); + v1.Add(p1 [567]); + + c4_View v2 = v1.Slice(1, -1, -2); + A(v2.GetSize() == 2); + A(p1 (v2[0]) == 456); + A(p1 (v2[1]) == 234); + + v1.Add(p1 [678]); + A(v1.GetSize() == 6); + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 678); + A(p1 (v2[1]) == 456); + A(p1 (v2[2]) == 234); + } E; + + B(c03, Slice reverse, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1; + v1.Add(p1 [123]); + v1.Add(p1 [234]); + v1.Add(p1 [345]); + v1.Add(p1 [456]); + v1.Add(p1 [567]); + + c4_View v2 = v1.Slice(1, 5, -1); + A(v2.GetSize() == 4); + A(p1 (v2[0]) == 567); + A(p1 (v2[1]) == 456); + A(p1 (v2[2]) == 345); + A(p1 (v2[3]) == 234); + + v1.Add(p1 [678]); + A(v1.GetSize() == 6); + A(v2.GetSize() == 4); + } E; + + B(c04, Cartesian product, 0) + { + c4_IntProp p1 ("p1"); + c4_IntProp p2 ("p2"); + + c4_View v1; + v1.Add(p1 [123]); + v1.Add(p1 [234]); + v1.Add(p1 [345]); + + c4_View v2; + v2.Add(p2 [111]); + v2.Add(p2 [222]); + + c4_View v3 = v1.Product(v2); + A(v3.GetSize() == 6); + A(p1 (v3[0]) == 123); + A(p2 (v3[0]) == 111); + A(p1 (v3[1]) == 123); + A(p2 (v3[1]) == 222); + A(p1 (v3[2]) == 234); + A(p2 (v3[2]) == 111); + A(p1 (v3[3]) == 234); + A(p2 (v3[3]) == 222); + A(p1 (v3[4]) == 345); + A(p2 (v3[4]) == 111); + A(p1 (v3[5]) == 345); + A(p2 (v3[5]) == 222); + + v1.Add(p1 [456]); + A(v3.GetSize() == 8); + v2.Add(p2 [333]); + A(v3.GetSize() == 12); + } E; + + B(c05, Remapping, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1; + v1.Add(p1 [123]); + v1.Add(p1 [234]); + v1.Add(p1 [345]); + + c4_View v2; + v2.Add(p1 [2]); + v2.Add(p1 [0]); + v2.Add(p1 [1]); + v2.Add(p1 [0]); + + c4_View v3 = v1.RemapWith(v2); + A(v3.GetSize() == 4); + A(p1 (v3[0]) == 345); + A(p1 (v3[1]) == 123); + A(p1 (v3[2]) == 234); + A(p1 (v3[3]) == 123); + } E; + + B(c06, Pairwise combination, 0) + { + c4_IntProp p1 ("p1"); + c4_IntProp p2 ("p2"); + + c4_View v1; + v1.Add(p1 [123]); + v1.Add(p1 [234]); + v1.Add(p1 [345]); + + c4_View v2; + v2.Add(p2 [111]); + v2.Add(p2 [222]); + v2.Add(p2 [333]); + + c4_View v3 = v1.Pair(v2); + A(v3.GetSize() == 3); + A(p1 (v3[0]) == 123); + A(p2 (v3[0]) == 111); + A(p1 (v3[1]) == 234); + A(p2 (v3[1]) == 222); + A(p1 (v3[2]) == 345); + A(p2 (v3[2]) == 333); + } E; + + B(c07, Concatenate views, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1; + v1.Add(p1 [123]); + v1.Add(p1 [234]); + v1.Add(p1 [345]); + + c4_View v2; + v2.Add(p1 [111]); + v2.Add(p1 [222]); + + c4_View v3 = v1.Concat(v2); + A(v3.GetSize() == 5); + A(p1 (v3[0]) == 123); + A(p1 (v3[1]) == 234); + A(p1 (v3[2]) == 345); + A(p1 (v3[3]) == 111); + A(p1 (v3[4]) == 222); + } E; + + B(c08, Rename property, 0) + { + c4_IntProp p1 ("p1"); + c4_IntProp p2 ("p2"); + + c4_View v1; + v1.Add(p1 [123]); + v1.Add(p1 [234]); + v1.Add(p1 [345]); + + c4_View v2 = v1.Rename(p1, p2); + A(v2.GetSize() == 3); + A(p2 (v2[0]) == 123); + A(p2 (v2[1]) == 234); + A(p2 (v2[2]) == 345); + A(p1 (v2[0]) == 0); + A(p1 (v2[1]) == 0); + A(p1 (v2[2]) == 0); + } E; + + B(c09, GroupBy operation, 0) + { + c4_StringProp p1 ("p1"); + c4_IntProp p2 ("p2"); + c4_ViewProp p3 ("p3"); + + c4_View v1, v2, v3; + + v1.Add(p1 [""]); + v1.Add(p1 ["1"] + p2 [1]); + v1.Add(p1 ["12"] + p2 [1]); + v1.Add(p1 ["12"] + p2 [2]); + v1.Add(p1 ["123"] + p2 [1]); + v1.Add(p1 ["123"] + p2 [2]); + v1.Add(p1 ["123"] + p2 [3]); + + v2 = v1.GroupBy(p1, p3); + A(v2.GetSize() == 4); + A(p1 (v2[0]) == (c4_String) ""); + A(p1 (v2[1]) == (c4_String) "1"); + A(p1 (v2[2]) == (c4_String) "12"); + A(p1 (v2[3]) == (c4_String) "123"); + + v3 = p3 (v2[0]); + A(v3.GetSize() == 1); + A(p2 (v3[0]) == 0); + v3 = p3 (v2[1]); + A(v3.GetSize() == 1); + A(p2 (v3[0]) == 1); + v3 = p3 (v2[2]); + A(v3.GetSize() == 2); + A(p2 (v3[0]) == 1); + A(p2 (v3[1]) == 2); + v3 = p3 (v2[3]); + A(v3.GetSize() == 3); + A(p2 (v3[0]) == 1); + A(p2 (v3[1]) == 2); + A(p2 (v3[2]) == 3); + + } E; + + B(c10, Counts operation, 0) + { + c4_StringProp p1 ("p1"); + c4_IntProp p2 ("p2"), p3 ("p3"); + + c4_View v1, v2, v3; + + v1.Add(p1 [""]); + v1.Add(p1 ["1"] + p2 [1]); + v1.Add(p1 ["12"] + p2 [1]); + v1.Add(p1 ["12"] + p2 [2]); + v1.Add(p1 ["123"] + p2 [1]); + v1.Add(p1 ["123"] + p2 [2]); + v1.Add(p1 ["123"] + p2 [3]); + + v2 = v1.Counts(p1, p3); + A(v2.GetSize() == 4); + A(p1 (v2[0]) == (c4_String) ""); + A(p1 (v2[1]) == (c4_String) "1"); + A(p1 (v2[2]) == (c4_String) "12"); + A(p1 (v2[3]) == (c4_String) "123"); + + A(p2 (v2[0]) == 0); + A(p2 (v2[1]) == 0); + A(p2 (v2[2]) == 0); + A(p2 (v2[3]) == 0); + + A(p3 (v2[0]) == 1); + A(p3 (v2[1]) == 1); + A(p3 (v2[2]) == 2); + A(p3 (v2[3]) == 3); + + } E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tcusto2.cpp b/akregator/src/mk4storage/metakit/tests/tcusto2.cpp new file mode 100644 index 000000000..53949592d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tcusto2.cpp @@ -0,0 +1,441 @@ +// tcusto2.cpp -- Regression test program, custom view tests +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestCustom2() +{ + B(c11, Unique operation, 0); + { + c4_IntProp p1 ("p1"), p2 ("p2"); + + c4_View v1, v2, v3; + + v1.Add(p1 [1] + p2 [11]); + v1.Add(p1 [1] + p2 [22]); + v1.Add(p1 [2] + p2 [33]); + v1.Add(p1 [2] + p2 [33]); + v1.Add(p1 [3] + p2 [44]); + v1.Add(p1 [4] + p2 [55]); + v1.Add(p1 [4] + p2 [55]); + v1.Add(p1 [4] + p2 [55]); + + v2 = v1.Unique(); + A(v2.GetSize() == 5); + A(p1 (v2[0]) == 1); + A(p1 (v2[1]) == 1); + A(p1 (v2[2]) == 2); + A(p1 (v2[3]) == 3); + A(p1 (v2[4]) == 4); + + A(p2 (v2[0]) == 11); + A(p2 (v2[1]) == 22); + A(p2 (v2[2]) == 33); + A(p2 (v2[3]) == 44); + A(p2 (v2[4]) == 55); + + } E; + + B(c12, Union operation, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1, v2, v3; + + v1.Add(p1 [1]); + v1.Add(p1 [2]); + v1.Add(p1 [3]); + + v2.Add(p1 [2]); + v2.Add(p1 [3]); + v2.Add(p1 [4]); + v2.Add(p1 [5]); + + v3 = v1.Union(v2); + A(v3.GetSize() == 5); + A(p1 (v3[0]) == 1); + A(p1 (v3[1]) == 2); + A(p1 (v3[2]) == 3); + A(p1 (v3[3]) == 4); + A(p1 (v3[4]) == 5); + } E; + + B(c13, Intersect operation, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1, v2, v3; + + v1.Add(p1 [1]); + v1.Add(p1 [2]); + v1.Add(p1 [3]); + + v2.Add(p1 [2]); + v2.Add(p1 [3]); + v2.Add(p1 [4]); + v2.Add(p1 [5]); + + v3 = v1.Intersect(v2); + A(v3.GetSize() == 2); + A(p1 (v3[0]) == 2); + A(p1 (v3[1]) == 3); + } E; + + B(c14, Different operation, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1, v2, v3; + + v1.Add(p1 [1]); + v1.Add(p1 [2]); + v1.Add(p1 [3]); + + v2.Add(p1 [2]); + v2.Add(p1 [3]); + v2.Add(p1 [4]); + v2.Add(p1 [5]); + + v3 = v1.Different(v2); + A(v3.GetSize() == 3); + A(p1 (v3[0]) == 1); + A(p1 (v3[1]) == 4); + A(p1 (v3[2]) == 5); + } E; + + B(c15, Minus operation, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1, v2, v3; + + v1.Add(p1 [1]); + v1.Add(p1 [2]); + v1.Add(p1 [3]); + + v2.Add(p1 [2]); + v2.Add(p1 [3]); + v2.Add(p1 [4]); + v2.Add(p1 [5]); + + v3 = v1.Minus(v2); + A(v3.GetSize() == 1); + A(p1 (v3[0]) == 1); + } E; + + B(c16, View comparisons, 0) + { + c4_IntProp p1 ("p1"); + + c4_View v1; + v1.Add(p1 [1]); + v1.Add(p1 [2]); + v1.Add(p1 [3]); + v1.Add(p1 [4]); + v1.Add(p1 [5]); + + A(v1 == v1); + A(v1 == v1.Slice(0)); + A(v1.Slice(0,2) < v1.Slice(0,3)); + A(v1.Slice(0,3) == v1.Slice(0,3)); + A(v1.Slice(0,4) > v1.Slice(0,3)); + A(v1.Slice(0,3) < v1.Slice(1,3)); + A(v1.Slice(0,3) < v1.Slice(1,4)); + A(v1.Slice(1,3) > v1.Slice(0,3)); + A(v1.Slice(1,4) > v1.Slice(0,3)); + } E; + + B(c17, Join operation, 0) + { + c4_StringProp p1 ("p1"), p2 ("p2"); + c4_IntProp p3 ("p3"); + + c4_View v1, v2, v3; + + v1.Add(p1 [""]); + v1.Add(p1 ["1"] + p2 ["a"]); + v1.Add(p1 ["12"] + p2 ["ab"]); + v1.Add(p1 ["123"] + p2 ["abc"]); + + v2.Add(p1 ["1"] + p3 [1]); + v2.Add(p1 ["12"] + p3 [1]); + v2.Add(p1 ["12"] + p3 [2]); + v2.Add(p1 ["123"] + p3 [1]); + v2.Add(p1 ["123"] + p3 [2]); + v2.Add(p1 ["123"] + p3 [3]); + + v3 = v1.Join(p1, v2); // inner join + A(v3.GetSize() == 6); + + A(p1 (v3[0]) == (c4_String) "1"); + A(p1 (v3[1]) == (c4_String) "12"); + A(p1 (v3[2]) == (c4_String) "12"); + A(p1 (v3[3]) == (c4_String) "123"); + A(p1 (v3[4]) == (c4_String) "123"); + A(p1 (v3[5]) == (c4_String) "123"); + + A(p2 (v3[0]) == (c4_String) "a"); + A(p2 (v3[1]) == (c4_String) "ab"); + A(p2 (v3[2]) == (c4_String) "ab"); + A(p2 (v3[3]) == (c4_String) "abc"); + A(p2 (v3[4]) == (c4_String) "abc"); + A(p2 (v3[5]) == (c4_String) "abc"); + + A(p3 (v3[0]) == 1); + A(p3 (v3[1]) == 1); + A(p3 (v3[2]) == 2); + A(p3 (v3[3]) == 1); + A(p3 (v3[4]) == 2); + A(p3 (v3[5]) == 3); + + v3 = v1.Join(p1, v2, true); // outer join + A(v3.GetSize() == 7); + + A(p1 (v3[0]) == (c4_String) ""); + A(p1 (v3[1]) == (c4_String) "1"); + A(p1 (v3[2]) == (c4_String) "12"); + A(p1 (v3[3]) == (c4_String) "12"); + A(p1 (v3[4]) == (c4_String) "123"); + A(p1 (v3[5]) == (c4_String) "123"); + A(p1 (v3[6]) == (c4_String) "123"); + + A(p2 (v3[0]) == (c4_String) ""); + A(p2 (v3[1]) == (c4_String) "a"); + A(p2 (v3[2]) == (c4_String) "ab"); + A(p2 (v3[3]) == (c4_String) "ab"); + A(p2 (v3[4]) == (c4_String) "abc"); + A(p2 (v3[5]) == (c4_String) "abc"); + A(p2 (v3[6]) == (c4_String) "abc"); + + A(p3 (v3[0]) == 0); + A(p3 (v3[1]) == 1); + A(p3 (v3[2]) == 1); + A(p3 (v3[3]) == 2); + A(p3 (v3[4]) == 1); + A(p3 (v3[5]) == 2); + A(p3 (v3[6]) == 3); + } E; + + B(c18, Groupby sort fix, 0) // fails in 1.8.4 (from P. Ritter, 14-10-1998) + { + c4_StringProp p1 ("Country"); + c4_StringProp p2 ("City"); + c4_ViewProp p3 ("SubList"); + + c4_View v1, v2, v3; + + v1.Add(p1 ["US"] + p2 ["Philadelphia"]); + v1.Add(p1 ["France"] + p2 ["Bordeaux"]); + v1.Add(p1 ["US"] + p2 ["Miami"]); + v1.Add(p1 ["France"] + p2 ["Paris"]); + v1.Add(p1 ["US"] + p2 ["Boston"]); + v1.Add(p1 ["France"] + p2 ["Nice"]); + v1.Add(p1 ["US"] + p2 ["NY"]); + v1.Add(p1 ["US"] + p2 ["Miami"]); + + v2 = v1.GroupBy(p1, p3); + A(v2.GetSize() == 2); + A(p1 (v2[0]) == (c4_String) "France"); + A(p1 (v2[1]) == (c4_String) "US"); + + v3 = p3 (v2[0]); + A(v3.GetSize() == 3); + A(p2 (v3[0]) == (c4_String) "Bordeaux"); + A(p2 (v3[1]) == (c4_String) "Nice"); + A(p2 (v3[2]) == (c4_String) "Paris"); + v3 = p3 (v2[1]); + A(v3.GetSize() == 5); + A(p2 (v3[0]) == (c4_String) "Boston"); + A(p2 (v3[1]) == (c4_String) "Miami"); + A(p2 (v3[2]) == (c4_String) "Miami"); + A(p2 (v3[3]) == (c4_String) "NY"); + A(p2 (v3[4]) == (c4_String) "Philadelphia"); + } E; + + B(c19, JoinProp operation, 0) // moved, used to also be called c15 + { + c4_StringProp p1 ("p1"); + c4_ViewProp p2 ("p2"); + c4_IntProp p3 ("p3"); + + c4_View v1, v2a, v2b, v2c, v3; + + v2a.Add(p3 [1]); + v2a.Add(p3 [2]); + v2a.Add(p3 [3]); + v1.Add(p1 ["123"] + p2 [v2a]); + + v2b.Add(p3 [1]); + v2b.Add(p3 [2]); + v1.Add(p1 ["12"] + p2 [v2b]); + + v2c.Add(p3 [1]); + v1.Add(p1 ["1"] + p2 [v2c]); + + v1.Add(p1 [""]); + + v3 = v1.JoinProp(p2); // inner join + A(v3.GetSize() == 6); + + A(p1 (v3[0]) == (c4_String) "123"); + A(p1 (v3[1]) == (c4_String) "123"); + A(p1 (v3[2]) == (c4_String) "123"); + A(p1 (v3[3]) == (c4_String) "12"); + A(p1 (v3[4]) == (c4_String) "12"); + A(p1 (v3[5]) == (c4_String) "1"); + + A(p3 (v3[0]) == 1); + A(p3 (v3[1]) == 2); + A(p3 (v3[2]) == 3); + A(p3 (v3[3]) == 1); + A(p3 (v3[4]) == 2); + A(p3 (v3[5]) == 1); + + v3 = v1.JoinProp(p2, true); // outer join + A(v3.GetSize() == 7); + + A(p1 (v3[0]) == (c4_String) "123"); + A(p1 (v3[1]) == (c4_String) "123"); + A(p1 (v3[2]) == (c4_String) "123"); + A(p1 (v3[3]) == (c4_String) "12"); + A(p1 (v3[4]) == (c4_String) "12"); + A(p1 (v3[5]) == (c4_String) "1"); + A(p1 (v3[6]) == (c4_String) ""); + + A(p3 (v3[0]) == 1); + A(p3 (v3[1]) == 2); + A(p3 (v3[2]) == 3); + A(p3 (v3[3]) == 1); + A(p3 (v3[4]) == 2); + A(p3 (v3[5]) == 1); + A(p3 (v3[6]) == 0); + } E; + + B(c20, Wide cartesian product, 0) + { + // added 2nd prop's to do a better test - 1999-12-23 + c4_IntProp p1 ("p1"); + c4_IntProp p2 ("p2"); + c4_IntProp p3 ("p3"); + c4_IntProp p4 ("p4"); + + c4_View v1; + v1.Add(p1 [123] + p2 [321]); + v1.Add(p1 [234] + p2 [432]); + v1.Add(p1 [345] + p2 [543]); + + c4_View v2; + v2.Add(p3 [111] + p4 [11]); + v2.Add(p3 [222] + p4 [22]); + + c4_View v3 = v1.Product(v2); + A(v3.GetSize() == 6); + A(p1 (v3[0]) == 123); + A(p2 (v3[0]) == 321); + A(p3 (v3[0]) == 111); + A(p4 (v3[0]) == 11); + A(p1 (v3[1]) == 123); + A(p2 (v3[1]) == 321); + A(p3 (v3[1]) == 222); + A(p4 (v3[1]) == 22); + A(p1 (v3[2]) == 234); + A(p2 (v3[2]) == 432); + A(p3 (v3[2]) == 111); + A(p4 (v3[2]) == 11); + A(p1 (v3[3]) == 234); + A(p2 (v3[3]) == 432); + A(p3 (v3[3]) == 222); + A(p4 (v3[3]) == 22); + A(p1 (v3[4]) == 345); + A(p2 (v3[4]) == 543); + A(p3 (v3[4]) == 111); + A(p4 (v3[4]) == 11); + A(p1 (v3[5]) == 345); + A(p2 (v3[5]) == 543); + A(p3 (v3[5]) == 222); + A(p4 (v3[5]) == 22); + + v1.Add(p1 [456]); + A(v3.GetSize() == 8); + v2.Add(p2 [333]); + A(v3.GetSize() == 12); + } E; + + B(c21, Join on compound key, 0) + { + c4_IntProp p1 ("p1"), p2 ("p2"), p3 ("p3"), p4 ("p4"); + + c4_View v1, v2, v3; + + v1.Add(p1 [1] + p2 [11] + p3 [111]); + v1.Add(p1 [2] + p2 [22] + p3 [222]); + v1.Add(p1 [3] + p2 [22] + p3 [111]); + + v2.Add(p2 [11] + p3 [111] + p4 [1111]); + v2.Add(p2 [22] + p3 [222] + p4 [2222]); + v2.Add(p2 [22] + p3 [222] + p4 [3333]); + v2.Add(p2 [22] + p3 [333] + p4 [4444]); + + // this works here, but it fails in Python, i.e. Mk4py 2.4.0 + v3 = v1.Join((p2, p3), v2); + + A(v3.GetSize() == 3); + + A(p1 (v3[0]) == 1); + A(p1 (v3[1]) == 2); + A(p1 (v3[2]) == 2); + + A(p2 (v3[0]) == 11); + A(p2 (v3[1]) == 22); + A(p2 (v3[2]) == 22); + + A(p3 (v3[0]) == 111); + A(p3 (v3[1]) == 222); + A(p3 (v3[2]) == 222); + + A(p4 (v3[0]) == 1111); + A(p4 (v3[1]) == 2222); + A(p4 (v3[2]) == 3333); + } E; + + B(c22, Groupby with selection, 0) + { + c4_Storage s1; + c4_View v1 = s1.GetAs("v1[p1:I,p2:I,p3:I]"); + c4_IntProp p1 ("p1"), p2 ("p2"), p3 ("p3"); + c4_ViewProp p4 ("p4"); + + v1.Add(p1[0] + p2[1] + p3[10]); + v1.Add(p1[1] + p2[1] + p3[20]); + v1.Add(p1[2] + p2[2] + p3[30]); + v1.Add(p1[3] + p2[3] + p3[40]); + v1.Add(p1[4] + p2[3] + p3[50]); + + s1.Commit(); + A(v1.GetSize() == 5); + + c4_View v2 = v1.GroupBy(p2,p4); + A(v2.GetSize() == 3); + + c4_View v3 = p4 (v2[0]); + A(v3.GetSize() == 2); + A(p3 (v3[0]) == 10); + A(p3 (v3[1]) == 20); + + c4_View v4 = p4 (v2[1]); + A(v4.GetSize() == 1); + A(p3 (v4[0]) == 30); + + c4_View v5 = p4 (v2[2]); + A(v5.GetSize() == 2); + A(p3 (v5[0]) == 40); + A(p3 (v5[1]) == 50); + + c4_View v6 = v4.Sort(); + A(v6.GetSize() == 1); + A(p1 (v6[0]) == 2); + A(p3 (v6[0]) == 30); + + } E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tdiffer.cpp b/akregator/src/mk4storage/metakit/tests/tdiffer.cpp new file mode 100644 index 000000000..16dc97c34 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tdiffer.cpp @@ -0,0 +1,52 @@ +// tdiffer.cpp -- Regression test program, differential commit tests +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestDiffer() +{ + B(d01, Commit aside, 0) W(d01a); W(d01b); + { + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("d01a", 1); + A(s1.Strategy().FileSize() == 0); + c4_View v1 = s1.GetAs("a[p1:I]"); + v1.Add(p1 [123]); + s1.Commit(); + } + { + c4_Storage s1 ("d01a", 0); + c4_Storage s2 ("d01b", 1); + s1.SetAside(s2); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + v1.Add(p1 [456]); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 123); + A(p1 (v1[1]) == 456); + s1.Commit(); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 123); + A(p1 (v1[1]) == 456); + s2.Commit(); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 123); + A(p1 (v1[1]) == 456); + } + { + c4_Storage s1 ("d01a", 0); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + c4_Storage s2 ("d01b", 0); + s1.SetAside(s2); + c4_View v2 = s1.View("a"); + A(v2.GetSize() == 2); + A(p1 (v2[0]) == 123); + A(p1 (v2[1]) == 456); + } + } D(d01a); D(d01b); R(d01a); R(d01b); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/textend.cpp b/akregator/src/mk4storage/metakit/tests/textend.cpp new file mode 100644 index 000000000..98331f1af --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/textend.cpp @@ -0,0 +1,195 @@ +// textend.cpp -- Regression test program, commit extend tests +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +#include "regress.h" + +const int kSize1 = 41; +const int kSize2 = 85; + +void TestExtend() +{ + B(e01, Extend new file, 0) W(e01a); + { + c4_IntProp p1 ("p1"); + c4_Storage s1 ("e01a", 2); + A(s1.Strategy().FileSize() == 0); + c4_View v1 = s1.GetAs("a[p1:I]"); + v1.Add(p1 [123]); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize1); + v1.Add(p1 [456]); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize2); + } D(e01a); R(e01a); E; + + B(e02, Extend committing twice, 0) W(e02a); + { + c4_IntProp p1 ("p1"); + c4_Storage s1 ("e02a", 2); + A(s1.Strategy().FileSize() == 0); + c4_View v1 = s1.GetAs("a[p1:I]"); + v1.Add(p1 [123]); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize1); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize1); + v1.Add(p1 [456]); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize2); + } D(e02a); R(e02a); E; + + B(e03, Read during extend, 0) W(e03a); + { + c4_IntProp p1 ("p1"); + c4_Storage s1 ("e03a", 2); + A(s1.Strategy().FileSize() == 0); + c4_View v1 = s1.GetAs("a[p1:I]"); + v1.Add(p1 [123]); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize1); + + { + c4_Storage s2 ("e03a", 0); + c4_View v2 = s2.View("a"); + A(v2.GetSize() == 1); + A(p1 (v2[0]) == 123); + } + + v1.Add(p1 [456]); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize2); + + { + c4_Storage s3 ("e03a", 0); + c4_View v3 = s3.View("a"); + A(v3.GetSize() == 2); + A(p1 (v3[0]) == 123); + A(p1 (v3[1]) == 456); + } + } D(e03a); R(e03a); E; + + B(e04, Extend during read, 0) W(e04a); + { + c4_IntProp p1 ("p1"); + + { + c4_Storage s1 ("e04a", 2); + A(s1.Strategy().FileSize() == 0); + c4_View v1 = s1.GetAs("a[p1:I]"); + v1.Add(p1 [123]); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize1); + } + + c4_Storage s2 ("e04a", 0); + c4_View v2 = s2.View("a"); + A(v2.GetSize() == 1); + A(p1 (v2[0]) == 123); + + c4_Storage s3 ("e04a", 0); // open, don't load + + { + c4_Storage s4 ("e04a", 2); + A(s4.Strategy().FileSize() == kSize1); + c4_View v4 = s4.View("a"); + v4.Add(p1 [123]); + s4.Commit(); + A(s4.Strategy().FileSize() > kSize1); // == kSize2); + } + + c4_View v2a = s2.View("a"); + A(v2a.GetSize() == 1); + A(p1 (v2a[0]) == 123); + + c4_View v3 = s3.View("a"); + A(v3.GetSize() == 1); + A(p1 (v3[0]) == 123); + + } D(e04a); R(e04a); E; + + B(e05, Test memory mapping, 0) W(e05a); + { + // this is not a test of MK, but of the underlying system code + + { + c4_FileStrategy fs; + bool f1 = fs.DataOpen("e05a", 1); + A(!f1); + fs.DataWrite(0, "hi!", 3); + A(fs._failure == 0); + A(fs.FileSize() == 3); + fs.DataCommit(0); + A(fs.FileSize() == 3); + fs.ResetFileMapping(); + if (fs._mapStart != 0) + { + A(fs._dataSize == 3); + c4_String s ((char*) fs._mapStart, 3); + A(s == "hi!"); + } + fs.DataWrite(3, "hello", 5); + A(fs._failure == 0); + A(fs.FileSize() == 8); + fs.DataCommit(0); + A(fs.FileSize() == 8); + if (fs._mapStart != 0) + { + A(fs._dataSize == 3); + c4_String s ((char*) fs._mapStart, 8); + A(s == "hi!hello"); + } + fs.DataWrite(100, "wow!", 4); + A(fs._failure == 0); + A(fs.FileSize() == 104); + fs.DataCommit(0); + A(fs.FileSize() == 104); + fs.ResetFileMapping(); + if (fs._mapStart != 0) + { + A(fs._dataSize == 104); + c4_String s ((char*) fs._mapStart + 100, 4); + A(s == "wow!"); + } + } + + // clear the file, so dump doesn't choke on it + FILE* fp = fopen("e05a", "w"); + A(fp != 0); + fclose(fp); + + } D(e05a); R(e05a); E; + + B(e06, Rollback during extend, 0) W(e06a); + { + c4_IntProp p1 ("p1"); + c4_Storage s1 ("e06a", 2); + A(s1.Strategy().FileSize() == 0); + c4_View v1 = s1.GetAs("a[p1:I]"); + v1.Add(p1 [123]); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize1); + + c4_Storage s2 ("e06a", 0); + c4_View v2 = s2.View("a"); + A(v2.GetSize() == 1); + A(p1 (v2[0]) == 123); + + v1.Add(p1 [456]); + s1.Commit(); + A(s1.Strategy().FileSize() == kSize2); +#if 0 +/* fails on NT + Samba, though it works fine with mmap'ing disabled */ + s2.Rollback(); + + c4_View v2a = s2.View("a"); + A(v2a.GetSize() == 2); + A(p1 (v2a[0]) == 123); + A(p1 (v2a[1]) == 456); +#else + c4_View v2a = s2.View("a"); + A(v2a.GetSize() == 1); + A(p1 (v2a[0]) == 123); +#endif + } D(e06a); R(e06a); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tformat.cpp b/akregator/src/mk4storage/metakit/tests/tformat.cpp new file mode 100644 index 000000000..ba6e92549 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tformat.cpp @@ -0,0 +1,306 @@ +// tformat.cpp -- Regression test program, (re-)format tests +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestFormat() +{ + B(f01, Add view to format, 0) W(f01a); + { + c4_IntProp p1 ("p1"); + c4_IntProp p2 ("p2"); + { + c4_Storage s1 ("f01a", 1); + s1.SetStructure("a[p1:I]"); + + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + s1.Commit(); + + c4_View v2 = s1.GetAs("b[p2:I]"); + + v2.Add(p2 [345]); + v2.Add(p2 [567]); + + s1.Commit(); + } + { + c4_Storage s1 ("f01a", 0); + + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + + c4_View v2 = s1.View("b"); + A(v2.GetSize() == 2); + A(p2 (v2[0]) == 345); + A(p2 (v2[1]) == 567); + } + } D(f01a); R(f01a); E; + + B(f02, Remove view from format, 0) W(f02a); + { + c4_IntProp p1 ("p1"); + c4_IntProp p2 ("p2"); + { + c4_Storage s1 ("f02a", 1); + s1.SetStructure("a[p1:I],b[p2:I]"); + + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + + c4_View v2 = s1.View("b"); + v2.Add(p2 [345]); + v2.Add(p2 [567]); + + s1.Commit(); + } + { + c4_Storage s1 ("f02a", 1); + s1.SetStructure("b[p2:I]"); + + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); // 19990916 new semantics, still as temp view + A(p1 (v1[0]) == 123); + + c4_View v2 = s1.View("b"); + A(v2.GetSize() == 2); + A(p2 (v2[0]) == 345); + A(p2 (v2[1]) == 567); + + s1.Commit(); + } + { + c4_Storage s1 ("f02a", 0); + + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 0); + + c4_View v2 = s1.View("b"); + A(v2.GetSize() == 2); + A(p2 (v2[0]) == 345); + A(p2 (v2[1]) == 567); + } + } D(f02a); R(f02a); E; + + B(f03, Rollback format change, 0) W(f03a); + { + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("f03a", 1); + s1.SetStructure("a[p1:I]"); + + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + + s1.Commit(); + + v1 = s1.GetAs("a"); + A(v1.GetSize() == 0); + + s1.Rollback(); + + v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + } + } D(f03a); R(f03a); E; + + B(f04, Rearrange format, 0) W(f04a); + { + c4_IntProp p1 ("p1"); + c4_IntProp p2 ("p2"); + { + c4_Storage s1 ("f04a", 1); + s1.SetStructure("a[p1:I],b[p2:I]"); + + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + + c4_View v2 = s1.View("b"); + v2.Add(p2 [345]); + v2.Add(p2 [567]); + + s1.Commit(); + } + { + c4_Storage s1 ("f04a", 1); + s1.SetStructure("b[p2:I],a[p1:I]"); + + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + + c4_View v2 = s1.View("b"); + A(v2.GetSize() == 2); + A(p2 (v2[0]) == 345); + A(p2 (v2[1]) == 567); + + s1.Commit(); + } + } D(f04a); R(f04a); E; + + B(f05, Nested reformat, 0) W(f05a); + { + c4_IntProp p1 ("p1"); + c4_IntProp p2 ("p2"); + { + c4_Storage s1 ("f05a", 1); + s1.SetStructure("a[p1:I],b[p2:I]"); + + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + + c4_View v2 = s1.View("b"); + v2.Add(p2 [345]); + v2.Add(p2 [567]); + + s1.Commit(); + } + { + c4_Storage s1 ("f05a", 1); + s1.SetStructure("a[p1:I],b[p1:I,p2:I]"); + + c4_View v2 = s1.View("b"); + p1 (v2[0]) = 543; + p1 (v2[1]) = 765; + + s1.Commit(); + } + { + c4_Storage s1 ("f05a", 0); + + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + + c4_View v2 = s1.View("b"); + A(v2.GetSize() == 2); + A(p1 (v2[0]) == 543); + A(p1 (v2[1]) == 765); + A(p2 (v2[0]) == 345); + A(p2 (v2[1]) == 567); + } + } D(f05a); R(f05a); E; + + B(f06, Flip foreign data, 0) + { + D(reversed); // not created here, only dump existing file + } E; + + B(f07, Automatic structure info (obsolete), 0) W(f07a); + { +/* Structure() and Store() are no longer supported + c4_StringProp p1 ("p1"), p2 ("p2"); + c4_Row r1 = p1 ["One"] + p2 ["Two"]; + c4_Row r2; + c4_View v1; + v1.Add(r1); + v1.Add(r2); + v1.Add(r1); + + c4_View v2 = v1.Structure(); + A(v2.GetSize() == 1); + + c4_ViewProp pView ("view"); + c4_View v3 = pView (v2[0]); + A(v3.GetSize() == 2); +*/ + #define FORMAT07 "dict[parent:I,index:I,view[name:S,type:S,child:I]]" + c4_Storage s1 ("f07a", 1); + s1.SetStructure(FORMAT07); + + //s1.View("dict") = v1.Structure(); + + s1.Commit(); + + } D(f07a); R(f07a); E; + + B(f08, Automatic storage format, 0) W(f08a); + { + c4_StringProp p1 ("p1"), p2 ("p2"); + c4_Row r1 = p1 ["One"] + p2 ["Two"]; + c4_Row r2; + c4_View v1; + v1.Add(r1); + v1.Add(r2); + v1.Add(r1); + + c4_Storage s1 ("f08a", 1); + + // changed 2000-03-15: Store is gone + //s1.Store("dict", v1); + c4_View v2 = s1.GetAs("dict[p1:S,p2:S]"); + v2.InsertAt(0, v1); + + s1.Commit(); + + } D(f08a); R(f08a); E; + + B(f09, Partial restructuring, 0) W(f09a); + { + c4_IntProp p1 ("p1"), p2 ("p2"), p3 ("p3"); + c4_Storage s1 ("f09a", 1); + + c4_View v1 = s1.GetAs("a[p1:I]"); + v1.SetSize(10); + + for (int i = 0; i < v1.GetSize(); ++i) + p1 (v1[i]) = 1000 + i; + + c4_View v2 = s1.GetAs("a[p1:I,p2:I]"); + + for (int j = 0; j < v2.GetSize(); j += 2) + p2 (v2[j]) = 2000 + j; + + c4_View v3 = s1.GetAs("a[p1:I,p2:I,p3:I]"); + + for (int k = 0; k < v3.GetSize(); k += 3) + p3 (v3[k]) = 3000 + k; + + s1.Commit(); + + } D(f09a); R(f09a); E; + + B(f10, Committed restructuring, 0) W(f10a); + { + c4_IntProp p1 ("p1"), p2 ("p2"), p3 ("p3"); + c4_Storage s1 ("f10a", 1); + + c4_View v1 = s1.GetAs("a[p1:I]"); + v1.SetSize(10); + + for (int i = 0; i < v1.GetSize(); ++i) + p1 (v1[i]) = 1000 + i; + + s1.Commit(); + + c4_View v2 = s1.GetAs("a[p1:I,p2:I]"); + + for (int j = 0; j < v2.GetSize(); j += 2) + p2 (v2[j]) = 2000 + j; + + s1.Commit(); + + c4_View v3 = s1.GetAs("a[p1:I,p2:I,p3:I]"); + + for (int k = 0; k < v3.GetSize(); k += 3) + p3 (v3[k]) = 3000 + k; + + s1.Commit(); + + } D(f10a); R(f10a); E; + + // 19990824: don't crash on GetAs with an inexistent view + B(f11, Delete missing view, 0) W(f11a); + { + c4_Storage s1 ("f11a", 1); + + c4_View v1 = s1.GetAs("a"); + v1.SetSize(10); + + s1.Commit(); + + } D(f11a); R(f11a); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tlimits.cpp b/akregator/src/mk4storage/metakit/tests/tlimits.cpp new file mode 100644 index 000000000..a66ccbf05 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tlimits.cpp @@ -0,0 +1,282 @@ +// tlimits.cpp -- Regression test program, limit tests +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestLimits() +{ + B(l00, Lots of properties, 0) W(l00a); + { + c4_String desc; + + for (int i = 1; i < 150; ++i) + { + char buf [20]; + sprintf(buf, ",p%d:I", i); + + desc += buf; + } + + desc = "a[" + desc.Mid(1) + "]"; + + c4_Storage s1 ("l00a", 1); + s1.SetStructure(desc); + c4_View v1 = s1.View("a"); + c4_IntProp p123 ("p123"); + v1.Add(p123 [123]); + s1.Commit(); + + } D(l00a); R(l00a); E; + + B(l01, Over 32 Kb of integers, 0) W(l01a); + { + c4_Storage s1 ("l01a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + c4_IntProp p1 ("p1"); + v1.SetSize(9000); + + for (int i = 0; i < v1.GetSize(); ++i) + { + p1 (v1[i]) = 1000000L + i; + + A(p1 (v1[i]) - 1000000L == i); + } + + for (int j = 0; j < v1.GetSize(); ++j) + { + A(p1 (v1[j]) - 1000000L == j); + } + + s1.Commit(); + + for (int k = 0; k < v1.GetSize(); ++k) + { + A(p1 (v1[k]) - 1000000L == k); + } + + } D(l01a); R(l01a); E; + + B(l02, Over 64 Kb of strings, 0) W(l02a); + { + static char* texts[3] = { "Alice in Wonderland", + "The wizard of Oz", + "I'm singin' in the rain" }; + + c4_Storage s1 ("l02a", 1); + s1.SetStructure("a[p1:S]"); + c4_View v1 = s1.View("a"); + c4_StringProp p1 ("p1"); + c4_Row r1; + + for (int i = 0; i < 3500; ++i) + { + p1 (r1) = texts [i % 3]; + v1.Add(r1); + + A(p1 (v1[i]) == (c4_String) texts [i % 3]); + } + + for (int j = 0; j < v1.GetSize(); ++j) + { + A(p1 (v1[j]) == (c4_String) texts [j % 3]); + } + + s1.Commit(); + + for (int k = 0; k < v1.GetSize(); ++k) + { + A(p1 (v1[k]) == (c4_String) texts [k % 3]); + } + + } D(l02a); R(l02a); E; + + B(l03, Force sections in storage, 0) W(l03a); W(l03b); + { + c4_ViewProp p1 ("p1"); + c4_IntProp p2 ("p2"); + + { + c4_Storage s1 ("l03a", 1); + s1.SetStructure("a[p1[p2:I]]"); + c4_View v1 = s1.View("a"); + + c4_View v2; + v2.SetSize(1); + + for (int i = 0; i < 500; ++i) + { + p2 (v2[0]) = 9000 + i; + v1.Add(p1 [v2]); + } + + s1.Commit(); + } + { + c4_Storage s1 ("l03a", 0); + c4_View v1 = s1.View("a"); + + for (int i = 0; i < 500; ++i) + { + c4_View v2 = p1 (v1[i]); + A(p2 (v2[0]) == 9000 + i); + } + + c4_FileStream fs1 (fopen("l03b", "wb"), true); + s1.SaveTo(fs1); + } + { + c4_Storage s1; + + c4_FileStream fs1 (fopen("l03b", "rb"), true); + s1.LoadFrom(fs1); + + c4_View v1 = s1.View("a"); + + for (int i = 0; i < 500; ++i) + { + c4_View v2 = p1 (v1[i]); + A(p2 (v2[0]) == 9000 + i); + } + } + } D(l03a); D(l03b); R(l03a); R(l03b); E; + + B(l04, Modify sections in storage, 0) W(l04a); + { + c4_ViewProp p1 ("p1"); + c4_IntProp p2 ("p2"); + + { + c4_Storage s1 ("l04a", 1); + s1.SetStructure("a[p1[p2:I]]"); + c4_View v1 = s1.View("a"); + + c4_View v2; + v2.SetSize(1); + + for (int i = 0; i < 500; ++i) + { + p2 (v2[0]) = 9000 + i; + v1.Add(p1 [v2]); + } + + s1.Commit(); + } + { + c4_Storage s1 ("l04a", 1); + c4_View v1 = s1.View("a"); + c4_View v2 = p1 (v1[0]); + + p2 (v2[0]) = 1; + // this corrupted file in 1.5: free space was bad after load + s1.Commit(); + } + { + c4_Storage s1 ("l04a", 0); + } + } D(l04a); R(l04a); E; + + B(l05, Delete from 32 Kb of strings, 0) W(l05a); + { + static char* texts[3] = { "Alice in Wonderland", + "The wizard of Oz", + "I'm singin' in the rain" }; + + c4_Storage s1 ("l05a", 1); + s1.SetStructure("a[p1:I,p2:S,p3:S]"); + c4_View v1 = s1.View("a"); + c4_IntProp p1 ("p1"); + c4_StringProp p2 ("p2"), p3 ("p3"); + c4_Row r1; + + for (int i = 0; i < 1750; ++i) + { + p1 (r1) = i; + p2 (r1) = texts [i % 3]; + p3 (r1) = texts [i % 3]; + v1.Add(r1); + + A(p2 (v1[i]) == (c4_String) texts [i % 3]); + } + + for (int j = 0; j < v1.GetSize(); ++j) + { + A(p1 (v1[j]) == j); + A(p2 (v1[j]) == (c4_String) texts [j % 3]); + A(p3 (v1[j]) == (c4_String) texts [j % 3]); + } + + s1.Commit(); + + while (v1.GetSize() > 1) // randomly remove entries + v1.RemoveAt((unsigned short) (211 * v1.GetSize()) % v1.GetSize()); + + s1.Commit(); + + } D(l05a); R(l05a); E; + + B(l06, Bit field manipulations, 0) W(l06a); + { + c4_IntProp p1 ("p1"); + c4_View v2; + + { + c4_Storage s1 ("l06a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + c4_Row r1; + + for (int i = 2; i <= 256; i <<= 1) + { + for (int j = 0; j < 18; ++j) + { + p1 (r1) = j & (i - 1); + + v1.InsertAt(j, r1, j + 1); + v2.InsertAt(j, r1, j + 1); + } + + s1.Commit(); + } + } + { + c4_Storage s1 ("l06a", 0); + c4_View v1 = s1.View("a"); + + int n = v2.GetSize(); + A(n == v1.GetSize()); + + for (int i = 0; i < n; ++i) + { + long v = p1 (v2[i]); + A(p1 (v1[i]) == v); + } + } + + } D(l06a); R(l06a); E; + + B(l07, Huge description, 0) W(l07a); + { + c4_String desc; + + for (int i = 1; i < 150; ++i) + { + char buf [50]; + // 1999-07-25: longer size to force over 4 Kb of description + sprintf(buf, ",a123456789a123456789a123456789p%d:I", i); + + desc += buf; + } + + desc = "a[" + desc.Mid(1) + "]"; + + c4_Storage s1 ("l07a", 1); + s1.SetStructure(desc); + c4_View v1 = s1.View("a"); + c4_IntProp p123 ("p123"); + v1.Add(p123 [123]); + s1.Commit(); + + } D(l07a); R(l07a); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tmapped.cpp b/akregator/src/mk4storage/metakit/tests/tmapped.cpp new file mode 100644 index 000000000..20f8de5f2 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tmapped.cpp @@ -0,0 +1,244 @@ +// tmapped.cpp -- Regression test program, mapped view tests +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestBlockDel(int pos_, int len_) +{ + printf("blockdel pos %d len %d\n", pos_, len_); + + c4_ViewProp p1 ("_B"); + c4_IntProp p2 ("p2"); + + c4_Storage s1; + c4_View v1 = s1.GetAs("v1[_B[p2:I]]"); + + int n = 0; + static int sizes[] = {999, 999, 999, 2, 0}; + + for (int i = 0; sizes[i]; ++i) { + c4_View v; + v.SetSize(sizes[i]); + for (int j = 0; j < sizes[i]; ++j) + p2 (v[j]) = ++n; + v1.Add(p1 [v]); + } + + c4_View v2 = v1.Blocked(); + A(v2.GetSize() == 2999); + + v2.RemoveAt(pos_, len_); + A(v2.GetSize() == 2999 - len_); +} + +void TestMapped() +{ + B(m01, Hash mapping, 0); + { + c4_StringProp p1 ("p1"); + + c4_Storage s1; + c4_View v1 = s1.GetAs("v1[p1:S]"); + c4_View v2 = s1.GetAs("v2[_H:I,_R:I]"); + c4_View v3 = v1.Hash(v2, 1); + + v3.Add(p1 ["b93655249726e5ef4c68e45033c2e0850570e1e07"]); + v3.Add(p1 ["2ab03fba463d214f854a71ab5c951cea096887adf"]); + v3.Add(p1 ["2e196eecb91b02c16c23360d8e1b205f0b3e3fa3d"]); + A(v3.GetSize() == 3); + + // infinite loop in 2.4.0, reported by Nathan Rogers, July 2001 + // happens when looking for missing key after a hash collision + int f = v3.Find(p1 ["7c0734c9187133f34588517fb5b39294076f22ba3"]); + A(f == -1); + } E; + + // example from Steve Baxter, Nov 2001, after block perf bugfix + // assertion failure on row 1001, due to commit data mismatch + B(m02, Blocked view bug, 0) W(m02a); + { + c4_BytesProp p1 ("p1"); + c4_Bytes h; + + c4_Storage s1 ("m02a", true); + c4_View v1 = s1.GetAs("v1[_B[p1:B]]"); + c4_View v2 = v1.Blocked(); + + for (int i = 0; i < 1005; ++i) { + h.SetBuffer(2500 + i); + v2.Add(p1 [h]); + + if (i >= 999) // will crash a few rounds later, at row 1001 + s1.Commit(); + } + + // reduce size to shorten the dump output + v2.RemoveAt(0, 990); + s1.Commit(); + + } D(m02a); R(m02a); E; + + B(m03, Hash adds, 0) W(m03a); + { + c4_StringProp p1 ("p1"); + + c4_Storage s1 ("m03a", true); + + c4_View d1 = s1.GetAs("d1[p1:S]"); + c4_View m1 = s1.GetAs("m1[_H:I,_R:I]"); + c4_View h1 = d1.Hash(m1); + + h1.Add(p1 ["one"]); + s1.Commit(); + + c4_View d2 = s1.GetAs("d2[p1:S]"); + c4_View m2 = s1.GetAs("m2[_H:I,_R:I]"); + c4_View h2 = d2.Hash(m2); + + h1.Add(p1 ["two"]); + h2.Add(p1 ["two"]); + s1.Commit(); + + c4_View d3 = s1.GetAs("d3[p1:S]"); + c4_View m3 = s1.GetAs("m3[_H:I,_R:I]"); + c4_View h3 = d3.Hash(m3); + + h1.Add(p1 ["three"]); + h2.Add(p1 ["three"]); + h3.Add(p1 ["three"]); + s1.Commit(); + + c4_View d4 = s1.GetAs("d4[p1:S]"); + c4_View m4 = s1.GetAs("m4[_H:I,_R:I]"); + c4_View h4 = d4.Hash(m4); + + h1.Add(p1 ["four"]); + h2.Add(p1 ["four"]); + h3.Add(p1 ["four"]); + h4.Add(p1 ["four"]); + s1.Commit(); + + } D(m03a); R(m03a); E; + + B(m04, Locate bug, 0) W(m04a); + { + c4_IntProp p1 ("p1"); + c4_StringProp p2 ("p2"); + + c4_Storage s1 ("m04a", true); + s1.AutoCommit(); + + c4_View v1 = s1.GetAs("v1[p1:I,p2:S]"); + + v1.Add(p1 [1] + p2 ["one"]); + v1.Add(p1 [2] + p2 ["two"]); + v1.Add(p1 [3] + p2 ["three"]); + s1.Commit(); + + c4_View v2 = v1.Ordered(); + A(v2.GetSize() == 3); + v2.Add(p1 [6] + p2 ["six"]); + v2.Add(p1 [5] + p2 ["five"]); + v2.Add(p1 [4] + p2 ["four"]); + A(v2.GetSize() == 6); + A(v1.GetSize() == 6); + + A(p1 (v1[0]) == 1); + A(p1 (v1[1]) == 2); + A(p1 (v1[2]) == 3); + A(p1 (v1[3]) == 4); + A(p1 (v1[4]) == 5); + A(p1 (v1[5]) == 6); + + A(v2.Find(p1 [4]) == 3); + A(v2.Search(p1 [4]) == 3); + + int i1 = -1; + A(v1.Locate(p1 [4], &i1) == 1); + A(i1 == 3); + + int i2 = -1; + A(v2.Locate(p1 [4], &i2) == 1); + A(i2 == 3); + + } D(m04a); R(m04a); E; + + // subviews are not relocated properly with blocked views in 2.4.7 + B(m05, Blocked view with subviews, 0) W(m05a); + { + char buf[10]; + c4_StringProp p1 ("p1"); + c4_IntProp p2 ("p2"); + c4_ViewProp pSv ("sv"); + + c4_Storage s1 ("m05a", true); + c4_View v1 = s1.GetAs("v1[_B[p1:S,sv[p2:I]]]"); + c4_View v2 = v1.Blocked(); + + for (int i = 0; i < 1000; ++i) { + sprintf(buf, "id-%d", i); + v2.Add(p1 [buf]); + + c4_View v3 = pSv (v2[i]); + v3.Add(p2 [i]); + } + + for (int j = 0; j < 1; ++j) { + sprintf(buf, "insert-%d", j); + v2.InsertAt(500, p1 [buf]); + } + + s1.Commit(); + + } D(m05a); R(m05a); E; + + // 2003/02/14 - assert fails for 2.4.8 in c4_Column::RemoveData + B(m06, Blocked view multi-row deletion, 0) W(m06a); + { + c4_IntProp p1 ("p1"); + + c4_Storage s1 ("m06a", true); + c4_View v1 = s1.GetAs("v1[p1:I]"); + c4_View v2 = s1.GetAs("v2[_B[_H:I,_R:I]]"); + c4_View v3 = v2.Blocked(); + c4_View v4 = v1.Hash(v3, 1); + + v4.Add(p1 [1]); + v4.Add(p1 [2]); + v4.RemoveAt(1); + + for (int i = 100; i < 1000; ++i) { + v4.Add(p1 [i]); + } + + s1.Commit(); + + } D(m06a); R(m06a); E; + + // 2003/03/07 - still not correct on blocked veiw deletions + B(m07, All blocked view multi-deletion cases, 0); + { + int i, j; + for (i = 0; i < 2; ++i) { + for (j = 1; j < 4; ++j) + TestBlockDel(i, j); + for (j = 998; j < 1002; ++j) + TestBlockDel(i, j); + for (j = 1998; j < 2002; ++j) + TestBlockDel(i, j); + } + for (i = 998; i < 1002; ++i) { + for (j = 1; j < 4; ++j) + TestBlockDel(i, j); + for (j = 998; j < 1002; ++j) + TestBlockDel(i, j); + } + for (i = 1; i < 4; ++i) + TestBlockDel(2999 - i, i); + for (i = 998; i < 1002; ++i) + TestBlockDel(2999 - i, i); + for (i = 1998; i < 2002; ++i) + TestBlockDel(2999 - i, i); + } E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tnotify.cpp b/akregator/src/mk4storage/metakit/tests/tnotify.cpp new file mode 100644 index 000000000..e630db951 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tnotify.cpp @@ -0,0 +1,444 @@ +// tnotify.cpp -- Regression test program, notification tests +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestNotify() +{ + B(n01, Add to selection, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + v1.Add(p1 [345]); + v1.Add(p1 [234]); + v1.Add(p1 [123]); + A(v1.GetSize() == 6); + c4_View v2 = v1.SelectRange(p1 [200], p1 [333]); + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + v1.Add(p1 [300]); + A(v1.GetSize() == 7); + A(v2.GetSize() == 4); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + A(p1 (v2[3]) == 300); + v1.Add(p1 [199]); + A(v1.GetSize() == 8); + A(v2.GetSize() == 4); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + A(p1 (v2[3]) == 300); + } E; + + B(n02, Remove from selection, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + v1.Add(p1 [345]); + v1.Add(p1 [234]); + v1.Add(p1 [123]); + A(v1.GetSize() == 6); + c4_View v2 = v1.SelectRange(p1 [200], p1 [333]); + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + v1.RemoveAt(2); + A(v1.GetSize() == 5); + A(v2.GetSize() == 2); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 234); + v1.RemoveAt(2); + A(v1.GetSize() == 4); + A(v2.GetSize() == 2); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 234); + } E; + + B(n03, Modify into selection, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + v1.Add(p1 [345]); + v1.Add(p1 [234]); + v1.Add(p1 [123]); + A(v1.GetSize() == 6); + c4_View v2 = v1.SelectRange(p1 [200], p1 [333]); + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + p1 (v1[5]) = 300; + A(v2.GetSize() == 4); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + A(p1 (v2[3]) == 300); + } E; + + B(n04, Modify out of selection, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + v1.Add(p1 [345]); + v1.Add(p1 [234]); + v1.Add(p1 [123]); + A(v1.GetSize() == 6); + c4_View v2 = v1.SelectRange(p1 [200], p1 [333]); + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + p1 (v1[2]) = 100; + A(v2.GetSize() == 2); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 234); + } E; + + B(n05, Add to sorted, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + v1.Add(p1 [345]); + v1.Add(p1 [234]); + v1.Add(p1 [123]); + A(v1.GetSize() == 6); + c4_View v2 = v1.Sort(); + A(v2.GetSize() == 6); + A(p1 (v2[0]) == 111); + A(p1 (v2[1]) == 123); + A(p1 (v2[2]) == 222); + A(p1 (v2[3]) == 234); + A(p1 (v2[4]) == 333); + A(p1 (v2[5]) == 345); + v1.Add(p1 [300]); + A(v2.GetSize() == 7); + A(p1 (v2[0]) == 111); + A(p1 (v2[1]) == 123); + A(p1 (v2[2]) == 222); + A(p1 (v2[3]) == 234); + A(p1 (v2[4]) == 300); + A(p1 (v2[5]) == 333); + A(p1 (v2[6]) == 345); + } E; + + B(n06, Remove from sorted, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.Add(p1 [111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + v1.Add(p1 [345]); + v1.Add(p1 [234]); + v1.Add(p1 [123]); + A(v1.GetSize() == 6); + c4_View v2 = v1.Sort(); + A(v2.GetSize() == 6); + A(p1 (v2[0]) == 111); + A(p1 (v2[1]) == 123); + A(p1 (v2[2]) == 222); + A(p1 (v2[3]) == 234); + A(p1 (v2[4]) == 333); + A(p1 (v2[5]) == 345); + v1.RemoveAt(2); + A(v2.GetSize() == 5); + A(p1 (v2[0]) == 111); + A(p1 (v2[1]) == 123); + A(p1 (v2[2]) == 222); + A(p1 (v2[3]) == 234); + A(p1 (v2[4]) == 345); + } E; + + B(n07, New property through sort, 0) + { + c4_IntProp p1 ("p1"), p2 ("p2"); + c4_View v1; + v1.Add(p1 [11]); + v1.Add(p1 [1]); + v1.Add(p1 [111]); + A(v1.FindProperty(p2.GetId()) < 0); + + c4_View v2 = v1.SortOn(p1); + A(v2.FindProperty(p2.GetId()) < 0); + + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 1); + A(p1 (v2[1]) == 11); + A(p1 (v2[2]) == 111); + + p2 (v1[0]) = 22; + A(v1.FindProperty(p2.GetId()) == 1); + A(v2.FindProperty(p2.GetId()) == 1); + + A(p2 (v2[1]) == 22); + } E; + + B(n08, Nested project and select, 0) + { + c4_IntProp p1 ("p1"), p2 ("p2"); + c4_View v1; + v1.Add(p1 [10] + p2 [1]); + v1.Add(p1 [11]); + v1.Add(p1 [12] + p2 [1]); + v1.Add(p1 [13]); + v1.Add(p1 [14] + p2 [1]); + v1.Add(p1 [15]); + v1.Add(p1 [16] + p2 [1]); + A(v1.GetSize() == 7); + + c4_View v2 = v1.Select(p2 [1]); + A(v2.GetSize() == 4); + A(p1 (v2[0]) == 10); + A(p1 (v2[1]) == 12); + A(p1 (v2[2]) == 14); + A(p1 (v2[3]) == 16); + + c4_View v3 = v2.Project(p1); + A(v3.GetSize() == 4); + A(p1 (v3[0]) == 10); + A(p1 (v3[1]) == 12); + A(p1 (v3[2]) == 14); + A(p1 (v3[3]) == 16); + + A(p2 (v3[0]) == 0); + A(p2 (v3[1]) == 0); + A(p2 (v3[2]) == 0); + A(p2 (v3[3]) == 0); + +/* not yet implemented: setting result of selection + p1 (v3[1]) = 123; + A(p1 (v3[1]) == 123); + A(p1 (v2[1]) == 123); + A(p1 (v1[2]) == 123); +*/ + } E; + + B(n09, Multiple dependencies, 0) + { + c4_IntProp p1 ("p1"), p2 ("p2"); + c4_View v1; + v1.Add(p1 [111] + p2[1111]); + v1.Add(p1 [222]); + v1.Add(p1 [333]); + v1.Add(p1 [345]); + v1.Add(p1 [234]); + v1.Add(p1 [123]); + A(v1.GetSize() == 6); + + c4_View v2 = v1.SelectRange(p1 [200], p1 [333]); + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + + c4_View v3 = v1.SelectRange(p1 [340], p1 [350]); + A(v3.GetSize() == 1); + A(p1 (v3[0]) == 345); + + c4_View v4 = v2.SortOn(p1); + A(v4.GetSize() == 3); + A(p1 (v4[0]) == 222); + A(p1 (v4[1]) == 234); + A(p1 (v4[2]) == 333); + + c4_View v5 = v3.SortOn(p1); + A(v5.GetSize() == 1); + A(p1 (v5[0]) == 345); + + p1 (v1[2]) = 346; + + A(v2.GetSize() == 2); + A(p1 (v2[0]) == 222); + A(p1 (v2[1]) == 234); + + A(v3.GetSize() == 2); + A(p1 (v3[0]) == 346); + A(p1 (v3[1]) == 345); + + A(v4.GetSize() == 2); + A(p1 (v4[0]) == 222); + A(p1 (v4[1]) == 234); + + A(v5.GetSize() == 2); + A(p1 (v5[0]) == 345); + A(p1 (v5[1]) == 346); + } E; + + B(n10, Modify sorted duplicates, 0) + { + c4_IntProp p1 ("p1"); + c4_View v1; + v1.SetSize(3); + p1 (v1[0]) = 0; + c4_View v2 = v1.Sort(); + p1 (v1[0]) = 1; + p1 (v1[1]) = 1; // crashed in 1.5, fix in: c4_SortSeq::PosInMap + } E; + + B(n11, Resize compound derived view, 0) + { + c4_IntProp p1 ("p1"), p2 ("p2"); + c4_View v1 = (p1, p2); + c4_View v2 = v1.SelectRange(p2 [200], p2 [333]); + c4_View v3 = v2.SortOn(p1); + A(v2.GetSize() == 0); + A(v3.GetSize() == 0); + v1.SetSize(1); // crashed in 1.5, fix in: c4_FilterSeq::Match + A(v1.GetSize() == 1); + A(v2.GetSize() == 0); + A(v3.GetSize() == 0); + v1[0] = p2 [300]; + A(v1.GetSize() == 1); + A(v2.GetSize() == 1); + A(v3.GetSize() == 1); + A(p2 (v2[0]) == 300); + v1.Add(p1 [199]); + A(v1.GetSize() == 2); + A(v2.GetSize() == 1); + A(p2 (v2[0]) == 300); + } E; + + B(n12, Alter multiply derived view, 0) + { + c4_IntProp p1 ("p1"); + c4_StringProp p2 ("p2"), p3 ("p3"); + c4_View v1 = (p1, p2); + c4_View v2 = v1.Select(p1 [1]); + c4_View v3 = v2.SortOn(p2); + c4_View v4 = v1.Select(p1 [2]); + c4_View v5 = v4.SortOn(p2); + + v1.Add(p1[1] + p2 ["een"] + p3 ["1"]); + v1.Add(p1[1] + p2 ["elf"] + p3 ["11"]); + v1.Add(p1[2] + p2 ["twee"] + p3 ["2"]); + v1.Add(p1[2] + p2 ["twaalf"] + p3 ["12"]); + v1.Add(p1[2] + p2 ["twintig"] + p3 ["20"]); + v1.Add(p1[2] + p2 ["tachtig"] + p3 ["80"]); + + A(v1.GetSize() == 6); + A(v2.GetSize() == 2); + A(v3.GetSize() == 2); + A(v4.GetSize() == 4); + A(v5.GetSize() == 4); + + A(p3 (v1[2]) == (c4_String) "2"); + A(p3 (v4[0]) == (c4_String) "2"); + + A(p3 (v3[0]) == (c4_String) "1"); + A(p3 (v3[1]) == (c4_String) "11"); + + A(p3 (v5[0]) == (c4_String) "80"); + A(p3 (v5[1]) == (c4_String) "12"); + A(p3 (v5[2]) == (c4_String) "2"); + A(p3 (v5[3]) == (c4_String) "20"); + + v1[3] = p1[2] + p2 ["twaalf"] + p3 ["12+"]; + + A(p3 (v3[0]) == (c4_String) "1"); + A(p3 (v3[1]) == (c4_String) "11"); + + A(p3 (v1[3]) == (c4_String) "12+"); + A(p3 (v4[1]) == (c4_String) "12+"); + + A(p3 (v5[0]) == (c4_String) "80"); + A(p3 (v5[1]) == (c4_String) "12+"); + A(p3 (v5[2]) == (c4_String) "2"); + A(p3 (v5[3]) == (c4_String) "20"); + } E; + + B(n13, Project without, 0) // failed in 1.8.4 + { + c4_IntProp p1 ("p1"), p2 ("p2"); + c4_View v1; + + v1.Add(p1 [1] + p2 [2]); + int n1 = v1.NumProperties(); + A(n1 == 2); + + c4_View v2 = v1.ProjectWithout(p2); + int n2 = v2.NumProperties(); + A(n2 == 1); + } E; + +/* + B(n14, Add to reverse sorted, 0) + { + c4_IntProp p1 ("p1"), p2 ("p2"); + c4_View v1; + v1.Add(p1 [333] + p2 [1]); + v1.Add(p1 [345] + p2 [1]); + v1.Add(p1 [234] + p2 [1]); + v1.Add(p1 [123] + p2 [0]); + A(v1.GetSize() == 4); + c4_View v1a = v1.Select(p2 [1]); + A(v1a.GetSize() == 3); + c4_View v1b = v1a.SelectRange(p1 [100], p1 [999]); + A(v1b.GetSize() == 3); + c4_View v2 = v1b.SortOnReverse(p1, p1); + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 345); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 234); + v1.Add(p1 [300] + p2 [1]); + A(v2.GetSize() == 4); + A(p1 (v2[0]) == 345); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 300); + A(p1 (v2[3]) == 234); + v1.Add(p1 [299] + p2 [1]); + A(v2.GetSize() == 5); + A(p1 (v2[0]) == 345); + A(p1 (v2[1]) == 333); + A(p1 (v2[2]) == 300); + A(p1 (v2[3]) == 299); + A(p1 (v2[4]) == 234); + } E; +*/ + // this failed in 2.4.8, reported by S. Selznick, 2002-11-22 + B(n14, Insert in non-mapped position, 0) W(n14a); + { + c4_IntProp p1 ("p1"); + c4_Storage s1 ("n14a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + + static int intlist[] = { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, -1 }; + for (int c = 0; -1 != intlist[c]; c++) + v1.Add(p1 [intlist[c]]); + + A(v1.GetSize() == 10); + c4_View v2 = v1.Select(p1 [1]); + A(v2.GetSize() == 3); + + v1.InsertAt(3, p1 [6]); + A(v1.GetSize() == 11); + A(v2.GetSize() == 3); + + v1.InsertAt(7, p1 [1]); + A(v1.GetSize() == 12); + A(v2.GetSize() == 4); + + s1.Commit(); + } D(n14a); R(n14a); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tresize.cpp b/akregator/src/mk4storage/metakit/tests/tresize.cpp new file mode 100644 index 000000000..e6011090d --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tresize.cpp @@ -0,0 +1,289 @@ +// trseize.cpp -- Regression test program, resizing tests +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +#include "regress.h" + +#include <stdlib.h> // strtol +#include <string.h> // memory functions + +class CResizer : public c4_Storage +{ +public: + CResizer (const char* file); + ~CResizer (); + + void Verify(); + + int Ins(int, int); + int Del(int, int); + +private: + enum { kMaxData = 15000 }; + char* _refData; + int _refSize; + + c4_View _attached; + c4_View _unattached; + c4_IntProp _prop; + + char _seed; + + CResizer (const CResizer&); // not implemented + void operator= (const CResizer&); // not implemented +}; + +CResizer::CResizer (const char* file) + : c4_Storage (file, 1), _refSize (0), _prop ("p1"), _seed (0) +{ + SetStructure("a[p1:I]"); + + _refData = new char [kMaxData]; + + _attached = View("a"); + + Verify(); +} + +CResizer::~CResizer () +{ + Verify(); + + Commit(); + + Verify(); + + delete [] _refData; +} + +void CResizer::Verify() +{ + int i; + + A(_refSize == _unattached.GetSize()); + A(_refSize == _attached.GetSize()); + + for (i = 0; i < _refSize; ++i) + { + A(_refData[i] == _prop (_unattached[i])); + A(_refData[i] == _prop (_attached[i])); + } +} + +int CResizer::Ins(int pos_, int cnt_) +{ + A(pos_ <= _refSize); + A(_refSize + cnt_ < kMaxData); + + memmove(_refData + pos_ + cnt_, _refData + pos_, _refSize - pos_); + _refSize += cnt_; + + c4_Row row; + _unattached.InsertAt(pos_, row, cnt_); + _attached.InsertAt(pos_, row, cnt_); + + for (int i = pos_; i < pos_ + cnt_; ++i) + { + _refData[i] = ++_seed; + _prop (_unattached[i]) = _seed; + _prop (_attached[i]) = _seed; + + if (_seed >= 123) + _seed = 0; + } + + Verify(); + + return _refSize; +} + +int CResizer::Del(int pos_, int cnt_) +{ + A(pos_ + cnt_ <= _refSize); + + _refSize -= cnt_; + memmove(_refData + pos_, _refData + pos_ + cnt_, _refSize - pos_); + + _unattached.RemoveAt(pos_, cnt_); + _attached.RemoveAt(pos_, cnt_); + + Verify(); + + return _refSize; +} + +void TestResize() +{ + B(r00, Simple insert, 0) W(r00a); + { + CResizer r1 ("r00a"); + + int n = r1.Ins(0, 250); + A(n == 250); + + } D(r00a); R(r00a); E; + + B(r01, Simple removes, 0) W(r01a); + { + CResizer r1 ("r01a"); + int n; + + n = r1.Ins( 0, 500); A(n == 500); + + n = r1.Del( 0, 50); A(n == 450); + n = r1.Del( 350, 100); A(n == 350); + n = r1.Del( 25, 150); A(n == 200); + n = r1.Del( 0, 200); A(n == 0); + + n = r1.Ins( 0, 15); A(n == 15); + + } D(r01a); R(r01a); E; + + B(r02, Large inserts and removes, 0) W(r02a); + { + int big = sizeof (int) == sizeof (short) ? 1000 : 4000; + + CResizer r1 ("r02a"); + int n; + + n = r1.Ins( 0, 2000); A(n == 2000); + n = r1.Ins( 0, 3000); A(n == 5000); + n = r1.Ins(5000, 1000 + big); A(n == 6000 + big); + n = r1.Ins( 100, 10); A(n == 6010 + big); + n = r1.Ins(4000, 100); A(n == 6110 + big); + n = r1.Ins( 0, 1001); A(n == 7111 + big); + + n = r1.Del(7111, big); A(n == 7111); + n = r1.Del( 0, 4111); A(n == 3000); + n = r1.Del( 10, 10); A(n == 2990); + n = r1.Del( 10, 10); A(n == 2980); + n = r1.Del( 5, 10); A(n == 2970); + n = r1.Del( 0, 990); A(n == 1980); + n = r1.Del( 3, 1975); A(n == 5); + + } D(r02a); R(r02a); E; + + B(r03, Binary property insertions, 0) W(r03a); + { + c4_BytesProp p1 ("p1"); + c4_Storage s1 ("r03a", 1); + s1.SetStructure("a[p1:B]"); + c4_View v1 = s1.View("a"); + + char buf [1024]; + + memset(buf, 0x11, sizeof buf); + v1.Add(p1 [c4_Bytes (buf, sizeof buf)]); + + memset(buf, 0x22, sizeof buf); + v1.Add(p1 [c4_Bytes (buf, sizeof buf / 2)]); + + s1.Commit(); + + memset(buf, 0x33, sizeof buf); + p1 (v1[1]) = c4_Bytes (buf, sizeof buf); // fix c4_Column::CopyData + + memset(buf, 0x44, sizeof buf); + v1.Add(p1 [c4_Bytes (buf, sizeof buf / 3)]); + + s1.Commit(); + + memset(buf, 0x55, sizeof buf); + v1.InsertAt(1, p1 [c4_Bytes (buf, sizeof buf)]); + + memset(buf, 0x66, sizeof buf); + v1.InsertAt(1, p1 [c4_Bytes (buf, sizeof buf / 4)]); + + s1.Commit(); + + } D(r03a); R(r03a); E; + + B(r04, Scripted string property tests, 0) W(r04a); + { + c4_StringProp p1 ("p1"); + c4_Storage s1 ("r04a", 1); + s1.SetStructure("a[p1:S]"); + + // This code implements a tiny language to specify tests in: + // + // "<X>,<Y>A" add X partial buffers of size Y + // "<X>a" add X full buffers at end + // "<X>,<Y>C" change entry X to a partial buffer of size Y + // "<X>c" change entry at position X to a full buffer + // "<X>,<Y>I" insert partial buffer of size Y at position X + // "<X>i" insert a full buffer at position X + // "<X>,<Y>R" remove Y entries at position X + // "<X>r" remove one entry at position X + // + // ">" commit changes + // "<" rollback changes + // + // " " ignore spaces + // "<X>," for additional args + // "<X>=" verify number of rows is X + + const char* scripts [] = + { + // A B C D E F G H I J + "5a 5a 5a 1r 5r 10r 6r 2r > 10=", + "5a 5a 5a 1,200C 5,200C 10,200C 6,200C 2,200C > 15=", + "5a 5a 5a 1,300C 5,300C 10,300C 6,300C 2,300C > 15=", + + // A B C D E F G H I J + "50a 50a 50a 10r 50r 100r 60r 20r > 145=", + "50a 50a 50a 10,200C 50,200C 100,200C 60,200C 20,200C > 150=", + "50a 50a 50a 10,300C 50,300C 100,300C 60,300C 20,300C > 150=", + + // A B C D E F G H I J + "50,0A 50,0A 50,0A 10c 50c 100c 60c 20c > 150=", // asserts in 1.7b1 + + // A B C D E + "3,3A 1,10C 1,1C > 3=", // asserts in 1.7 - June 6 build + + "", + 0 + }; + + for (int i = 0; scripts[i]; ++i) + { + c4_View v1 = s1.View("a"); + v1.RemoveAll(); + s1.Commit(); + A(v1.GetSize() == 0); // start with a clean slate each time + + const char* p = scripts[i]; + + char fill = '@'; + int save = 0; + c4_Row row; + + while (*p) + { + // default is a string of 255 chars (with additional null byte) + p1 (row) = c4_String (++fill, 255); + + int arg = (int) strtol(p, (char**) &p, 10); // loses const + + switch (*p++) + { + case 'A': p1 (row) = c4_String (fill, arg); arg = save; + case 'a': while (--arg >= 0) v1.Add(row); break; + case 'C': p1 (row) = c4_String (fill, arg); arg = save; + case 'c': v1.SetAt(arg, row); break; + case 'I': p1 (row) = c4_String (fill, arg); arg = save; + case 'i': v1.InsertAt(arg, row); break; + case 'R': v1.RemoveAt(save, arg); break; + case 'r': v1.RemoveAt(arg); break; + case '>': s1.Commit(); break; + case '<': s1.Rollback(); v1 = s1.View("a"); break; + case ' ': break; + case ',': save = arg; break; + case '=': A(v1.GetSize() == arg); break; + } + } + } + + s1.Commit(); + + } D(r04a); R(r04a); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tstore1.cpp b/akregator/src/mk4storage/metakit/tests/tstore1.cpp new file mode 100644 index 000000000..c071648a6 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tstore1.cpp @@ -0,0 +1,180 @@ +// tstore1.cpp -- Regression test program, storage tests, part 1 +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestStores1() +{ + B(s00, Simple storage, 0) W(s00a); + { + c4_Storage s1 ("s00a", 1); + s1.SetStructure("a[p1:I]"); + s1.Commit(); + } D(s00a); R(s00a); E; + + B(s01, Integer storage, 0) W(s01a); + { + c4_IntProp p1 ("p1"); + c4_Storage s1 ("s01a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + v1.Add(p1 [456]); + v1.InsertAt(1, p1 [789]); + A(v1.GetSize() == 3); + s1.Commit(); + A(v1.GetSize() == 3); + } D(s01a); R(s01a); E; + +#if !q4_TINY + B(s02, Float storage, 0) W(s02a); + { + c4_FloatProp p1 ("p1"); + c4_Storage s1 ("s02a", 1); + s1.SetStructure("a[p1:F]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [12.3]); + v1.Add(p1 [45.6]); + v1.InsertAt(1, p1 [78.9]); + s1.Commit(); + } D(s02a); R(s02a); E; +#endif + + B(s03, String storage, 0) W(s03a); + { + c4_StringProp p1 ("p1"); + c4_Storage s1 ("s03a", 1); + s1.SetStructure("a[p1:S]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 ["one"]); + v1.Add(p1 ["two"]); + v1.InsertAt(1, p1 ["three"]); + s1.Commit(); + } D(s03a); R(s03a); E; + + B(s04, View storage, 0) W(s04a); + { + c4_StringProp p1 ("p1"); + c4_ViewProp p2 ("p2"); + c4_IntProp p3 ("p3"); + c4_Storage s1 ("s04a", 1); + s1.SetStructure("a[p1:S,p2[p3:I]]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 ["one"]); + v1.Add(p1 ["two"]); + c4_View v2 = p2 (v1[0]); + v2.Add(p3 [1]); + v2 = p2 (v1[1]); + v2.Add(p3 [11]); + v2.Add(p3 [22]); + v1.InsertAt(1, p1 ["three"]); + v2 = p2 (v1[1]); + v2.Add(p3 [111]); + v2.Add(p3 [222]); + v2.Add(p3 [333]); + s1.Commit(); + } D(s04a); R(s04a); E; + + B(s05, Store and reload, 0) W(s05a); + { + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("s05a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + s1.Commit(); + } + { + c4_Storage s1 ("s05a", 0); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + } + } D(s05a); R(s05a); E; + + B(s06, Commit twice, 0) W(s06a); + { + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("s06a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + s1.Commit(); + v1.Add(p1 [234]); + s1.Commit(); + } + { + c4_Storage s1 ("s06a", 0); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 123); + A(p1 (v1[1]) == 234); + } + } D(s06a); R(s06a); E; + + B(s07, Commit modified, 0) W(s07a); + { + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("s07a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + s1.Commit(); + p1 (v1[0]) = 234; + s1.Commit(); + } + { + c4_Storage s1 ("s07a", 0); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 234); + } + } D(s07a); R(s07a); E; + + B(s08, View after storage, 0) W(s08a); + { + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("s08a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + s1.Commit(); + } + c4_View v1; + { + c4_Storage s1 ("s08a", 0); + v1 = s1.View("a"); + } + // 19990916 - semantics changed, view now 1 row, but 0 props + A(v1.GetSize() == 1); + A(v1.NumProperties() == 0); + v1.InsertAt(0, p1 [234]); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 234); + A(p1 (v1[1]) == 0); // the original value is gone + } D(s08a); R(s08a); E; + + B(s09, Copy storage, 0) W(s09a); W(s09b); + { + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("s09a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + s1.Commit(); + } + { + c4_Storage s1 ("s09a", 0); + c4_Storage s2 ("s09b", 1); + s2.SetStructure("a[p1:I]"); + s2.View("a") = s1.View("a"); + s2.Commit(); + } + } D(s09a); D(s09b); R(s09a); R(s09b); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tstore2.cpp b/akregator/src/mk4storage/metakit/tests/tstore2.cpp new file mode 100644 index 000000000..371ffcca5 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tstore2.cpp @@ -0,0 +1,326 @@ +// tstore2.cpp -- Regression test program, storage tests, part 2 +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestStores2() +{ + B(s10, Stream storage, 0) W(s10a); W(s10b); W(s10c); + { + // s10a is original + // s10b is a copy, random access + // s10c is a serialized copy + c4_StringProp p1 ("p1"); + c4_ViewProp p2 ("p2"); + c4_IntProp p3 ("p3"); + { + c4_Storage s1 ("s10a", 1); + s1.SetStructure("a[p1:S,p2[p3:I]]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 ["one"]); + v1.Add(p1 ["two"]); + c4_View v2 = p2 (v1[0]); + v2.Add(p3 [1]); + v2 = p2 (v1[1]); + v2.Add(p3 [11]); + v2.Add(p3 [22]); + v1.InsertAt(1, p1 ["three"]); + v2 = p2 (v1[1]); + v2.Add(p3 [111]); + v2.Add(p3 [222]); + v2.Add(p3 [333]); + s1.Commit(); + } + { + c4_Storage s1 ("s10a", 0); + c4_Storage s2 ("s10b", 1); + s2.SetStructure("a[p1:S,p2[p3:I]]"); + s2.View("a") = s1.View("a"); + s2.Commit(); + } + { + c4_Storage s3 ("s10b", 0); + + c4_FileStream fs1 (fopen("s10c", "wb"), true); + s3.SaveTo(fs1); + } + { + c4_Storage s1 ("s10c", 0); // new after 2.01: serialized is no longer special + + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 3); + c4_View v2 = p2 (v1[0]); + A(v2.GetSize() == 1); + c4_View v3 = p2 (v1[1]); + A(v3.GetSize() == 3); + c4_View v4 = p2 (v1[2]); + A(v4.GetSize() == 2); + } + { + c4_Storage s1; + + c4_FileStream fs1 (fopen("s10c", "rb"), true); + s1.LoadFrom(fs1); + + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 3); + c4_View v2 = p2 (v1[0]); + A(v2.GetSize() == 1); + c4_View v3 = p2 (v1[1]); + A(v3.GetSize() == 3); + c4_View v4 = p2 (v1[2]); + A(v4.GetSize() == 2); + } + { + c4_Storage s1 ("s10c", 1); + + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 3); + c4_View v2 = p2 (v1[0]); + A(v2.GetSize() == 1); + c4_View v3 = p2 (v1[1]); + A(v3.GetSize() == 3); + c4_View v4 = p2 (v1[2]); + A(v4.GetSize() == 2); + v1.Add(p1 ["four"]); + s1.Commit(); + } + { + c4_Storage s1 ("s10c", 0); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 4); + c4_View v2 = p2 (v1[0]); + A(v2.GetSize() == 1); + c4_View v3 = p2 (v1[1]); + A(v3.GetSize() == 3); + c4_View v4 = p2 (v1[2]); + A(v4.GetSize() == 2); + c4_View v5 = p2 (v1[3]); + A(v5.GetSize() == 0); + } + } D(s10a); D(s10b); D(s10c); R(s10a); R(s10b); R(s10c); E; + + B(s11, Commit and rollback, 0) W(s11a); + { + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("s11a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + s1.Commit(); + } + { + c4_Storage s1 ("s11a", 0); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + v1.InsertAt(0, p1 [234]); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 234); + A(p1 (v1[1]) == 123); + s1.Rollback(); + // 19990916 - semantics changed, still 2 rows, but 0 props + A(v1.GetSize() == 2); + A(v1.NumProperties() == 0); + v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + } + } D(s11a); R(s11a); E; + + B(s12, Remove subview, 0) W(s12a); + { + c4_IntProp p1 ("p1"), p3 ("p3"); + c4_ViewProp p2 ("p2"); + { + c4_Storage s1 ("s12a", 1); + s1.SetStructure("a[p1:I,p2[p3:I]]"); + c4_View v1 = s1.View("a"); + c4_View v2; + v2.Add(p3 [234]); + v1.Add(p1 [123] + p2 [v2]); + s1.Commit(); + } + { + c4_Storage s1 ("s12a", 1); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 123); + c4_View v2 = p2 (v1[0]); + A(v2.GetSize() == 1); + A(p3 (v2[0]) == 234); + v1.RemoveAt(0); + A(v1.GetSize() == 0); + s1.Commit(); + A(v1.GetSize() == 0); + } + } D(s12a); R(s12a); E; + + B(s13, Remove middle subview, 0) W(s13a); + { + c4_IntProp p1 ("p1"), p3 ("p3"); + c4_ViewProp p2 ("p2"); + { + c4_Storage s1 ("s13a", 1); + s1.SetStructure("a[p1:I,p2[p3:I]]"); + c4_View v1 = s1.View("a"); + + c4_View v2a; + v2a.Add(p3 [234]); + v1.Add(p1 [123] + p2 [v2a]); + + c4_View v2b; + v2b.Add(p3 [345]); + v2b.Add(p3 [346]); + v1.Add(p1 [124] + p2 [v2b]); + + c4_View v2c; + v2c.Add(p3 [456]); + v2c.Add(p3 [457]); + v2c.Add(p3 [458]); + v1.Add(p1 [125] + p2 [v2c]); + + s1.Commit(); + } + { + c4_Storage s1 ("s13a", 1); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 3); + A(p1 (v1[0]) == 123); + A(p1 (v1[1]) == 124); + A(p1 (v1[2]) == 125); + c4_View v2a = p2 (v1[0]); + A(v2a.GetSize() == 1); + A(p3 (v2a[0]) == 234); + c4_View v2b = p2 (v1[1]); + A(v2b.GetSize() == 2); + A(p3 (v2b[0]) == 345); + c4_View v2c = p2 (v1[2]); + A(v2c.GetSize() == 3); + A(p3 (v2c[0]) == 456); + v1.RemoveAt(1); + A(v1.GetSize() == 2); + v2a = p2 (v1[0]); + A(v2a.GetSize() == 1); + A(p3 (v2a[0]) == 234); + v2b = p2 (v1[1]); + A(v2b.GetSize() == 3); + A(p3 (v2b[0]) == 456); + s1.Commit(); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 123); + A(p1 (v1[1]) == 125); + } + } D(s13a); R(s13a); E; + + B(s14, Replace attached subview, 0) W(s14a); + { + c4_IntProp p1 ("p1"); + c4_ViewProp p2 ("p2"); + { + c4_Storage s1 ("s14a", 1); + s1.SetStructure("a[p1:I,p2[p3:I]]"); + c4_View v1 = s1.View("a"); + + v1.Add(p1 [123] + p2 [c4_View ()]); + A(v1.GetSize() == 1); + + v1[0] = p2 [c4_View ()]; + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 0); + + s1.Commit(); + } + } D(s14a); R(s14a); E; + + B(s15, Add after removed subviews, 0) W(s15a); + { + c4_IntProp p1 ("p1"), p3 ("p3"); + c4_ViewProp p2 ("p2"); + { + c4_Storage s1 ("s15a", 1); + s1.SetStructure("a[p1:I,p2[p3:I]]"); + c4_View v1 = s1.View("a"); + + c4_View v2; + v2.Add(p3 [234]); + + v1.Add(p1 [123] + p2 [v2]); + v1.Add(p1 [456] + p2 [v2]); + v1.Add(p1 [789] + p2 [v2]); + A(v1.GetSize() == 3); + + v1[0] = v1[2]; + v1.RemoveAt(2); + + v1[0] = v1[1]; + v1.RemoveAt(1); + + v1.RemoveAt(0); + + v1.Add(p1 [111] + p2 [v2]); + + s1.Commit(); + } + } D(s15a); R(s15a); E; + + B(s16, Add after removed ints, 0) W(s16a); + { + c4_IntProp p1 ("p1"); + + c4_Storage s1 ("s16a", 1); + s1.SetStructure("a[p1:I,p2[p3:I]]"); + c4_View v1 = s1.View("a"); + + v1.Add(p1 [1]); + v1.Add(p1 [2]); + v1.Add(p1 [3]); + + v1.RemoveAt(2); + v1.RemoveAt(1); + v1.RemoveAt(0); + + v1.Add(p1 [4]); + + s1.Commit(); + + } D(s16a); R(s16a); E; + + B(s17, Add after removed strings, 0) W(s17a); + { + c4_StringProp p1 ("p1"); + + c4_Storage s1 ("s17a", 1); + s1.SetStructure("a[p1:S,p2[p3:I]]"); + c4_View v1 = s1.View("a"); + + v1.Add(p1 ["one"]); + v1.Add(p1 ["two"]); + v1.Add(p1 ["three"]); + + v1.RemoveAt(2); + v1.RemoveAt(1); + v1.RemoveAt(0); + + v1.Add(p1 ["four"]); + + s1.Commit(); + + } D(s17a); R(s17a); E; + + B(s18, Empty storage, 0) W(s18a); + { + c4_Storage s1 ("s18a", 1); + + } D(s18a); R(s18a); E; + + B(s19, Empty view outlives storage, 0) W(s19a); + { + c4_View v1; + c4_Storage s1 ("s19a", 1); + v1 = s1.GetAs("a[p1:I,p2:S]"); + + } D(s19a); R(s19a); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tstore3.cpp b/akregator/src/mk4storage/metakit/tests/tstore3.cpp new file mode 100644 index 000000000..21418151c --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tstore3.cpp @@ -0,0 +1,366 @@ +// tstore3.cpp -- Regression test program, storage tests, part 3 +// $Id$ +// This is part of Metakit, the homepage is http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestStores3() +{ + B(s20, View outlives storage, 0) W(s20a); + { + c4_IntProp p1 ("p1"); + c4_View v1; + + { + c4_Storage s1 ("s20a", 1); + v1 = s1.GetAs("a[p1:I,p2:S]"); + v1.Add(p1 [123]); + } + + // 19990916 - semantics changed, rows kept but no properties + //A(p1 (v1[0]) == 123); + A(v1.GetSize() == 1); + A(v1.NumProperties() == 0); + + } D(s20a); R(s20a); E; + + B(s21, Test demo scenario, 0) W(s21a); + { + c4_StringProp p1 ("p1"), p2 ("p2"); + { + c4_Storage storage ("s21a", 1); + storage.SetStructure("a[p1:S,p2:S]"); + c4_View v1; + c4_Row r1; + + p1 (r1) = "One"; + p2 (r1) = "Un"; + v1.Add(r1); + A(v1.GetSize() == 1); + + p1 (r1) = "Two"; + p2 (r1) = "Deux"; + v1.Add(r1); + A(v1.GetSize() == 2); + + // changed 2000-03-15: Store is gone + //v1 = storage.Store("a", v1); + v1 = storage.View("a") = v1; + + A(v1.GetSize() == 2); + A(p1 (v1[1]) == (c4_String) "Two"); + A(p2 (v1[1]) == (c4_String) "Deux"); + A(p1 (v1[0]) == (c4_String) "One"); + A(p2 (v1[0]) == (c4_String) "Un"); + + storage.Commit(); + A(v1.GetSize() == 2); + A(p1 (v1[1]) == (c4_String) "Two"); + A(p2 (v1[1]) == (c4_String) "Deux"); + A(p1 (v1[0]) == (c4_String) "One"); + A(p2 (v1[0]) == (c4_String) "Un"); + + c4_String s1 (p1 (v1[1])); + c4_String s2 (p2 (v1[1])); + A(s1 == "Two"); + A(s2 == "Deux"); + + storage.Commit(); + + v1.Add(p1 ["Three"] + p2 ["Trois"]); + + storage.Commit(); + A(v1.GetSize() == 3); + A(p2 (v1[2]) == (c4_String) "Trois"); + + v1 = storage.GetAs("a[p1:S,p2:S,p3:I]"); + A(v1.GetSize() == 3); + A(p2 (v1[2]) == (c4_String) "Trois"); + + c4_IntProp p3 ("p3"); + p3 (v1[1]) = 123; + + storage.Commit(); + A(v1.GetSize() == 3); + A(p2 (v1[2]) == (c4_String) "Trois"); + + c4_View v2 = storage.GetAs("b[p4:I]"); + + c4_IntProp p4 ("p4"); + v2.Add(p4 [234]); + + storage.Commit(); + A(v1.GetSize() == 3); + A(p2 (v1[2]) == (c4_String) "Trois"); + + c4_IntProp p4a ("p4"); + v1.InsertAt(2, p1 ["Four"] + p4a [345]); + + storage.Commit(); + A(v1.GetSize() == 4); + A(p1 (v1[0]) == (c4_String) "One"); + A(p1 (v1[1]) == (c4_String) "Two"); + A(p1 (v1[2]) == (c4_String) "Four"); + A(p1 (v1[3]) == (c4_String) "Three"); + A(p2 (v1[3]) == (c4_String) "Trois"); + A(v2.GetSize() == 1); + A(p4 (v2[0]) == 234); + } + { + c4_Storage storage ("s21a", 0); + c4_View v1 = storage.View("a"); + A(v1.GetSize() == 4); + A(p1 (v1[0]) == (c4_String) "One"); + A(p1 (v1[1]) == (c4_String) "Two"); + A(p1 (v1[2]) == (c4_String) "Four"); + A(p1 (v1[3]) == (c4_String) "Three"); + c4_View v2 = storage.View("b"); + c4_IntProp p4 ("p4"); + A(v2.GetSize() == 1); + A(p4 (v2[0]) == 234); + } + } D(s21a); R(s21a); E; + +#if !q4_TINY + B(s22, Double storage, 0) W(s22a); + { + c4_DoubleProp p1 ("p1"); + c4_Storage s1 ("s22a", 1); + s1.SetStructure("a[p1:D]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [1234.5678]); + v1.Add(p1 [2345.6789]); + v1.InsertAt(1, p1 [3456.7890]); + s1.Commit(); + } D(s22a); R(s22a); E; +#endif + + B(s23, Find absent record, 0) W(s23a); + { + c4_Storage s1 ("s23a", 1); + s1.SetStructure("v[h:S,p:I,a:I,b:I,c:I,d:I,e:I,f:I,g:I,x:I]"); + c4_View view = s1.View("v"); + + c4_StringProp H("h"); + c4_IntProp P("p"); + + c4_Row row; + H(row) = "someString"; + P(row) = 99; + + int x = view.Find(row); + A(x == -1); + + } D(s23a); R(s23a); E; + + B(s24, Bitwise storage, 0) W(s24a); + { + c4_IntProp p1 ("p1"); + + int m = 9; + + // insert values in front, but check fractional sizes at each step + for (int n = 0; n < m; ++n) + { + { + c4_Storage s1 ("s24a", 1); + s1.SetStructure("a1[p1:I],a2[p1:I],a3[p1:I],a4[p1:I]"); + s1.AutoCommit(); // new feature in 1.6 + + c4_View v1 = s1.View("a1"); + c4_View v2 = s1.View("a2"); + c4_View v3 = s1.View("a3"); + c4_View v4 = s1.View("a4"); + + c4_Row row; + int k = ~ n; + + p1 (row) = k & 0x01; + v1.InsertAt(0, row); + + p1 (row) = k & 0x03; + v2.InsertAt(0, row); + + p1 (row) = k & 0x0F; + v3.InsertAt(0, row); + + p1 (row) = k & 0x7F; + v4.InsertAt(0, row); + } + // the following checks that all tiny size combinations work + { + c4_Storage s1 ("s24a", 0); + + c4_View v1 = s1.View("a1"); + c4_View v2 = s1.View("a2"); + c4_View v3 = s1.View("a3"); + c4_View v4 = s1.View("a4"); + + A(v1.GetSize() == n + 1); + A(v2.GetSize() == n + 1); + A(v3.GetSize() == n + 1); + A(v4.GetSize() == n + 1); + } + } + + c4_Storage s1 ("s24a", 0); + + c4_View v1 = s1.View("a1"); + c4_View v2 = s1.View("a2"); + c4_View v3 = s1.View("a3"); + c4_View v4 = s1.View("a4"); + + A(v1.GetSize() == m); + A(v2.GetSize() == m); + A(v3.GetSize() == m); + A(v4.GetSize() == m); + + // now check that the inserted values are correct + for (int i = 0; i < m; ++i) + { + int j = m - i - 1; + int k = ~ i; + + A(p1 (v1[j]) == (k & 0x01)); + A(p1 (v2[j]) == (k & 0x03)); + A(p1 (v3[j]) == (k & 0x0F)); + A(p1 (v4[j]) == (k & 0x7F)); + } + + } D(s24a); R(s24a); E; + + B(s25, Bytes storage, 0) W(s25a); + { + c4_Bytes hi ("hi", 2); + c4_Bytes gday ("gday", 4); + c4_Bytes hello ("hello", 5); + + c4_BytesProp p1 ("p1"); + c4_Storage s1 ("s25a", 1); + s1.SetStructure("a[p1:B]"); + c4_View v1 = s1.View("a"); + + v1.Add(p1 [hi]); + A(p1 (v1[0]) == hi); + v1.Add(p1 [hello]); + A(p1 (v1[0]) == hi); + A(p1 (v1[1]) == hello); + v1.InsertAt(1, p1 [gday]); + A(p1 (v1[0]) == hi); + A(p1 (v1[1]) == gday); + A(p1 (v1[2]) == hello); + s1.Commit(); + A(p1 (v1[0]) == hi); + A(p1 (v1[1]) == gday); + A(p1 (v1[2]) == hello); + + } D(s25a); R(s25a); E; + + B(s26, Bitwise autosizing, 0) W(s26a); + { + c4_IntProp p1 ("p1"), p2 ("p2"), p3 ("p3"), p4 ("p4"); + c4_Storage s1 ("s26a", 1); + s1.SetStructure("a[p1:I,p2:I,p3:I,p4:I]"); + c4_View v1 = s1.View("a"); + + v1.Add(p1 [1] + p2 [3] + p3 [15] + p4 [127]); + A(p1 (v1[0]) == 1); + A(p2 (v1[0]) == 3); + A(p3 (v1[0]) == 15); + A(p4 (v1[0]) == 127); + + p1 (v1[0]) = 100000L; + p2 (v1[0]) = 100000L; + p3 (v1[0]) = 100000L; + p4 (v1[0]) = 100000L; + + // these failed in 1.61 + A(p1 (v1[0]) == 100000L); + A(p2 (v1[0]) == 100000L); + A(p3 (v1[0]) == 100000L); + A(p4 (v1[0]) == 100000L); + + s1.Commit(); + + } D(s26a); R(s26a); E; + + B(s27, Bytes restructuring, 0) W(s27a); + { + c4_Bytes test ("test", 4); + + c4_BytesProp p1 ("p1"); + c4_Storage s1 ("s27a", 1); + + c4_Row row; + p1 (row) = test; + + c4_View v1; + v1.Add(row); + + // changed 2000-03-15: Store is gone + //s1.Store("a", v1); // asserts in 1.61 + c4_View v2 = s1.GetAs("a[p1:B]"); + v2.InsertAt(0, v1); + + s1.Commit(); + + } D(s27a); R(s27a); E; + +#if !q4_TINY + B(s28, Doubles added later, 0) W(s28a); + { + c4_FloatProp p1 ("p1"); + c4_DoubleProp p2 ("p2"); + c4_ViewProp p3 ("p3"); + + c4_Storage s1 ("s28a", 1); + s1.SetStructure("a[p1:F,p2:D,p3[p1:F,p2:D]]"); + c4_View v1 = s1.View("a"); + + c4_Row r1; + + p1 (r1) = 123; + p2 (r1) = 123; + + c4_View v2; + v2.Add (p1 [234] + p2 [234]); + p3 (r1) = v2; + + v1.Add(r1); + double x1 = p1 (v1[0]); + A(x1 == p2 (v1[0])); + + v2 = p3 (v1[0]); + double x2 = p1 (v2[0]); + A(x2 == p2 (v2[0])); // fails in 1.6 + + s1.Commit(); + + } D(s28a); R(s28a); E; +#endif + + B(s29, Delete bytes property, 0) W(s29a); + { + { + c4_BytesProp p1 ("p1"); + + c4_Storage s1 ("s29a", 1); + s1.SetStructure("a[p1:B]"); + c4_View v1 = s1.View("a"); + + int data = 99; + v1.Add(p1 [c4_Bytes (&data, sizeof data)]); + + s1.Commit(); + } + { + c4_Storage s1 ("s29a", 1); + c4_View v1 = s1.View("a"); + + v1.RemoveAt(0); // asserts in 1.7 + + s1.Commit(); + } + + } D(s29a); R(s29a); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tstore4.cpp b/akregator/src/mk4storage/metakit/tests/tstore4.cpp new file mode 100644 index 000000000..930c074c3 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tstore4.cpp @@ -0,0 +1,323 @@ +// tstore4.cpp -- Regression test program, storage tests, part 4 +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestStores4() +{ + B(s30, Memo storage, 0) W(s30a); + { + c4_Bytes hi ("hi", 2); + c4_Bytes gday ("gday", 4); + c4_Bytes hello ("hello", 5); + + c4_MemoProp p1 ("p1"); + c4_Storage s1 ("s30a", 1); + s1.SetStructure("a[p1:B]"); + c4_View v1 = s1.View("a"); + + v1.Add(p1 [hi]); + A(p1 (v1[0]) == hi); + v1.Add(p1 [hello]); + A(p1 (v1[0]) == hi); + A(p1 (v1[1]) == hello); + v1.InsertAt(1, p1 [gday]); + A(p1 (v1[0]) == hi); + A(p1 (v1[1]) == gday); + A(p1 (v1[2]) == hello); + s1.Commit(); + A(p1 (v1[0]) == hi); + A(p1 (v1[1]) == gday); + A(p1 (v1[2]) == hello); + + } D(s30a); R(s30a); E; + + // this failed in the unbuffered 1.8.5a interim release in Mk4tcl 1.0.5 + B(s31, Check sort buffer use, 0) W(s31a); + { + c4_IntProp p1 ("p1"); + c4_Storage s1 ("s31a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [3]); + v1.Add(p1 [1]); + v1.Add(p1 [2]); + s1.Commit(); + + c4_View v2 = v1.SortOn(p1); + A(v2.GetSize() == 3); + A(p1 (v2[0]) == 1); + A(p1 (v2[1]) == 2); + A(p1 (v2[2]) == 3); + + } D(s31a); R(s31a); E; + + // this failed in 1.8.6, fixed 19990828 + B(s32, Set memo empty or same size, 0) W(s32a); + { + c4_Bytes empty; + c4_Bytes full ("full", 4); + c4_Bytes more ("more", 4); + + c4_MemoProp p1 ("p1"); + c4_Storage s1 ("s32a", 1); + s1.SetStructure("a[p1:B]"); + c4_View v1 = s1.View("a"); + + v1.Add(p1 [full]); + A(p1 (v1[0]) == full); + s1.Commit(); + A(p1 (v1[0]) == full); + + p1 (v1[0]) = empty; + A(p1 (v1[0]) == empty); + s1.Commit(); + A(p1 (v1[0]) == empty); + + p1 (v1[0]) = more; + A(p1 (v1[0]) == more); + s1.Commit(); + A(p1 (v1[0]) == more); + + p1 (v1[0]) = full; + A(p1 (v1[0]) == full); + s1.Commit(); + A(p1 (v1[0]) == full); + + } D(s32a); R(s32a); E; + + // this failed in 1.8.6, fixed 19990828 + B(s33, Serialize memo fields, 0) W(s33a); W(s33b); W(s33c); + { + c4_Bytes hi ("hi", 2); + c4_Bytes gday ("gday", 4); + c4_Bytes hello ("hello", 5); + + c4_MemoProp p1 ("p1"); + + c4_Storage s1 ("s33a", 1); + s1.SetStructure("a[p1:B]"); + c4_View v1 = s1.View("a"); + + v1.Add(p1 [hi]); + v1.Add(p1 [gday]); + v1.Add(p1 [hello]); + A(p1 (v1[0]) == hi); + A(p1 (v1[1]) == gday); + A(p1 (v1[2]) == hello); + s1.Commit(); + A(p1 (v1[0]) == hi); + A(p1 (v1[1]) == gday); + A(p1 (v1[2]) == hello); + + { + c4_FileStream fs1 (fopen("s33b", "wb"), true); + s1.SaveTo(fs1); + } + + c4_Storage s2 ("s33c", 1); + + c4_FileStream fs2 (fopen("s33b", "rb"), true); + s2.LoadFrom(fs2); + + c4_View v2 = s2.View("a"); + A(p1 (v2[0]) == hi); + A(p1 (v2[1]) == gday); + A(p1 (v2[2]) == hello); + s2.Commit(); + A(p1 (v2[0]) == hi); + A(p1 (v2[1]) == gday); + A(p1 (v2[2]) == hello); + s2.Commit(); + A(p1 (v2[0]) == hi); + A(p1 (v2[1]) == gday); + A(p1 (v2[2]) == hello); + + } D(s33a); D(s33b); D(s33c); R(s33a); R(s33b); R(s33c); E; + + // check smarter commit and commit failure on r/o + B(s34, Smart and failed commits, 0) W(s34a); + { + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("s34a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [111]); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 111); + bool f1 = s1.Commit(); + A(f1); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 111); + bool f2 = s1.Commit(); + A(f2); // succeeds, but should not write anything + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 111); + } + { + c4_Storage s1 ("s34a", 0); + c4_View v1 = s1.View("a"); + v1.Add(p1 [222]); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 111); + A(p1 (v1[1]) == 222); + bool f1 = s1.Commit(); + A(!f1); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 111); + A(p1 (v1[1]) == 222); + } + } D(s34a); R(s34a); E; + + B(s35, Datafile with preamble, 0) W(s35a); + { + { + c4_FileStream fs1 (fopen("s35a", "wb"), true); + fs1.Write("abc", 3); + } + c4_IntProp p1 ("p1"); + { + c4_Storage s1 ("s35a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [111]); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 111); + bool f1 = s1.Commit(); + A(f1); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 111); + bool f2 = s1.Commit(); + A(f2); // succeeds, but should not write anything + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 111); + } + { + c4_FileStream fs1 (fopen("s35a", "rb"), true); + char buffer [10]; + int n1 = fs1.Read(buffer, 3); + A(n1 == 3); + A(c4_String (buffer, 3) == "abc"); + } + { + c4_Storage s1 ("s35a", 0); + c4_View v1 = s1.View("a"); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 111); + v1.Add(p1 [222]); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 111); + A(p1 (v1[1]) == 222); + bool f1 = s1.Commit(); + A(!f1); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 111); + A(p1 (v1[1]) == 222); + } + } D(s35a); R(s35a); E; + + B(s36, Commit after load, 0) W(s36a); W(s36b); + { + c4_IntProp p1 ("p1"); + + c4_Storage s1 ("s36a", 1); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + v1.Add(p1 [111]); + A(v1.GetSize() == 1); + A(p1 (v1[0]) == 111); + + { + c4_FileStream fs1 (fopen("s36b", "wb"), true); + s1.SaveTo(fs1); + } + + p1 (v1[0]) = 222; + v1.Add(p1 [333]); + bool f1 = s1.Commit(); + A(f1); + A(v1.GetSize() == 2); + A(p1 (v1[0]) == 222); + A(p1 (v1[1]) == 333); + + c4_FileStream fs2 (fopen("s36b", "rb"), true); + s1.LoadFrom(fs2); + //A(v1.GetSize() == 0); // should be detached, but it's still 2 + + c4_View v2 = s1.View("a"); + A(v2.GetSize() == 1); + A(p1 (v2[0]) == 111); + + // this fails in 2.4.0, reported by James Lupo, August 2001 + bool f2 = s1.Commit(); + A(f2); + } D(s36a); D(s36b); R(s36a); R(s36b); E; + + // fails in 2.4.1, reported Oct 31. 2001 by Steve Baxter + B(s37, Change short partial fields, 0) W(s37a); + { + c4_BytesProp p1 ("p1"); + c4_Storage s1( "s37a", true ); + c4_View v1 = s1.GetAs("v1[key:I,p1:B]"); + + v1.Add(p1 [c4_Bytes ("12345", 6)]); + A(v1.GetSize() == 1); + s1.Commit(); + + c4_Bytes buf = p1 (v1[0]); + A(buf.Size() == 6); + A(buf == c4_Bytes ("12345", 6)); + buf = p1(v1[0]).Access(1,3); + A(buf == c4_Bytes ("234", 3)); + p1 (v1[0]).Modify(c4_Bytes ("ab", 2), 2, 0); + s1.Commit(); + + buf = p1 (v1[0]); + A(buf == c4_Bytes ("12ab5", 6)); + } D(s37a); R(s37a); E; + + // Gross memory use (but no leaks), January 2002, Murat Berk + B(s38, Lots of empty subviews, 0) W(s38a); + { + c4_BytesProp p1 ("p1"); + { + c4_Storage s1( "s38a", true ); + c4_View v = s1.GetAs("v[v1[p1:S]]"); + + v.SetSize(100000); + s1.Commit(); + } + { + c4_Storage s2( "s38a", true ); + c4_View v2 = s2.View("v"); + // this should not materialize all the empty subviews + v2.SetSize(v2.GetSize() + 1); + // nor should this + s2.Commit(); + } + { + c4_Storage s3( "s38a", true ); + c4_View v3 = s3.View("v"); + v3.RemoveAt(1, v3.GetSize() - 2); + A(v3.GetSize() == 2); + s3.Commit(); + } + } D(s38a); R(s38a); E; + + // Fix bug introduced on 7-2-2002, as reported by M. Berk + B(s39, Do not detach empty top-level views, 0) W(s39a); + { + c4_IntProp p1 ("p1"); + c4_Storage s1( "s39a", true ); + c4_View v1 = s1.GetAs("v1[p1:I]"); + s1.Commit(); + A(v1.GetSize() == 0); + v1.Add(p1 [123]); + A(v1.GetSize() == 1); + s1.Commit(); + c4_View v2 = s1.View("v1"); + A(v2.GetSize() == 1); // fails with 0 due to recent bug + } D(s39a); R(s39a); E; +} diff --git a/akregator/src/mk4storage/metakit/tests/tstore5.cpp b/akregator/src/mk4storage/metakit/tests/tstore5.cpp new file mode 100644 index 000000000..1e50b91f3 --- /dev/null +++ b/akregator/src/mk4storage/metakit/tests/tstore5.cpp @@ -0,0 +1,286 @@ +// tstore5.cpp -- Regression test program, storage tests, part 5 +// $Id$ +// This is part of Metakit, see http://www.equi4.com/metakit/ + +#include "regress.h" + +void TestStores5() +{ + B(s40, LoadFrom after commit, 0) W(s40a); + { + c4_IntProp p1 ("p1"); + + { // create datafile by streaming out + c4_Storage s1; + s1.SetStructure("a[p1:I]"); + + c4_View v1 = s1.View("a"); + v1.Add(p1 [123]); + A(p1 (v1[0]) == 123); + A(v1.GetSize() == 1); + + c4_FileStream fs1 (fopen("s40a", "wb"), true); + s1.SaveTo(fs1); + } + { // it should load just fine + c4_Storage s2; + c4_FileStream fs1 (fopen("s40a", "rb"), true); + bool ok = s2.LoadFrom(fs1); + A(ok); + + c4_View v1 = s2.View("a"); + A(p1 (v1[0]) == 123); + A(v1.GetSize() == 1); + } + { // open the datafile and commit a change + c4_Storage s3 ("s40a", true); + + c4_View v1 = s3.View("a"); + A(p1 (v1[0]) == 123); + A(v1.GetSize() == 1); + p1 (v1[0]) = 456; + s3.Commit(); + A(p1 (v1[0]) == 456); + A(v1.GetSize() == 1); + } + { // it should load fine and show the last changes + c4_Storage s4; + c4_FileStream fs1 (fopen("s40a", "rb"), true); + bool ok = s4.LoadFrom(fs1); + A(ok); + + c4_View v1 = s4.View("a"); + A(p1 (v1[0]) == 456); + A(v1.GetSize() == 1); + } + { // it should open just fine in the normal way as well + c4_Storage s5 ("s40a", false); + c4_View v1 = s5.View("a"); + A(p1 (v1[0]) == 456); + A(v1.GetSize() == 1); + } + } D(s40a); R(s40a); E; + + // 2002-03-13: failure on Win32, Modify calls base class GetNthMemoCol + B(s41, Partial modify blocked, 0) W(s41a); + { + c4_BytesProp p1 ("p1"); + c4_Storage s1 ("s41a", true); + c4_View v1 = s1.GetAs("a[_B[p1:B]]"); + + // custom viewers did not support partial access in 2.4.3 + c4_View v2 = v1.Blocked(); + s1.Commit(); + + v2.SetSize(1); + + c4_BytesRef m = p1 (v2[0]); + m.Modify(c4_Bytes ("abcdefgh", 8), 0); + + s1.Commit(); + + } D(s41a); R(s41a); E; + + B(s42, Get descriptions, 0) + { + c4_Storage s1; + s1.SetStructure("a[p1:I],b[p2:S]"); + + c4_String x1 = s1.Description(); + A(x1 == "a[p1:I],b[p2:S]"); + + c4_String x2 = s1.Description("b"); + A(x2 == "p2:S"); + + const char* cp = s1.Description("c"); + A(cp == 0); + } E; + + // 2002-04-24: VPI subview ints clobbered + B(s43, View reuse after sub-byte ints, 0) W(s43a); + { + c4_IntProp p1 ("p1"); + c4_Storage s1 ("s43a", true); + c4_View v1 = s1.GetAs("a[p1:I]"); + + v1.Add(p1 [0]); + v1.Add(p1 [1]); + s1.Commit(); + + v1.SetSize(1); // 1 is an even trickier bug than 0 + s1.Commit(); + + // adding the following two lines works around the 2.4.4 bug + //s1.Rollback(); + //v1 = s1.GetAs("a[p1:I]"); + + v1.Add(p1 [12345]); + s1.Commit(); + + //int n = p1 (v1[1]); + A(p1 (v1[1]) == 12345); + + } D(s43a); R(s43a); E; + + B(s44, Bad memo free space, 0) W(s44a); + { + c4_IntProp p1 ("p1"); + c4_BytesProp p2 ("p2"); + c4_Storage s1 ("s44a", true); + c4_View v1 = s1.GetAs("a[p1:I,p2:B]"); + + c4_Bytes data; + t4_byte* p = data.SetBuffer(12345); + for (int i = 0; i < data.Size(); ++i) + p[i] = (t4_byte) i; + + v1.Add(p2 [data]); + s1.Commit(); + + p1 (v1[0]) = 1; + s1.Commit(); + + p1 (v1[0]) = 0; + s1.Commit(); + + c4_Bytes temp = p2 (v1[0]); + A(temp == data); // this failed in 2.4.5 + + } D(s44a); R(s44a); E; + + B(s45, Bad subview memo free space, 0) W(s45a); + { + c4_IntProp p1 ("p1"); + c4_ViewProp p2 ("p2"); + c4_BytesProp p3 ("p3"); + c4_Storage s1 ("s45a", true); + c4_View v1 = s1.GetAs("a[p1:I,p2[p3:B]]"); + + c4_Bytes data; + t4_byte* p = data.SetBuffer(12345); + for (int i = 0; i < data.Size(); ++i) + p[i] = (t4_byte) i; + + v1.SetSize(1); + c4_View v2 = p2 (v1[0]); + v2.Add(p3 [data]); + s1.Commit(); + + p1 (v1[0]) = 1; + s1.Commit(); + + p1 (v1[0]) = 0; + s1.Commit(); + + c4_View v3 = p2 (v1[0]); + c4_Bytes temp = p3 (v3[0]); + A(temp == data); // this failed in 2.4.5 + + } D(s45a); R(s45a); E; + + B(s46, LoadFrom after commit, 0) W(s46a); + { + c4_IntProp p1 ("p1"); + + { + c4_Storage s1 ("s46a", true); + s1.SetStructure("a[p1:I]"); + c4_View v1 = s1.View("a"); + + v1.Add(p1 [11]); + v1.Add(p1 [22]); + v1.Add(p1 [33]); + v1.Add(p1 [44]); + v1.Add(p1 [55]); + v1.Add(p1 [66]); + v1.Add(p1 [77]); + v1.Add(p1 [88]); + v1.Add(p1 [99]); + + s1.Commit(); + } + { + c4_Storage s2 ("s46a", true); + c4_View v2 = s2.View("a"); + + v2.Add(p1 [1000]); // force 1->2 byte ints + v2.InsertAt(7, c4_Row ()); + v2.InsertAt(4, c4_Row ()); + + //for (int i = 6; i <= 9; ++i) printf("%d\n", (int) p1 (v2[i])); + + A(p1 (v2[6]) == 66); + A(p1 (v2[8]) == 0); + A(p1 (v2[9]) == 88); + A(p1 (v2[7]) == 77); // this failed in 2.4.6 + + s2.Commit(); + } + } D(s46a); R(s46a); E; + + // 2004-01-16 bad property type crashes MK 2.4.9.2 and before + // this hits an assertion in debug mode, so then it has to be disabled + B(s47, Defining bad property type, 0) + { + c4_IntProp p1 ("p2"); + + c4_Storage s1; +#if defined(NDEBUG) + c4_View v1 = s1.GetAs("v1[p1:A]"); +#else + // assertions are enabled, turn this into a dummy test instead + c4_View v1 = s1.GetAs("v1[p1:I]"); +#endif + v1.Add(p1 [123]); + + A(v1.GetSize() == 1); + A(p1 (v1 [0]) == 123); + } E; + + // 2004-01-18 file damaging bug, when resizing a comitted subview + // to empty, committing, and then resizing back to containing data. + // Fortunately this usage pattern never happened in blocked views! + B(s48, Resize subview to zero and back, 0) W(s48a); W(s48b); + { + { + c4_Storage s1 ("s48a", true); + c4_View v1 = s1.GetAs("v1[v2[p1:I]]"); + v1.SetSize(1); + s1.Commit(); + } + { + c4_Storage s1 ("s48a", true); + c4_View v1 = s1.View("v1"); + v1.SetSize(0); + s1.Commit(); + // the problem is that the in-memory copy has forgotten that it + // has nothing left on disk, and a comparison is done later on to + // avoid saving unmodified data - the bad decision is that data has + // not changed, but actually it has and must be reallocated! + // (fixes are in c4_FormatV::Insert and c4_FormatV::Remove) + v1.SetSize(1); + s1.Commit(); + // at this point, the 2.4.9.2 file is corrupt! + c4_FileStream fs1 (fopen("s48b", "wb"), true); + s1.SaveTo(fs1); + } + { + // using this damaged datafile will then crash + c4_Storage s1 ("s48a", false); + c4_View v1 = s1.View("v1"); + v1.SetSize(2); + } + } D(s48a); D(s48b); R(s48a); R(s48b); E; + + // 2004-01-20 better handling of bad input: ignore repeated props + B(s49, Specify conflicting properties, 0) W(s49a); + { + c4_Storage s1 ("s49a", true); + c4_View v1 = s1.GetAs("v1[p1:I,p1:S]"); + c4_View v2 = s1.GetAs("v2[p1:I,P1:S]"); + c4_View v3 = s1.GetAs("v3[v3[^]]"); + c4_String x1 = s1.Description(); + A(x1 == "v1[p1:I],v2[p1:I],v3[v3[^]]"); + s1.Commit(); + } D(s49a); E; +} diff --git a/akregator/src/mk4storage/mk4config.kcfg b/akregator/src/mk4storage/mk4config.kcfg new file mode 100644 index 000000000..2067756cf --- /dev/null +++ b/akregator/src/mk4storage/mk4config.kcfg @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="akregatorrc" /> + <group name="StorageMK4" > + <entry key="Commit Interval" type="Int" > + <label>Commit Interval</label> + <whatsthis>Commit interval in seconds for writing back changes</whatsthis> + <default>3</default> + </entry> + <entry key="Archive Path" type="String" > + <whatsthis>Path to archive</whatsthis> + <default></default> + </entry> + </group> +</kcfg> diff --git a/akregator/src/mk4storage/mk4config.kcfgc b/akregator/src/mk4storage/mk4config.kcfgc new file mode 100644 index 000000000..d7285cd60 --- /dev/null +++ b/akregator/src/mk4storage/mk4config.kcfgc @@ -0,0 +1,6 @@ +File=mk4config.kcfg +ClassName=MK4Config +Singleton=true +NameSpace=Akregator +Mutators=true +MemberVariables=private diff --git a/akregator/src/mk4storage/mk4confwidget.cpp b/akregator/src/mk4storage/mk4confwidget.cpp new file mode 100644 index 000000000..fb95e1602 --- /dev/null +++ b/akregator/src/mk4storage/mk4confwidget.cpp @@ -0,0 +1,92 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "mk4config.h" +#include "mk4confwidget.h" +#include "storagemk4impl.h" + +#include <qcheckbox.h> +#include <qlabel.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kurlrequester.h> + +namespace Akregator { +namespace Backend { + +MK4ConfWidget::MK4ConfWidget() : MK4ConfWidgetBase() +{ + if (MK4Config::archivePath() == StorageMK4Impl::defaultArchivePath() || MK4Config::archivePath().isEmpty()) + { + filereq->setURL(StorageMK4Impl::defaultArchivePath()); + MK4Config::setArchivePath(StorageMK4Impl::defaultArchivePath()); + cbUseDefault->setChecked(true); + filereq->setEnabled(false); + label->setEnabled(false); + } + else + { + cbUseDefault->setChecked(false); + filereq->setEnabled(true); + label->setEnabled(true); + } + filereq->setURL(MK4Config::archivePath()); + connect(cbUseDefault, SIGNAL(toggled(bool)), this, SLOT(slotChkBoxUseDefault(bool))); + +} + +void MK4ConfWidget::accept() +{ + + QString path = cbUseDefault->isChecked() ? StorageMK4Impl::defaultArchivePath() : filereq->url(); + if (path != MK4Config::archivePath()) + { + // TODO: if the user changed the archive location, inform him that + // the archive is not migrated automatically, but that he has to + // close Akregator and copy the files over/use some fancy CLI tool not + // yet written + } + MK4Config::setArchivePath(path); + MK4Config::writeConfig(); + MK4ConfWidgetBase::accept(); +} + +void MK4ConfWidget::slotChkBoxUseDefault(bool checked) +{ + if (checked) + { + filereq->setURL(StorageMK4Impl::defaultArchivePath()); + filereq->setEnabled(false); + } + else + { + filereq->setEnabled(true); + } +} + + +} +} + +#include "mk4confwidget.moc" diff --git a/akregator/src/mk4storage/mk4confwidget.h b/akregator/src/mk4storage/mk4confwidget.h new file mode 100644 index 000000000..e697c21bc --- /dev/null +++ b/akregator/src/mk4storage/mk4confwidget.h @@ -0,0 +1,48 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef AKREGATOR_BACKEND_MK4CONFWIDGET_H +#define AKREGATOR_BACKEND_MK4CONFWIDGET_H + +#include "mk4confwidgetbase.h" + +namespace Akregator { +namespace Backend { + +class MK4ConfWidget : public MK4ConfWidgetBase +{ + Q_OBJECT + public: + + MK4ConfWidget(); + + public slots: + virtual void accept(); + void slotChkBoxUseDefault(bool checked); +}; + +} +} + +#endif // AKREGATOR_BACKEND_MK4CONFWIDGET_H diff --git a/akregator/src/mk4storage/mk4confwidgetbase.ui b/akregator/src/mk4storage/mk4confwidgetbase.ui new file mode 100644 index 000000000..cc91559af --- /dev/null +++ b/akregator/src/mk4storage/mk4confwidgetbase.ui @@ -0,0 +1,178 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>Akregator::Backend::MK4ConfWidgetBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>MK4ConfWidgetBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>377</width> + <height>115</height> + </rect> + </property> + <property name="caption"> + <string>Metakit Settings</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <property name="modal"> + <bool>true</bool> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>cbUseDefault</cstring> + </property> + <property name="text"> + <string>Use default location</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>label</cstring> + </property> + <property name="text"> + <string>Archive location:</string> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>filereq</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>Horizontal Spacing2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>140</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonOk</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonApply</cstring> + </property> + <property name="text"> + <string>&Apply</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonCancel</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>MK4ConfWidgetBase</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>buttonCancel</sender> + <signal>clicked()</signal> + <receiver>MK4ConfWidgetBase</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>cbUseDefault</sender> + <signal>toggled(bool)</signal> + <receiver>label</receiver> + <slot>setDisabled(bool)</slot> + </connection> + <connection> + <sender>cbUseDefault</sender> + <signal><No Signal></signal> + <receiver>cbUseDefault</receiver> + <slot><No)</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/akregator/src/mk4storage/mk4plugin.cpp b/akregator/src/mk4storage/mk4plugin.cpp new file mode 100644 index 000000000..a475a226a --- /dev/null +++ b/akregator/src/mk4storage/mk4plugin.cpp @@ -0,0 +1,50 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "mk4plugin.h" + +#include <klocale.h> + +#include "storagefactorymk4impl.h" +#include "storagefactoryregistry.h" + +AKREGATOR_EXPORT_PLUGIN( Akregator::Backend::MK4Plugin ) + +namespace Akregator { +namespace Backend { + +bool MK4Plugin::init() +{ + m_factory = new StorageFactoryMK4Impl(); + return StorageFactoryRegistry::self()->registerFactory(m_factory, "metakit"); +} + +MK4Plugin::~MK4Plugin() +{ + StorageFactoryRegistry::self()->unregisterFactory("metakit"); + delete m_factory; +} + +} +} diff --git a/akregator/src/mk4storage/mk4plugin.h b/akregator/src/mk4storage/mk4plugin.h new file mode 100644 index 000000000..0c46e4fb5 --- /dev/null +++ b/akregator/src/mk4storage/mk4plugin.h @@ -0,0 +1,49 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef AKREGATOR_BACKEND_MK4PLUGIN_H +#define AKREGATOR_BACKEND_MK4PLUGIN_H + +#include "../plugin.h" + +class QString; + +namespace Akregator { +namespace Backend { + +class StorageFactory; + +class MK4Plugin : public Akregator::Plugin +{ + public: + virtual ~MK4Plugin(); + virtual bool init(); + + private: + StorageFactory* m_factory; +}; + +} +} +#endif // AKREGATOR_BACKEND_MK4PLUGIN_H diff --git a/akregator/src/mk4storage/storagefactorymk4impl.cpp b/akregator/src/mk4storage/storagefactorymk4impl.cpp new file mode 100644 index 000000000..9303bb965 --- /dev/null +++ b/akregator/src/mk4storage/storagefactorymk4impl.cpp @@ -0,0 +1,71 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#include "storagefactorymk4impl.h" +#include "storagemk4impl.h" +//#include "mk4confwidget.h" +//#include "mk4config.h" + +#include <klocale.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qwidget.h> + +namespace Akregator { +namespace Backend { + +Storage* StorageFactoryMK4Impl::createStorage(const QStringList& params) const +{ + Storage* storage = new StorageMK4Impl; + storage->initialize(params); + return storage; +} + +QString StorageFactoryMK4Impl::key() const +{ + return "metakit"; +} + +QString StorageFactoryMK4Impl::name() const +{ + return i18n("Metakit"); +} + + +void StorageFactoryMK4Impl::configure() +{ /* + MK4ConfWidgetBase* confWidget = new MK4ConfWidget(); + // fill with Settings + + + if (confWidget->exec() == QDialog::Accepted) + { + // store and apply settings + } + + delete confWidget; + */ +} + +} +} diff --git a/akregator/src/mk4storage/storagefactorymk4impl.h b/akregator/src/mk4storage/storagefactorymk4impl.h new file mode 100644 index 000000000..b5e51db9d --- /dev/null +++ b/akregator/src/mk4storage/storagefactorymk4impl.h @@ -0,0 +1,53 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef STORAGEFACTORYMK4IMPL_H +#define STORAGEFACTORYMK4IMPL_H + +#include "storagefactory.h" + +class QString; +class QStringList; + +namespace Akregator { +namespace Backend { + +class Storage; + +class StorageFactoryMK4Impl : public StorageFactory +{ + public: + virtual QString key() const; + virtual QString name() const; + virtual void configure(); + virtual Storage* createStorage(const QStringList& params) const; + virtual bool isConfigurable() const { return false; } + virtual bool allowsMultipleWriteAccess() const { return false; } + +}; + +} +} + +#endif diff --git a/akregator/src/mk4storage/storagemk4impl.cpp b/akregator/src/mk4storage/storagemk4impl.cpp new file mode 100644 index 000000000..8a3af0e02 --- /dev/null +++ b/akregator/src/mk4storage/storagemk4impl.cpp @@ -0,0 +1,402 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net> + 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ +#include "storagemk4impl.h" +#include "feedstoragemk4impl.h" + +#include <mk4.h> + +#include <qmap.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qtimer.h> + +#include <kdebug.h> +#include <kstandarddirs.h> + +namespace Akregator { +namespace Backend { + +class StorageMK4Impl::StorageMK4ImplPrivate +{ + public: + StorageMK4ImplPrivate() : modified(false), + purl("url"), + pFeedList("feedList"), + pTagSet("tagSet"), + punread("unread"), + ptotalCount("totalCount"), + plastFetch("lastFetch") {} + + c4_Storage* storage; + c4_View archiveView; + bool autoCommit; + bool modified; + QMap<QString, FeedStorage*> feeds; + QStringList feedURLs; + c4_StringProp purl, pFeedList, pTagSet; + c4_IntProp punread, ptotalCount, plastFetch; + QString archivePath; + + bool taggingEnabled; + + c4_Storage* feedListStorage; + c4_View feedListView; +}; + +bool StorageMK4Impl::taggingEnabled() const +{ + return d->taggingEnabled; +} + +void StorageMK4Impl::setArchivePath(const QString& archivePath) +{ + if (archivePath.isNull()) // if isNull, reset to default + d->archivePath = defaultArchivePath(); + else + d->archivePath = archivePath; +} + +QString StorageMK4Impl::archivePath() const +{ + return d->archivePath; +} + +StorageMK4Impl::StorageMK4Impl() : d(new StorageMK4ImplPrivate) +{ + setArchivePath(QString::null); // set path to default +} + +QString StorageMK4Impl::defaultArchivePath() +{ + return KGlobal::dirs()->saveLocation("data", "akregator")+"Archive"; +} + +StorageMK4Impl::~StorageMK4Impl() +{ + close(); + delete d; + d = 0; +} +void StorageMK4Impl::initialize(const QStringList& params) +{ + d->taggingEnabled = false; + + QStringList::ConstIterator it = params.begin(); + QStringList::ConstIterator end = params.end(); + + for ( ; it != end; ++it) + { + QStringList tokens = QStringList::split("=", *it); + if (tokens.count() == 2 && *(tokens.at(0)) == "taggingEnabled" + && *(tokens.at(1)) == "true") + { + d->taggingEnabled = true; + } + + } +} + +bool StorageMK4Impl::open(bool autoCommit) +{ + QString filePath = d->archivePath +"/archiveindex.mk4"; + d->storage = new c4_Storage(filePath.local8Bit(), true); + d->archiveView = d->storage->GetAs("archive[url:S,unread:I,totalCount:I,lastFetch:I]"); + c4_View hash = d->storage->GetAs("archiveHash[_H:I,_R:I]"); + d->archiveView = d->archiveView.Hash(hash, 1); // hash on url + d->autoCommit = autoCommit; + + filePath = d->archivePath +"/feedlistbackup.mk4"; + d->feedListStorage = new c4_Storage(filePath.local8Bit(), true); + d->feedListView = d->feedListStorage->GetAs("archive[feedList:S,tagSet:S]"); + return true; +} + +bool StorageMK4Impl::autoCommit() const +{ + return d->autoCommit; +} + +bool StorageMK4Impl::close() +{ + QMap<QString, FeedStorage*>::Iterator it; + QMap<QString, FeedStorage*>::Iterator end(d->feeds.end() ) ; + for (it = d->feeds.begin(); it != end; ++it) + { + it.data()->close(); + delete it.data(); + } + if(d->autoCommit) + d->storage->Commit(); + + delete d->storage; + d->storage = 0; + + d->feedListStorage->Commit(); + delete d->feedListStorage; + d->feedListStorage = 0; + + return true; +} + +bool StorageMK4Impl::commit() +{ + QMap<QString, FeedStorage*>::Iterator it; + QMap<QString, FeedStorage*>::Iterator end(d->feeds.end() ) ; + for ( it = d->feeds.begin(); it != end; ++it ) + it.data()->commit(); + + if(d->storage) + { + d->storage->Commit(); + return true; + } + + return false; +} + +bool StorageMK4Impl::rollback() +{ + QMap<QString, FeedStorage*>::Iterator it; + QMap<QString, FeedStorage*>::Iterator end(d->feeds.end() ) ; + for ( it = d->feeds.begin(); it != end; ++it ) + it.data()->rollback(); + + if(d->storage) + { + d->storage->Rollback(); + return true; + } + return false; +} + +int StorageMK4Impl::unreadFor(const QString &url) +{ + c4_Row findrow; + d->purl(findrow) = url.ascii(); + int findidx = d->archiveView.Find(findrow); + + return findidx != -1 ? d->punread(d->archiveView.GetAt(findidx)) : 0; +} + +void StorageMK4Impl::setUnreadFor(const QString &url, int unread) +{ + c4_Row findrow; + d->purl(findrow) = url.ascii(); + int findidx = d->archiveView.Find(findrow); + if (findidx == -1) + return; + findrow = d->archiveView.GetAt(findidx); + d->punread(findrow) = unread; + d->archiveView.SetAt(findidx, findrow); + markDirty(); +} + +int StorageMK4Impl::totalCountFor(const QString &url) +{ + c4_Row findrow; + d->purl(findrow) = url.ascii(); + int findidx = d->archiveView.Find(findrow); + + return findidx != -1 ? d->ptotalCount(d->archiveView.GetAt(findidx)) : 0; +} + +void StorageMK4Impl::setTotalCountFor(const QString &url, int total) +{ + c4_Row findrow; + d->purl(findrow) = url.ascii(); + int findidx = d->archiveView.Find(findrow); + if (findidx == -1) + return; + findrow = d->archiveView.GetAt(findidx); + d->ptotalCount(findrow) = total; + d->archiveView.SetAt(findidx, findrow); + markDirty(); +} + +int StorageMK4Impl::lastFetchFor(const QString& url) +{ + c4_Row findrow; + d->purl(findrow) = url.ascii(); + int findidx = d->archiveView.Find(findrow); + + return (findidx != -1 ? d->plastFetch(d->archiveView.GetAt(findidx)) : 0); +} + +void StorageMK4Impl::setLastFetchFor(const QString& url, int lastFetch) +{ + c4_Row findrow; + d->purl(findrow) = url.ascii(); + int findidx = d->archiveView.Find(findrow); + if (findidx == -1) + return; + findrow = d->archiveView.GetAt(findidx); + d->plastFetch(findrow) = lastFetch; + d->archiveView.SetAt(findidx, findrow); + markDirty(); +} + +void StorageMK4Impl::markDirty() +{ + if (!d->modified) + { + d->modified = true; + // commit changes after 3 seconds + QTimer::singleShot(3000, this, SLOT(slotCommit())); + } +} + +void StorageMK4Impl::slotCommit() +{ + if (d->modified) + commit(); + d->modified = false; +} + +FeedStorage* StorageMK4Impl::archiveFor(const QString& url) +{ + if (!d->feeds.contains(url)) + { + FeedStorage* fs = new FeedStorageMK4Impl(url, this); + d->feeds[url] = fs; + c4_Row findrow; + d->purl(findrow) = url.ascii(); + int findidx = d->archiveView.Find(findrow); + if (findidx == -1) + { + d->punread(findrow) = 0; + d->ptotalCount(findrow) = 0; + d->plastFetch(findrow) = 0; + d->archiveView.Add(findrow); + markDirty(); + } + fs->convertOldArchive(); + } + return d->feeds[url]; +} + +QStringList StorageMK4Impl::feeds() const +{ + // TODO: cache list + QStringList list; + int size = d->archiveView.GetSize(); + for (int i = 0; i < size; i++) + list += QString(d->purl(d->archiveView.GetAt(i))); + // fill with urls + return list; + +} + +void StorageMK4Impl::add(Storage* source) +{ + QStringList feeds = source->feeds(); + QStringList::ConstIterator end(feeds.end() ) ; + + for (QStringList::ConstIterator it = feeds.begin(); it != end; ++it) + { + FeedStorage* fa = archiveFor(*it); + fa->add(source->archiveFor(*it)); + } +} + + +void StorageMK4Impl::clear() +{ + QStringList feeds; + int size = d->archiveView.GetSize(); + for (int i = 0; i < size; i++) + feeds += QString(d->purl(d->archiveView.GetAt(i))); + QStringList::ConstIterator end(feeds.end() ) ; + + for (QStringList::ConstIterator it = feeds.begin(); it != end; ++it) + { + FeedStorage* fa = archiveFor(*it); + fa->clear(); + fa->commit(); + // FIXME: delete file (should be 0 in size now) + } + d->storage->RemoveAll(); + +} + +void StorageMK4Impl::storeFeedList(const QString& opmlStr) +{ + + if (d->feedListView.GetSize() == 0) + { + c4_Row row; + d->pFeedList(row) = !opmlStr.isEmpty() ? opmlStr.utf8().data() : ""; + d->pTagSet(row) = ""; + d->feedListView.Add(row); + } + else + { + c4_Row row = d->feedListView.GetAt(0); + d->pFeedList(row) = !opmlStr.isEmpty() ? opmlStr.utf8().data() : ""; + d->feedListView.SetAt(0, row); + } + markDirty(); +} + +QString StorageMK4Impl::restoreFeedList() const +{ + if (d->feedListView.GetSize() == 0) + return ""; + + c4_Row row = d->feedListView.GetAt(0); + return QString::fromUtf8(d->pFeedList(row)); +} + +void StorageMK4Impl::storeTagSet(const QString& xmlStr) +{ + + if (d->feedListView.GetSize() == 0) + { + c4_Row row; + d->pTagSet(row) = !xmlStr.isEmpty() ? xmlStr.utf8().data() : ""; + d->pFeedList(row) = ""; + d->feedListView.Add(row); + } + else + { + c4_Row row = d->feedListView.GetAt(0); + d->pTagSet(row) = !xmlStr.isEmpty() ? xmlStr.utf8().data() : ""; + d->feedListView.SetAt(0, row); + } + markDirty(); +} + +QString StorageMK4Impl::restoreTagSet() const +{ + if (d->feedListView.GetSize() == 0) + return ""; + + c4_Row row = d->feedListView.GetAt(0); + return QString::fromUtf8(d->pTagSet(row)); +} + +} // namespace Backend +} // namespace Akregator + +#include "storagemk4impl.moc" diff --git a/akregator/src/mk4storage/storagemk4impl.h b/akregator/src/mk4storage/storagemk4impl.h new file mode 100644 index 000000000..7b3a43783 --- /dev/null +++ b/akregator/src/mk4storage/storagemk4impl.h @@ -0,0 +1,130 @@ +/* + This file is part of Akregator. + + Copyright (C) 2005 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net> + 2005 Frank Osterfeld <frank.osterfeld@kdemail.net> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef STORAGEMK4IMPL_H +#define STORAGEMK4IMPL_H + +#include "storage.h" + +namespace Akregator { +namespace Backend { + +/** + * Metakit implementation of Storage interface + */ +class StorageMK4Impl : public Storage +{ + Q_OBJECT + public: + + StorageMK4Impl(); + StorageMK4Impl(const StorageMK4Impl&); + StorageMK4Impl &operator =(const StorageMK4Impl&); + virtual ~StorageMK4Impl(); + + + /** KGlobal::dirs()->saveLocation("data", "akregator")+"/Archive" */ + static QString defaultArchivePath(); + + /** sets the directory where the metakit files will be stored. + + @param archivePath the path to the archive, or QString::null to reset it to the default. + */ + void setArchivePath(const QString& archivePath); + + /** returns the path to the metakit archives */ + QString archivePath() const; + + + + virtual void initialize(const QStringList& params); + /** + * Open storage and prepare it for work. + * @return true on success. + */ + virtual bool open(bool autoCommit = false); + + /** + * Commit changes made in feeds and articles, making them persistent. + * @return true on success. + */ + virtual bool commit(); + + /** + * Rollback changes made in feeds and articles, reverting to last committed values. + * @returns true on success. + */ + virtual bool rollback(); + + /** + * Closes storage, freeing all allocated resources. Called from destructor, so you don't need to call it directly. + * @return true on success. + */ + virtual bool close(); + + /** + * @return Article archive for feed at given url. + */ + virtual FeedStorage* archiveFor(const QString &url); + virtual bool autoCommit() const; + virtual int unreadFor(const QString &url); + virtual void setUnreadFor(const QString &url, int unread); + virtual int totalCountFor(const QString &url); + virtual void setTotalCountFor(const QString &url, int total); + virtual int lastFetchFor(const QString& url); + virtual void setLastFetchFor(const QString& url, int lastFetch); + + virtual QStringList feeds() const; + + virtual void storeFeedList(const QString& opmlStr); + virtual QString restoreFeedList() const; + + virtual void storeTagSet(const QString& xmlStr); + virtual QString restoreTagSet() const; + + /** adds all feed storages from a source to this storage + existing articles are replaced + */ + virtual void add(Storage* source); + + /** deletes all feed storages in this archive */ + virtual void clear(); + + virtual bool taggingEnabled() const; + + void markDirty(); + + protected slots: + virtual void slotCommit(); + + private: + class StorageMK4ImplPrivate; + StorageMK4ImplPrivate *d; +}; + +} +} + +#endif // STORAGEMK4IMPL_H |