#include <iostream>
#include <string>
#include <map>
#include <fstream>
#include <strstream>
#include <cstring>
#include <string>
#include <deque>
#include "REEvaluator.h"
#include "amvutils.h"
using namespace std;
namespace amv {
struct bookNode;
struct linkBookNode {
bookNode *pbn;
linkBookNode(): pbn(0)
{
}
};
struct bookNode {
string title;
deque<string> content;
map<string,linkBookNode> childs;
void showContent() const
{
int i;
for(i=0; i<content.size(); ++i)
{
cout<<content[i]<<endl;
}
cout<<endl;
map<string,linkBookNode>::const_iterator it1=childs.begin();
for(; it1!=childs.end(); ++it1)
{
cout<<it1->first<<'\t';
cout<<it1->second.pbn->title<<endl;
}
}
template <class It>
bookNode *find(It first, It last)
{
linkBookNode *p=0;
if(childs.find(*first)==childs.end())
return 0;
for(p=&(childs[*first]); ++first!=last;)
{
if(p->pbn->childs.find(*first)==p->pbn->childs.end())
{
return 0;
}
p=&(p->pbn->childs[*first]);
}
return p->pbn;
}
template <class It>
bookNode *add(It first, It last)
{
linkBookNode *p=0;
for(p=&(childs[*first]); ++first!=last;)
{
p=&(p->pbn->childs[*first]);
}
if(!p->pbn)
p->pbn=new bookNode;
return p->pbn;
}
};
class book {
bookNode *root;
amv::REEvaluator REEsection;
char delimiter;
bool getContent(istream &is, deque<string> &content)
{
char line[4096];
string s;
while(is.getline(line,4096))
{
istrstream istr(line,strlen(line));
content.push_back(line);
if(REEsection.getLexema(istr,s))
return true;
}
return false;
}
template <class It>
void getTitle(It first, It last, string &title)
{
for( ; first!=last; ++first)
{
if(!first->empty())
break;
}
if(first!=last)
title=*first;
else
title="Sín título";
}
public:
book(const char *filename, const char *REsection="[0-9]+<(.<[0-9]+)*", char delim='.'): root(0), REEsection(REsection), delimiter(delim)
{
ifstream is(filename);
if(is)
{
root=new bookNode;
bookNode *pbn;
bool pending=false;
char line[4096], line1[4096];
string s,s1;
deque<string> v;
root->title=filename;
root->content.push_back(root->title);
while(true)
{
if(pending)
{
v=amv::split<deque<string>,string>(s1,delimiter);
pbn=root->add(v.begin(),v.end());
pending=getContent(is,pbn->content);
if(pending)
{
s1=pbn->content.back();
pbn->content.pop_back();
getTitle(pbn->content.begin(),pbn->content.end(),pbn->title);
}
else
{
getTitle(pbn->content.begin(),pbn->content.end(),pbn->title);
break;
}
}
else
{
is.getline(line,4096);
istrstream istr(line,strlen(line));
if(REEsection.getLexema(istr,s))
{
v=amv::split<deque<string>,string>(s,delimiter);
pbn=root->add(v.begin(),v.end());
pending=getContent(is,pbn->content);
if(pending)
{
s1=pbn->content.back();
pbn->content.pop_back();
getTitle(pbn->content.begin(),pbn->content.end(),pbn->title);
}
else
{
getTitle(pbn->content.begin(),pbn->content.end(),pbn->title);
break;
}
}
}
}
}
else
cerr<<"No se encontró el archivo con los datos del libro\n";
}
void show1()
{
string s;
bookNode *pbn;
cerr<<"Sección: ";
while(cin>>s)
{
if(REEsection.eval(s.begin(),s.end()))
{
deque<string> v=amv::split<deque<string>,string>(s,delimiter);
if(pbn=root->find(v.begin(),v.end()))
pbn->showContent();
else
cerr<<"El número de sección que tecleó no existe\n";
}
else
cerr<<"Use el formato x"<<delimiter<<"y"<<delimiter<<"z para las secciones\n";
cerr<<"\nSección: ";
}
}
void show()
{
string s,prompt=": ";
bookNode *pbn=root, *pbn1;
deque<string> position;
pbn->showContent();
cerr<<endl<<prompt;
while(cin>>s)
{
if(s=="0")
{
if(position.empty())
{
cerr<<"\nHasta la vista\n";
return;
}
else
position.pop_back();
}
else if(s=="?")
{
pbn->showContent();
cerr<<endl<<prompt;
continue;
}
else
position.push_back(s);
if(position.size())
{
if(pbn1=root->find(position.begin(),position.end()))
{
pbn=pbn1;
pbn->showContent();
}
else
{
cerr<<"El número de sección que tecleó no existe\n";
position.pop_back();
}
}
else
{
pbn=root;
pbn->showContent();
}
prompt=position.size()? join(position,'.')+": ": ": ";
cerr<<endl<<prompt;
}
}
operator bool() const
{
return root;
}
};
}
int main()
{
amv::book book1("cpp.txt");
if(book1)
{
book1.show();
}
else
cerr<<"No se pudo crear el libro\n";
return 0;
}