gough_dfa->length = gough_size;
/* copy in blocks */
- memcpy((u8 *)gough_dfa.get() + edge_prog_offset, &edge_blocks[0],
- byte_length(edge_blocks));
+ copy_bytes((u8 *)gough_dfa.get() + edge_prog_offset, edge_blocks);
if (top_prog_offset) {
- memcpy((u8 *)gough_dfa.get() + top_prog_offset, &top_blocks[0],
- byte_length(top_blocks));
- }
- if (!temp_blocks.empty()) {
- memcpy((u8 *)gough_dfa.get() + prog_base_offset, &temp_blocks[0],
- byte_length(temp_blocks));
+ copy_bytes((u8 *)gough_dfa.get() + top_prog_offset, top_blocks);
}
+ copy_bytes((u8 *)gough_dfa.get() + prog_base_offset, temp_blocks);
return gough_dfa;
}
repeat->horizon = rsi.horizon;
repeat->packedCtrlSize = rsi.packedCtrlSize;
repeat->stateSize = rsi.stateSize;
- memcpy(repeat->packedFieldSizes, rsi.packedFieldSizes.data(),
- byte_length(rsi.packedFieldSizes));
+ copy_bytes(repeat->packedFieldSizes, rsi.packedFieldSizes);
repeat->patchCount = rsi.patchCount;
repeat->patchSize = rsi.patchSize;
repeat->encodingSize = rsi.encodingSize;
// Copy in the sparse lookup table.
if (br.type == REPEAT_SPARSE_OPTIMAL_P) {
assert(!rsi.table.empty());
- memcpy(info_ptr + tableOffset, rsi.table.data(),
- byte_length(rsi.table));
+ copy_bytes(info_ptr + tableOffset, rsi.table);
}
// Fill the tug mask.
for (u32 i = 0; i < num_repeats; i++) {
repeatOffsets[i] = offset;
+ assert(repeats[i].first);
memcpy((char *)limex + offset, repeats[i].first.get(),
repeats[i].second);
offset += repeats[i].second;
// Write repeat offset lookup table.
assert(ISALIGNED_N((char *)limex + repeatOffsetsOffset, alignof(u32)));
- memcpy((char *)limex + repeatOffsetsOffset, repeatOffsets.data(),
- byte_length(repeatOffsets));
+ copy_bytes((char *)limex + repeatOffsetsOffset, repeatOffsets);
limex->repeatOffset = repeatOffsetsOffset;
limex->repeatCount = num_repeats;
limex->exReportOffset = exceptionReportsOffset;
assert(ISALIGNED_N((char *)limex + exceptionReportsOffset,
alignof(ReportID)));
- memcpy((char *)limex + exceptionReportsOffset, reports.data(),
- byte_length(reports));
+ copy_bytes((char *)limex + exceptionReportsOffset, reports);
}
static
info->packedCtrlSize = rsi.packedCtrlSize;
info->horizon = rsi.horizon;
info->minPeriod = minPeriod;
- memcpy(&info->packedFieldSizes, rsi.packedFieldSizes.data(),
- byte_length(rsi.packedFieldSizes));
+ copy_bytes(&info->packedFieldSizes, rsi.packedFieldSizes);
info->patchCount = rsi.patchCount;
info->patchSize = rsi.patchSize;
info->encodingSize = rsi.encodingSize;
nfa->length = verify_u32(len);
info->length = verify_u32(sizeof(RepeatInfo)
+ sizeof(u64a) * (rsi.patchSize + 1));
- memcpy(table, rsi.table.data(), byte_length(rsi.table));
+ copy_bytes(table, rsi.table);
}
}
sizeof(internal_report));
}
-static
-void populateInvDkeyTable(char *ptr, const ReportManager &rm) {
- vector<ReportID> table = rm.getDkeyToReportTable();
- memcpy(ptr, table.data(), byte_length(table));
-}
-
static
bool hasSimpleReports(const vector<Report> &reports) {
auto it = find_if(reports.begin(), reports.end(), isComplexReport);
engine->ekeyCount = rm.numEkeys();
engine->dkeyCount = rm.numDkeys();
engine->invDkeyOffset = dkeyOffset;
- populateInvDkeyTable(ptr + dkeyOffset, rm);
+ copy_bytes(ptr + dkeyOffset, rm.getDkeyToReportTable());
engine->somHorizon = ssm.somPrecision();
engine->somLocationCount = ssm.numSomSlots();
buildLitBenefits(*this, engine.get(), base_lits_benefits_offset);
// Copy in other tables
- memcpy(ptr + bc.engine_blob_base, bc.engine_blob.data(),
- byte_length(bc.engine_blob));
-
- memcpy(ptr + engine->literalOffset, literalTable.data(),
- byte_length(literalTable));
- memcpy(ptr + engine->roleOffset, bc.roleTable.data(),
- byte_length(bc.roleTable));
- copy(leftInfoTable.begin(), leftInfoTable.end(),
- (LeftNfaInfo *)(ptr + engine->leftOffset));
+ copy_bytes(ptr + bc.engine_blob_base, bc.engine_blob);
+ copy_bytes(ptr + engine->literalOffset, literalTable);
+ copy_bytes(ptr + engine->roleOffset, bc.roleTable);
+ copy_bytes(ptr + engine->leftOffset, leftInfoTable);
fillLookaroundTables(ptr + lookaroundTableOffset,
ptr + lookaroundReachOffset, bc.lookaround);
fillInSomRevNfas(engine.get(), ssm, rev_nfa_table_offset, rev_nfa_offsets);
- memcpy(ptr + engine->predOffset, predTable.data(), byte_length(predTable));
- memcpy(ptr + engine->rootRoleOffset, rootRoleTable.data(),
- byte_length(rootRoleTable));
- memcpy(ptr + engine->anchoredReportMapOffset, art.data(), byte_length(art));
- memcpy(ptr + engine->anchoredReportInverseMapOffset, arit.data(),
- byte_length(arit));
- memcpy(ptr + engine->multidirectOffset, mdr_reports.data(),
- byte_length(mdr_reports));
-
- copy(activeLeftIter.begin(), activeLeftIter.end(),
- (mmbit_sparse_iter *)(ptr + engine->activeLeftIterOffset));
-
- memcpy(ptr + engine->sideOffset, sideTable.data(), byte_length(sideTable));
+ copy_bytes(ptr + engine->predOffset, predTable);
+ copy_bytes(ptr + engine->rootRoleOffset, rootRoleTable);
+ copy_bytes(ptr + engine->anchoredReportMapOffset, art);
+ copy_bytes(ptr + engine->anchoredReportInverseMapOffset, arit);
+ copy_bytes(ptr + engine->multidirectOffset, mdr_reports);
+ copy_bytes(ptr + engine->activeLeftIterOffset, activeLeftIter);
+ copy_bytes(ptr + engine->sideOffset, sideTable);
DEBUG_PRINTF("rose done %p\n", engine.get());
return engine;
#ifndef UTIL_CONTAINER_H
#define UTIL_CONTAINER_H
+#include "ue2common.h"
+
#include <algorithm>
+#include <cassert>
+#include <cstring>
#include <set>
+#include <type_traits>
#include <utility>
namespace ue2 {
return keys;
}
+/**
+ * \brief Return the length in bytes of the given vector of (POD) objects.
+ */
template<typename T>
typename std::vector<T>::size_type byte_length(const std::vector<T> &vec) {
+ static_assert(std::is_pod<T>::value, "should be pod");
return vec.size() * sizeof(T);
}
+/**
+ * \brief Copy the given vector of POD objects to the given location in memory.
+ * It is safe to give this function an empty vector.
+ */
+template<typename T>
+void *copy_bytes(void *dest, const std::vector<T> &vec) {
+ static_assert(std::is_pod<T>::value, "should be pod");
+ assert(dest);
+
+ // Since we're generally using this function to write into the bytecode,
+ // dest should be appropriately aligned for T.
+ assert(ISALIGNED_N(dest, alignof(T)));
+
+ if (vec.empty()) {
+ return dest; // Protect memcpy against null pointers.
+ }
+ assert(vec.data() != nullptr);
+ return std::memcpy(dest, vec.data(), byte_length(vec));
+}
+
template<typename OrderedContainer1, typename OrderedContainer2>
bool is_subset_of(const OrderedContainer1 &small, const OrderedContainer2 &big) {
static_assert(std::is_same<typename OrderedContainer1::value_type,