crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Хочу написать свой формат базы данных! (Точнее таблицы), Получится один файл - одна таблица!
Strikevld
  опции профиля:
сообщение 24.10.2011, 22:40
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 53
Регистрация: 6.9.2011
Пользователь №: 2849

Спасибо сказали: 6 раз(а)




Репутация:   0  


Хочу сделать свою базу данных для:
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;
}
// код пока сыроват конечно, но когда-нибудь это будет исправлено



Что думаете о данном коде, да и о затее в целом!
Мошь ченибудь потом доделать???
Выразите свои мысли пожалуйста!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
maint
  опции профиля:
сообщение 25.10.2011, 6:13
Сообщение #2


Участник
**

Группа: Участник
Сообщений: 235
Регистрация: 3.8.2009
Из: Иркутск
Пользователь №: 982

Спасибо сказали: 28 раз(а)




Репутация:   2  


все когда то по молодости делали свою базу данных. У некоторых даже получалось. Работа с таблицей, вроде даже без индексов. Напоминает реализацию, dbf - кажется
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Strikevld
  опции профиля:
сообщение 25.10.2011, 7:12
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 53
Регистрация: 6.9.2011
Пользователь №: 2849

Спасибо сказали: 6 раз(а)




Репутация:   0  


Неа здесь будет по индексам!
Просто в этом классе colnames, rownames и items открыты!
А в другом будут функции типа cellAt!

Эх,, на мой взгляд моя таблица будет всё-же лучше!
(Пробежался щас по описанию dbf "DBF - Википедиа")
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
maint
  опции профиля:
сообщение 25.10.2011, 7:31
Сообщение #4


Участник
**

Группа: Участник
Сообщений: 235
Регистрация: 3.8.2009
Из: Иркутск
Пользователь №: 982

Спасибо сказали: 28 раз(а)




Репутация:   2  


Цитата(Strikevld @ 25.10.2011, 13:12) *
Неа здесь будет по индексам!
Просто в этом классе colnames, rownames и items открыты!
А в другом будут функции типа cellAt!

Эх,, на мой взгляд моя таблица будет всё-же лучше!
(Пробежался щас по описанию dbf "DBF - Википедиа")

даже не сомневаюсь, по поводу личного удобства. Я одной своей базой написанной лет 20 назад иногда пользуюсь для небольших задач. Может и что то большее выйдет у вас, чем личное. Мясо нарастет, а там посмотрите.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Strikevld
  опции профиля:
сообщение 4.11.2011, 17:55
Сообщение #5


Студент
*

Группа: Участник
Сообщений: 53
Регистрация: 6.9.2011
Пользователь №: 2849

Спасибо сказали: 6 раз(а)




Репутация:   0  


Вот посмотрите и скажите как вам это!
Эта программа как раз реализует то что мне надо было!


(Самым простым способом протестировать таблицы, я счел написанием их редактора)
В будущем собираюсь сделать возможность выбора в ячейке информации из ячейки другой таблицы(-файла)!
Скажите ваше мнение пожалуйста!

Ссылка на файл..... (release.7z - Файлообменник RGhost)

Начальный этап, мне кажется я завершил!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 19.4.2024, 18:02