00001
00002 #ifndef __chm_h__
00003 #define __chm_h__
00004
00005 #include <string>
00006 #include <ostream>
00007 #include <istream>
00008 #include <vector>
00009 #include <list>
00010 #include <map>
00011
00021 struct chmFile;
00022
00027 namespace chm {
00028
00030 struct chm_topics_tree {
00031 std::string title;
00032 std::string path;
00033 chm_topics_tree *parent;
00034 std::list<chm_topics_tree *> children;
00035
00036 ~chm_topics_tree ();
00037 };
00038
00040 struct chm_search_document {
00041 std::string title;
00042 std::string path;
00043 std::vector<int> offsets;
00044 };
00045
00047 struct chm_search_match {
00048 int is_title;
00049 std::string key;
00050 std::vector<chm_search_document> documents;
00051 };
00052
00054 class chmfile {
00055 public:
00057 chmfile (const std::string& path);
00058 virtual ~chmfile ();
00059
00061 bool is_open () const;
00062
00064 void close ();
00065
00067 inline operator bool() const { return is_open(); }
00068
00070 bool read (const std::string& path, std::ostream& out) const;
00071
00074 bool read (const std::string& path, std::vector<char>& out) const;
00075
00077 bool read (const std::string& path, char *buf, size_t buf_size) const;
00078
00080 std::streamsize file_size (const std::string& path) const;
00081
00083 bool file_exists (const std::string& path) const;
00084
00086 enum readdir_type { files = 1, dirs = 2, special = 4, meta = 8 };
00087
00090 bool readdir (const std::string& path, std::list<std::string>& entries, int type = files|dirs) const;
00091
00096 std::streambuf* open (const std::string& path, size_t buf_size = 1024) const;
00097
00098 inline const std::string& get_title () const { return title; }
00099 inline const std::string& get_home_file () const { return home_file; }
00100 inline const std::string& get_generator () const { return generator; }
00101 inline const std::string& get_index_file () const { return index_file; }
00102 inline const std::string& get_topics_file () const { return topics_file; }
00103 inline const std::string& get_path () const { return path; }
00104
00108 const chm_topics_tree * get_topics_tree () const;
00109
00111 bool search_index (const std::string& txt, std::list<chm_search_match>& found,
00112 bool whole_words = true, bool titles_only = true) const;
00113
00119 bool cache (const std::string& path);
00121 void cache_search_database ();
00122
00123 private:
00124 mutable chmFile *chm;
00125 std::string path;
00126
00127 std::string title, home_file, generator, index_file, topics_file;
00128
00129 mutable chm_topics_tree *tree;
00130
00131 chmfile (const chmfile&);
00132 chmfile& operator= (const chmfile&);
00133
00134 typedef std::map<std::string,std::vector<char> > cache_data_t;
00135 cache_data_t cache_data;
00136 };
00137
00148 class chmistream : public std::istream {
00149 public:
00151 chmistream (const chmfile& chm, const std::string& path, size_t buf_size = 1024);
00152
00155 std::streamsize read_left () const;
00156
00157 virtual ~chmistream ();
00158
00160 inline size_t get_encint()
00161 {
00162 size_t result = 0;
00163 int shift = 0;
00164
00165 while (1) {
00166 int n = get();
00167 result |= (n & 0x7f) << shift;
00168 shift += 7;
00169 if ( !(n & 0x80) ) break;
00170 };
00171
00172 return result;
00173 }
00174
00176 inline unsigned long get_dword ()
00177 {
00178 char buf[4];
00179 read (buf, 4);
00180 size_t res = 0;
00181 res |= (unsigned char)buf[0] << 0;
00182 res |= (unsigned char)buf[1] << 8;
00183 res |= (unsigned char)buf[2] << 16;
00184 res |= (unsigned char)buf[3] << 24;
00185 return res;
00186 }
00187
00190 inline unsigned int get_word ()
00191 {
00192 char buf[2];
00193 read (buf, 2);
00194 unsigned int res = 0;
00195 res |= (unsigned char)buf[0] << 0;
00196 res |= (unsigned char)buf[1] << 8;
00197 return res;
00198 }
00199
00203 inline unsigned long get_sr (int , int r, int& pos)
00204 {
00205 int b = peek();
00206 int p = 0;
00207 while ( (1 << pos) & b ) {
00208 p++;
00209 pos++;
00210 if ( pos == 8 ) {
00211 get();
00212 b = peek ();
00213 pos = 0;
00214 }
00215 }
00216
00217 pos++;
00218 if ( pos == 8 ) {
00219 get ();
00220 b = peek ();
00221 pos = 0;
00222 }
00223
00224 if ( p > 1 ) r += p - 1;
00225
00226 unsigned long res = 0;
00227
00228 for ( int i = 0; i < r; i++ ) {
00229 res |= ((1 << pos) & b) ? (1 << i) : 0;
00230 pos++;
00231 if ( pos == 8 ) {
00232 get ();
00233 b = peek ();
00234 pos = 0;
00235 }
00236 }
00237
00238 res |= 1 << r;
00239
00240 return res;
00241 }
00242
00243 inline void get_sr_finish (int &pos)
00244 {
00245 if ( pos ) {
00246 get();
00247 pos = 0;
00248 }
00249 }
00250
00251 private:
00252 std::streambuf *buf;
00253 bool release;
00254 };
00255
00256 }
00257
00258 #endif // __chm_h__
00259