2
* Copyright 2009 CrossWire Bible Society (http://www.crosswire.org)
3
* CrossWire Bible Society
7
* This program is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU General Public License as published by the
9
* Free Software Foundation version 2.
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* General Public License for more details.
18
#include <entriesblk.h>
24
const int EntriesBlock::METAHEADERSIZE = 4;
26
const int EntriesBlock::METAENTRYSIZE = 8;
27
// offset(4); size(4);
29
EntriesBlock::EntriesBlock(const char *iBlock, unsigned long size) {
31
block = (char *)calloc(1, size);
32
memcpy(block, iBlock, size);
35
block = (char *)calloc(1, sizeof(__u32));
40
EntriesBlock::EntriesBlock() {
41
block = (char *)calloc(1, sizeof(__u32));
45
EntriesBlock::~EntriesBlock() {
50
void EntriesBlock::setCount(int count) {
51
__u32 rawCount = archtosword32(count);
52
memcpy(block, &rawCount, sizeof(__u32));
56
int EntriesBlock::getCount() {
58
memcpy(&count, block, sizeof(__u32));
59
count = swordtoarch32(count);
64
void EntriesBlock::getMetaEntry(int index, unsigned long *offset, unsigned long *size) {
69
if (index >= getCount()) // assert index < count
72
// first 4 bytes is count, each 6 bytes after is each meta entry
73
memcpy(&rawOffset, block + METAHEADERSIZE + (index * METAENTRYSIZE), sizeof(rawOffset));
74
memcpy(&rawSize, block + METAHEADERSIZE + (index * METAENTRYSIZE) + sizeof(rawOffset), sizeof(rawSize));
76
*offset = (unsigned long)swordtoarch32(rawOffset);
77
*size = (unsigned long)swordtoarch32(rawSize);
81
void EntriesBlock::setMetaEntry(int index, unsigned long offset, unsigned long size) {
82
__u32 rawOffset = archtosword32(offset);
83
__u32 rawSize = archtosword32(size);
85
if (index >= getCount()) // assert index < count
88
// first 4 bytes is count, each 6 bytes after is each meta entry
89
memcpy(block + METAHEADERSIZE + (index * METAENTRYSIZE), &rawOffset, sizeof(rawOffset));
90
memcpy(block + METAHEADERSIZE + (index * METAENTRYSIZE) + sizeof(rawOffset), &rawSize, sizeof(rawSize));
94
const char *EntriesBlock::getRawData(unsigned long *retSize) {
95
unsigned long max = 4;
99
for (loop = 0; loop < getCount(); loop++) {
100
getMetaEntry(loop, &offset, &size);
101
max = ((offset + size) > max) ? (offset + size) : max;
108
int EntriesBlock::addEntry(const char *entry) {
109
unsigned long dataSize;
110
getRawData(&dataSize);
111
unsigned long len = strlen(entry);
112
unsigned long offset;
114
int count = getCount();
115
unsigned long dataStart = METAHEADERSIZE + (count * METAENTRYSIZE);
116
// new meta entry + new data size + 1 because null
117
block = (char *)realloc(block, dataSize + METAENTRYSIZE + len + 1);
118
// shift right to make room for new meta entry
119
memmove(block + dataStart + METAENTRYSIZE, block + dataStart, dataSize - dataStart);
121
for (int loop = 0; loop < count; loop++) {
122
getMetaEntry(loop, &offset, &size);
123
if (offset) { // if not a deleted entry
124
offset += METAENTRYSIZE;
125
setMetaEntry(loop, offset, size);
129
offset = dataSize; // original dataSize before realloc
131
// add our text to the end
132
memcpy(block + offset + METAENTRYSIZE, entry, size);
135
// add our meta entry
136
setMetaEntry(count, offset + METAENTRYSIZE, size);
137
// return index of our new entry
142
const char *EntriesBlock::getEntry(int entryIndex) {
143
unsigned long offset;
145
static const char *empty = "";
147
getMetaEntry(entryIndex, &offset, &size);
148
return (offset) ? block+offset : empty;
152
unsigned long EntriesBlock::getEntrySize(int entryIndex) {
153
unsigned long offset;
156
getMetaEntry(entryIndex, &offset, &size);
157
return (offset) ? size : 0;
161
void EntriesBlock::removeEntry(int entryIndex) {
162
unsigned long offset;
163
unsigned long size, size2;
164
unsigned long dataSize;
165
getRawData(&dataSize);
166
getMetaEntry(entryIndex, &offset, &size);
167
int count = getCount();
169
if (!offset) // already deleted
172
// shift left to retrieve space used for old entry
173
memmove(block + offset, block + offset + size, dataSize - (offset + size));
175
// fix offset for all entries after our entry that were shifted left
176
for (int loop = entryIndex + 1; loop < count; loop++) {
177
getMetaEntry(loop, &offset, &size2);
178
if (offset) { // if not a deleted entry
180
setMetaEntry(loop, offset, size2);
184
// zero out our meta entry
185
setMetaEntry(entryIndex, 0L, 0);