#include "Dzdbook.h"
#include "Xtostr.h"
using namespace std;
Dzdbook::Dzdbook(File file){
extern size_t maxchapsize;
extern string prefixtitle;
//处理书名
string mainame=file.getmainame();
bookname=s2ws(mainame);
size_t tsize=bookname.size();
if(tsize>20)
bookname=bookname.substr(0,10)+wstring(L"...")+bookname.substr(bookname.size()-10,10);
mainame=ws2s(bookname);
ifstream in(file.getfilename().c_str());
int lineinchapc=0; //章节中的行数
size_t charcount=0; //章节中的字符数
size_t sumchapsize=0; //本次读取后章节中的字符数
size_t lastsumchapsize=0; //上次读取后章节中的字符数
int chapindex=1;
Chapter chap;
string chapname=prefixtitle+" 1";
chap.chapname=s2ws(chapname);
//只需每读一个字符检查已读txt文件中的字符数
//和dzd文件中的行数(等于txt文件中行数加上满行数)
while(!in.eof()){
lastsumchapsize=(charcount+lineinchapc)*2+lineinchapc;
string sline;
getline(in,sline,'\n');
if(sline==" ") continue;
wstring wsline=s2ws(sline);
lineinchapc++;
lineinchapc += wsline.size()/nfullinec;
charcount += wsline.size();
sumchapsize=(charcount+lineinchapc)*2+lineinchapc;
//不变式:有读出来的字符没有送入chap
while(true){
//未送入chap的字符大于maxfilesize
if(sumchapsize>=maxchapsize) {
size_t chartoget=((maxchapsize-lastsumchapsize)*nfullinec/(2*nfullinec+3))-1;
if(chartoget>wsline.size()) chartoget=wsline.size();
wstring wlinetowrite=wsline.substr(0,chartoget);
//填入chaplines
size_t fullinec;
//分成满行填入chaplines
for(fullinec=0;fullinec<wlinetowrite.size()/nfullinec;fullinec++){
wstring fulline=wlinetowrite.substr(fullinec*nfullinec,nfullinec);
lineinchapc++;
chap.chaplines.push_back(fulline);
}
//已写入fullinec个满行,检查是否还有字符
if(wlinetowrite.size()>fullinec*nfullinec){
wstring unfulline=wlinetowrite.substr(fullinec*nfullinec,wsline.size()-fullinec*nfullinec);
lineinchapc++;
chap.chaplines.push_back(unfulline);
}
chap.charcount=charcount-wsline.size()+chartoget;
//cout<<chapname<<" linescount:"<<chap.chaplines.size()<<endl; ///
book.push_back(chap);
chap.chaplines.clear();
lineinchapc=0;
charcount=0;
sumchapsize=0;
lastsumchapsize=0;
wsline=wsline.substr(chartoget,string::npos);
lineinchapc++;
lineinchapc += wsline.size()/nfullinec;
charcount += wsline.size();
sumchapsize=(charcount+lineinchapc)*2+lineinchapc;
//完成一个章节还没有到文件尾,或者charcount不为零必须再创建一个章节
if(!in.eof()||charcount>0){
chapindex++;
chapname=prefixtitle+" "+Xtostr(chapindex);
chap.chapname=s2ws(chapname);
chap.chaplines.clear();
}
}
else {
//填入chaplines
size_t fullinec;
//分成满行填入chaplines
for(fullinec=0;fullinec<wsline.size()/nfullinec;fullinec++){
wstring fulline=wsline.substr(fullinec*nfullinec,nfullinec);
lineinchapc++;
chap.chaplines.push_back(fulline);
}
//已写入fullinec个满行,检查是否还有字符
if(wsline.size()>fullinec*nfullinec){
wstring unfulline=wsline.substr(fullinec*nfullinec,wsline.size()-fullinec*nfullinec);
lineinchapc++;
chap.chaplines.push_back(unfulline);
}
//是否还有继续读的必要
if(in.eof()) {
//cout<<chapname<<" linescount:"<<chap.chaplines.size()<<endl; ///
chap.charcount=charcount;
book.push_back(chap);
chap.chaplines.clear();
}
break;
}
}
}
}
void Dzdbook::writetofile(ofstream &dzdout) throw (Error){
int linecount=0;
int Echarcount=0;
int Ccharcount=0;
int chapcount=book.size();
char blank[512];
memset(blank,0,sizeof(blank));
//写入认证头
dzdout.write(authead,212);
//书名占位
dzdout.write(blank,80);
//书签占位
dzdout.write(blank,508);
//写入章节信息
list<Chapter>::iterator chapiter;
int intzero=0;
//所有章节标题字符数之和
int sumchaptitlsize=0;
for(chapiter=book.begin();chapiter!=book.end();chapiter++)
sumchaptitlsize +=chapiter->chapname.size();
if(sumchaptitlsize>255) throw Error("章节标题字符数过大。");
int linfoffset=0x320+6*4*chapcount+sumchaptitlsize*2;
for(chapiter=book.begin();chapiter!=book.end();chapiter++){
dzdout.write((char *)&intzero,sizeof (int));
dzdout.put('\1');
dzdout.put(chapiter->chapname.size());
dzdout.put('\0');
dzdout.put('\0');
linecount=chapiter->chaplines.size();
dzdout.write((char *)&linecount,sizeof (int));
Echarcount=linecount+sizeof(promote)-2;
dzdout.write((char *)&Echarcount,sizeof (int));
Ccharcount=chapiter->charcount;
dzdout.write((char *)&Ccharcount,sizeof (int));
dzdout.write((char *)&linfoffset,sizeof (int));
//cout<<"linfoffset="<<hex<<linfoffset<<endl;
linfoffset += linecount*2+Echarcount+Ccharcount*2;
}
//写入所有章节标题
for(chapiter=book.begin();chapiter!=book.end();chapiter++){
int tsize=chapiter->chapname.size();
for(int m=0;m<2*tsize;m++) dzdout.put(*((char *)(chapiter->chapname.data())+m));
}
//写入每个章节的行信息和行数据
for(chapiter=book.begin();chapiter!=book.end();chapiter++){
//行信息
list<wstring>::iterator lineiter;
dzdout.put(sizeof(promote)-1);
lineiter=chapiter->chaplines.begin();
dzdout.put(lineiter->size());
lineiter++;
for(;lineiter!=chapiter->chaplines.end();lineiter++){
dzdout.put(1);
dzdout.put(lineiter->size());
}
//行数据
dzdout.write(promote,sizeof(promote)-1);
for(int i=0;i<chapiter->chaplines.size()-1;i++) dzdout.put(' ');
lineiter=chapiter->chaplines.begin();
for(;lineiter!=chapiter->chaplines.end();lineiter++){
for(int n=0;n<2*lineiter->size();n++) dzdout.put(*(((char *)(lineiter->data())+n)));
}
}
//fill some bytes
dzdout.seekp(0x3,ios::beg);
dzdout.put(bookname.size());
dzdout.seekp(0xD4,ios::beg);
for(int j=0;j<2*bookname.size();j++) dzdout.put(*((char *)(bookname.data())+j));
dzdout.seekp(0x126,ios::beg);
dzdout.put(chapcount);
dzdout.seekp(0x127,ios::beg);
dzdout.put(sumchaptitlsize);
dzdout.close();
}