Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Класс редактирования данных. Нужны советы по реализации


Автор: formut 15.9.2014, 21:41
Есть задача: написать класс, позволяющий редактировать данные в памяти. Указатель на данные и их начальный размер передаются в конструктор. Редактирование, на первый взгляд, тривиальное и реализуется тремя методами класса:
Код
void Change(unsigned long StartByte, const void *NewData, unsigned long DataSize);
void Delete(unsigned long StartByte, unsigned long Size);
void Insert(unsigned long StartByte, const void *Data, unsigned long DataSize);
Казалось бы, все просто: выделяй память, заменяй, удаляй, добавляй... Однако в процессе редактирования данных промежуточные итоги мне не нужны - требуется только конечный результат. Поэтому возникла мысль не изменять данные при каждом вызове методов, а только лишь сохранять информацию об изменениях. А когда будет запрошен результат, тогда уж и формировать его.

Представим, есть объект класса с переданным ему для редактирования блоком данных. Допустим, у нас произошел последовательный вызов таких методов:
Код
Insert(5, MyData, 10); // Вставляем между 4-ым и 5-ым байтами 10 байтов MyData.
Delete(7, 2);          // Удаляем 7-ой и 8-ой байты.
Delete(4, 10);         // Удаляем с 4-го по 13-ый байты.
На деле, такая запись аналогична записи:
Код
Delete(4, 2);
Поэтому реальное изменение данных "на лету" не оптимально, если учесть, что промежуточный результат (как я уже писал) мне не интересен. "Компоновкой" получившегося должен заниматься отдельный метод, возвращающий результат всей работы объекта:
Код
unsigned long GetData(void *Buffer, unsigned long BufferSize);
Осталось только придумать, как хранить и обрабатывать информацию о поступивших изменениях. Вот с этим-то у меня и затык. Ничего, что очевидно выигрывает у memcpy() и memmove() по скорости и ресурсам, в голову не приходит. Поделитесь своими мыслями.

Ах, да! Чуть не забыл главное условие: никаких стандартных и, уж тем более, сторонних библиотек. Только "чистый" C++ и WinAPI.

Автор: sQu1rr 15.9.2014, 21:50
что подрузамевает delete? удаление байт со смещением, и уменьшение размеров исходных данных? как vector.remove или как его там? или просто затирание 0ми?
Если второе, то изменение ланных на лету - оптимально

Это я к тому что если передается указатель на данные, то не вы же контролируете их размер

Правда как тогда будет insert работать - ума не приложу

Автор: math64 16.9.2014, 08:11
Чтобы много не выдумывать, Вам следует применить базу данных, умеющую работать в памяти, например sqlite. Перед началом измененией начинаете тразакцию transaction(), в конце делаете commit() или rollback() чтобы отказаться от изменений. Или реализуйте механизм транзакций самостоятельно.

Автор: xvr 16.9.2014, 11:42
Цитата(formut @  15.9.2014,  21:41 Найти цитируемый пост)
Поэтому реальное изменение данных "на лету" не оптимально, если учесть, что промежуточный результат (как я уже писал) мне не интересен. "Компоновкой" получившегося должен заниматься отдельный метод, возвращающий результат всей работы объекта:

Вычисление того, что в результате нужно будет сделать над исходными данными при применении к ним последовательности операций тоже требует времени и ресурсов, причем скорее всего больше, чем само копирование данных. Так что 'удалять промежуточные шаги' имеет смысл только в том случае, если у вас очень большие массивы данных либо вы планируете применять одни и те же модификации многократно.

Для этого можно покрыть ваш массив данных набором интервалов. Изначально есть 1 интервал, покрывающий весь массив и содержащий данные массива. Далее каждое действие выполняется над текущим набором интервалов, в результате получается новый набор. Ну и в конце по результирующему набору строится выходной массив.

Для вашего примера (положим начальный массив был 20 байтов):
Код

// Original interval: 0-19 @org
Insert(4, MyData, 10); // Вставляем между 4-ым и 5-ым байтами 10 байтов MyData.
// 0-3 @org, 4-13 @MyData, 14-28 @org+4
Delete(7, 2);          // Удаляем 7-ой и 8-ой байты.
// 0-3 @org, 4-6 @MyData, 7-11 @MyData+5, 12-26 @org+4
Delete(4, 10);         // Удаляем с 4-го по 13-ый байты.
// 0-3 @org, 4-18 @org+6


Автор: math64 17.9.2014, 08:57
Только учтите, если будете действовать как советует xvr, промежуточные данные (MyData) должны сохраняться до получения результата.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)