]> sigrok.org Git - pulseview.git/blobdiff - pv/data/segment.cpp
DecodeSignal: Allow muxed logic data to be cached
[pulseview.git] / pv / data / segment.cpp
index a2a213afcdcbca59a6c0bba9a66632bdc78af7d8..ae9788fc676724d06166f8ffd851767f5abe6362 100644 (file)
 #include <cassert>
 #include <cstdlib>
 #include <cstring>
-#include <vector>
 
 using std::lock_guard;
+using std::min;
 using std::recursive_mutex;
-using std::vector;
 
 namespace pv {
 namespace data {
 
-const uint64_t Segment::MaxChunkSize = 10*1024*1024;  /* 10MiB */
+const uint64_t Segment::MaxChunkSize = 10 * 1024 * 1024;  /* 10MiB */
 
 Segment::Segment(uint64_t samplerate, unsigned int unit_size) :
        sample_count_(0),
@@ -47,8 +46,7 @@ Segment::Segment(uint64_t samplerate, unsigned int unit_size) :
 
        // Determine the number of samples we can fit in one chunk
        // without exceeding MaxChunkSize
-       chunk_size_ = std::min(MaxChunkSize,
-               (MaxChunkSize / unit_size_) * unit_size_);
+       chunk_size_ = min(MaxChunkSize, (MaxChunkSize / unit_size_) * unit_size_);
 
        // Create the initial chunk
        current_chunk_ = new uint8_t[chunk_size_];
@@ -119,8 +117,7 @@ void Segment::append_single_sample(void *data)
        // There will always be space for at least one sample in
        // the current chunk, so we do not need to test for space
 
-       memcpy(current_chunk_ + (used_samples_ * unit_size_),
-               data, unit_size_);
+       memcpy(current_chunk_ + (used_samples_ * unit_size_), data, unit_size_);
        used_samples_++;
        unused_samples_--;
 
@@ -138,48 +135,52 @@ void Segment::append_samples(void* data, uint64_t samples)
 {
        lock_guard<recursive_mutex> lock(mutex_);
 
-       if (unused_samples_ >= samples) {
-               // All samples fit into the current chunk
-               memcpy(current_chunk_ + (used_samples_ * unit_size_),
-                       data, (samples * unit_size_));
-               used_samples_ += samples;
-               unused_samples_ -= samples;
-       } else {
-               // Only a part of the samples fit, split data up between chunks
-               memcpy(current_chunk_ + (used_samples_ * unit_size_),
-                       data, (unused_samples_ * unit_size_));
-               const uint64_t remaining_samples = samples - unused_samples_;
-
-               // If we're out of memory, this will throw std::bad_alloc
-               current_chunk_ = new uint8_t[chunk_size_];
-               data_chunks_.push_back(current_chunk_);
-               memcpy(current_chunk_, (uint8_t*)data + (unused_samples_ * unit_size_),
-                       (remaining_samples * unit_size_));
-
-               used_samples_ = remaining_samples;
-               unused_samples_ = (chunk_size_ / unit_size_) - remaining_samples;
-       }
-
-       if (unused_samples_ == 0) {
-               // If we're out of memory, this will throw std::bad_alloc
-               current_chunk_ = new uint8_t[chunk_size_];
-               data_chunks_.push_back(current_chunk_);
-               used_samples_ = 0;
-               unused_samples_ = chunk_size_ / unit_size_;
-       }
+       const uint8_t* data_byte_ptr = (uint8_t*)data;
+       uint64_t remaining_samples = samples;
+       uint64_t data_offset = 0;
+
+       do {
+               uint64_t copy_count = 0;
+
+               if (remaining_samples <= unused_samples_) {
+                       // All samples fit into the current chunk
+                       copy_count = remaining_samples;
+               } else {
+                       // Only a part of the samples fit, fill up current chunk
+                       copy_count = unused_samples_;
+               }
+
+               const uint8_t* dest = &(current_chunk_[used_samples_ * unit_size_]);
+               const uint8_t* src = &(data_byte_ptr[data_offset]);
+               memcpy((void*)dest, (void*)src, (copy_count * unit_size_));
+
+               used_samples_ += copy_count;
+               unused_samples_ -= copy_count;
+               remaining_samples -= copy_count;
+               data_offset += (copy_count * unit_size_);
+
+               if (unused_samples_ == 0) {
+                       // If we're out of memory, this will throw std::bad_alloc
+                       current_chunk_ = new uint8_t[chunk_size_];
+                       data_chunks_.push_back(current_chunk_);
+                       used_samples_ = 0;
+                       unused_samples_ = chunk_size_ / unit_size_;
+               }
+       } while (remaining_samples > 0);
 
        sample_count_ += samples;
 }
 
-uint8_t* Segment::get_raw_samples(uint64_t start, uint64_t count) const
+void Segment::get_raw_samples(uint64_t start, uint64_t count,
+       uint8_t* dest) const
 {
        assert(start < sample_count_);
        assert(start + count <= sample_count_);
        assert(count > 0);
+       assert(dest != nullptr);
 
        lock_guard<recursive_mutex> lock(mutex_);
 
-       uint8_t* dest = new uint8_t[count * unit_size_];
        uint8_t* dest_ptr = dest;
 
        uint64_t chunk_num = (start * unit_size_) / chunk_size_;
@@ -188,7 +189,7 @@ uint8_t* Segment::get_raw_samples(uint64_t start, uint64_t count) const
        while (count > 0) {
                const uint8_t* chunk = data_chunks_[chunk_num];
 
-               uint64_t copy_size = std::min(count * unit_size_,
+               uint64_t copy_size = min(count * unit_size_,
                        chunk_size_ - chunk_offs);
 
                memcpy(dest_ptr, chunk + chunk_offs, copy_size);
@@ -199,8 +200,6 @@ uint8_t* Segment::get_raw_samples(uint64_t start, uint64_t count) const
                chunk_num++;
                chunk_offs = 0;
        }
-
-       return dest;
 }
 
 SegmentRawDataIterator* Segment::begin_raw_sample_iteration(uint64_t start)
@@ -222,16 +221,12 @@ SegmentRawDataIterator* Segment::begin_raw_sample_iteration(uint64_t start)
 
 void Segment::continue_raw_sample_iteration(SegmentRawDataIterator* it, uint64_t increase)
 {
-       lock_guard<recursive_mutex> lock(mutex_);
-
+       // Fail gracefully if we are asked to deliver data we don't have
        if (it->sample_index > sample_count_)
-       {
-               // Fail gracefully if we are asked to deliver data we don't have
                return;
-       } else {
-               it->sample_index += increase;
-               it->chunk_offs += (increase * unit_size_);
-       }
+
+       it->sample_index += increase;
+       it->chunk_offs += (increase * unit_size_);
 
        if (it->chunk_offs > (chunk_size_ - 1)) {
                it->chunk_num++;
@@ -254,6 +249,5 @@ void Segment::end_raw_sample_iteration(SegmentRawDataIterator* it)
        }
 }
 
-
 } // namespace data
 } // namespace pv