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 #if __BYTE_ORDER == __LITTLE_ENDIAN // convenience shortcut
00179 unsigned long res = 0;
00180 read ((char *)&res, 4);
00181 return res;
00182 #else
00183 char buf[4];
00184 read (buf, 4);
00185 size_t res = buf[0];
00186 res |= buf[1] << 8;
00187 res |= buf[2] << 16;
00188 res |= buf[3] << 24;
00189 return res;
00190 #endif
00191 }
00192
00195 inline unsigned int get_word ()
00196 {
00197 #if __BYTE_ORDER == __LITTLE_ENDIAN // convenience shortcut
00198 unsigned int res = 0;
00199 read ((char *)&res, 2);
00200 return res;
00201 #else
00202 char buf[2];
00203 read (buf, 2);
00204 unsigned int res = buf[0];
00205 res |= buf[1] << 8;
00206 return res;
00207 #endif
00208 }
00209
00213 inline unsigned long get_sr (int s, int r, int& pos)
00214 {
00215 int b = peek();
00216 int p = 0;
00217 while ( (1 << pos) & b ) {
00218 p++;
00219 pos++;
00220 if ( pos == 8 ) {
00221 get();
00222 b = peek ();
00223 pos = 0;
00224 }
00225 }
00226
00227 pos++;
00228 if ( pos == 8 ) {
00229 get ();
00230 b = peek ();
00231 pos = 0;
00232 }
00233
00234 if ( p > 1 ) r += p - 1;
00235
00236 unsigned long res = 0;
00237
00238 for ( int i = 0; i < r; i++ ) {
00239 res |= ((1 << pos) & b) ? (1 << i) : 0;
00240 pos++;
00241 if ( pos == 8 ) {
00242 get ();
00243 b = peek ();
00244 pos = 0;
00245 }
00246 }
00247
00248 res |= 1 << r;
00249
00250 return res;
00251 }
00252
00253 inline void get_sr_finish (int &pos)
00254 {
00255 if ( pos ) {
00256 get();
00257 pos = 0;
00258 }
00259 }
00260
00261 private:
00262 std::streambuf *buf;
00263 bool release;
00264 };
00265
00266 }
00267
00268 #endif // __chm_h__
00269