/
MaximU
/
application
Обзор
Документация
Войти
/
MaximU
/
application
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
replay.cpp
401 строка
10 KB
Максим
Приведение типов в стиле c++.
09 июл 2026, 02:14
09 июл 2026, 02:14
abb0e18
Код
Авторство
О чём код?
#include "replay.h" #include <algorithm> /*! * \brief Читает заголовок файла. * \param fileName Имя файла. * \param header Заголовок файла. * \return Признак успешного чтения заголовка файла. */ bool Replay::getHeader(const QString &fileName, Replay::Header &header) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { return false; } if (file.read(reinterpret_cast<char *>(&header), sizeof(header)) != sizeof(header)) { return false;; } return true; } /*! * \brief Конструктор. */ Replay::Header::Header() { std::fill(signature, signature + sizeof(signature) / sizeof(char), '\0'); version = 0; std::fill(reserve, reserve + sizeof(reserve) / sizeof(int), 0); } /*! * \brief Конструктор. */ Replay::RecordContext::RecordContext() { } /*! * \brief Начинает запись. * \param fileName Имя файла. * \param signature Сигнатура. * \param version Версия. * \return Признак успешного создания файла. */ bool Replay::RecordContext::open(const QString &fileName, const QString &signature, int version) { try { mFile.setFileName(fileName); if (!mFile.open(QIODevice::WriteOnly)) { throw 0; } //// Запись заголовка файла. Header header; memset(header.signature, 0, sizeof(header.signature)); memcpy(header.signature, signature.toUtf8().data(), signature.toUtf8().size()); header.version = version; header.reserve[0] = 0; header.reserve[1] = 0; header.reserve[2] = 0; header.reserve[3] = 0; header.reserve[4] = 0; header.reserve[5] = 0; header.reserve[6] = 0; header.reserve[7] = 0; header.reserve[8] = 0; header.reserve[9] = 0; if (mFile.write(reinterpret_cast<const char *>(&header), sizeof(header)) != sizeof(header)) { throw 1; } //// Запись количества блоков в файле. int64_t tmp = 0; if (mFile.write(reinterpret_cast<const char *>(&tmp), sizeof(tmp)) != sizeof(tmp)) { throw 2; } //// mBytesCount = mFile.size(); mPortions.resize(0); } catch (...) { mFile.close(); mFile.setFileName(QString()); mBytesCount = 0; mPortions.resize(0); return false; } return true; } /*! * \brief Завершает запись. */ void Replay::RecordContext::close() { mFile.close(); mBytesCount = 0; mPortions.clear(); } /*! * \brief Возвращает признак активности записи. * \return Признак активности записи. */ bool Replay::RecordContext::isOpen() { return mFile.isOpen(); } /*! * \brief Возвращает имя файла для записи. * \return Имя файла для записи. */ QString Replay::RecordContext::fileName() { return mFile.fileName(); } /*! * \brief Возвращает количество записанных в текущий файл блоков информации. * \return Количество записанных в текущий файл блоков информации. */ int Replay::RecordContext::portionCount() { return mPortions.size(); } /*! * \brief Возвращает количество записанной информации в байтах. * \return Количество записанной информации в байтах. */ int64_t Replay::RecordContext::byteCount() { return mBytesCount; } /*! * \brief Выполняет запись порции информации. * \param data Массив входной информации. * \param length Длина массива. * \param time Время. * \param offsetUTC Смещение отностительно UTC [c]. * \return признак успешного завершения записи порции информации. */ bool Replay::RecordContext::recordPortion(char *data, int64_t length, time_t time, long offsetUTC) { //// Переход в позицию начала записи следующего блока. if (!mFile.seek(mFile.size() - (sizeof(int64_t) + mPortions.size() * sizeof(PortionInfo)))) { return false; } //// Резервирование памяти для записи информации о новых блоках. const int PortionsResizeStep = 2048; if (mPortions.size() % PortionsResizeStep == 0) { mPortions.reserve(mPortions.size() + PortionsResizeStep); } //// Сохранение служебной информации о новом блоке. mPortions.resize(mPortions.size() + 1); mPortions.last().position = mFile.pos(); mPortions.last().size = length; mPortions.last().time = time; mPortions.last().offsetUTC = offsetUTC; //// Запись порции. if (mFile.write(data, length) != length) { return false; } //// Запись служебной информации. int64_t tmp = mPortions.count(); if (mFile.write(reinterpret_cast<const char *>(mPortions.begin()), tmp * sizeof(PortionInfo)) != tmp * static_cast<int>(sizeof(PortionInfo))) { return false; } if (mFile.write(reinterpret_cast<const char *>(&tmp), sizeof(tmp)) != sizeof(tmp)) { return false; } //// mBytesCount += length + sizeof(PortionInfo); return true; } /*! * \brief Конструктор. */ Replay::PlayContext::PlayContext() { } /*! * \brief Начинает воспроизведение. * \param fileName Имя файла. * \param signature Сигнатура. В случае ошибки сигнатуры в signature помещается прочитанная сигнатура. * \param version Версия. В случае ошибки версии в version помещается прочитанная версия. * \return Признак успешного открытия файла. */ bool Replay::PlayContext::open(const QString &fileName, QString &signature, int &version) { try { Replay::Header header; mFile.setFileName(fileName); if (!mFile.open(QIODevice::ReadOnly)) { throw 0; } //// Проверка заголовка файла. if (mFile.read(reinterpret_cast<char *>(&header), sizeof(header)) != sizeof(header)) { throw 1; } if (memcmp(header.signature, signature.toUtf8().data(), signature.toUtf8().size()) != 0) { signature = header.signature; throw 2; } if (version != header.version) { version = header.version; throw 3; } //// Чтение информации о расположении порций в файле. int64_t portionCount = 0; if (!mFile.seek(mFile.size() - sizeof(portionCount))) { throw 4; } if (mFile.read(reinterpret_cast<char *>(&portionCount), sizeof(portionCount)) != sizeof(portionCount)) { throw 5; } QVector<PortionInfo> tmp(portionCount); if (!mFile.seek(mFile.size() - sizeof(portionCount) - portionCount * sizeof(PortionInfo))) { throw 6; } if (mFile.read(reinterpret_cast<char *>(tmp.data()), portionCount * sizeof(PortionInfo)) != portionCount * static_cast<int>(sizeof(PortionInfo))) { throw 7; } mPortions = tmp; } catch (...) { mFile.close(); mFile.setFileName(QString()); mPortions.clear(); return false; } //// return true; } /*! * \brief Завершает воспроизведение. */ void Replay::PlayContext::close() { mCursor = 0; mFile.close(); } /*! * \brief Возвращает признак активности воспроизведения. * \return Признак активности воспроизведения. */ bool Replay::PlayContext::isOpen() { return mFile.isOpen(); } /*! * \brief Возвращает имя файла для воспроизведения. * \return Имя файла для воспроизведения. */ QString Replay::PlayContext::fileName() { return mFile.fileName(); } /*! * \brief Возвращает количество порций информации. * \return Количество порций информации. */ int Replay::PlayContext::portionCount() { return mPortions.size(); } /*! * \brief Возвращает индекс порции информации для воспроизведения. * \return Индекс порции информации для воспроизведения. */ int Replay::PlayContext::cursor() { return mCursor; } /*! * \brief Устанавливает индекс порции информации для воспроизведения. * \param value Индекс порции информации для воспроизведения. */ void Replay::PlayContext::setCursor(int value) { mCursor = value; } /*! * \brief Возвращает текущую порцию информации для воспроизведения. * \return Текущая порция информации для воспроизведения. */ const Replay::PortionInfo &Replay::PlayContext::currentPortion() { return mPortions[mCursor]; } /*! * \brief Возвращает предыдущую порцию информации для воспроизведения. * \return Предыдущая порция информации для воспроизведения. */ const Replay::PortionInfo &Replay::PlayContext::previousPortion() { return mPortions[mCursor - 1]; } /*! * \brief Воспроизводит порцию информации. * \param data Указатель на массив прочитанной информации. * \param length Длина прочитанной порции. */ bool Replay::PlayContext::playPortion(char *data, int64_t &length) { if (!mFile.seek(mPortions[mCursor].position)) { return false; } //// Чтение порции. length = mFile.read(data, mPortions[mCursor].size); if (length != mPortions[mCursor].size) { return false; } //// mCursor ++; return true; }