diff --git a/QtPMbrowser/pmbrowserwindow.cpp b/QtPMbrowser/pmbrowserwindow.cpp index f11697a..06875ae 100644 --- a/QtPMbrowser/pmbrowserwindow.cpp +++ b/QtPMbrowser/pmbrowserwindow.cpp @@ -604,28 +604,28 @@ void PMbrowserWindow::formatStimMetadataAsTableExport(std::ostream& os, int max_ const auto tli = ui->treePulse->topLevelItem(i); if (tli->isHidden()) continue; const auto& grp = *(tli->data(0, Qt::UserRole).value()); - auto gpr_count = grp.extractValue(GrGroupCount); + auto gpr_count = grp.extractValue(GrGroupCount); std::string grp_entry = formatParamListExportTable(grp, parametersGroup); int Nse = tli->childCount(); for (int j = 0; j < Nse; ++j) { // level: series const auto se_item = tli->child(j); if (se_item->isHidden()) continue; const auto& series = *(se_item->data(0, Qt::UserRole).value()); - auto se_count = series.extractValue(SeSeriesCount); + auto se_count = series.extractValue(SeSeriesCount); std::string se_entry = formatParamListExportTable(series, parametersSeries); int M = se_item->childCount(); for (int k = 0; k < M; ++k) { // level: sweep const auto sw_item = se_item->child(k); if (sw_item->isHidden()) continue; const auto& sweep = *(sw_item->data(0, Qt::UserRole).value()); - auto sw_count = sweep.extractValue(SwSweepCount); + auto sw_count = sweep.extractValue(SwSweepCount); std::string sw_entry = formatParamListExportTable(sweep, parametersSweep); int Nsw = sw_item->childCount(); for (int l = 0; l < Nsw; ++l) { // level: trace const auto tr_item = sw_item->child(l); if (tr_item->isHidden()) continue; const auto& trace = *(tr_item->data(0, Qt::UserRole).value()); - auto tr_count = trace.extractValue(TrTraceCount); + auto tr_count = trace.extractValue(TrTraceCount); std::string tr_entry = formatParamListExportTable(trace, parametersTrace); os << gpr_count << '\t' << se_count << '\t' << sw_count << '\t' << tr_count << @@ -1051,29 +1051,22 @@ void PMbrowserWindow::printAmplifierState(const hkTreeNode* series) { assert(series->getLevel() == hkTreeNode::LevelSeries); hkTreeNode amprecord; - amprecord.len = AmplifierStateSize; - //auto buffer = std::make_unique(amprecord.len); - //amprecord.Data = buffer.get(); amprecord.isSwapped = series->getIsSwapped(); auto ampstateflag = series->extractInt32(SeAmplStateFlag), ampstateref = series->extractInt32(SeAmplStateRef); if (ampstateflag > 0 || ampstateref == 0) { // use local amp state record - amprecord.Data = series->Data + SeOldAmpState; - //std::memcpy(buffer.get(), series->Data + SeOldAmpState, amprecord.len); + amprecord.Data = series->Data.subspan(SeOldAmpState, AmplifierStateSize); std::string s; formatParamList(amprecord, parametersAmpplifierState, s); ui->textEdit->append(QString("Amplifier State:\n%1\n").arg(QString(s.c_str()))); } else { - // auto secount = series->extractInt32(SeSeriesCount); const auto& amproot = datfile->GetAmpTree().GetRootNode(); - const auto& ampse = amproot.Children.at(size_t(ampstateref) - 1); // Is this correct? Or seCount? + const auto& ampse = amproot.Children.at(static_cast(ampstateref) - 1); // Is this correct? Or seCount? for(const auto& ampre : ampse.Children) { // there might be multiple amplifiers auto ampstatecount = ampre.extractInt32(AmStateCount); - amprecord.Data = series->Data + SeOldAmpState; - //std::memcpy(buffer.get(), ampre.Data + AmAmplifierState, amprecord.len); - //amprecord.Data = ampre.Data.get() + AmAmplifierState; + amprecord.Data = ampre.Data.subspan(AmAmplifierState, AmplifierStateSize); std::string s; formatParamList(amprecord, parametersAmpplifierState, s); ui->textEdit->append(QString("Amplifier State (Amp #%1):\n%2\n").arg(ampstatecount).arg(QString(s.c_str()))); diff --git a/hekatoolslib/DatFile.cpp b/hekatoolslib/DatFile.cpp index 838db06..f888105 100644 --- a/hekatoolslib/DatFile.cpp +++ b/hekatoolslib/DatFile.cpp @@ -126,16 +126,16 @@ void DatFile::formatStimMetadataAsTableExport(std::ostream& os, int max_level) auto& rootnode = GetPulTree().GetRootNode(); metadataCreateTableHeader(os); for (const auto& grp : rootnode.Children) { - auto gpr_count = grp.extractValue(GrGroupCount); + auto gpr_count = grp.extractValue(GrGroupCount); std::string grp_entry = formatParamListExportTable(grp, parametersGroup); for (const auto& series : grp.Children) { - auto se_count = series.extractValue(SeSeriesCount); + auto se_count = series.extractValue(SeSeriesCount); std::string se_entry = formatParamListExportTable(series, parametersSeries); for (const auto& sweep : series.Children) { - auto sw_count = sweep.extractValue(SwSweepCount); + auto sw_count = sweep.extractValue(SwSweepCount); std::string sw_entry = formatParamListExportTable(sweep, parametersSweep); for (const auto& trace : sweep.Children) { - auto tr_count = trace.extractValue(TrTraceCount); + auto tr_count = trace.extractValue(TrTraceCount); std::string tr_entry = formatParamListExportTable(trace, parametersTrace); os << gpr_count << '\t' << se_count << '\t' << sw_count << '\t' << tr_count << @@ -162,10 +162,10 @@ double DatFile::getTraceHolding(const hkTreeNode& trace, std::string& unit) } if (std::isnan(holding)) { // we can also try to get this info from the stim tree (usuful for old files): - auto linkedDAchannel = trace.extractValue(TrLinkDAChannel) - 1; + auto linkedDAchannel = trace.extractValue(TrLinkDAChannel) - 1; assert(linkedDAchannel >= 0); const auto& sweep_record = *trace.getParent(); - int stim_index = sweep_record.extractValue(SwStimCount) - 1; + int stim_index = sweep_record.extractValue(SwStimCount) - 1; const auto& stim_node = GetPgfTree().GetRootNode().Children.at(stim_index); const auto& channel0_record = stim_node.Children.at(linkedDAchannel); int linked_channel = channel0_record.extractInt32(chLinkedChannel) - 1; diff --git a/hekatoolslib/hkTree.cpp b/hekatoolslib/hkTree.cpp index 64c335a..6cfea87 100644 --- a/hekatoolslib/hkTree.cpp +++ b/hekatoolslib/hkTree.cpp @@ -70,12 +70,12 @@ namespace hkLib { void hkTree::LoadToNode(hkTreeNode* parent, hkTreeNode& node, char** pdata, int level) { node.tree = this; - auto size = static_cast(LevelSizes.at(level)); + auto size = static_cast(LevelSizes.at(level)); node.level = level; - node.len = size; + //node.len = size; node.isSwapped = isSwapped; node.Parent = parent; - node.Data = *pdata; + node.Data = std::span( *pdata, size ); *pdata += size; uint32_t nchildren; std::memcpy(&nchildren, *pdata, sizeof(uint32_t)); @@ -129,7 +129,7 @@ namespace hkLib { char hkTreeNode::getChar(std::size_t offset) const { - if (len < offset + sizeof(char)) { + if (Data.size() < offset + sizeof(char)) { throw std::out_of_range("offset too large while accessing tree node"); } return Data[offset]; @@ -137,7 +137,7 @@ namespace hkLib { const std::optional hkTreeNode::getUserParamDescr(std::size_t offset) const { - if (len < offset + UserParamDescr::Size) { + if (Data.size() < offset + UserParamDescr::Size) { //throw std::out_of_range("offset too large while accessing tree node"); return std::nullopt; } @@ -151,10 +151,10 @@ namespace hkLib { const std::string_view hkTreeNode::getString(std::size_t offset) const { - if (len <= offset) { + if (Data.size() <= offset) { throw std::out_of_range("offset too large while accessing tree node"); } - return std::string_view(Data + offset); + return std::string_view(Data.data() + offset); } std::ostream& operator<<(std::ostream& os, const UserParamDescr& p) diff --git a/hekatoolslib/hkTree.h b/hekatoolslib/hkTree.h index 1aad7ed..4625668 100644 --- a/hekatoolslib/hkTree.h +++ b/hekatoolslib/hkTree.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace hkLib { @@ -206,7 +207,7 @@ namespace hkLib { { static_assert(std::is_arithmetic_v, "must be arithmetic type"); T t{}; - auto src = Data + offset; + auto src = Data.data() + offset; if (!isSwapped) { std::copy(src, src + sizeof t, reinterpret_cast(&t)); } @@ -215,8 +216,12 @@ namespace hkLib { } return t; } + template bool checkOffset(std::size_t offset) const noexcept + { + return (Data.size() >= offset + sizeof(T)); + } public: - hkTreeNode() : Parent{ nullptr }, Data{ nullptr }, len{ 0 }, Children{}, level{ -1 }, isSwapped{ false } {}; + hkTreeNode() : Parent{ nullptr }, Data{ }, Children{}, level{ -1 }, isSwapped{ false } {}; hkTreeNode(hkTreeNode&&) = default; hkTreeNode(const hkTreeNode&) = delete; hkTreeNode& operator=(const hkTreeNode&) = delete; @@ -231,7 +236,7 @@ namespace hkLib { /// extracted value template T extractValue(std::size_t offset) const { - if (len < offset + sizeof(T)) { + if (!checkOffset(offset)) { throw std::out_of_range("offset too large while accessing tree node"); } return extractValueNoCheck(offset); @@ -244,7 +249,7 @@ namespace hkLib { /// std::optional containing value if offset is valid template std::optional extractValueOpt(std::size_t offset) const { - if (len < offset + sizeof(T)) { + if (!checkOffset(offset)) { return std::nullopt; } else { @@ -262,7 +267,7 @@ namespace hkLib { /// extracted value or default value template T extractValue(std::size_t offset, T defaultValue) const noexcept { - if (len < offset + sizeof(T)) { + if (!checkOffset(offset)) { return defaultValue; } return extractValueNoCheck(offset); @@ -274,8 +279,8 @@ namespace hkLib { LevelSweep = 3, LevelTrace = 4 }; - int32_t extractInt32(std::size_t offset) const { return extractValue(offset); }; - uint16_t extractUInt16(std::size_t offset) const { return extractValue(offset); }; + int32_t extractInt32(std::size_t offset) const { return extractValue(offset); }; + uint16_t extractUInt16(std::size_t offset) const { return extractValue(offset); }; double extractLongReal(std::size_t offset) const { return extractValue(offset); }; double extractLongRealNoThrow(std::size_t offset) const noexcept //! instead of throwing an exception, returns NaN if out of range { @@ -286,14 +291,14 @@ namespace hkLib { const std::optional getUserParamDescr(std::size_t offset) const; template const std::string_view getString(std::size_t offset) const { - if (len < offset + N) { + if (!checkOffset(offset)) { return "n/a"; } - const auto* p = Data + offset; + const auto* p = Data.data() + offset; if (p[N - 1]) { // in theory, string is not zero terminated // unfortunately, some PM version mess this up - // by not prperly zero-initializing the cahr array + // by not prperly zero-initializing the char array return std::string_view(p, std::min(std::strlen(p), N)); } else { @@ -315,9 +320,7 @@ namespace hkLib { public: hkTreeNode* Parent; - //std::unique_ptr Data; - const char* Data; - std::size_t len; //!< Length (in bytes) of data + std::span Data; std::vector Children; int level; bool isSwapped;