Skip to content

Instantly share code, notes, and snippets.

@cjxgm
Last active August 29, 2015 14:22
Show Gist options
  • Save cjxgm/c74cdd00549b7d7e218a to your computer and use it in GitHub Desktop.
Save cjxgm/c74cdd00549b7d7e218a to your computer and use it in GitHub Desktop.
tag stack with hash identifier
#include <string> // with std::hash<std::string>
#include <utility> // for std::move
#include <sstream>
#include <vector>
#include <iomanip> // for std::quoted
namespace tag_stack_detail
{
struct tag_stack
{
void push(std::string const& x) { push_formatted(format(x)); }
void pop() { stack.pop_back(); }
auto& top() const { return stack.back(); }
auto top_id() const { return hash(top()); }
operator bool () const { return stack.size(); }
private:
std::vector<std::string> stack;
std::hash<std::string> hash;
void push_formatted(std::string x)
{
if (stack.size()) x = top() + x;
stack.emplace_back(std::move(x));
}
static std::string format(std::string const& x)
{
std::ostringstream ss;
ss << std::quoted(x, '/');
auto s = ss.str();
s.pop_back();
return s;
}
};
}
using tag_stack_detail::tag_stack;
//-------------------------- testing ------------------------------
#include <iostream>
#include <functional>
using std::cerr;
namespace
{
struct scope_guard
{
using destructor = std::function<void ()>;
scope_guard(destructor dtor) : dtor{std::move(dtor)} {}
~scope_guard() { dtor(); }
auto cancel() { return std::move(dtor); }
// only movable
scope_guard(scope_guard &&) = default;
scope_guard(scope_guard const&) = delete;
scope_guard& operator = (scope_guard &&) = default;
scope_guard& operator = (scope_guard const&) = delete;
private:
const destructor dtor;
};
void inspect(tag_stack const& ts)
{
constexpr auto pointer_size = sizeof(void*);
cerr << std::setw(2*pointer_size) << std::setfill('0')
<< std::hex << ts.top_id() << ": " << ts.top() << "\n";
}
scope_guard push(tag_stack& ts, std::string const& x)
{
ts.push(x);
cerr << "push ";
inspect(ts);
return {[&ts] {
cerr << "pop ";
inspect(ts);
ts.pop();
}};
}
auto push(tag_stack& ts, int x) { return push(ts, std::to_string(x)); }
}
int main()
{
tag_stack ts;
auto _1 = push(ts, R"tag(gar/ba\ge)tag");
auto _2 = push(ts, R"tag(tree)tag");
auto _3 = push(ts, R"tag(node)tag");
for (int i=0; i<10; i++)
push(ts, i);
}
push 3d90e898df906cc4: /gar\/ba\\ge
push fb3a3017c9f99f73: /gar\/ba\\ge/tree
push 19964e57ac82223e: /gar\/ba\\ge/tree/node
push 4fd535267d400fc6: /gar\/ba\\ge/tree/node/0
pop 4fd535267d400fc6: /gar\/ba\\ge/tree/node/0
push e10651048e5e484c: /gar\/ba\\ge/tree/node/1
pop e10651048e5e484c: /gar\/ba\\ge/tree/node/1
push 0a46755946cb5c1a: /gar\/ba\\ge/tree/node/2
pop 0a46755946cb5c1a: /gar\/ba\\ge/tree/node/2
push 2036d911db5cf454: /gar\/ba\\ge/tree/node/3
pop 2036d911db5cf454: /gar\/ba\\ge/tree/node/3
push 1cf920d039696c48: /gar\/ba\\ge/tree/node/4
pop 1cf920d039696c48: /gar\/ba\\ge/tree/node/4
push 4b4a2f69ca0b9a5c: /gar\/ba\\ge/tree/node/5
pop 4b4a2f69ca0b9a5c: /gar\/ba\\ge/tree/node/5
push ee14365926808a2b: /gar\/ba\\ge/tree/node/6
pop ee14365926808a2b: /gar\/ba\\ge/tree/node/6
push 44d58e7c66a68c24: /gar\/ba\\ge/tree/node/7
pop 44d58e7c66a68c24: /gar\/ba\\ge/tree/node/7
push 0a4981f430bf6ba2: /gar\/ba\\ge/tree/node/8
pop 0a4981f430bf6ba2: /gar\/ba\\ge/tree/node/8
push cf2375ead1618810: /gar\/ba\\ge/tree/node/9
pop cf2375ead1618810: /gar\/ba\\ge/tree/node/9
pop 19964e57ac82223e: /gar\/ba\\ge/tree/node
pop fb3a3017c9f99f73: /gar\/ba\\ge/tree
pop 3d90e898df906cc4: /gar\/ba\\ge
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment