]> sigrok.org Git - pulseview.git/commitdiff
Fix #811 by using a hashed annotation text backing storage
authorSoeren Apel <redacted>
Sat, 18 Apr 2020 07:28:33 +0000 (09:28 +0200)
committerUwe Hermann <redacted>
Sun, 3 May 2020 15:20:55 +0000 (17:20 +0200)
pv/data/decode/annotation.cpp
pv/data/decode/annotation.hpp
pv/data/decode/rowdata.cpp
pv/data/decode/rowdata.hpp
pv/data/decodesignal.hpp

index 689c08dec6eaf16a1ba9a52acc259fd38c30f36e..9f86b2bab84362e26503233c3cb516ee7ebcdf41 100644 (file)
@@ -26,6 +26,7 @@ extern "C" {
 
 #include <pv/data/decode/annotation.hpp>
 #include <pv/data/decode/decoder.hpp>
+#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<QString>* 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<QString>();
-
-       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<QString>* 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
index e599bdd447343e75254fe00aa879109a6feb52da..df99ecb980676247cf62ae6c891505af273ada16 100644 (file)
@@ -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<QString>* 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<QString>* annotations_;
-       const Row *row_;
+       const vector<QString>* texts_;
        Class ann_class_id_;
+       const RowData* data_;
 };
 
 } // namespace decode
index fc1480a117c590278b57fd57846d55f38f668fec..fc635b2452db765e7bd8896b6d6e6c474abc36da 100644 (file)
@@ -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<QString>* 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;
        }
index 48b6a41a68a260783dd0740b8ac57f63448eb4e9..f01aa3ca81c2f71a24c61dc71f7b1d1ba67f7139 100644 (file)
 #ifndef PULSEVIEW_PV_DATA_DECODE_ROWDATA_HPP
 #define PULSEVIEW_PV_DATA_DECODE_ROWDATA_HPP
 
+#include <unordered_map>
 #include <vector>
 
+#include <QHash>
+#include <QString>
+
 #include <libsigrokdecode/libsigrokdecode.h>
 
 #include <pv/data/decode/annotation.hpp>
 
 using std::deque;
-using std::vector;
+using std::unordered_map;
+
+namespace std {
+  template<> struct hash<QString> {
+    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<Annotation> annotations_;
+       unordered_map<QString, vector<QString> > ann_texts_;  // unordered_map since pointers must not change
        Row* row_;
        uint64_t prev_ann_start_sample_;
 };
index 51745b7baab8a8d3bf1237e80d9fa96bb10a458e..f961b7c3a740b6bb9bc8a010147da64ce9e814db 100644 (file)
@@ -82,7 +82,7 @@ struct DecodeSegment
        // Copy constructor is a no-op
        DecodeSegment(DecodeSegment&& ds) { (void)ds; };
 
-       map<const Row*, RowData> annotation_rows;
+       map<const Row*, RowData> 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;