#include <pv/data/decode/annotation.hpp>
#include <pv/data/decode/decoder.hpp>
+#include "pv/data/decode/rowdata.hpp"
using std::vector;
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;
Annotation::~Annotation()
{
- delete annotations_;
}
uint64_t Annotation::start_sample() 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
namespace decode {
class Row;
+class RowData;
class Annotation
{
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();
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
assert(row);
}
+const Row* RowData::row() const
+{
+ return row_;
+}
+
uint64_t RowData::get_max_sample() const
{
if (annotations_.empty())
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
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;
}
#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 {
public:
RowData(Row* row);
+ const Row* row() const;
+
uint64_t get_max_sample() const;
uint64_t get_annotation_count() const;
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_;
};
// 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;