Хочу сделать свою базу данных для:
1. Того чтобы использовать в своих проектах!
2. Упростить себе жизнь :-)))
3. Для саморазвития.
Прошу не пинайте сильно, не говорите ничего о SQL'ах!
Код который я уже написал и ещё напишу мне кажется гораздо проще и понятнее чем код *SQL*
1 файл одна таблица, никаких подключений и т.п. открываешь и читаешь и пишешь! -Рай!
Тока вот интересно мнение других людей! Что скажете по этому поводу?
Таблица будет состоять из форматированного заголовка и последовательных элементов!
Всё в таблице размерами не ограничивается!
(ну разве что размер всего файла-таблицы не может быть больше чем максимальный размер int64 / 2 в байтах!)
Напишу потом также модель для такой таблицы! Думаю будет удобно т.к. ничего нигде не буферизуется,
данные будут напрямую читаться и писаться в файл!
Пока я написал тока класс заголовка(SFileTableHeader), он будет внутри самого класса файла-таблицы(SFileTable)
и не будет доступен вне этого класса! т.е. заголовком будет оперировать тока сам SFileTable
sfiletableheader.h
#ifndef SFILETABLEHEADER_H
#define SFILETABLEHEADER_H
#include <QObject>
#include <QVector>
struct ELEMENT { // ячейка
qint64 address; // стартовый адрес байтов ячейки
qint64 length; // длина
ELEMENT() {
address = 0;
length = 0;
}
};
class SFileTableHeader : public QObject
{ // Каждая ячейка самой таблицы будет из сырых байт
Q_OBJECT
public:
bool ignoreErrors;
QVector < QByteArray > colnames; // как-бы имена столбцов
QVector < QByteArray > rownames; // тут имена строк
QVector < QVector < ELEMENT > > items;
explicit SFileTableHeader(QObject *parent = 0);
void clear(void); // очистить всё
qint32 columnsCount(void); // кол-во столбцов
qint32 rowsCount(void); // кол-во колонок
static qint32 sizeFromChars(char * four, qint32 pos = 0); // описание в .cpp
static qint64 sizeFromChars64(char * four, qint32 pos = 0);
qint32 headerSize(void); // нужный для записи в файл размер заголовка
bool load(char * hdr); // загрузить всё из прочитанного заголовка
QByteArray get(void); // получить то что будем писать в файл
void resize(qint32 columns, qint32 rows); // изм. размер "без вопросов"
void appendColumns(qint32 count); // добавить в конец колонок
void appendRows(qint32 count); // здесь строк
void appendColumn(void); // здесь и ниже одну
void appendRow(void);
void columnMoveUp(qint32 column); // сдвинуть колонку влево
void columnMoveDown(qint32 column); // здесь вправо
void moveColumn(qint32 column, qint32 newposition); // в нужную позицию
void rowMoveUp(qint32 row); // то же и здесь тока вверх
void rowMoveDown(qint32 row); // и вниз
void moveRow(qint32 row, qint32 newposition); //
void insertColumns(qint32 position, qint32 count = 1); // тут ясно
void insertRows(qint32 position, qint32 count = 1);
bool isValid(void); // проверить правильность заголовка (простая проверка)
signals:
public slots:
};
#endif // SFILETABLEHEADER_H
sfiletableheader.cpp
#include "sfiletableheader.h"
SFileTableHeader::SFileTableHeader(QObject *parent) :
QObject(parent)
{
clear();
ignoreErrors = false; // использоваться будет позже (в других версиях)
}
void SFileTableHeader::clear(void)
{ // всё очищаем
colnames.clear();
rownames.clear();
items.clear();
}
qint32 SFileTableHeader::columnsCount(void)
{ // количество колонок
return (qint32)colnames.size();
}
qint32 SFileTableHeader::rowsCount(void)
{ // количество строк
return (qint32)rownames.size();
}
qint32 SFileTableHeader::sizeFromChars(char * four, qint32 pos)
{ // берём число в сыром виде из 4 байт и возвращаем его
qint32 result;
((char*)&result)[0] = four[(pos + 0)];
((char*)&result)[1] = four[(pos + 1)];
((char*)&result)[2] = four[(pos + 2)];
((char*)&result)[3] = four[(pos + 3)];
return result;
}
qint64 SFileTableHeader::sizeFromChars64(char * four, qint32 pos)
{ // здесь берём из 8 байт
qint64 result;
((char*)&result)[0] = four[(pos + 0)];
((char*)&result)[1] = four[(pos + 1)];
((char*)&result)[2] = four[(pos + 2)];
((char*)&result)[3] = four[(pos + 3)];
((char*)&result)[4] = four[(pos + 4)];
((char*)&result)[5] = four[(pos + 5)];
((char*)&result)[6] = four[(pos + 6)];
((char*)&result)[7] = four[(pos + 7)];
return result;
}
qint32 SFileTableHeader::headerSize(void)
{ // подсчитываем сколько байт будет занимать записанный заголовок
qint32 result = 12; // сразу 4 заголовок, 4 столбцы, 4 строки
for (qint32 i = 0; i < colnames.size(); i++) { // строки
result += (colnames[i].size() + 4); // колво байт + идентификатор длины
}
for (qint32 i = 0; i < rownames.size(); i++) { // столбцы
result += (rownames[i].size() + 4);
}
// стартовый адрес (8 байт) и длина (8) ячейки
result += ((colnames.size() * rownames.size()) * 16);
return result;
}
bool SFileTableHeader::load(char * hdr)
{ // парсим заголовок уже прочитанный из файла
clear(); // очищаем сперва всё
//qint32 hdrsize = sizeFromChars(hdr, 0);
qint32 colcount = sizeFromChars(hdr, 4);
qint32 rowcount = sizeFromChars(hdr, 8);
qint32 temp = 0, pos = 12;
colnames.resize(colcount);
for (qint32 i = 0; i < colcount; i++) { // заполняем имена колонок
temp = sizeFromChars(hdr, pos);
pos += 4;
for (qint32 x = 0; x < temp; x++) {
colnames[i].append(hdr[(pos + x)]);
}
pos += temp;
temp = 0;
}
if (colnames.size() != colcount) {
if (!ignoreErrors)
return false;
}
for (qint32 i = 0; i < rowcount; i++) { // имена строк
temp = sizeFromChars(hdr, pos);
pos += 4;
for (qint32 x = 0; x < temp; x++) {
rownames[i].append(hdr[(pos + x)]);
}
pos += temp;
temp = 0;
}
if (rownames.size() != rowcount) {
if (!ignoreErrors)
return false;
}
items.resize(rowcount);
for (qint32 x = 0; x < rowcount; x++) { // заполняем инфу о ячейках
items[x].resize(colcount);
for (qint32 y = 0; y < colcount; y++) {
items[x][y].address = sizeFromChars64(hdr, pos);
pos += 4;
items[x][y].length = sizeFromChars64(hdr, pos);
pos += 4;
}
}
return true;
}
QByteArray SFileTableHeader::get(void)
{ // получаем сырые данные этого заголовка для записи в файл
qint32 temp = headerSize();
QByteArray result; result.resize(temp);
if (!temp)
return result;
for (qint32 i = 0; i < 4; i++) {
result[i] = ((char*)&temp)[i];
}
qint32 pos = 4;
temp = colnames.size();
for (qint32 i = 0; i < 4; i++) {
result[(pos + i)] = ((char*)&temp)[i];
}
pos += 4;
temp = rownames.size();
for (qint32 i = 0; i < 4; i++) {
result[(pos + i)] = ((char*)&temp)[i];
}
pos += 4;
for (qint32 x = 0; x < colnames.size(); x++) {
temp = colnames[x].size();
for (qint32 i = 0; i < 4; i++) {
result[(pos + i)] = ((char*)&temp)[i];
}
pos += 4;
for (qint32 i = 0; i < colnames[x].size(); i++) {
result[(pos + i)] = colnames[x][i];
}
pos += colnames[x].size();
}
for (qint32 x = 0; x < rownames.size(); x++) {
temp = rownames[x].size();
for (qint32 i = 0; i < 4; i++) {
result[(pos + i)] = ((char*)&temp)[i];
}
pos += 4;
for (qint32 i = 0; i < rownames[x].size(); i++) {
result[(pos + i)] = rownames[x][i];
}
pos += rownames[x].size();
}
for (qint32 x = 0; x < rownames.size(); x++) {
for (qint32 y = 0; y < colnames.size(); y++) {
for (qint32 i = 0; i < 8; i++) {
result[(pos + i)] = ((char*)&items[x][y].address)[i];
}
pos += 8;
for (qint32 i = 0; i < 8; i++) {
result[(pos + i)] = ((char*)&items[x][y].length)[i];
}
pos += 8;
}
}
return result;
}
void SFileTableHeader::resize(qint32 columns, qint32 rows)
{
if ((columns < 0)||(rows < 0))
return;
if (rows != rownames.size()) {
int lastrows = rownames.size();
rownames.resize(rows);
items.resize(rows);
if (columns == colnames.size()) {
for (int i = lastrows; i < rownames.size(); i++) {
items[i].resize(columns);
}
}
}
if (columns != colnames.size()) {
colnames.resize(columns);
for (qint32 i = 0; i < rownames.size(); i++) {
items[i].resize(columns);
}
}
}
void SFileTableHeader::appendColumns(qint32 count)
{
resize((colnames.size() + count), rownames.size());
}
void SFileTableHeader::appendRows(qint32 count)
{
resize(colnames.size(), (rownames.size() + count));
}
void SFileTableHeader::appendColumn(void)
{
appendColumns(1); // зачем повторяться! так лучше!
}
void SFileTableHeader::appendRow(void)
{
appendRows(1);
}
void SFileTableHeader::columnMoveUp(qint32 column)
{
if ((column < 0)||(column >= (colnames.size() - 1)))
return;
QByteArray qba = colnames[column];
colnames[column] = colnames[(column + 1)];
colnames[(column + 1)] = qba;
}
void SFileTableHeader::columnMoveDown(qint32 column)
{
if ((column < 1)||(column >= colnames.size()))
return;
QByteArray qba = colnames[column];
colnames[column] = colnames[(column - 1)];
colnames[(column - 1)] = qba;
}
void SFileTableHeader::moveColumn(qint32 column, qint32 newposition)
{
if (column > newposition) {
if ((column < 1)||(column >= colnames.size())||(newposition >= colnames.size())||(newposition < 0))
return;
qint32 thispos = column;
while (thispos > newposition) {
columnMoveDown(thispos);
thispos--;
}
}
else {
if ((column < 0)||(column >= (colnames.size() - 1))||(newposition >= colnames.size())||(newposition < 0))
return;
qint32 thispos = column;
while (thispos < newposition) {
columnMoveUp(thispos);
thispos++;
}
}
}
void SFileTableHeader::rowMoveUp(qint32 row)
{
if ((row < 0)||(row >= (rownames.size() - 1)))
return;
QByteArray qba = rownames[row];
rownames[row] = rownames[(row + 1)];
rownames[(row + 1)] = qba;
}
void SFileTableHeader::rowMoveDown(qint32 row)
{
if ((row < 1)||(row >= rownames.size()))
return;
QByteArray qba = rownames[row];
rownames[row] = rownames[(row - 1)];
rownames[(row - 1)] = qba;
}
void SFileTableHeader::moveRow(qint32 row, qint32 newposition)
{
if (row > newposition) {
if ((row < 1)||(row >= rownames.size())||(newposition >= rownames.size())||(newposition < 0))
return;
qint32 thispos = row;
while (thispos > newposition) {
rowMoveDown(thispos);
thispos--;
}
}
else {
if ((row < 0)||(row >= (rownames.size() - 1))||(newposition >= rownames.size())||(newposition < 0))
return;
qint32 thispos = row;
while (thispos < newposition) {
rowMoveUp(thispos);
thispos++;
}
}
}
void SFileTableHeader::insertColumns(qint32 position, qint32 count)
{
if ((count < 1)||(position < 0)||(position > colnames.size()))
return;
if (position == colnames.size()) {
appendColumns(count);
return;
}
colnames.insert(position, count, QByteArray());
ELEMENT etmp; // образец
for (qint32 i = 0; i < items.size(); i++)
items[i].insert(position, count, etmp);
}
void SFileTableHeader::insertRows(qint32 position, qint32 count)
{
if ((count < 1)||(position < 0)||(position > rownames.size()))
return;
if (position == rownames.size()) {
appendRows(count);
return;
}
rownames.insert(position, count, QByteArray());
QVector < ELEMENT > vec;
items.insert(position, count, vec);
for (qint32 i = 0; i < items.size(); i++) {
if (items[i].size() != colnames.size())
items[i].resize(colnames.size());
}
}
bool SFileTableHeader::isValid(void)
{ // вот такая простейшая проверка
if (rownames.size() != items.size())
return false;
for (qint32 i = 0; i < rownames.size(); i++) {
if (colnames.size() != items[i].size())
return false;
}
return true;
}
// код пока сыроват конечно, но когда-нибудь это будет исправлено
Что думаете о данном коде, да и о затее в целом!
Мошь ченибудь потом доделать???
Выразите свои мысли пожалуйста!