
Добавил:
korayakov
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабы / 2 / lab.05.by mice / spice / src / csp_file
.cpp/*******************************************************************************
* file: csp_file.cpp *
* version: 0.0.1 *
* author: d-evil [tmd] (mailto:d-evil.tmd@mail.ru) *
* description: not available *
*******************************************************************************/
#include "csp_file.h"
////////////////////////////////////////////////////////////////////////////////
// csp_file public definitions
csp_file::csp_file() {
_hfile = NULL;
_items_in_arch = _DEF_ITEMS_IN_ARCH;
_arch_sz = sizeof(ssp_arch) + sizeof(ssp_item)*(_items_in_arch - 1);
_cur_arch = NULL;
_cur_arch_pos = 0;
}
csp_file::~csp_file() {
if (NULL != _hfile) finish_using();
_free_arch(_cur_arch);
}
int csp_file::set_items_in_arch(const int items_in_arch) {
if (NULL != _hfile) return -1;
return _set_items_in_arch(items_in_arch);
}
int csp_file::total_datagrams() const {
const int in_arches = (_header.total_arches - 1) * _header.items_in_arch;
return in_arches + _cur_arch_pos;
}
int csp_file::use_handle(const HANDLE hfile, const bool ro) {
_hfile = hfile;
_ro_mode = ro;
if (0 != _read_header()) {
// try to write header
if (ro) return -1;
if (0 != SetFilePointer(_hfile, 0, NULL, FILE_BEGIN)) return -1;
if (FALSE == SetEndOfFile(_hfile)) return -1;
_make_header();
if (0 != _write_header()) return -1;
_free_arch(_cur_arch);
_cur_arch = _write_new_arch(0);
if (NULL == _cur_arch) return -1;
_cur_arch_pos = 0;
}
return 0;
}
int csp_file::flush(const int flush_mode) {
if (_ro_mode) return 0;
if (FLUSH_ARCHES & flush_mode) {
if (0 != _save_arch(_cur_arch)) return -1;
}
if (FLUSH_HEADER & flush_mode) {
if (0 != _write_header()) return -1;
}
return 0;
}
int csp_file::finish_using() {
int rev = flush();
_free_arch(_cur_arch);
_cur_arch = NULL;
_cur_arch_pos = 0;
_hfile = NULL;
return rev;
}
csp_file::ssp_arch *csp_file::load_first_arch() {
const int pos = _header.first_arch;
if (pos != SetFilePointer(_hfile, pos, NULL, FILE_BEGIN)) return NULL;
ssp_arch *const arch = (ssp_arch *)malloc(_arch_sz);
if (NULL == arch) return NULL;
DWORD wr;
ReadFile(_hfile, arch, _arch_sz, &wr, NULL);
if (wr != _arch_sz) {
_free_arch(arch);
return NULL;
}
return arch;
}
csp_file::ssp_arch *csp_file::load_next_arch(ssp_arch *const arch, const bool reuse) {
const int pos = arch->next;
if (0 == pos) {
if (reuse) _free_arch(arch);
return NULL;
}
if (!reuse) return _load_arch_from(pos, NULL);
if (NULL == _load_arch_from(pos, arch)) {
_free_arch(arch);
return NULL;
}
return arch;
}
int csp_file::add_dtgm(const char *const dtgm, const int sz) {
DWORD ep = SetFilePointer(_hfile, 0, NULL, FILE_END);
DWORD wr;
WriteFile(_hfile, dtgm, sz, &wr, NULL);
if (sz != wr) return -1;
_cur_arch->items[_cur_arch_pos].pos = ep;
_cur_arch->items[_cur_arch_pos].length = sz;
++_cur_arch_pos;
if (_cur_arch_pos > (int)_header.items_in_arch) return -1;
if (_cur_arch_pos == _header.items_in_arch) {
ssp_arch *temp_arch = _write_new_arch(_cur_arch->num + 1);
if (NULL == temp_arch) return -1;
_cur_arch->next = temp_arch->pos;
if (0 != _save_arch(_cur_arch)) {
_free_arch(temp_arch);
return -1;
}
_free_arch(_cur_arch);
_cur_arch = temp_arch;
_cur_arch_pos = 0;
}
return 0;
}
int csp_file::load_dtgm(const ssp_arch *const arch, const int num, char *const dtgm) {
if (num >= _items_in_arch) return -1;
const int pos = arch->items[num].pos;
if (pos != SetFilePointer(_hfile, pos, NULL, FILE_BEGIN)) return -1;
const int len = arch->items[num].length;
DWORD wr;
ReadFile(_hfile, dtgm, len, &wr, NULL);
if (wr != len) return -1;
return 0;
}
int csp_file::load_dtgm(const int num, char *const dtgm, int *const sz) {
const int arch_num = num / _header.items_in_arch;
ssp_arch *arch = _load_arch(arch_num);
if (NULL == arch) return -1;
const int item_num = num % _header.items_in_arch;
if (item_num >= _arch_used(arch)) {
_free_arch(arch);
return -1;
}
int len = arch->items[item_num].length;
if (len > *sz) {
_free_arch(arch);
*sz = len;
return -1;
}
if (0 != load_dtgm(arch, item_num, dtgm)) {
_free_arch(arch);
return -1;
}
*sz = len;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// csp_file protected definitions
const char csp_file::_SPF_TYPE_STR[] = ".SPF";
int csp_file::_set_items_in_arch(const int items_in_arch) {
if (0 >= items_in_arch) return -1;
_items_in_arch = items_in_arch;
_arch_sz = sizeof(ssp_arch) + sizeof(ssp_item)*(_items_in_arch - 1);
return 0;
}
int csp_file::_arch_used(const ssp_arch *const arch) {
for (int i = _header.items_in_arch - 1; 0 <= i; --i) {
if (0 != arch->items[i].pos) return i+1;
}
return 0;
}
int csp_file::_read_header() {
if (0 != SetFilePointer(_hfile, 0, NULL, FILE_BEGIN)) return -1;
DWORD wr = 0;
ReadFile(_hfile, &_header, sizeof(_header), &wr, NULL);
if (sizeof(_header) != wr) return -1;
if (0 != memcmp(_header.type, _SPF_TYPE_STR, sizeof(_header.type))) return -1;
if (_header.version_hi != _VERSION_HI) return -1;
if (_header.version_lo != _VERSION_LO) return -1;
if (0 != _set_items_in_arch(_header.items_in_arch)) return -1;
// load last arch
_free_arch(_cur_arch);
_cur_arch = _load_arch_from(_header.last_arch);
if (NULL == _cur_arch) return -1;
_cur_arch_pos = _arch_used(_cur_arch);
if (_cur_arch_pos < _items_in_arch || _ro_mode) return 0;
// if last arch is full
//TODO: return 0;
return -1;
}
int csp_file::_write_header() {
DWORD wr = SetFilePointer(_hfile, 0, NULL, FILE_BEGIN);
if (0 != wr) return -1;
WriteFile(_hfile, &_header, sizeof(_header), &wr, NULL);
if (sizeof(_header) != wr) return -1;
return 0;
}
void csp_file::_make_header(const int total_arches, const int last_arch) {
memcpy(_header.type, _SPF_TYPE_STR, sizeof(_header.type));
_header.version_hi = _VERSION_HI;
_header.version_lo = _VERSION_LO;
if (0 != total_arches) _header.total_arches = total_arches;
else _header.total_arches = 0;
_header.items_in_arch = _items_in_arch;
_header.first_arch = _DEF_ARCH_OFFSET;
if (0 != last_arch) _header.last_arch = last_arch;
else _header.last_arch = _DEF_ARCH_OFFSET;
}
csp_file::ssp_arch *csp_file::_load_arch_from(const int pos, ssp_arch *const garch) {
if (pos != SetFilePointer(_hfile, pos, NULL, FILE_BEGIN)) return NULL;
ssp_arch *arch;
if (NULL == garch) {
arch = (ssp_arch *)malloc(_arch_sz);
if (NULL == arch) return NULL;
} else arch = garch;
DWORD wr;
ReadFile(_hfile, arch, _arch_sz, &wr, NULL);
if (wr != _arch_sz) {
if (NULL != garch) free(arch);
return NULL;
}
return arch;
}
csp_file::ssp_arch *csp_file::_load_arch(const int num, ssp_arch *const garch) {
DWORD wr;
ssp_arch temp_arch;
unsigned int cp = _header.first_arch;
for (;;) {
wr = SetFilePointer(_hfile, cp, NULL, FILE_BEGIN);
if (wr != cp) return NULL;
ReadFile(_hfile, &temp_arch, sizeof(temp_arch), &wr, NULL);
if (wr != sizeof(temp_arch)) return NULL;
if (num == temp_arch.num) break;
if (0 == (cp = temp_arch.next)) return NULL;
}
return _load_arch_from(cp, garch);
}
int csp_file::_save_arch(const ssp_arch *const arch) {
DWORD wr = SetFilePointer(_hfile, arch->pos, NULL, FILE_BEGIN);
if (wr != arch->pos) return -1;
WriteFile(_hfile, arch, _arch_sz, &wr, NULL);
if (wr != _arch_sz) return -1;
return 0;
}
csp_file::ssp_arch *csp_file::_write_new_arch(const int num) {
ssp_arch *arch = (ssp_arch *)malloc(_arch_sz);
if (NULL == arch) return NULL;
memset(arch, 0, _arch_sz);
arch->num = num;
if (0 == num) arch->pos = _header.first_arch;
else arch->pos = SetFilePointer(_hfile, 0, NULL, FILE_END);
if (0 != _save_arch(arch)) {
free(arch);
arch = NULL;
}
_header.last_arch = arch->pos;
++_header.total_arches;
return arch;
}
void csp_file::_free_arch(ssp_arch *const arch) {
free(arch);
}
Соседние файлы в папке src