Add 'ostream' method to class StreamBuffer, and use it.
This commit is contained in:
@@ -246,6 +246,10 @@ public:
|
|||||||
//
|
//
|
||||||
Channel *get_stdio_channel();
|
Channel *get_stdio_channel();
|
||||||
|
|
||||||
|
// Obtain the output buffer of the stdio channel as an ostream.
|
||||||
|
//
|
||||||
|
std::ostream &stdostream() { return get_stdio_channel()->out()->ostream(); }
|
||||||
|
|
||||||
// Fetches the lua source, and takes ownership of it. The DrivenEngine
|
// Fetches the lua source, and takes ownership of it. The DrivenEngine
|
||||||
// no longer contains the source after calling this.
|
// no longer contains the source after calling this.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include "invocation.hpp"
|
#include "invocation.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
class LpxClient : public DrivenEngine {
|
class LpxClient : public DrivenEngine {
|
||||||
public:
|
public:
|
||||||
@@ -36,15 +35,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void do_lua(const std::string &lua) {
|
void do_lua(const std::string &lua) {
|
||||||
std::cerr << "Lua: " << lua << std::endl;
|
stdostream() << "Lua: " << lua << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_command(const util::StringVec &words) {
|
void do_command(const util::StringVec &words) {
|
||||||
std::cerr << "Command: ";
|
stdostream() << "Command: ";
|
||||||
for (const std::string &word : words) {
|
for (const std::string &word : words) {
|
||||||
std::cerr << word << " ";
|
stdostream() << word << " ";
|
||||||
}
|
}
|
||||||
std::cerr << std::endl;
|
stdostream() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void console_process(const std::string &line) {
|
void console_process(const std::string &line) {
|
||||||
@@ -57,7 +56,7 @@ public:
|
|||||||
do_command(console_.words());
|
do_command(console_.words());
|
||||||
console_.clear();
|
console_.clear();
|
||||||
} else if (action == LuaConsole::DO_SYNTAX) {
|
} else if (action == LuaConsole::DO_SYNTAX) {
|
||||||
std::cerr << console_.syntax() << std::endl;
|
stdostream() << console_.syntax() << std::endl;
|
||||||
console_.clear();
|
console_.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +73,7 @@ public:
|
|||||||
// Check for communication from server..
|
// Check for communication from server..
|
||||||
if (channel_ != nullptr) {
|
if (channel_ != nullptr) {
|
||||||
if (channel_->closed()) {
|
if (channel_->closed()) {
|
||||||
std::cerr << "Server closed connection " << channel_->error() << std::endl;
|
stdostream() << "Server closed connection " << channel_->error() << std::endl;
|
||||||
channel_.reset();
|
channel_.reset();
|
||||||
// stop_driver();
|
// stop_driver();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -477,6 +477,38 @@ void *StreamBuffer::lua_reader_ud(int64_t size) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class StreamBufferWriter : public std::streambuf {
|
||||||
|
private:
|
||||||
|
StreamBuffer *target_;
|
||||||
|
public:
|
||||||
|
StreamBufferWriter(StreamBuffer *t) : target_(t) {}
|
||||||
|
|
||||||
|
virtual int_type overflow(int_type c) {
|
||||||
|
if (c != EOF) {
|
||||||
|
target_->write_uint8(c);
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class StreamBufferOStream : public std::ostream {
|
||||||
|
private:
|
||||||
|
StreamBufferWriter writer_;
|
||||||
|
public:
|
||||||
|
StreamBufferOStream(StreamBuffer *t) : std::ostream(nullptr), writer_(t) {
|
||||||
|
rdbuf(&writer_);
|
||||||
|
}
|
||||||
|
virtual ~StreamBufferOStream() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream &StreamBuffer::ostream() {
|
||||||
|
if (ostream_ == nullptr) {
|
||||||
|
ostream_.reset(new StreamBufferOStream(this));
|
||||||
|
}
|
||||||
|
return *ostream_;
|
||||||
|
}
|
||||||
|
|
||||||
static bool streq(const char *str, const char *data) {
|
static bool streq(const char *str, const char *data) {
|
||||||
int len = strlen(str);
|
int len = strlen(str);
|
||||||
return memcmp(str, data, len) == 0;
|
return memcmp(str, data, len) == 0;
|
||||||
@@ -611,5 +643,11 @@ LuaDefine(unittests_streambuffer, "c") {
|
|||||||
eqsb1.write_int32(34);
|
eqsb1.write_int32(34);
|
||||||
LuaAssert(L, !eqsb1.contents_equal(&eqsb2));
|
LuaAssert(L, !eqsb1.contents_equal(&eqsb2));
|
||||||
|
|
||||||
|
// Check the OStream functionality.
|
||||||
|
StreamBuffer ossb;
|
||||||
|
ossb.ostream() << "Testing.";
|
||||||
|
ossb.ostream() << "Foo.";
|
||||||
|
LuaAssertStrEq(L, ossb.read_entire_contents(), "Testing.Foo.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,6 +387,9 @@ public:
|
|||||||
static const char *lua_reader(lua_State *L, void *data, size_t *size);
|
static const char *lua_reader(lua_State *L, void *data, size_t *size);
|
||||||
void *lua_reader_ud(int64_t bytes);
|
void *lua_reader_ud(int64_t bytes);
|
||||||
|
|
||||||
|
// Get an ostream that writes into the StreamBuffer.
|
||||||
|
std::ostream &ostream();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Start and end of the allocated block.
|
// Start and end of the allocated block.
|
||||||
char *buf_lo_;
|
char *buf_lo_;
|
||||||
@@ -409,6 +412,9 @@ private:
|
|||||||
const char *lua_reader_data_;
|
const char *lua_reader_data_;
|
||||||
int64_t lua_reader_size_;
|
int64_t lua_reader_size_;
|
||||||
|
|
||||||
|
// The ostream. Only allocated on demand.
|
||||||
|
std::unique_ptr<std::ostream> ostream_;
|
||||||
|
|
||||||
// Initialize with a new buffer.
|
// Initialize with a new buffer.
|
||||||
void init(bool fixed, bool owned, char *buf, int64_t size);
|
void init(bool fixed, bool owned, char *buf, int64_t size);
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
|
||||||
#include "luastack.hpp"
|
#include "luastack.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "gui.hpp"
|
#include "gui.hpp"
|
||||||
@@ -52,13 +51,13 @@ public:
|
|||||||
|
|
||||||
void TextGame::do_view_command(const StringVec &cmd) {
|
void TextGame::do_view_command(const StringVec &cmd) {
|
||||||
if (cmd.size() != 1) {
|
if (cmd.size() != 1) {
|
||||||
std::cerr << "v command (view) takes no arguments" << std::endl;
|
stdostream() << "v command (view) takes no arguments" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int64_t id : world_->get_near(actor_id_, 100, true)) {
|
for (int64_t id : world_->get_near(actor_id_, 100, true)) {
|
||||||
const Tangible *tan = world_->tangible_get(id);
|
const Tangible *tan = world_->tangible_get(id);
|
||||||
const AnimStep &aqback = tan->anim_queue_.back();
|
const AnimStep &aqback = tan->anim_queue_.back();
|
||||||
std::cerr << id << ": " << aqback.graphic() << " " << aqback.plane() << " " << aqback.xyz().debug_string() << std::endl;
|
stdostream() << id << ": " << aqback.graphic() << " " << aqback.plane() << " " << aqback.xyz().debug_string() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,14 +68,14 @@ void TextGame::do_menu_command(const StringVec &cmd) {
|
|||||||
} else if (cmd.size() == 2) {
|
} else if (cmd.size() == 2) {
|
||||||
id = util::strtoint(cmd[1], -1);
|
id = util::strtoint(cmd[1], -1);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "m command (menu) expects a tangible ID or defaults to actor_id" << std::endl;
|
stdostream() << "m command (menu) expects a tangible ID or defaults to actor_id" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gui_place_ = id;
|
gui_place_ = id;
|
||||||
world_->update_gui(actor_id_, id, &gui_);
|
world_->update_gui(actor_id_, id, &gui_);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (const GuiElt &elt : gui_.elts()) {
|
for (const GuiElt &elt : gui_.elts()) {
|
||||||
std::cerr << index << " " << elt.label() << std::endl;
|
stdostream() << index << " " << elt.label() << std::endl;
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,16 +85,16 @@ void TextGame::do_choose_command(const StringVec &cmd) {
|
|||||||
if (cmd.size() == 1) {
|
if (cmd.size() == 1) {
|
||||||
index = util::strtoint(cmd[0], -1);
|
index = util::strtoint(cmd[0], -1);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "c command (choose) expects a menu line number" << std::endl;
|
stdostream() << "c command (choose) expects a menu line number" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const Gui::EltVec &elts = gui_.elts();
|
const Gui::EltVec &elts = gui_.elts();
|
||||||
if ((index < 0) || (index >= int(elts.size()))) {
|
if ((index < 0) || (index >= int(elts.size()))) {
|
||||||
std::cerr << "No menu item #" << index << std::endl;
|
stdostream() << "No menu item #" << index << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string action = elts[index].action();
|
std::string action = elts[index].action();
|
||||||
std::cerr << "Invoking plan: " << action << std::endl;
|
stdostream() << "Invoking plan: " << action << std::endl;
|
||||||
InvocationData dummyresult;
|
InvocationData dummyresult;
|
||||||
dummyresult["flavor"] = "chocolate";
|
dummyresult["flavor"] = "chocolate";
|
||||||
dummyresult["color"] = "blue";
|
dummyresult["color"] = "blue";
|
||||||
@@ -112,7 +111,7 @@ void TextGame::do_lua(const std::string &exp) {
|
|||||||
|
|
||||||
void TextGame::do_snapshot_command(const StringVec &cmd) {
|
void TextGame::do_snapshot_command(const StringVec &cmd) {
|
||||||
if (cmd.size() != 1) {
|
if (cmd.size() != 1) {
|
||||||
std::cerr << "s command (snapshot) takes no arguments" << std::endl;
|
stdostream() << "s command (snapshot) takes no arguments" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
world_->snapshot();
|
world_->snapshot();
|
||||||
@@ -120,7 +119,7 @@ void TextGame::do_snapshot_command(const StringVec &cmd) {
|
|||||||
|
|
||||||
void TextGame::do_rollback_command(const StringVec &cmd) {
|
void TextGame::do_rollback_command(const StringVec &cmd) {
|
||||||
if (cmd.size() != 1) {
|
if (cmd.size() != 1) {
|
||||||
std::cerr << "r command (rollback) takes no arguments" << std::endl;
|
stdostream() << "r command (rollback) takes no arguments" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
world_->rollback();
|
world_->rollback();
|
||||||
@@ -131,7 +130,7 @@ void TextGame::do_tick_command(const StringVec &cmd) {
|
|||||||
if (cmd.size() == 2) {
|
if (cmd.size() == 2) {
|
||||||
clock = util::strtoint(cmd[1], -1);
|
clock = util::strtoint(cmd[1], -1);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "t command (tick) expects a time value" << std::endl;
|
stdostream() << "t command (tick) expects a time value" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
world_->run_scheduled_threads(clock);
|
world_->run_scheduled_threads(clock);
|
||||||
@@ -139,7 +138,7 @@ void TextGame::do_tick_command(const StringVec &cmd) {
|
|||||||
|
|
||||||
void TextGame::do_quit_command(const StringVec &cmd) {
|
void TextGame::do_quit_command(const StringVec &cmd) {
|
||||||
if (cmd.size() != 1) {
|
if (cmd.size() != 1) {
|
||||||
std::cerr << "q command (quit) takes no arguments" << std::endl;
|
stdostream() << "q command (quit) takes no arguments" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
actor_id_ = 0;
|
actor_id_ = 0;
|
||||||
@@ -155,7 +154,7 @@ void TextGame::do_command(const StringVec &words) {
|
|||||||
else if (words[0] == "t") do_tick_command(words);
|
else if (words[0] == "t") do_tick_command(words);
|
||||||
else if (util::validinteger(words[0])) do_choose_command(words);
|
else if (util::validinteger(words[0])) do_choose_command(words);
|
||||||
else {
|
else {
|
||||||
std::cerr << "Unknown command: " << words[0] << std::endl;
|
stdostream() << "Unknown command: " << words[0] << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +163,7 @@ void TextGame::check_redirects() {
|
|||||||
for (const auto &p : redir) {
|
for (const auto &p : redir) {
|
||||||
if (p.first == actor_id_) {
|
if (p.first == actor_id_) {
|
||||||
actor_id_ = p.second;
|
actor_id_ = p.second;
|
||||||
std::cerr << "Login actor ID: " << actor_id_ << std::endl;
|
stdostream() << "Login actor ID: " << actor_id_ << std::endl;
|
||||||
gui_.clear();
|
gui_.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,7 +176,7 @@ void TextGame::channel_printbuffer() {
|
|||||||
printbuffer_line_ = printbuffer->first_line();
|
printbuffer_line_ = printbuffer->first_line();
|
||||||
}
|
}
|
||||||
while (printbuffer_line_ < printbuffer->first_unchecked()) {
|
while (printbuffer_line_ < printbuffer->first_unchecked()) {
|
||||||
std::cerr << "* " << printbuffer->nth(printbuffer_line_) << std::endl;
|
stdostream() << "* " << printbuffer->nth(printbuffer_line_) << std::endl;
|
||||||
printbuffer_line_ += 1;
|
printbuffer_line_ += 1;
|
||||||
}
|
}
|
||||||
if (printbuffer_line_ > printbuffer->first_line()) {
|
if (printbuffer_line_ > printbuffer->first_line()) {
|
||||||
@@ -195,7 +194,7 @@ void TextGame::event_init(int argc, char *argv[])
|
|||||||
world_->run_unittests();
|
world_->run_unittests();
|
||||||
actor_id_ = world_->create_login_actor();
|
actor_id_ = world_->create_login_actor();
|
||||||
printbuffer_line_ = 0;
|
printbuffer_line_ = 0;
|
||||||
std::cerr << "Login actor ID: " << actor_id_ << std::endl;
|
stdostream() << "Login actor ID: " << actor_id_ << std::endl;
|
||||||
get_stdio_channel()->out()->write_bytes(console_.get_prompt());
|
get_stdio_channel()->out()->write_bytes(console_.get_prompt());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +215,7 @@ void TextGame::event_update()
|
|||||||
console_.clear();
|
console_.clear();
|
||||||
channel_printbuffer();
|
channel_printbuffer();
|
||||||
} else if (action == LuaConsole::DO_SYNTAX) {
|
} else if (action == LuaConsole::DO_SYNTAX) {
|
||||||
std::cerr << console_.syntax() << std::endl;
|
stdostream() << console_.syntax() << std::endl;
|
||||||
console_.clear();
|
console_.clear();
|
||||||
}
|
}
|
||||||
check_redirects();
|
check_redirects();
|
||||||
|
|||||||
Reference in New Issue
Block a user