Diffstat (limited to 'noncore/apps/opie-reader/Reb.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/apps/opie-reader/Reb.cpp | 789 |
1 files changed, 789 insertions, 0 deletions
diff --git a/noncore/apps/opie-reader/Reb.cpp b/noncore/apps/opie-reader/Reb.cpp new file mode 100644 index 0000000..2e6c1fc --- a/dev/null +++ b/noncore/apps/opie-reader/Reb.cpp | |||
@@ -0,0 +1,789 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | #include <qimage.h> | ||
4 | #include "decompress.h" | ||
5 | #include "Reb.h" | ||
6 | #include "my_list.h" | ||
7 | #include "Bkmks.h" | ||
8 | #include "Model.h" | ||
9 | /* | ||
10 | #ifdef offsetof | ||
11 | #define OffsetOf(type, field) ((int) offsetof(type, field)) | ||
12 | #else | ||
13 | #define OffsetOf(type, field) ((int) ((char *) &((type *) 0)->field)) | ||
14 | #endif | ||
15 | |||
16 | template<class T> | ||
17 | UInt32 binarychop(T* data, UInt32 n, T val) | ||
18 | { | ||
19 | UInt32 jl = 0,jh = n-1,jm = (jl+jh)/2; | ||
20 | while (jh > jl+1) | ||
21 | { | ||
22 | if (data[jm] > val) | ||
23 | { | ||
24 | jh = jm; | ||
25 | } | ||
26 | else | ||
27 | { | ||
28 | jl = jm; | ||
29 | } | ||
30 | jm = (jl+jh)/2; | ||
31 | } | ||
32 | return jl; | ||
33 | } | ||
34 | |||
35 | template<class T, class D> | ||
36 | UInt32 binarychop(D* data, UInt32 n, T val, UInt32 offset) | ||
37 | { | ||
38 | UInt32 jl = 0,jh = n-1,jm = (jl+jh)/2; | ||
39 | while (jh > jl+1) | ||
40 | { | ||
41 | T* d = reinterpret_cast<T*>(reinterpret_cast<char*>(data+jm)+offset); | ||
42 | if (*d > val) | ||
43 | { | ||
44 | jh = jm; | ||
45 | } | ||
46 | else | ||
47 | { | ||
48 | jl = jm; | ||
49 | } | ||
50 | jm = (jl+jh)/2; | ||
51 | } | ||
52 | return jl; | ||
53 | } | ||
54 | */ | ||
55 | |||
56 | CReb::CReb() | ||
57 | : | ||
58 | fin(NULL), m_indexpages(NULL), m_pagedetails(NULL),tagoffset(0), | ||
59 | tags(NULL), paras(NULL), noparas(0), joins(NULL), nojoins(0) | ||
60 | { | ||
61 | } | ||
62 | |||
63 | CReb::~CReb() | ||
64 | { | ||
65 | if (fin != NULL) fclose(fin); | ||
66 | if (m_indexpages != NULL) delete [] m_indexpages; | ||
67 | if (m_pagedetails != NULL) delete [] m_pagedetails; | ||
68 | if (tags != NULL) delete [] tags; | ||
69 | if (paras != NULL) delete [] paras; | ||
70 | if (joins != NULL) delete [] joins; | ||
71 | } | ||
72 | |||
73 | unsigned int CReb::locate() | ||
74 | { | ||
75 | return m_pagedetails[currentpage.pageno()].pagestart+currentpage.offset(); | ||
76 | } | ||
77 | |||
78 | void CReb::locate(unsigned int n) | ||
79 | { | ||
80 | /* | ||
81 | UInt32 cp = nopages-1; | ||
82 | for (int i = 0; i < nopages; ++i) | ||
83 | { | ||
84 | if (m_pagedetails[i].pagestart > n) | ||
85 | { | ||
86 | cp = i-1; | ||
87 | break; | ||
88 | } | ||
89 | } | ||
90 | qDebug("Requesting %u from page %u [%u]", n, cp, n - m_pagedetails[cp].pagestart); | ||
91 | */ | ||
92 | //UInt32 jl = binarychop<UInt32, Page_detail>(m_pagedetails, nopages, n, OffsetOf(Page_detail, pagestart)); | ||
93 | |||
94 | UInt32 jl = 0,jh = nopages-1,jm = (jl+jh)/2; | ||
95 | while (jh > jl+1) | ||
96 | { | ||
97 | if (m_pagedetails[jm].pagestart > n) | ||
98 | { | ||
99 | jh = jm; | ||
100 | } | ||
101 | else | ||
102 | { | ||
103 | jl = jm; | ||
104 | } | ||
105 | jm = (jl+jh)/2; | ||
106 | } | ||
107 | |||
108 | unsuspend(); | ||
109 | Page_detail rs = m_pagedetails[jl]; | ||
110 | UInt32 val = n - rs.pagestart; | ||
111 | if (jl != currentpage.pageno()) readindex(jl); | ||
112 | currentpage.setoffset(page2pos(jl), jl, ((rs.flags & 8) != 0), rs.len, val); | ||
113 | if (noparas > 0) | ||
114 | { | ||
115 | //jl = binarychop<int, ParaRef>(paras, noparas, val, OffsetOf(ParaRef, pos)); | ||
116 | |||
117 | UInt32 jl = 0,jh = noparas-1,jm = (jl+jh)/2; | ||
118 | while (jh > jl+1) | ||
119 | { | ||
120 | if (paras[jm].pos > val) | ||
121 | { | ||
122 | jh = jm; | ||
123 | } | ||
124 | else | ||
125 | { | ||
126 | jl = jm; | ||
127 | } | ||
128 | jm = (jl+jh)/2; | ||
129 | } | ||
130 | |||
131 | qDebug("TAGS:%s", (const char*)tags[paras[jl].tag]); | ||
132 | tagstring = tags[paras[jl].tag]+"<br>"; // Add br to set extra space to 0 | ||
133 | tagoffset = 0; | ||
134 | } | ||
135 | unsigned long current = locate(); | ||
136 | if (m_currentstart > current || current > m_currentend) | ||
137 | { | ||
138 | start2endSection(); | ||
139 | } | ||
140 | if (current != n) qDebug("ERROR:Ended up at %u", current); | ||
141 | } | ||
142 | |||
143 | bool CReb::getFile(const QString& href, const QString& nm) | ||
144 | { | ||
145 | qDebug("File:%s, Name:%s", (const char*)href, (const char*)nm); | ||
146 | QMap<QString, UInt32>::Iterator iter = m_index.find(href); | ||
147 | if (iter != m_index.end()) | ||
148 | { | ||
149 | qDebug("REB:BEFORE:%u", locate()); | ||
150 | startpage(iter.data()); | ||
151 | qDebug("REB:AFTER:%u", locate()); | ||
152 | return true; | ||
153 | } | ||
154 | else | ||
155 | { | ||
156 | return false; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | QImage* CReb::getPicture(const QString& ref) | ||
161 | { | ||
162 | QMap<QString, UInt32>::Iterator iter = m_index.find(ref); | ||
163 | if (iter != m_index.end()) | ||
164 | { | ||
165 | unsuspend(); | ||
166 | Page_detail rs = m_pagedetails[iter.data()]; | ||
167 | char* imgbuffer = new char[rs.len]; | ||
168 | fseek(fin, page2pos(iter.data()), SEEK_SET); | ||
169 | fread(imgbuffer, rs.len, 1, fin); | ||
170 | QByteArray arr; | ||
171 | arr.assign((const char*)imgbuffer, rs.len); | ||
172 | QImage* qimage = new QImage(arr); | ||
173 | return qimage; | ||
174 | } | ||
175 | else | ||
176 | { | ||
177 | return NULL; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | CList<Bkmk>* CReb::getbkmklist() { return NULL; } | ||
182 | |||
183 | void CReb::home() | ||
184 | { | ||
185 | startpage(m_homepage); | ||
186 | } | ||
187 | |||
188 | int CReb::OpenFile(const char *src) | ||
189 | { | ||
190 | m_binary = false; | ||
191 | if (fin != NULL) fclose(fin); | ||
192 | fin = fopen(src, "r"); | ||
193 | if (fin == NULL) | ||
194 | { | ||
195 | return -1; | ||
196 | } | ||
197 | UInt32 type; | ||
198 | fseek(fin, 6, SEEK_SET); | ||
199 | fread(&type, 1, sizeof(type), fin); | ||
200 | qDebug("CREB:Okay %x", type); | ||
201 | |||
202 | if (type == 0x4f56554e || type == 0x574d4954 || type == 0x576d6954) | ||
203 | { | ||
204 | struct stat _stat; | ||
205 | stat(src, &_stat); | ||
206 | file_length = _stat.st_size; | ||
207 | fread(&m_blocksize, 1, sizeof(m_blocksize), fin); | ||
208 | if (type == 0x574d4954 || type == 0x576d6954) | ||
209 | { | ||
210 | if (type == 0x576d6954) m_binary = true; | ||
211 | qDebug("Blocksize(1) %x", m_blocksize); | ||
212 | unsigned char ct = (m_blocksize >> 24) & 0xff; | ||
213 | qDebug("Compress type:%x", ct); | ||
214 | switch (ct) | ||
215 | { | ||
216 | case 0: | ||
217 | m_decompress = UnZip; | ||
218 | break; | ||
219 | case 3: | ||
220 | m_decompress = getdecompressor("PluckerDecompress3"); | ||
221 | break; | ||
222 | case 4: | ||
223 | m_decompress = getdecompressor("PluckerDecompress4"); | ||
224 | break; | ||
225 | } | ||
226 | if (m_decompress == NULL) return -1; | ||
227 | m_blocksize = 1024*(m_blocksize & 0xffffff); | ||
228 | } | ||
229 | else | ||
230 | { | ||
231 | m_blocksize = 4096; | ||
232 | m_decompress = UnZip; | ||
233 | } | ||
234 | qDebug("Blocksize %u", m_blocksize); | ||
235 | currentpage.init(fin, m_blocksize, m_decompress); | ||
236 | qDebug("Its a REB!!!!"); | ||
237 | fseek(fin, 0x18, SEEK_SET); | ||
238 | fread(&toc, 1, sizeof(toc), fin); | ||
239 | qDebug("Expect this to be 128 or 20:%x", toc); | ||
240 | fread(&type, 1, sizeof(type), fin); | ||
241 | qDebug("File length:%u", type); | ||
242 | fseek(fin, toc, SEEK_SET); | ||
243 | fread(&nopages, 1, sizeof(nopages), fin); | ||
244 | m_indexpages = new UInt32[nopages]; | ||
245 | m_pagedetails = new Page_detail[nopages]; | ||
246 | qDebug("There are %u pages", nopages); | ||
247 | UInt32 loc = 0; | ||
248 | UInt32 homeguess = nopages-1; | ||
249 | QString homeurl; | ||
250 | for (int i = 0; i < nopages; ++i) | ||
251 | { | ||
252 | char name[32]; | ||
253 | UInt32 len, pos, flags; | ||
254 | fread(name, 1, 32, fin); | ||
255 | fread(&len, 1, 4, fin); | ||
256 | fread(&pos, 1, 4, fin); | ||
257 | fread(&flags, 1, 4, fin); | ||
258 | //qDebug("Page %u (%s) is %u bytes at %u (%u) of type %u", i, name, len, pos, loc, flags); | ||
259 | m_index[name] = i; | ||
260 | m_pagedetails[i] = Page_detail(loc, len, flags); | ||
261 | |||
262 | if (QString(name).find(".htm", 0, false) >= 0) | ||
263 | { | ||
264 | if (homeguess > i) homeguess = i; | ||
265 | if ((flags & 8) != 0) | ||
266 | { | ||
267 | UInt32 lastpos = ftell(fin); | ||
268 | loc += pagelength(i); | ||
269 | fseek(fin, lastpos, SEEK_SET); | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | loc += len; | ||
274 | } | ||
275 | } | ||
276 | if ((flags & 2) != 0) | ||
277 | { | ||
278 | UInt32 lastpos = ftell(fin); | ||
279 | RBPage* idx = new RBPage(); | ||
280 | idx->init(fin, m_blocksize, m_decompress); | ||
281 | idx->startpage(page2pos(i), i, ((flags & 8) != 0), len); | ||
282 | int c = 0; | ||
283 | while (c != EOF) | ||
284 | { | ||
285 | QString s(""); | ||
286 | while (1) | ||
287 | { | ||
288 | c = idx->getch(this); | ||
289 | if (c == 10 || c == EOF) break; | ||
290 | s += c; | ||
291 | } | ||
292 | if (s.left(5) == "BODY=") | ||
293 | { | ||
294 | homeurl = s.right(s.length()-5); | ||
295 | qDebug("Home:%s", (const char*)homeurl); | ||
296 | } | ||
297 | else | ||
298 | { | ||
299 | qDebug("Info:%s", (const char*)s); | ||
300 | } | ||
301 | } | ||
302 | delete idx; | ||
303 | fseek(fin, lastpos, SEEK_SET); | ||
304 | } | ||
305 | } | ||
306 | text_length = loc; | ||
307 | qDebug("Looking for homepage"); | ||
308 | if (homeurl.isEmpty()) | ||
309 | { | ||
310 | m_homepage = homeguess; | ||
311 | } | ||
312 | else | ||
313 | { | ||
314 | QMap<QString, UInt32>::Iterator iter = m_index.find(homeurl); | ||
315 | if (iter != m_index.end()) | ||
316 | { | ||
317 | m_homepage = iter.data(); | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | m_homepage = homeguess; | ||
322 | } | ||
323 | } | ||
324 | m_homepos = m_pagedetails[m_homepage].pagestart; | ||
325 | qDebug("Finding indices"); | ||
326 | for (QMap<QString, UInt32>::Iterator iter = m_index.begin(); iter != m_index.end(); ++iter) | ||
327 | { | ||
328 | QString href = iter.key(); | ||
329 | if (href.find(".htm", 0, false) >= 0) | ||
330 | { | ||
331 | QString hind = href.left(href.find(".htm", 0, false))+".hidx"; | ||
332 | //qDebug("Index is %s", (const char*)hind); | ||
333 | QMap<QString, UInt32>::Iterator iter2 = m_index.find(hind); | ||
334 | if (iter2 != m_index.end()) | ||
335 | { | ||
336 | m_indexpages[iter.data()] = iter2.data(); | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | qDebug("Going home"); | ||
341 | home(); | ||
342 | return 0; | ||
343 | } | ||
344 | else | ||
345 | { | ||
346 | char * tmp = (char*)(&type); | ||
347 | for (int i = 0; i < 4; ++i) qDebug("%d:%c", i, tmp[i]); | ||
348 | return -1; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | UInt32 CReb::page2pos(UInt32 page) | ||
353 | { | ||
354 | fseek(fin, toc+40+44*page, SEEK_SET); | ||
355 | UInt32 pos; | ||
356 | fread(&pos, 1, 4, fin); | ||
357 | return pos; | ||
358 | } | ||
359 | |||
360 | UInt32 CReb::pagelength(UInt32 pagenum) | ||
361 | { | ||
362 | fseek(fin, toc+40+44*pagenum, SEEK_SET); | ||
363 | UInt32 pos; | ||
364 | fread(&pos, 1, 4, fin); | ||
365 | fseek(fin, pos+4, SEEK_SET); | ||
366 | UInt32 len; | ||
367 | fread(&len, 1, sizeof(len), fin); | ||
368 | return len; | ||
369 | } | ||
370 | |||
371 | void CReb::readindex(UInt32 cp) | ||
372 | { | ||
373 | if (joins != NULL) | ||
374 | { | ||
375 | delete [] joins; | ||
376 | joins = NULL; | ||
377 | } | ||
378 | if (tags != NULL) | ||
379 | { | ||
380 | delete [] tags; | ||
381 | tags = NULL; | ||
382 | } | ||
383 | if (paras != NULL) | ||
384 | { | ||
385 | delete [] paras; | ||
386 | paras = NULL; | ||
387 | } | ||
388 | noparas = 0; | ||
389 | nojoins = 0; | ||
390 | names.clear(); | ||
391 | |||
392 | UInt32 rspage = m_indexpages[cp]; | ||
393 | if (rspage != 0) | ||
394 | { | ||
395 | Page_detail rs = m_pagedetails[rspage]; | ||
396 | int count = 0; | ||
397 | RBPage* idx = new RBPage(); | ||
398 | idx->init(fin, m_blocksize, m_decompress); | ||
399 | idx->startpage(page2pos(rspage), rspage, ((rs.flags & 8) != 0), rs.len); | ||
400 | int c = 0; | ||
401 | int phase = 0; | ||
402 | int i; | ||
403 | if (m_binary) | ||
404 | { | ||
405 | count = idx->getuint(this); | ||
406 | qDebug("tag count:%d", count); | ||
407 | tags = new QString[count]; | ||
408 | for (int i = 0; i < count; ++i) | ||
409 | { | ||
410 | QString s; | ||
411 | while (1) | ||
412 | { | ||
413 | c = idx->getch(this); | ||
414 | if (c == 0 || c == EOF) break; | ||
415 | s += c; | ||
416 | } | ||
417 | unsigned short val = idx->getuint(this); | ||
418 | if (val != 0xffff) | ||
419 | { | ||
420 | tags[i] = tags[val]+s; | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | tags[i] = s; | ||
425 | } | ||
426 | //qDebug("tags[%d](%d) = %s", i, val, (const char*)tags[i]); | ||
427 | } | ||
428 | noparas = idx->getint(this); | ||
429 | qDebug("Para count %d", noparas); | ||
430 | paras = new ParaRef[noparas]; | ||
431 | for (int i = 0; i < noparas; ++i) | ||
432 | { | ||
433 | paras[i] = ParaRef(idx->getint(this), idx->getuint(this)); | ||
434 | } | ||
435 | count = idx->getint(this); | ||
436 | qDebug("Name count %d", count); | ||
437 | for (int i = 0; i < count; ++i) | ||
438 | { | ||
439 | QString s; | ||
440 | while (1) | ||
441 | { | ||
442 | c = idx->getch(this); | ||
443 | if (c == 0 || c == EOF) break; | ||
444 | s += c; | ||
445 | } | ||
446 | int val = idx->getint(this); | ||
447 | names[s.mid(1,s.length()-2)] = val; | ||
448 | qDebug("names[%s] = %d", (const char*)s, val); | ||
449 | } | ||
450 | count = idx->getint(this); | ||
451 | qDebug("Join count %d", count); | ||
452 | if (count > 0) | ||
453 | { | ||
454 | nojoins = count+2; | ||
455 | joins = new UInt32[count+2]; | ||
456 | joins[0] = 0; | ||
457 | joins[count+1] = currentpage.length(); | ||
458 | for (int i = 1; i < count+1; ++i) | ||
459 | { | ||
460 | joins[i] = idx->getint(this); | ||
461 | } | ||
462 | } | ||
463 | } | ||
464 | else | ||
465 | { | ||
466 | while (c != EOF) | ||
467 | { | ||
468 | QString s(""); | ||
469 | while (1) | ||
470 | { | ||
471 | c = idx->getch(this); | ||
472 | if (c == 10 || c == EOF) break; | ||
473 | s += c; | ||
474 | } | ||
475 | //qDebug("%s", (const char*)s); | ||
476 | if (count > 0) | ||
477 | { | ||
478 | --count; | ||
479 | int sp = s.findRev(' '); | ||
480 | QString l = s.left(sp); | ||
481 | int val = s.right(s.length()-sp).toInt(); | ||
482 | switch (phase) | ||
483 | { | ||
484 | case 4: | ||
485 | //qDebug("Join %d is at offset %d", i, val); | ||
486 | joins[i++] = val; | ||
487 | break; | ||
488 | case 3: | ||
489 | //qDebug("Name %s is at offset %d", (const char*)l.mid(1,l.length()-2), val+m_pagedetails[cp].pagestart); | ||
490 | names[l.mid(1,l.length()-2)] = val; | ||
491 | break; | ||
492 | case 1: | ||
493 | //qDebug("%s:%d [%d]", (const char*)l, val, i); | ||
494 | if (val >= 0) | ||
495 | { | ||
496 | tags[i++] = tags[val]+l; | ||
497 | } | ||
498 | else | ||
499 | { | ||
500 | tags[i++] = l; | ||
501 | } | ||
502 | //qDebug("TAG:%s", (const char*)tags[i-1]); | ||
503 | break; | ||
504 | case 2: | ||
505 | paras[i++] = ParaRef(QString(l).toInt(), val); | ||
506 | //qDebug("Para:%u - %u (%s)", QString(l).toInt(), val, (const char*)s); | ||
507 | break; | ||
508 | default: | ||
509 | qDebug("%s:%d", (const char*)l, val); | ||
510 | break; | ||
511 | } | ||
512 | } | ||
513 | else | ||
514 | { | ||
515 | QString key = "[tags "; | ||
516 | if (s.left(key.length()) == key) | ||
517 | { | ||
518 | phase = 1; | ||
519 | i = 0; | ||
520 | count = s.mid(key.length(),s.length()-key.length()-1).toInt(); | ||
521 | qDebug("%s:%s:%d", (const char*)key, (const char*)s, count); | ||
522 | tags = new QString[count]; | ||
523 | } | ||
524 | key = "[paragraphs "; | ||
525 | if (s.left(key.length()) == key) | ||
526 | { | ||
527 | phase = 2; | ||
528 | i = 0; | ||
529 | count = s.mid(key.length(),s.length()-key.length()-1).toInt(); | ||
530 | qDebug("%s:%s:%d", (const char*)key, (const char*)s, count); | ||
531 | paras = new ParaRef[count]; | ||
532 | noparas = count; | ||
533 | } | ||
534 | key = "[names "; | ||
535 | if (s.left(key.length()) == key) | ||
536 | { | ||
537 | phase = 3; | ||
538 | count = s.mid(key.length(),s.length()-key.length()-1).toInt(); | ||
539 | qDebug("%s:%s:%d", (const char*)key, (const char*)s, count); | ||
540 | } | ||
541 | key = "[joins "; | ||
542 | if (s.left(key.length()) == key) | ||
543 | { | ||
544 | phase = 4; | ||
545 | count = s.mid(key.length(),s.length()-key.length()-1).toInt(); | ||
546 | qDebug("%s:%s:%d", (const char*)key, (const char*)s, count); | ||
547 | nojoins = count+2; | ||
548 | i = 1; | ||
549 | joins = new UInt32[count+2]; | ||
550 | joins[0] = 0; | ||
551 | joins[count+1] = currentpage.length(); | ||
552 | qDebug("%s:%s:%d", (const char*)key, (const char*)s, count); | ||
553 | } | ||
554 | qDebug("ZC:%s", (const char*)s); | ||
555 | } | ||
556 | } | ||
557 | } | ||
558 | // for (int i = 0; i < nojoins; ++i) qDebug("JOINS:%u %u", i, joins[i]); | ||
559 | delete idx; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | bool CReb::findanchor(const QString& _info) | ||
564 | { | ||
565 | QMap<QString, int>::Iterator iter = names.find(_info); | ||
566 | if (iter != names.end()) | ||
567 | { | ||
568 | locate(iter.data()+m_pagedetails[currentpage.pageno()].pagestart); | ||
569 | return true; | ||
570 | } | ||
571 | return false; | ||
572 | } | ||
573 | |||
574 | #ifdef USEQPE | ||
575 | void CReb::suspend() | ||
576 | { | ||
577 | CExpander::suspend(fin); | ||
578 | } | ||
579 | void CReb::unsuspend() | ||
580 | { | ||
581 | CExpander::unsuspend(fin); | ||
582 | } | ||
583 | #endif | ||
584 | |||
585 | #ifndef __STATIC | ||
586 | extern "C" | ||
587 | { | ||
588 | CExpander* newcodec() { return new CReb; } | ||
589 | } | ||
590 | #endif | ||
591 | |||
592 | void CReb::startpage(UInt32 pgno) | ||
593 | { | ||
594 | Page_detail rs = m_pagedetails[pgno]; | ||
595 | unsuspend(); | ||
596 | readindex(pgno); | ||
597 | currentpage.startpage(page2pos(pgno), pgno, ((rs.flags & 8) != 0), rs.len); | ||
598 | } | ||
599 | |||
600 | void CReb::startpage(UInt32 _cp, bool _isCompressed, UInt32 _len) | ||
601 | { | ||
602 | unsuspend(); | ||
603 | readindex(_cp); | ||
604 | currentpage.startpage(page2pos(_cp), _cp, _isCompressed, _len); | ||
605 | } | ||
606 | |||
607 | void RBPage::initpage(UInt32 pos, size_t _cp, bool _isCompressed, UInt32 _len) | ||
608 | { | ||
609 | filepos = pos; | ||
610 | m_pageno = _cp; | ||
611 | m_Compressed = _isCompressed; | ||
612 | m_pagelen = _len; | ||
613 | currentchunk = 0; | ||
614 | pageoffset = 0; | ||
615 | |||
616 | if (chunklist != NULL) delete [] chunklist; | ||
617 | |||
618 | fseek(fin, filepos, SEEK_SET); | ||
619 | if (m_Compressed) | ||
620 | { | ||
621 | fread(&nochunks, 1, sizeof(nochunks), fin); | ||
622 | fread(&m_pagelen, 1, sizeof(m_pagelen), fin); | ||
623 | chunklist = new UInt32[nochunks]; | ||
624 | fread(chunklist, nochunks, 4, fin); | ||
625 | } | ||
626 | else | ||
627 | { | ||
628 | chunklist = NULL; | ||
629 | nochunks = (_len+m_blocksize-1)/m_blocksize; | ||
630 | } | ||
631 | m_startoff = 0; | ||
632 | m_endoff = m_pagelen; | ||
633 | chunkpos = ftell(fin); | ||
634 | qDebug("Compressed:%u Expanded:%u", _len, m_pagelen); | ||
635 | } | ||
636 | |||
637 | void RBPage::startpage(UInt32 pos, UInt32 _cp, bool _isCompressed, UInt32 _len) | ||
638 | { | ||
639 | initpage(pos, _cp, _isCompressed, _len); | ||
640 | readchunk(); | ||
641 | } | ||
642 | |||
643 | int CReb::getch() | ||
644 | { | ||
645 | if (tagoffset < tagstring.length()) | ||
646 | return tagstring[tagoffset++].unicode(); | ||
647 | else | ||
648 | return currentpage.getch(this); | ||
649 | } | ||
650 | |||
651 | int RBPage::getch(CReb* parent) | ||
652 | { | ||
653 | if (chunkoffset >= chunklen) | ||
654 | { | ||
655 | if (++currentchunk >= nochunks) | ||
656 | { | ||
657 | --currentchunk; | ||
658 | return EOF; | ||
659 | } | ||
660 | pageoffset += chunklen; | ||
661 | parent->unsuspend(); | ||
662 | readchunk(); | ||
663 | } | ||
664 | if (offset() == m_endoff) return EOF; | ||
665 | return chunk[chunkoffset++]; | ||
666 | } | ||
667 | |||
668 | unsigned short int RBPage::getuint(CReb* parent) | ||
669 | { | ||
670 | unsigned short int ret = 0; | ||
671 | char *buffer = (char*)(&ret); | ||
672 | for (int i = 0; i < 2; ++i) | ||
673 | { | ||
674 | int ch = getch(parent); | ||
675 | if (ch == EOF) return 0; | ||
676 | buffer[i] = ch; | ||
677 | } | ||
678 | return ret; | ||
679 | } | ||
680 | |||
681 | int RBPage::getint(CReb* parent) | ||
682 | { | ||
683 | int ret = 0; | ||
684 | char *buffer = (char*)(&ret); | ||
685 | for (int i = 0; i < 4; ++i) | ||
686 | { | ||
687 | int ch = getch(parent); | ||
688 | if (ch == EOF) return 0; | ||
689 | buffer[i] = ch; | ||
690 | } | ||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | void RBPage::readchunk() | ||
695 | { | ||
696 | if (m_Compressed) | ||
697 | { | ||
698 | chunkoffset = 0; | ||
699 | fseek(fin, chunkpos, SEEK_SET); | ||
700 | UInt8* inbuf = new UInt8[chunklist[currentchunk]]; | ||
701 | fread(inbuf, 1, chunklist[currentchunk], fin); | ||
702 | chunklen = (*m_decompress)(inbuf, chunklist[currentchunk], chunk, m_blocksize); | ||
703 | delete [] inbuf; | ||
704 | chunkpos = ftell(fin); | ||
705 | } | ||
706 | else | ||
707 | { | ||
708 | chunkoffset = 0; | ||
709 | chunklen = m_blocksize; | ||
710 | if (m_blocksize*(currentchunk+1) > m_pagelen) | ||
711 | { | ||
712 | chunklen = m_pagelen - currentchunk*m_blocksize; | ||
713 | } | ||
714 | fseek(fin, chunkpos, SEEK_SET); | ||
715 | chunklen = fread(chunk, 1, chunklen, fin); | ||
716 | chunkpos = ftell(fin); | ||
717 | } | ||
718 | } | ||
719 | |||
720 | void RBPage::setoffset(UInt32 pos, size_t _cp, bool _isCompressed, UInt32 _len, UInt32 _offset) | ||
721 | { | ||
722 | if (m_pageno != _cp) | ||
723 | { | ||
724 | initpage(pos, _cp, _isCompressed, _len); | ||
725 | } | ||
726 | else | ||
727 | { | ||
728 | if (m_Compressed) | ||
729 | { | ||
730 | chunkpos = filepos + sizeof(nochunks) + sizeof(m_pagelen) + 4*nochunks; | ||
731 | } | ||
732 | else | ||
733 | { | ||
734 | chunkpos = filepos; | ||
735 | } | ||
736 | } | ||
737 | |||
738 | currentchunk = _offset/m_blocksize; | ||
739 | pageoffset = m_blocksize*currentchunk; | ||
740 | if (m_Compressed) | ||
741 | { | ||
742 | for (int i = 0; i < currentchunk; ++i) | ||
743 | { | ||
744 | chunkpos += chunklist[i]; | ||
745 | } | ||
746 | } | ||
747 | else | ||
748 | { | ||
749 | chunkpos += pageoffset; | ||
750 | } | ||
751 | readchunk(); | ||
752 | chunkoffset = _offset - pageoffset; | ||
753 | } | ||
754 | |||
755 | void CReb::start2endSection() | ||
756 | { | ||
757 | if (m_pagedetails != NULL) | ||
758 | { | ||
759 | if (nojoins > 0) | ||
760 | { | ||
761 | //UInt32 jl = binarychop<UInt32>(joins, nojoins, currentpage.offset()); | ||
762 | |||
763 | UInt32 jl = 0,jh = nojoins-1,jm = (jl+jh)/2; | ||
764 | while (jh > jl+1) | ||
765 | { | ||
766 | if (joins[jm] > currentpage.offset()) | ||
767 | { | ||
768 | jh = jm; | ||
769 | } | ||
770 | else | ||
771 | { | ||
772 | jl = jm; | ||
773 | } | ||
774 | jm = (jl+jh)/2; | ||
775 | } | ||
776 | |||
777 | currentpage.m_startoff = joins[jl]; | ||
778 | currentpage.m_endoff = joins[jl+1]-1; | ||
779 | //currentpage.m_endoff = joins[jh]-1; | ||
780 | } | ||
781 | m_currentstart = m_pagedetails[currentpage.pageno()].pagestart+currentpage.m_startoff; | ||
782 | m_currentend = m_pagedetails[currentpage.pageno()].pagestart+currentpage.m_endoff; | ||
783 | } | ||
784 | else | ||
785 | { | ||
786 | m_currentstart = m_currentend = 0; | ||
787 | } | ||
788 | qDebug("s2e:[%u, %u, %u]", m_currentstart, locate(), m_currentend); | ||
789 | } | ||