A little code cleanup in AnimQueue

This commit is contained in:
2023-08-16 15:40:30 -04:00
parent 26129004d1
commit b7b215f79c
2 changed files with 46 additions and 64 deletions

View File

@@ -9,10 +9,6 @@
#include <cmath>
#include <cstdlib>
util::SharedStdString make_shared_string(const StreamBuffer &sb) {
return std::make_shared<std::string>(sb.view());
}
static const char *vtname(AnimValueType vt) {
switch (vt) {
case T_UNINITIALIZED: return "uninitialized";
@@ -423,26 +419,6 @@ void AnimCoreState::decode(std::string_view s) {
}
}
struct StepBreakout {
uint64_t hash;
std::string_view encstep;
StepBreakout(uint64_t h, std::string_view e) : hash(h), encstep(e) {}
};
using StepBreakoutVec = eng::vector<StepBreakout>;
StepBreakoutVec encqueue_breakout(std::string_view encqueue) {
StepBreakoutVec result;
StreamBuffer sb(encqueue);
while (!sb.empty()) {
uint64_t hash = sb.read_uint64();
std::string_view encstep = sb.read_string_view();
result.emplace_back(hash, encstep);
}
return result;
}
// Just return the hash of the very last step. (Steps are stored last to first).
static uint64_t encqueue_final_hash(std::string_view encqueue) {
StreamBuffer sb(encqueue);
@@ -450,6 +426,7 @@ static uint64_t encqueue_final_hash(std::string_view encqueue) {
return hash;
}
// Return the encstep for the final step of the animation queue.
static std::string_view encqueue_final_encstep(std::string_view encqueue) {
StreamBuffer sb(encqueue);
sb.read_uint64();
@@ -457,9 +434,9 @@ static std::string_view encqueue_final_encstep(std::string_view encqueue) {
return result;
}
// Return the encqueue for the first N steps. If there aren't that
// many steps, then just return them all.
std::string_view encqueue_firstn(std::string_view encqueue, int n) {
// Return the encqueue for the first N steps.
// If there aren't that many steps, then just return them all.
std::string_view encqueue_finaln(std::string_view encqueue, int n) {
StreamBuffer sb(encqueue);
while ((n > 0) && (!sb.empty())) {
sb.read_uint64();
@@ -487,13 +464,13 @@ void AnimQueue::clear(const AnimState &state) {
uint64_t hash = hash_encstep(0, encstep);
result.write_uint64(hash);
result.write_string(encstep);
encqueue_ = make_shared_string(result);
encqueue_ = std::make_shared<std::string>(result.view());
}
void AnimQueue::set_limit(int nkeep) {
assert((nkeep >= 2) && (nkeep <= 250));
size_limit_ = nkeep;
encqueue_ = std::make_shared<std::string>(encqueue_firstn(*encqueue_, nkeep));
encqueue_ = std::make_shared<std::string>(encqueue_finaln(*encqueue_, nkeep));
}
void AnimQueue::add(const AnimState &state) {
@@ -503,8 +480,8 @@ void AnimQueue::add(const AnimState &state) {
StreamBuffer result;
result.write_uint64(hash);
result.write_string(encstep);
result.write_bytes(encqueue_firstn(*encqueue_, size_limit_ - 1));
encqueue_ = make_shared_string(result);
result.write_bytes(encqueue_finaln(*encqueue_, size_limit_ - 1));
encqueue_ = std::make_shared<std::string>(result.view());
}
void AnimQueue::serialize(StreamBuffer *sb) const {
@@ -557,35 +534,39 @@ bool AnimQueue::exactly_equal_fast(const AnimQueue &other) const {
return true;
}
eng::string AnimQueue::steps_debug_string() const {
StepBreakoutVec breakout = encqueue_breakout(*encqueue_);
eng::ostringstream oss;
void AnimQueue::print_debug_string(eng::ostringstream &oss, bool full) const {
bool first = true;
for (int i = breakout.size() - 1; i >= 0; i--) {
const StepBreakout &step = breakout[i];
if (!first) oss << "; ";
if (full) {
oss << "limit=" << size_limit();
first = false;
AnimState state(step.encstep);
state.print_debug_string(oss);
}
// Break out the steps.
eng::vector<std::string_view> encsteps;
StreamBuffer sb(*encqueue_);
while (!sb.empty()) {
sb.read_uint64();
encsteps.push_back(sb.read_string_view());
}
for (int i = encsteps.size() - 1; i >= 0; i --) {
if (!first) oss << "; ";
AnimState state(encsteps[i]);
state.print_debug_string(oss);
first = false;
}
}
eng::string AnimQueue::steps_debug_string() const {
eng::ostringstream oss;
print_debug_string(oss, false);
return oss.str();
}
eng::string AnimQueue::full_debug_string() const {
StepBreakoutVec breakout = encqueue_breakout(*encqueue_);
eng::ostringstream oss;
oss << "limit=" << size_limit();
for (int i = breakout.size() - 1; i >= 0; i--) {
const StepBreakout &step = breakout[i];
oss << "; ";
AnimState state(step.encstep);
state.print_debug_string(oss);
}
print_debug_string(oss, true);
return oss.str();
}
// Get the final entry, xyz and plane only.
//
AnimCoreState AnimQueue::get_final_core_state() const {
std::string_view encstep = encqueue_final_encstep(*encqueue_);
AnimCoreState result;
@@ -593,8 +574,6 @@ AnimCoreState AnimQueue::get_final_core_state() const {
return result;
}
// Get the final entry, all persistent variables.
//
AnimState AnimQueue::get_final_persistent() const {
std::string_view encstep = encqueue_final_encstep(*encqueue_);
AnimState result;
@@ -602,8 +581,6 @@ AnimState AnimQueue::get_final_persistent() const {
return result;
}
// Get the final entry, everything persistent and non-persistent.
//
AnimState AnimQueue::get_final_everything() const {
std::string_view encstep = encqueue_final_encstep(*encqueue_);
AnimState result;
@@ -611,7 +588,6 @@ AnimState AnimQueue::get_final_everything() const {
return result;
}
LuaDefine(unittests_animqueue, "", "some unit tests") {
// Useful objects.
AnimQueue aq, aqs;

View File

@@ -22,23 +22,28 @@
// by mixing the hash value of the previous step with the hash value
// of the encoded string of key-value pairs.
//
//
///////////////////////////////////////////////////////////////////
//
// SERIALIZED STORAGE
//
// The entired animation queue is stored in a serialized format,
// as a shared string. This means that the animation queue can be
// passed to the graphics engine as a single string. This vastly
// simplifies the API for passing the animation queue to the
// graphics engine. It also vastly reduces the amount of computation
// done during the graphics engine probe: all we have to do is get
// the already existing string and pass a reference to it.
// passed to the graphics engine as a single string. This can be
// accomplished by the function EngineWrapper.get_animation_queues.
//
// However, that means that when manipulating the animation queue,
// we have to decode it, manipulate it, and then reencode it. This
// is a good tradeoff: we update animation queues rarely, compared
// to how often we pass them to the graphics engine.
// The fact that the queue is stored in a serialized format means
// that when manipulating the animation queue, we have to decode it,
// manipulate it, and then reencode it.
//
// From an efficiency perspective, this means that manipulation is
// slower, but passing the strings to the graphics engine is faster
// and simpler. This is a good tradeoff: we manipulate animation
// queues rarely, compared to how often we pass them to the graphics
// engine.
//
///////////////////////////////////////////////////////////////////
//
// THE SERIALIZED REPRESENTATION
//
// So first, you need to know how to serialize a single animation
// step. Remember, an animation step consists of a list of key-value
@@ -287,6 +292,7 @@ public:
// Debug strings.
//
void print_debug_string(eng::ostringstream &oss, bool full) const;
eng::string steps_debug_string() const;
eng::string full_debug_string() const;