]> sigrok.org Git - pulseview.git/blob - pv/data/decode/rowdata.cpp
a9c2e2a883b8eee89dbc518e8bb18aae25bb8607
[pulseview.git] / pv / data / decode / rowdata.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2014 Joel Holdsworth <joel@airwebreathe.org.uk>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <cassert>
21
22 #include <pv/data/decode/decoder.hpp>
23 #include <pv/data/decode/row.hpp>
24 #include <pv/data/decode/rowdata.hpp>
25
26 using std::vector;
27
28 namespace pv {
29 namespace data {
30 namespace decode {
31
32 RowData::RowData(Row* row) :
33         row_(row),
34         prev_ann_start_sample_(0)
35 {
36         assert(row);
37 }
38
39 const Row* RowData::row() const
40 {
41         return row_;
42 }
43
44 uint64_t RowData::get_max_sample() const
45 {
46         if (annotations_.empty())
47                 return 0;
48         return annotations_.back().end_sample();
49 }
50
51 uint64_t RowData::get_annotation_count() const
52 {
53         return annotations_.size();
54 }
55
56 void RowData::get_annotation_subset(
57         deque<const pv::data::decode::Annotation*> &dest,
58         uint64_t start_sample, uint64_t end_sample) const
59 {
60         // Determine whether we must apply per-class filtering or not
61         bool all_ann_classes_enabled = true;
62         bool all_ann_classes_disabled = true;
63
64         uint32_t max_ann_class_id = 0;
65         for (AnnotationClass* c : row_->ann_classes()) {
66                 if (!c->visible())
67                         all_ann_classes_enabled = false;
68                 else
69                         all_ann_classes_disabled = false;
70                 if (c->id > max_ann_class_id)
71                         max_ann_class_id = c->id;
72         }
73
74         if (all_ann_classes_enabled) {
75                 // No filtering, send everyting out as-is
76                 for (const auto& annotation : annotations_)
77                         if ((annotation.end_sample() > start_sample) &&
78                                 (annotation.start_sample() <= end_sample))
79                                 dest.push_back(&annotation);
80         } else {
81                 if (!all_ann_classes_disabled) {
82                         // Filter out invisible annotation classes
83                         vector<size_t> class_visible;
84                         class_visible.resize(max_ann_class_id + 1, 0);
85                         for (AnnotationClass* c : row_->ann_classes())
86                                 if (c->visible())
87                                         class_visible[c->id] = 1;
88
89                         for (const auto& annotation : annotations_)
90                                 if ((class_visible[annotation.ann_class_id()]) &&
91                                         (annotation.end_sample() > start_sample) &&
92                                         (annotation.start_sample() <= end_sample))
93                                         dest.push_back(&annotation);
94                 }
95         }
96 }
97
98 const deque<Annotation>& RowData::annotations() const
99 {
100         return annotations_;
101 }
102
103 const Annotation* RowData::emplace_annotation(srd_proto_data *pdata)
104 {
105         const srd_proto_data_annotation *const pda = (const srd_proto_data_annotation*)pdata->data;
106
107         Annotation::Class ann_class_id = (Annotation::Class)(pda->ann_class);
108
109         // Look up the longest annotation text to see if we have it in storage.
110         // This implies that if the longest text is the same, the shorter texts
111         // are expected to be the same, too. PDs that violate this assumption
112         // should be considered broken.
113         const char* const* ann_texts = (char**)pda->ann_text;
114         const QString ann0 = QString::fromUtf8(ann_texts[0]);
115         vector<QString>* storage_entry = &(ann_texts_[ann0]);
116
117         if (storage_entry->empty()) {
118                 while (*ann_texts) {
119                         storage_entry->emplace_back(QString::fromUtf8(*ann_texts));
120                         ann_texts++;
121                 }
122                 storage_entry->shrink_to_fit();
123         }
124
125
126         const Annotation* result = nullptr;
127
128         // We insert the annotation in a way so that the annotation list
129         // is sorted by start sample. Otherwise, we'd have to sort when
130         // painting, which is expensive
131
132         if (pdata->start_sample < prev_ann_start_sample_) {
133                 // Find location to insert the annotation at
134
135                 auto it = annotations_.end();
136                 do {
137                         it--;
138                 } while ((it->start_sample() > pdata->start_sample) && (it != annotations_.begin()));
139
140                 // Allow inserting at the front
141                 if (it != annotations_.begin())
142                         it++;
143
144                 it = annotations_.emplace(it, pdata->start_sample, pdata->end_sample,
145                         storage_entry, ann_class_id, this);
146                 result = &(*it);
147         } else {
148                 annotations_.emplace_back(pdata->start_sample, pdata->end_sample,
149                         storage_entry, ann_class_id, this);
150                 result = &(annotations_.back());
151                 prev_ann_start_sample_ = pdata->start_sample;
152         }
153
154         return result;
155 }
156
157 }  // namespace decode
158 }  // namespace data
159 }  // namespace pv