Support for debug_string method for testing
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
#include "luastack.hpp"
|
||||
#include "animqueue.hpp"
|
||||
#include "streambuffer.hpp"
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
AnimStep::AnimStep() {
|
||||
clear();
|
||||
@@ -252,6 +254,75 @@ bool AnimStep::echoes(const AnimStep &prev) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string AnimStep::debug_string() const {
|
||||
std::ostringstream oss;
|
||||
oss << "id=" << id();
|
||||
oss << " action=" << action();
|
||||
if (has_plane()) {
|
||||
oss << " plane=" << plane();
|
||||
}
|
||||
if (has_x()) {
|
||||
oss << " x=" << xyz().x;
|
||||
}
|
||||
if (has_y()) {
|
||||
oss << " y=" << xyz().y;
|
||||
}
|
||||
if (has_z()) {
|
||||
oss << " z=" << xyz().z;
|
||||
}
|
||||
if (has_facing()) {
|
||||
oss << " facing=" << facing();
|
||||
}
|
||||
if (has_graphic()) {
|
||||
oss << " graphic=" << graphic();
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
bool AnimStep::from_string(const std::string &config) {
|
||||
clear();
|
||||
util::stringvec parts = util::split(config, ' ');
|
||||
for (int i = 0; i < int(parts.size()); i++) {
|
||||
const std::string &part = parts[i];
|
||||
if (part == "") continue;
|
||||
util::stringvec lr = util::split(part, '=');
|
||||
if (lr.size() != 2) return false;
|
||||
const std::string &key = lr[0];
|
||||
const std::string &val = lr[1];
|
||||
if (key == "action") {
|
||||
action_ = val;
|
||||
} else if (key == "id") {
|
||||
int64_t id = util::strtoint(val, -1);
|
||||
if (id < 0) return false;
|
||||
id_ = id;
|
||||
} else if (key == "plane") {
|
||||
set_plane(val);
|
||||
} else if (key == "x") {
|
||||
double v = util::strtodouble(val);
|
||||
if (std::isnan(v)) return false;
|
||||
set_x(v);
|
||||
} else if (key == "y") {
|
||||
double v = util::strtodouble(val);
|
||||
if (std::isnan(v)) return false;
|
||||
set_y(v);
|
||||
} else if (key == "z") {
|
||||
double v = util::strtodouble(val);
|
||||
if (std::isnan(v)) return false;
|
||||
set_z(v);
|
||||
} else if (key == "facing") {
|
||||
double v = util::strtodouble(val);
|
||||
if (std::isnan(v)) return false;
|
||||
set_facing(v);
|
||||
} else if (key == "graphic") {
|
||||
set_graphic(val);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
AnimQueue::AnimQueue(util::WorldType wt) {
|
||||
world_type_ = wt;
|
||||
size_limit_ = 10; // Default size limit.
|
||||
@@ -293,11 +364,16 @@ void AnimQueue::clear_steps() {
|
||||
mutated();
|
||||
}
|
||||
|
||||
void AnimQueue::set_size_limit(int n) {
|
||||
void AnimQueue::full_clear_and_set_limit(int n) {
|
||||
assert(n >= 1);
|
||||
if (size_limit_ == n) return;
|
||||
clear_steps();
|
||||
size_limit_ = n;
|
||||
while (int(steps_.size()) > size_limit_) {
|
||||
version_number_ = 1;
|
||||
}
|
||||
void AnimQueue::set_limit(int n) {
|
||||
assert(n >= 1);
|
||||
size_limit_ = n;
|
||||
while (int(steps_.size()) > n) {
|
||||
steps_.pop_front();
|
||||
}
|
||||
steps_.front().keep_state_only();
|
||||
@@ -345,6 +421,16 @@ bool AnimQueue::valid() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string AnimQueue::debug_string() const {
|
||||
std::ostringstream oss;
|
||||
oss << "version=" << version_number();
|
||||
oss << "; limit=" << size_limit();
|
||||
for (int i = 0; i < int(size()); i++) {
|
||||
oss << "; " << nth(i).debug_string();
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void AnimQueue::serialize(StreamBuffer *sb) {
|
||||
assert(valid()); // can't serialize an invalid animqueue.
|
||||
sb->write_int64(version_number_);
|
||||
@@ -469,163 +555,98 @@ LuaDefine(unittests_animqueue, "c") {
|
||||
AnimQueue aq(util::WORLD_TYPE_MASTER);
|
||||
StreamBuffer sb;
|
||||
AnimQueue aqds(util::WORLD_TYPE_S_SYNC);
|
||||
aq.set_size_limit(3);
|
||||
|
||||
LuaAssert(L, aq.valid());
|
||||
LuaAssert(L, aq.size() == 1);
|
||||
const AnimStep *st = &aq.nth(0);
|
||||
LuaAssert(L, st->id() == 0);
|
||||
LuaAssert(L, st->action() == "");
|
||||
LuaAssert(L, st->bits() == AnimStep::HAS_EVERYTHING);
|
||||
LuaAssert(L, st->facing() == 0.0);
|
||||
LuaAssert(L, st->xyz() == util::XYZ(0,0,0));
|
||||
LuaAssert(L, st->graphic() == "");
|
||||
LuaAssert(L, st->plane() == "");
|
||||
|
||||
// Test the step setters.
|
||||
stp.clear();
|
||||
LuaAssertStrEq(L, stp.debug_string(), "id=0 action=");
|
||||
stp.set_facing(180);
|
||||
LuaAssert(L, stp.facing() == 180);
|
||||
LuaAssert(L, stp.bits() == AnimStep::HAS_FACING);
|
||||
LuaAssertStrEq(L, stp.debug_string(), "id=0 action= facing=180");
|
||||
stp.set_x(3);
|
||||
LuaAssert(L, stp.xyz() == util::XYZ(3, 0, 0));
|
||||
LuaAssert(L, stp.bits() == (AnimStep::HAS_FACING | AnimStep::HAS_X));
|
||||
LuaAssertStrEq(L, stp.debug_string(), "id=0 action= x=3 facing=180");
|
||||
stp.set_y(4);
|
||||
LuaAssert(L, stp.xyz() == util::XYZ(3, 4, 0));
|
||||
LuaAssert(L, stp.bits() == (AnimStep::HAS_FACING | AnimStep::HAS_X | AnimStep::HAS_Y));
|
||||
LuaAssertStrEq(L, stp.debug_string(), "id=0 action= x=3 y=4 facing=180");
|
||||
stp.set_z(5);
|
||||
LuaAssert(L, stp.xyz() == util::XYZ(3, 4, 5));
|
||||
LuaAssert(L, stp.bits() == (AnimStep::HAS_FACING | AnimStep::HAS_X | AnimStep::HAS_Y | AnimStep::HAS_Z));
|
||||
LuaAssertStrEq(L, stp.debug_string(), "id=0 action= x=3 y=4 z=5 facing=180");
|
||||
stp.set_plane("somewhere");
|
||||
LuaAssert(L, stp.plane() == "somewhere");
|
||||
LuaAssert(L, stp.bits() == (AnimStep::HAS_FACING | AnimStep::HAS_XYZ | AnimStep::HAS_PLANE));
|
||||
LuaAssertStrEq(L, stp.debug_string(), "id=0 action= plane=somewhere x=3 y=4 z=5 facing=180");
|
||||
stp.set_graphic("something");
|
||||
LuaAssert(L, stp.graphic() == "something");
|
||||
LuaAssert(L, stp.bits() == (AnimStep::HAS_FACING | AnimStep::HAS_XYZ | AnimStep::HAS_PLANE | AnimStep::HAS_GRAPHIC));
|
||||
LuaAssertStrEq(L, stp.debug_string(), "id=0 action= plane=somewhere x=3 y=4 z=5 facing=180 graphic=something");
|
||||
|
||||
// Add a step.
|
||||
stp.clear();
|
||||
stp.set_action("walk");
|
||||
aq.add(12345, stp);
|
||||
// Test the step parser.
|
||||
LuaAssert(L, stp.from_string("id=123 action=walk x=1 y=2 z=3 facing=4 plane=p graphic=g"));
|
||||
LuaAssertStrEq(L, stp.debug_string(), "id=123 action=walk plane=p x=1 y=2 z=3 facing=4 graphic=g");
|
||||
|
||||
// Test a blank queue.
|
||||
aq.full_clear_and_set_limit(3);
|
||||
LuaAssert(L, aq.valid());
|
||||
LuaAssert(L, aq.size() == 2);
|
||||
st = &aq.nth(1);
|
||||
LuaAssert(L, st->id() == 12345);
|
||||
LuaAssert(L, st->action() == "walk");
|
||||
LuaAssert(L, st->bits() == 0);
|
||||
LuaAssert(L, st->facing() == 0.0);
|
||||
LuaAssert(L, st->xyz() == util::XYZ(0,0,0));
|
||||
LuaAssert(L, st->graphic() == "");
|
||||
LuaAssert(L, st->plane() == "");
|
||||
LuaAssertStrEq(L, aq.debug_string(), "version=1; limit=3; id=0 action= plane= x=0 y=0 z=0 facing=0 graphic=");
|
||||
|
||||
// Add a step to a queue.
|
||||
aq.full_clear_and_set_limit(3);
|
||||
LuaAssert(L, stp.from_string("action=walk"));
|
||||
aq.add(12345, stp);
|
||||
LuaAssertStrEq(L, aq.debug_string(),
|
||||
"version=2; limit=3; "
|
||||
"id=0 action= plane= x=0 y=0 z=0 facing=0 graphic=; "
|
||||
"id=12345 action=walk");
|
||||
|
||||
// Exceed the length limit, dropping first element.
|
||||
stp.clear();
|
||||
stp.set_action("walk");
|
||||
aq.full_clear_and_set_limit(3);
|
||||
LuaAssert(L, stp.from_string("action=walk plane=foo"));
|
||||
aq.add(12345, stp);
|
||||
aq.add(12346, stp);
|
||||
aq.add(12347, stp);
|
||||
LuaAssert(L, aq.size() == 3);
|
||||
LuaAssert(L, aq.nth(0).id() == 0);
|
||||
LuaAssert(L, aq.nth(0).action() == "");
|
||||
LuaAssert(L, aq.nth(0).bits() == AnimStep::HAS_EVERYTHING);
|
||||
LuaAssert(L, aq.nth(1).id() == 12346);
|
||||
LuaAssert(L, aq.nth(2).id() == 12347);
|
||||
LuaAssert(L, aq.valid());
|
||||
LuaAssertStrEq(L, aq.debug_string(),
|
||||
"version=4; limit=3; "
|
||||
"id=0 action= plane=foo x=0 y=0 z=0 facing=0 graphic=; "
|
||||
"id=12346 action=walk plane=foo; "
|
||||
"id=12347 action=walk plane=foo"
|
||||
);
|
||||
|
||||
// Test serialization and deserialization.
|
||||
aq.set_size_limit(5);
|
||||
aq.clear_steps();
|
||||
|
||||
stp.clear();
|
||||
stp.set_action("walk");
|
||||
stp.set_xyz(util::XYZ(3,4,5));
|
||||
aq.full_clear_and_set_limit(5);
|
||||
LuaAssert(L, stp.from_string("action=walk x=3 y=4 z=5"));
|
||||
aq.add(12345, stp);
|
||||
|
||||
stp.clear();
|
||||
stp.set_action("setgraphic");
|
||||
stp.set_graphic("banana");
|
||||
LuaAssert(L, stp.from_string("action=setgraphic graphic=banana"));
|
||||
aq.add(12346, stp);
|
||||
|
||||
stp.clear();
|
||||
stp.set_action("setfacing");
|
||||
stp.set_facing(301.0);
|
||||
LuaAssert(L, stp.from_string("action=setfacing facing=301"));
|
||||
aq.add(12347, stp);
|
||||
|
||||
aq.serialize(&sb);
|
||||
aqds.deserialize(&sb);
|
||||
|
||||
LuaAssert(L, aqds.size_limit() == 5);
|
||||
LuaAssert(L, aqds.size() == 4);
|
||||
|
||||
LuaAssert(L, aqds.nth(0).id() == 0);
|
||||
LuaAssert(L, aqds.nth(0).bits() == AnimStep::HAS_EVERYTHING);
|
||||
LuaAssert(L, aqds.nth(0).action() == "");
|
||||
LuaAssert(L, aqds.nth(0).facing() == 0.0);
|
||||
LuaAssert(L, aqds.nth(0).xyz() == util::XYZ(0,0,0));
|
||||
LuaAssert(L, aqds.nth(0).graphic() == "");
|
||||
LuaAssert(L, aqds.nth(0).plane() == "");
|
||||
LuaAssertStrEq(L, aqds.debug_string(),
|
||||
"version=4; limit=5; "
|
||||
"id=0 action= plane= x=0 y=0 z=0 facing=0 graphic=; "
|
||||
"id=12345 action=walk x=3 y=4 z=5; "
|
||||
"id=12346 action=setgraphic graphic=banana; "
|
||||
"id=12347 action=setfacing facing=301"
|
||||
);
|
||||
|
||||
LuaAssert(L, aqds.nth(1).id() == 12345);
|
||||
LuaAssert(L, aqds.nth(1).bits() == AnimStep::HAS_XYZ);
|
||||
LuaAssert(L, aqds.nth(1).action() == "walk");
|
||||
LuaAssert(L, aqds.nth(1).facing() == 0.0);
|
||||
LuaAssert(L, aqds.nth(1).xyz() == util::XYZ(3,4,5));
|
||||
LuaAssert(L, aqds.nth(1).graphic() == "");
|
||||
LuaAssert(L, aqds.nth(1).plane() == "");
|
||||
|
||||
LuaAssert(L, aqds.nth(2).id() == 12346);
|
||||
LuaAssert(L, aqds.nth(2).bits() == AnimStep::HAS_GRAPHIC);
|
||||
LuaAssert(L, aqds.nth(2).action() == "setgraphic");
|
||||
LuaAssert(L, aqds.nth(2).facing() == 0.0);
|
||||
LuaAssert(L, aqds.nth(2).xyz() == util::XYZ(3,4,5));
|
||||
LuaAssert(L, aqds.nth(2).graphic() == "banana");
|
||||
LuaAssert(L, aqds.nth(2).plane() == "");
|
||||
|
||||
LuaAssert(L, aqds.nth(3).id() == 12347);
|
||||
LuaAssert(L, aqds.nth(3).bits() == AnimStep::HAS_FACING);
|
||||
LuaAssert(L, aqds.nth(3).action() == "setfacing");
|
||||
LuaAssert(L, aqds.nth(3).facing() == 301.0);
|
||||
LuaAssert(L, aqds.nth(3).xyz() == util::XYZ(3,4,5));
|
||||
LuaAssert(L, aqds.nth(3).graphic() == "banana");
|
||||
LuaAssert(L, aqds.nth(3).plane() == "");
|
||||
|
||||
// Test difference transmission
|
||||
// Start with an anim queue with an initial state and a single action.
|
||||
aq.set_size_limit(10);
|
||||
aqds.set_size_limit(10);
|
||||
aq.clear_steps();
|
||||
aqds.clear_steps();
|
||||
|
||||
stp.clear();
|
||||
stp.set_action("walk");
|
||||
stp.set_xyz(util::XYZ(3,4,5));
|
||||
aq.full_clear_and_set_limit(10);
|
||||
aqds.full_clear_and_set_limit(10);
|
||||
|
||||
// Add a single action to the queue and DT
|
||||
LuaAssert(L, stp.from_string("action=walk x=3 y=4 z=5"));
|
||||
aq.add(12345, stp);
|
||||
|
||||
sb.clear();
|
||||
LuaAssert(L, aqds.make_patch(aq, &sb));
|
||||
aqds.apply_patch(&sb);
|
||||
LuaAssert(L, aqds.size_and_steps_equal(aq));
|
||||
|
||||
// Add another action.
|
||||
stp.clear();
|
||||
stp.set_action("fnord");
|
||||
stp.set_facing(123);
|
||||
stp.set_plane("where");
|
||||
// Add another action and DT
|
||||
LuaAssert(L, stp.from_string("action=fnord plane=where facing=123"));
|
||||
aq.add(232, stp);
|
||||
|
||||
// Generate diffs, but add 4 extra bytes.
|
||||
sb.clear();
|
||||
LuaAssert(L, aqds.make_patch(aq, &sb));
|
||||
sb.write_uint32(0);
|
||||
|
||||
// Apply the diffs, 4 extra bytes should remain.
|
||||
aqds.apply_patch(&sb);
|
||||
LuaAssert(L, sb.total_writes() - sb.total_reads() == 4);
|
||||
LuaAssert(L, aqds.size_and_steps_equal(aq));
|
||||
|
||||
// Change the queue size limit.
|
||||
aq.set_size_limit(13);
|
||||
|
||||
// Generate diffs, but add 4 extra bytes.
|
||||
aq.set_limit(13);
|
||||
sb.clear();
|
||||
LuaAssert(L, !aqds.size_and_steps_equal(aq));
|
||||
LuaAssert(L, aqds.make_patch(aq, &sb));
|
||||
@@ -639,7 +660,7 @@ LuaDefine(unittests_animqueue, "c") {
|
||||
LuaAssert(L, aqds.size_and_steps_equal(aq));
|
||||
|
||||
// Discard all but the last action.
|
||||
aq.set_size_limit(1);
|
||||
aq.set_limit(1);
|
||||
|
||||
sb.clear();
|
||||
LuaAssert(L, aqds.make_patch(aq, &sb));
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <cassert>
|
||||
#include <ostream>
|
||||
#include <unordered_map>
|
||||
#include "streambuffer.hpp"
|
||||
#include "util.hpp"
|
||||
@@ -155,8 +156,15 @@ public:
|
||||
|
||||
// Verify that this step echoes the previous step.
|
||||
bool echoes(const AnimStep &prev) const;
|
||||
|
||||
// Convert to a string for debugging purposes.
|
||||
std::string debug_string() const;
|
||||
|
||||
// Convert a string to an animstep (for testing only).
|
||||
bool from_string(const std::string &s);
|
||||
};
|
||||
|
||||
|
||||
class AnimQueue {
|
||||
private:
|
||||
util::WorldType world_type_;
|
||||
@@ -174,6 +182,7 @@ public:
|
||||
const AnimStep &nth(int n) const { return steps_[n]; }
|
||||
size_t size() const { return steps_.size(); }
|
||||
int32_t size_limit() const { return size_limit_; }
|
||||
int64_t version_number() const { return version_number_; }
|
||||
|
||||
// Return true if the size limit and steps are identical.
|
||||
bool size_and_steps_equal(const AnimQueue &aq) const;
|
||||
@@ -199,10 +208,14 @@ public:
|
||||
const AnimStep &back() const;
|
||||
|
||||
// (For testing): change the size limit.
|
||||
void set_size_limit(int32_t n);
|
||||
|
||||
void full_clear_and_set_limit(int szl);
|
||||
void set_limit(int szl);
|
||||
|
||||
// (For testing): make sure the invariants are preserved.
|
||||
bool valid() const;
|
||||
|
||||
// Convert to a string for debugging purposes.
|
||||
std::string debug_string() const;
|
||||
};
|
||||
|
||||
#endif // ANIMQUEUE_HPP
|
||||
|
||||
@@ -514,5 +514,5 @@ public:
|
||||
|
||||
#define LuaStringify(x) #x
|
||||
#define LuaAssert(L, x) if (!(x)) { luaL_error((L), "Assert failed: %s (file %s line %d)", LuaStringify(x), __FILE__, __LINE__); }
|
||||
|
||||
#define LuaAssertStrEq(L, x, y) { std::string _s1_ = (x); std::string _s2_ = (y); if (_s1_ != _s2_) luaL_error((L), "Assert failed: value=%s (file %s line %d)", _s1_.c_str(), __FILE__, __LINE__); }
|
||||
#endif // LUASTACK_HPP
|
||||
|
||||
@@ -85,7 +85,7 @@ void TextGame::do_view_command(const StringVec &cmd) {
|
||||
for (int64_t id : world_->get_near(actor_id_, 100, true)) {
|
||||
const Tangible *tan = world_->tangible_get(id);
|
||||
const AnimStep &aqback = tan->anim_queue_.back();
|
||||
std::cerr << id << ": " << aqback.graphic() << " " << aqback.plane() << " " << aqback.xyz() << std::endl;
|
||||
std::cerr << id << ": " << aqback.graphic() << " " << aqback.plane() << " " << aqback.xyz().debug_string() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "util.hpp"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <cmath>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#define stat _stat
|
||||
@@ -12,6 +13,21 @@
|
||||
|
||||
namespace util {
|
||||
|
||||
stringvec split(const std::string &s, char sep) {
|
||||
stringvec result;
|
||||
int start = 0;
|
||||
for (int i = 0; i < int(s.size()); i++) {
|
||||
if (s[i] == sep) {
|
||||
result.push_back(s.substr(start, i-start));
|
||||
start = i+1;
|
||||
}
|
||||
}
|
||||
if (start < int(s.size())) {
|
||||
result.push_back(s.substr(start));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string tolower(std::string input) {
|
||||
for (int i = 0; i < int(input.size()); i++) {
|
||||
input[i] = std::tolower(input[i]);
|
||||
@@ -42,6 +58,16 @@ int64_t strtoint(const std::string &value, int64_t errval) {
|
||||
}
|
||||
}
|
||||
|
||||
double strtodouble(const std::string &value) {
|
||||
char *endptr;
|
||||
double result = strtod(value.c_str(), &endptr);
|
||||
if (endptr == value.c_str() + value.size()) {
|
||||
return result;
|
||||
} else {
|
||||
return std::nan("");
|
||||
}
|
||||
}
|
||||
|
||||
std::string ltrim(std::string s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
@@ -97,31 +123,10 @@ double distance_squared(double x1, double y1, double x2, double y2) {
|
||||
return dx*dx + dy*dy;
|
||||
}
|
||||
|
||||
// These hash functions are part of Bob Jenkins' Lookup3.
|
||||
#define hash_rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
|
||||
#define hash_mix(a,b,c) { \
|
||||
a -= c; a ^= hash_rot(c, 4); c += b; \
|
||||
b -= a; b ^= hash_rot(a, 6); a += c; \
|
||||
c -= b; c ^= hash_rot(b, 8); b += a; \
|
||||
a -= c; a ^= hash_rot(c,16); c += b; \
|
||||
b -= a; b ^= hash_rot(a,19); a += c; \
|
||||
c -= b; c ^= hash_rot(b, 4); b += a; \
|
||||
}
|
||||
|
||||
#define hash_final(a,b,c) { \
|
||||
c ^= b; c -= hash_rot(b,14); \
|
||||
a ^= c; a -= hash_rot(c,11); \
|
||||
b ^= a; b -= hash_rot(a,25); \
|
||||
c ^= b; c -= hash_rot(b,16); \
|
||||
a ^= c; a -= hash_rot(c,4); \
|
||||
b ^= a; b -= hash_rot(a,14); \
|
||||
c ^= b; c -= hash_rot(b,24); \
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream &out, const XYZ &xyz) {
|
||||
out << "(" << xyz.x << "," << xyz.y << "," << xyz.z << ")";
|
||||
return out;
|
||||
std::string XYZ::debug_string() const {
|
||||
std::ostringstream oss;
|
||||
oss << "(" << x << "," << y << "," << z << ")";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
@@ -22,6 +22,9 @@ using stringvec = std::vector<std::string>;
|
||||
using stringset = std::set<std::string>;
|
||||
using HashValue = std::pair<uint64_t, uint64_t>;
|
||||
|
||||
// Split a string into multiple strings
|
||||
stringvec split(const std::string &s, char sep);
|
||||
|
||||
// String to lowercase/uppercase
|
||||
std::string tolower(std::string input);
|
||||
std::string toupper(std::string input);
|
||||
@@ -32,6 +35,9 @@ bool validinteger(const std::string &value);
|
||||
// String to integer. Returns errval if the number is not parseable.
|
||||
int64_t strtoint(const std::string &value, int64_t errval);
|
||||
|
||||
// String to double. Returns NAN if the number is not parseable.
|
||||
double strtodouble(const std::string &value);
|
||||
|
||||
// Trim strings: left end, right end, both ends.
|
||||
std::string ltrim(std::string s);
|
||||
std::string rtrim(std::string s);
|
||||
@@ -49,6 +55,7 @@ std::string get_file_fingerprint(const std::string &path);
|
||||
// Calculate distance between two points
|
||||
double distance_squared(double x1, double y1, double x2, double y2);
|
||||
|
||||
|
||||
// An XYZ coordinate, general purpose.
|
||||
struct XYZ {
|
||||
float x, y, z;
|
||||
@@ -56,8 +63,9 @@ struct XYZ {
|
||||
XYZ(float ix, float iy, float iz) { x=ix; y=iy; z=iz; }
|
||||
bool operator ==(const XYZ &o) const { return x==o.x && y == o.y && z==o.z; }
|
||||
bool operator !=(const XYZ &o) const { return x!=o.x || y != o.y || z!=o.z; }
|
||||
std::string debug_string() const;
|
||||
};
|
||||
std::ostream & operator << (std::ostream &out, const XYZ &xyz);
|
||||
|
||||
} // namespace util
|
||||
|
||||
#endif // UTIL_HPP
|
||||
|
||||
Reference in New Issue
Block a user