mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-02 02:49:28 +00:00
Made an attempt to come up with a data structure that actually makes sense (though perhaps this is textbook list
rather than vector
stuff? I guess it depends on the frequency I expect inserts to occur versus reads) and to implement inserts. Though the Period
s aren't yet honoured.
This commit is contained in:
parent
1df478d250
commit
8f937ceac8
@ -11,18 +11,77 @@
|
|||||||
using namespace Storage::Disk;
|
using namespace Storage::Disk;
|
||||||
|
|
||||||
PCMPatchedTrack::PCMPatchedTrack(std::shared_ptr<Track> underlying_track) :
|
PCMPatchedTrack::PCMPatchedTrack(std::shared_ptr<Track> underlying_track) :
|
||||||
underlying_track_(underlying_track),
|
underlying_track_(underlying_track)
|
||||||
active_patch_((size_t)-1)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void PCMPatchedTrack::add_segment(const Time &start_position, const PCMSegment &segment)
|
|
||||||
{
|
{
|
||||||
patches_.emplace_back(start_position, segment);
|
Time zero(0);
|
||||||
|
Time one(1);
|
||||||
|
periods_.emplace_back(zero, one, zero, nullptr);
|
||||||
|
active_period_ = &periods_.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCMPatchedTrack::add_segment(const Time &start_time, const PCMSegment &segment)
|
||||||
|
{
|
||||||
|
event_sources_.emplace_back(segment);
|
||||||
|
|
||||||
|
Time zero(0);
|
||||||
|
Period insertion_period(start_time, start_time + event_sources_.back().get_length(), zero, &event_sources_.back());
|
||||||
|
|
||||||
|
// the new segment may wrap around, so divide it up into track-length parts if required
|
||||||
|
Time one = Time(1);
|
||||||
|
while(insertion_period.end_time > one)
|
||||||
|
{
|
||||||
|
Time next_end_time = insertion_period.end_time - one;
|
||||||
|
insertion_period.end_time = one;
|
||||||
|
insert_period(insertion_period);
|
||||||
|
|
||||||
|
insertion_period.start_time = zero;
|
||||||
|
insertion_period.end_time = next_end_time;
|
||||||
|
}
|
||||||
|
insert_period(insertion_period);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCMPatchedTrack::insert_period(const Period &period)
|
||||||
|
{
|
||||||
|
// find the existing period that the new period starts in
|
||||||
|
size_t start_index = 0;
|
||||||
|
while(periods_[start_index].start_time >= period.end_time) start_index++;
|
||||||
|
|
||||||
|
// find the existing period that the new period end in
|
||||||
|
size_t end_index = 0;
|
||||||
|
while(periods_[end_index].end_time < period.end_time) end_index++;
|
||||||
|
|
||||||
|
// perform a division if called for
|
||||||
|
if(start_index == end_index)
|
||||||
|
{
|
||||||
|
Period right_period = periods_[start_index];
|
||||||
|
|
||||||
|
Time adjustment = period.start_time - right_period.start_time;
|
||||||
|
right_period.end_time += adjustment;
|
||||||
|
right_period.segment_start_time += adjustment;
|
||||||
|
|
||||||
|
periods_[start_index].end_time = period.start_time;
|
||||||
|
periods_.insert(periods_.begin() + (int)start_index + 1, period);
|
||||||
|
periods_.insert(periods_.begin() + (int)start_index + 2, right_period);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// perform a left chop on the thing at the start and a right chop on the thing at the end
|
||||||
|
periods_[start_index].end_time = period.start_time;
|
||||||
|
|
||||||
|
Time adjustment = period.start_time - periods_[end_index].start_time;
|
||||||
|
periods_[end_index].end_time += adjustment;
|
||||||
|
periods_[end_index].segment_start_time += adjustment;
|
||||||
|
|
||||||
|
// remove anything in between
|
||||||
|
periods_.erase(periods_.begin() + (int)start_index + 1, periods_.begin() + (int)end_index - 1);
|
||||||
|
|
||||||
|
// insert the new period
|
||||||
|
periods_.insert(periods_.begin() + (int)start_index + 1, period);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Track::Event PCMPatchedTrack::get_next_event()
|
Track::Event PCMPatchedTrack::get_next_event()
|
||||||
{
|
{
|
||||||
// if(active_patch_ == (size_t)-1)
|
|
||||||
return underlying_track_->get_next_event();
|
return underlying_track_->get_next_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define PCMPatchedTrack_hpp
|
#define PCMPatchedTrack_hpp
|
||||||
|
|
||||||
#include "PCMTrack.hpp"
|
#include "PCMTrack.hpp"
|
||||||
|
#include "PCMSegment.hpp"
|
||||||
|
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
namespace Disk {
|
namespace Disk {
|
||||||
@ -29,7 +30,7 @@ class PCMPatchedTrack: public Track {
|
|||||||
Replaces whatever is currently on the track from @c start_position to @c start_position + segment length
|
Replaces whatever is currently on the track from @c start_position to @c start_position + segment length
|
||||||
with the contents of @c segment.
|
with the contents of @c segment.
|
||||||
*/
|
*/
|
||||||
void add_segment(const Time &start_position, const PCMSegment &segment);
|
void add_segment(const Time &start_time, const PCMSegment &segment);
|
||||||
|
|
||||||
// To satisfy Storage::Disk::Track
|
// To satisfy Storage::Disk::Track
|
||||||
Event get_next_event();
|
Event get_next_event();
|
||||||
@ -37,13 +38,20 @@ class PCMPatchedTrack: public Track {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Track> underlying_track_;
|
std::shared_ptr<Track> underlying_track_;
|
||||||
struct Patch {
|
std::vector<PCMSegmentEventSource> event_sources_;
|
||||||
Time start_position;
|
|
||||||
PCMSegment segment;
|
struct Period {
|
||||||
Patch(const Time &start_position, const PCMSegment &segment) : start_position(start_position), segment(segment) {}
|
Time start_time, end_time;
|
||||||
|
Time segment_start_time;
|
||||||
|
PCMSegmentEventSource *event_source; // nullptr => use the underlying track
|
||||||
|
|
||||||
|
Period(const Time &start_time, const Time &end_time, const Time &segment_start_time, PCMSegmentEventSource *event_source) :
|
||||||
|
start_time(start_time), end_time(end_time), segment_start_time(segment_start_time), event_source(event_source) {}
|
||||||
};
|
};
|
||||||
std::vector<Patch> patches_;
|
std::vector<Period> periods_;
|
||||||
size_t active_patch_;
|
Period *active_period_;
|
||||||
|
|
||||||
|
void insert_period(const Period &period);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ namespace Storage {
|
|||||||
struct Time {
|
struct Time {
|
||||||
unsigned int length, clock_rate;
|
unsigned int length, clock_rate;
|
||||||
Time() : length(0), clock_rate(1) {}
|
Time() : length(0), clock_rate(1) {}
|
||||||
|
Time(unsigned int int_value) : length(int_value), clock_rate(1) {}
|
||||||
Time(unsigned int length, unsigned int clock_rate) : length(length), clock_rate(clock_rate) {}
|
Time(unsigned int length, unsigned int clock_rate) : length(length), clock_rate(clock_rate) {}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Loading…
Reference in New Issue
Block a user