LINUX.ORG.RU

с++, хранилище для raw-данных.

 , ,


0

1

Мне нужно хранить записи вида int tag; float vec[n] причём n может быть любым, но константным для всего хранилища.

Соответственно, есть функции для чтения и записи сигнатурой: read/write(int index, int n, int& tag, float*vec): index — номер элемента, n — размер хранимых векторов. Хранилище может быть настроено или в row-major или в column-major order, т.е. данные хранятся или как «tag1, vec1[..n], tag2, vec2[..n], ..., tagN, vecN[..n]» или как «tag1, tag2, .., tagN, vec1[..n], vec2[..n], ..., vecN[..n]»

Т.е. при наивной имплементации, я бы вроде как мог хранить всё это в std::byte*, вызывать reinterpret_cast и высчитывать нужные смещения через sizeof элементов, но что-то мне подсказывает что тут можно легко нарушить strict aliasing rule и получить UB. Как такие вещи полагается делать кошерно и переносимо?

★★★★★

Последнее исправление: thunar (всего исправлений: 4)

Вы собираетесь изобрести велосипед. То, что вы хотите, называется базой данных ключ-значение. Искать те, к которым можно обращаться из C++, в google по словам

key value store c++

Сразу находятся варианты in-memory (хранение в памяти), persistent (с сохранением на диске). Ещё есть варианты для больших данных и временнЫх рядов. Находите подходящие и смотрите отзывы.

Partisan ★★★★★
()

float *a = (float*)mmap(NULL, sizeof(float) * n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);

realbarmaley ★★
()
Ответ на: комментарий от thunar

Вот что я хотел:

struct pool_t {

private:
	std::byte   *data;
	size_t       tk, v0, vk, vj; 

public:
	enum ord {row, col};

	//------------------------------------------------------------------//
	pool_t (std::byte* p, int nk, int nj, ord arg) : data(p) {
		switch (arg) {
			case ord::row:
			tk = sizeof(int) + sizeof(float)*nj;
			v0 = sizeof(int);
			vk = sizeof(int) + sizeof(float)*nj;
			vj = sizeof(float);
			return;
			case ord::col:
			tk = sizeof(int);
			v0 = sizeof(int)*nk;
			vk = sizeof(float);
			vj = sizeof(float)*nk;
			return;
		}
	}

	//------------------------------------------------------------------//
	void readpt
	(const int& k, const int& n, int& tag, float vec[]) {
		std::byte *ptag{data + tk*k}, *pvec{data + v0 + vk*k};
		
		tag = *reinterpret_cast<int*>(ptag);
		for (int j=0; j<n; ++j) {
			vec[j] = *reinterpret_cast<float*>(pvec + vj*j);
		}
	}

	//------------------------------------------------------------------//
	void writept
	(const int& k, const int& n, const int& tag, const float vec[]) {
		std::byte *ptag{data + tk*k}, *pvec{data + v0 + vk*k};
		
		*reinterpret_cast<int*>(ptag) = tag;
		for (int j=0; j<n; ++j) {
			*reinterpret_cast<float*>(pvec + vj*j) = vec[j];
		}
	}
};

thunar ★★★★★
() автор топика
Последнее исправление: thunar (всего исправлений: 2)

n элементов одинакового типа - это массив.

или std::vector

вообще вопрос не в хранении, а в использовании. в зависимости от преимущественных сценариев использования, метод хранения может быть разным - оптимальным для вашего варианта использования.

например если требуется частая вставка/удаление из произвольного места, то лучше std::list, если элементы только накапливаются в хвост и не удаляются и количество записей неограничено - то std::vector. если число элементов известно заранее std::array.

alysnix ★★★
()
Ответ на: комментарий от Partisan

То, что вы хотите, называется базой данных ключ-значение.

А как называется желание всобачить БД туда, где хватило бы текстового файла?

nightmarez
()

Т.е. при наивной имплементации, я бы вроде как мог хранить всё это в std::byte*, вызывать reinterpret_cast и высчитывать нужные смещения через sizeof элементов

Нельзя это сериализовать в строку?

nightmarez
()

Ну так, а в чем трабла? Пишешь первым делом число, потом просто флоты друг за другом.

zerhud
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.