Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы / 2 / lab.05.by mice / spice / src / csp_file

.cpp
Скачиваний:
11
Добавлен:
17.04.2013
Размер:
8.44 Кб
Скачать
/*******************************************************************************
* 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