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; // long guatanteed to be 4 bytes 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; // int guaranteed to be 2 bytes 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++; // skip the 0 of p 00228 if ( pos == 8 ) { 00229 get (); 00230 b = peek (); 00231 pos = 0; 00232 } 00233 00234 if ( p > 1 ) r += p - 1; // r now has number of bits for q 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