From: Soeren Apel Date: Sat, 18 Apr 2020 07:28:33 +0000 (+0200) Subject: Fix #811 by using a hashed annotation text backing storage X-Git-Url: https://sigrok.org/gitweb/?a=commitdiff_plain;ds=sidebyside;h=1dcd9b18186741d3ce3164f7e8d6cb13abb578d3;p=pulseview.git Fix #811 by using a hashed annotation text backing storage --- diff --git a/pv/data/decode/annotation.cpp b/pv/data/decode/annotation.cpp index 689c08de..9f86b2ba 100644 --- a/pv/data/decode/annotation.cpp +++ b/pv/data/decode/annotation.cpp @@ -26,6 +26,7 @@ extern "C" { #include #include +#include "pv/data/decode/rowdata.hpp" using std::vector; @@ -33,52 +34,33 @@ namespace pv { namespace data { namespace decode { -Annotation::Annotation(const srd_proto_data *const pdata, const Row *row) : - start_sample_(pdata->start_sample), - end_sample_(pdata->end_sample), - row_(row) +Annotation::Annotation(uint64_t start_sample, uint64_t end_sample, + const vector* texts, Class ann_class_id, const RowData *data) : + start_sample_(start_sample), + end_sample_(end_sample), + texts_(texts), + ann_class_id_(ann_class_id), + data_(data) { - assert(pdata); - const srd_proto_data_annotation *const pda = - (const srd_proto_data_annotation*)pdata->data; - assert(pda); - - ann_class_id_ = (Class)(pda->ann_class); - - annotations_ = new vector(); - - const char *const *annotations = (char**)pda->ann_text; - while (*annotations) { - annotations_->push_back(QString::fromUtf8(*annotations)); - annotations++; - } - - annotations_->shrink_to_fit(); } Annotation::Annotation(Annotation&& a) : start_sample_(a.start_sample_), end_sample_(a.end_sample_), - annotations_(a.annotations_), - row_(a.row_), - ann_class_id_(a.ann_class_id_) + texts_(a.texts_), + ann_class_id_(a.ann_class_id_), + data_(a.data_) { - a.annotations_ = nullptr; } Annotation& Annotation::operator=(Annotation&& a) { if (&a != this) { - if (annotations_) - delete annotations_; - start_sample_ = a.start_sample_; end_sample_ = a.end_sample_; - annotations_ = a.annotations_; - row_ = a.row_; + texts_ = a.texts_; ann_class_id_ = a.ann_class_id_; - - a.annotations_ = nullptr; + data_ = a.data_; } return *this; @@ -86,7 +68,6 @@ Annotation& Annotation::operator=(Annotation&& a) Annotation::~Annotation() { - delete annotations_; } uint64_t Annotation::start_sample() const @@ -107,24 +88,24 @@ Annotation::Class Annotation::ann_class_id() const const QString Annotation::ann_class_name() const { const AnnotationClass* ann_class = - row_->decoder()->get_ann_class_by_id(ann_class_id_); + data_->row()->decoder()->get_ann_class_by_id(ann_class_id_); return QString(ann_class->name); } const vector* Annotation::annotations() const { - return annotations_; + return texts_; } const QString Annotation::longest_annotation() const { - return annotations_->front(); + return texts_->front(); } const Row* Annotation::row() const { - return row_; + return data_->row(); } bool Annotation::operator<(const Annotation &other) const diff --git a/pv/data/decode/annotation.hpp b/pv/data/decode/annotation.hpp index e599bdd4..df99ecb9 100644 --- a/pv/data/decode/annotation.hpp +++ b/pv/data/decode/annotation.hpp @@ -34,6 +34,7 @@ namespace data { namespace decode { class Row; +class RowData; class Annotation { @@ -41,7 +42,8 @@ public: typedef uint32_t Class; public: - Annotation(const srd_proto_data *const pdata, const Row *row); + Annotation(uint64_t start_sample, uint64_t end_sample, + const vector* texts, Class ann_class_id, const RowData *data); Annotation(Annotation&& a); Annotation& operator=(Annotation&& a); ~Annotation(); @@ -61,9 +63,9 @@ public: private: uint64_t start_sample_; uint64_t end_sample_; - vector* annotations_; - const Row *row_; + const vector* texts_; Class ann_class_id_; + const RowData* data_; }; } // namespace decode diff --git a/pv/data/decode/rowdata.cpp b/pv/data/decode/rowdata.cpp index fc1480a1..fc635b24 100644 --- a/pv/data/decode/rowdata.cpp +++ b/pv/data/decode/rowdata.cpp @@ -36,6 +36,11 @@ RowData::RowData(Row* row) : assert(row); } +const Row* RowData::row() const +{ + return row_; +} + uint64_t RowData::get_max_sample() const { if (annotations_.empty()) @@ -92,6 +97,24 @@ void RowData::get_annotation_subset( const Annotation* RowData::emplace_annotation(srd_proto_data *pdata) { + const srd_proto_data_annotation *const pda = (const srd_proto_data_annotation*)pdata->data; + + Annotation::Class ann_class_id = (Annotation::Class)(pda->ann_class); + + // Look up the longest annotation text to see if we have it in storage + const char* const* ann_texts = (char**)pda->ann_text; + const QString ann0 = QString::fromUtf8(ann_texts[0]); + vector* storage_entry = &(ann_texts_[ann0]); + + if (storage_entry->empty()) { + while (*ann_texts) { + storage_entry->emplace_back(QString::fromUtf8(*ann_texts)); + ann_texts++; + } + storage_entry->shrink_to_fit(); + } + + const Annotation* result = nullptr; // We insert the annotation in a way so that the annotation list @@ -110,10 +133,12 @@ const Annotation* RowData::emplace_annotation(srd_proto_data *pdata) if (it != annotations_.begin()) it++; - it = annotations_.emplace(it, pdata, row_); + it = annotations_.emplace(it, pdata->start_sample, pdata->end_sample, + storage_entry, ann_class_id, this); result = &(*it); } else { - annotations_.emplace_back(pdata, row_); + annotations_.emplace_back(pdata->start_sample, pdata->end_sample, + storage_entry, ann_class_id, this); result = &(annotations_.back()); prev_ann_start_sample_ = pdata->start_sample; } diff --git a/pv/data/decode/rowdata.hpp b/pv/data/decode/rowdata.hpp index 48b6a41a..f01aa3ca 100644 --- a/pv/data/decode/rowdata.hpp +++ b/pv/data/decode/rowdata.hpp @@ -20,14 +20,26 @@ #ifndef PULSEVIEW_PV_DATA_DECODE_ROWDATA_HPP #define PULSEVIEW_PV_DATA_DECODE_ROWDATA_HPP +#include #include +#include +#include + #include #include using std::deque; -using std::vector; +using std::unordered_map; + +namespace std { + template<> struct hash { + std::size_t operator()(const QString& s) const noexcept { + return (size_t) qHash(s); + } + }; +} namespace pv { namespace data { @@ -40,6 +52,8 @@ class RowData public: RowData(Row* row); + const Row* row() const; + uint64_t get_max_sample() const; uint64_t get_annotation_count() const; @@ -56,6 +70,7 @@ public: private: deque annotations_; + unordered_map > ann_texts_; // unordered_map since pointers must not change Row* row_; uint64_t prev_ann_start_sample_; }; diff --git a/pv/data/decodesignal.hpp b/pv/data/decodesignal.hpp index 51745b7b..f961b7c3 100644 --- a/pv/data/decodesignal.hpp +++ b/pv/data/decodesignal.hpp @@ -82,7 +82,7 @@ struct DecodeSegment // Copy constructor is a no-op DecodeSegment(DecodeSegment&& ds) { (void)ds; }; - map annotation_rows; + map annotation_rows; // Note: Row is the same for all segments while RowData is not pv::util::Timestamp start_time; double samplerate; int64_t samples_decoded_incl, samples_decoded_excl;