* Copyright 2011 kubtek <kubtek@mail.com>
*
* This file is part of StarDict.
*
* StarDict is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* StarDict is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with StarDict. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef STORAGE_IMPL_H_
#define STORAGE_IMPL_H_
#include "stddict.h"
#include "storage.h"
class ResDict;
class rindex_file
{
public:
rindex_file(void);
virtual ~rindex_file() {}
static rindex_file* Create(const std::string& filebasename,
const char* mainext, std::string& fullfilename);
virtual bool load(const std::string& url, gulong _filecount, gulong fsize,
bool CreateCacheFile) = 0;
virtual bool lookup(const char *str, guint32 &entry_offset, guint32 &entry_size) = 0;
protected:
gulong filecount;
};
class offset_rindex: public rindex_file
{
public:
offset_rindex(void);
~offset_rindex(void);
bool load(const std::string& url, gulong _filecount, gulong fsize,
bool CreateCacheFile);
bool lookup(const char *str, guint32 &entry_offset, guint32 &entry_size);
private:
bool lookup(const char *str, glong &idx);
const gchar *read_first_on_page_key(glong page_idx);
const gchar *get_first_on_page_key(glong page_idx);
const gchar *get_key(glong idx);
void get_data(glong idx, guint32 &entry_offset, guint32 &entry_size);
gulong load_page(glong page_idx);
static const gint ENTR_PER_PAGE=32;
* Size of a key in index is not limited. Use this value to allocate a buffer
* and read the first chunk from the index file. */
static const size_t DEFAULT_KEY_SIZE=256;
* number page_num. 0<= page_num <= npages-2
* oft_file.get_wordoffset(npages-1) - offset of the next to the last element
* in the index file
* oft_file.get_wordoffset(page_num+1) - oft_file.get_wordoffset(page_num)
* - size of data on the page number page_num, in bytes. */
cache_file oft_file;
FILE *idxfile;
std::vector<char> buffer;
* The page number npages-2 always contains at least one element.
* It may contain from 1 to ENTR_PER_PAGE elements.
* To be exact it contains nentr elements, that may be calculated as follows:
* nentr = filecount%ENTR_PER_PAGE;
* if(nentr == 0)
* nentr = ENTR_PER_PAGE;
* The page number npages-1 (the last) is always empty. */
gulong npages;
struct index_entry {
glong page_idx;
std::string keystr;
void assign(glong i, const std::string& str) {
page_idx=i;
keystr.assign(str);
}
};
* last - first key on the pre-last page (last page addressing real data)
* middle - first key on the middle page
* read_last - last key in the index */
index_entry first, last, middle, real_last;
struct page_entry {
gchar *keystr;
guint32 off, size;
};
std::vector<gchar> page_data;
struct page_t {
glong page_idx;
page_entry entries[ENTR_PER_PAGE];
page_t(): page_idx(-1) {}
void fill(gchar *data, gint nent, glong page_idx_);
} page;
};
class compressed_rindex: public rindex_file
{
public:
compressed_rindex(void);
~compressed_rindex(void);
bool load(const std::string& url, gulong _filecount, gulong fsize,
bool CreateCacheFile);
bool lookup(const char *str, guint32 &entry_offset, guint32 &entry_size);
private:
bool lookup(const char *str, glong &idx);
const gchar *get_key(glong idx);
void get_data(glong idx, guint32 &entry_offset, guint32 &entry_size);
gchar *idxdatabuf;
* followed by data offset and size. See ".ridx" file format.
* filelist.size() == number of files + 1 */
std::vector<gchar *> filelist;
};
class File_ResourceStorage {
public:
explicit File_ResourceStorage(const std::string &resdir);
~File_ResourceStorage(void);
* return value in file name encoding */
const std::string& get_file_path(const std::string &key);
const char *get_file_content(const std::string &key);
private:
std::string resdir;
std::string filepath;
gchar* data;
};
class Database_ResourceStorage {
public:
Database_ResourceStorage(void);
~Database_ResourceStorage(void);
bool load(const std::string& rifofilename, bool CreateCacheFile);
FileHolder get_file_path(const std::string &key);
const char *get_file_content(const std::string &key);
private:
bool load_rifofile(const std::string& rifofilename, gulong& filecount,
gulong& indexfilesize);
void clear_cache(void);
int find_in_cache(const std::string& key) const;
size_t put_in_cache(const std::string& key, const FileHolder& file);
private:
static const size_t FILE_CACHE_SIZE = 20;
struct FileCacheEntity
{
std::string key;
FileHolder file;
};
FileCacheEntity FileCache[FILE_CACHE_SIZE];
size_t cur_cache_ind;
rindex_file *ridx_file;
ResDict *dict;
};
#endif