diff --git a/clients/c_cpp/example.c b/clients/c_cpp/example.c new file mode 100644 index 0000000..21b65b8 --- /dev/null +++ b/clients/c_cpp/example.c @@ -0,0 +1,29 @@ + #include "pipe_io.h" + + +void run2() { + pipe_io pipeio = pipeio_new_io("in", "out"); + const char* line; + while ((line = pipeio_recv_msg(&pipeio.reader))) { + pipeio_send_msg(&pipeio.writer, line); + } + pipeio_close_io(&pipeio); +} + +void msg_handler(const char* msg, void* ctx) { + pipe_writer* writer = (pipe_writer*)(ctx); + pipeio_send_msg(writer, msg); +} + +void run1() { + pipe_io pipeio = pipeio_new_io("in", "out"); + pipeio_set_msg_handler(&pipeio.reader, &msg_handler, &pipeio.writer); + pipeio_run(&pipeio.reader); + pipeio_close_io(&pipeio); +} + +int main() { + run1(); // or run2(); + // note that run1 and run2 do the same thing + // and you can use whichever API you prefer +} diff --git a/clients/c_cpp/example.cpp b/clients/c_cpp/example.cpp new file mode 100644 index 0000000..c8538f1 --- /dev/null +++ b/clients/c_cpp/example.cpp @@ -0,0 +1,13 @@ +#include +#include +#include +#include "pipe_io.hpp" + + +int main() { + PipeIO pipe_io("in", "out"); + pipe_io.reader.set_message_handler( + [&pipe_io](std::string msg){pipe_io.writer.send_message(msg);} + ); + pipe_io.reader.run(); +} diff --git a/clients/c_cpp/pipe_io.h b/clients/c_cpp/pipe_io.h index 09f7023..8289629 100644 --- a/clients/c_cpp/pipe_io.h +++ b/clients/c_cpp/pipe_io.h @@ -9,25 +9,30 @@ typedef struct pipe_reader { FILE* stream; char* line_buf; size_t buf_size; + void (*msg_handler)(const char*, void*); + void* handler_ctx; } pipe_reader; -pipe_reader new_pipe_reader(const char* pipe_path) { +static void null_handler(const char* msg, void* ctx) {} + +pipe_reader pipeio_new_reader(const char* pipe_path) { pipe_reader preader; preader.stream = fopen(pipe_path, "r"); preader.line_buf = NULL; preader.buf_size = 0; + preader.msg_handler = &null_handler; return preader; } -bool check_pipe_reader(const pipe_reader* preader) { +bool pipeio_check_reader(const pipe_reader* preader) { if (!preader || preader->stream == NULL) { return false; } return true; } -const char* recv_msg_pipe_reader(pipe_reader* preader) { - if (!check_pipe_reader(preader)) { +const char* pipeio_recv_msg(pipe_reader* preader) { + if (!pipeio_check_reader(preader)) { return NULL; } ssize_t read = getline(&preader->line_buf, &preader->buf_size, preader->stream); @@ -38,8 +43,22 @@ const char* recv_msg_pipe_reader(pipe_reader* preader) { return NULL; } -void close_pipe_reader(pipe_reader* preader) { - if (!check_pipe_reader(preader)) { +void pipeio_set_msg_handler(pipe_reader* preader, void (*msg_handler)(const char*, void*), void* handler_ctx) { + if (msg_handler != NULL && handler_ctx != NULL) { + preader->msg_handler = msg_handler; + preader->handler_ctx = handler_ctx; + } +} + +void pipeio_run(pipe_reader* preader) { + const char* line; + while ((line = pipeio_recv_msg(preader))) { + (*preader->msg_handler)(line, preader->handler_ctx); + } +} + +void pipeio_close_reader(pipe_reader* preader) { + if (!pipeio_check_reader(preader)) { return; } fclose(preader->stream); @@ -55,21 +74,21 @@ typedef struct pipe_writer { FILE* stream; } pipe_writer; -pipe_writer new_pipe_writer(const char* pipe_path) { +pipe_writer pipeio_new_writer(const char* pipe_path) { pipe_writer pwriter; pwriter.stream = fopen(pipe_path, "w"); return pwriter; } -bool check_pipe_writer(const pipe_writer* pwriter) { +bool pipeio_check_writer(const pipe_writer* pwriter) { if (!pwriter || pwriter->stream == NULL) { return false; } return true; } -bool send_msg_pipe_writer(pipe_writer* pwriter, const char* msg) { - if (!check_pipe_writer(pwriter)) { +bool pipeio_send_msg(pipe_writer* pwriter, const char* msg) { + if (!pipeio_check_writer(pwriter)) { return false; } fprintf(pwriter->stream, "%s\n", msg); @@ -77,8 +96,8 @@ bool send_msg_pipe_writer(pipe_writer* pwriter, const char* msg) { return true; } -void close_pipe_writer(pipe_writer* pwriter) { - if (!check_pipe_writer(pwriter)) { +void pipeio_close_writer(pipe_writer* pwriter) { + if (!pipeio_check_writer(pwriter)) { return; } fclose(pwriter->stream); @@ -87,42 +106,42 @@ void close_pipe_writer(pipe_writer* pwriter) { typedef struct pipe_io { - pipe_reader preader; - pipe_writer pwriter; + pipe_reader reader; + pipe_writer writer; } pipe_io; -pipe_io new_pipe_io(const char* in_pipe_path, const char* out_pipe_path) { +pipe_io pipeio_new_io(const char* in_pipe_path, const char* out_pipe_path) { pipe_io pipeio; - pipeio.preader = new_pipe_reader(in_pipe_path); - pipeio.pwriter = new_pipe_writer(out_pipe_path); + pipeio.reader = pipeio_new_reader(in_pipe_path); + pipeio.writer = pipeio_new_writer(out_pipe_path); return pipeio; } -bool check_pipe_io(const pipe_io* pipeio) { +bool pipeio_check_io(const pipe_io* pipeio) { if (!pipeio) { return false; } - return (check_pipe_reader(&pipeio->preader) && check_pipe_writer(&pipeio->pwriter)); + return (pipeio_check_reader(&pipeio->reader) && pipeio_check_writer(&pipeio->writer)); } -const char* recv_msg_pipe_io(pipe_io* pipeio) { - if (!check_pipe_io(pipeio)) { - return NULL; - } - return recv_msg_pipe_reader(&pipeio->preader); -} - -bool send_msg_pipe_io(pipe_io* pipeio, const char* msg) { - if (!check_pipe_io(pipeio)) { - return false; - } - return send_msg_pipe_writer(&pipeio->pwriter, msg); -} - -void close_pipe_io(pipe_io* pipeio) { - if (!check_pipe_io(pipeio)) { +void pipeio_close_io(pipe_io* pipeio) { + if (!pipeio_check_io(pipeio)) { return; } - close_pipe_reader(&pipeio->preader); - close_pipe_writer(&pipeio->pwriter); + pipeio_close_reader(&pipeio->reader); + pipeio_close_writer(&pipeio->writer); } + +// const char* recv_msg_pipe_io(pipe_io* pipeio) { +// if (!check_pipe_io(pipeio)) { +// return NULL; +// } +// return recv_msg_pipe_reader(&pipeio->preader); +// } + +// bool send_msg_pipe_io(pipe_io* pipeio, const char* msg) { +// if (!check_pipe_io(pipeio)) { +// return false; +// } +// return send_msg_pipe_writer(&pipeio->pwriter, msg); +// } diff --git a/clients/c_cpp/pipe_io.hpp b/clients/c_cpp/pipe_io.hpp index 57ffd8d..da73d9a 100644 --- a/clients/c_cpp/pipe_io.hpp +++ b/clients/c_cpp/pipe_io.hpp @@ -3,15 +3,16 @@ extern "C" { } #include #include +#include class PipeReader { public: - PipeReader(const char* pipe_path) - :preader(new_pipe_reader(pipe_path)) {} + PipeReader(const std::string& pipe_path) + :preader(pipeio_new_reader(pipe_path.c_str())) {} virtual ~PipeReader() { - close_pipe_reader(&this->preader); + pipeio_close_reader(&this->preader); } PipeReader(PipeReader&) = delete; @@ -19,31 +20,34 @@ public: PipeReader& operator=(const PipeReader&) = delete; PipeReader& operator=(const PipeReader&&) = delete; + void set_message_handler(std::function message_handler) { + this->message_handler = message_handler; + } + void run() { while (const char* linebuf = this->recv_message()) { std::string msg(linebuf); - this->handle_message(msg); + this->message_handler(msg); } } const char* recv_message() { - return recv_msg_pipe_reader(&this->preader); + return pipeio_recv_msg(&this->preader); } - virtual void handle_message(std::string msg) {} - private: pipe_reader preader; + std::function message_handler = [](std::string){}; }; class PipeWriter { public: - PipeWriter(const char* pipe_path) - :pwriter(new_pipe_writer(pipe_path)) {} + PipeWriter(const std::string& pipe_path) + :pwriter(pipeio_new_writer(pipe_path.c_str())) {} virtual ~PipeWriter() { - close_pipe_writer(&this->pwriter); + pipeio_close_writer(&this->pwriter); } PipeWriter(PipeReader&) = delete; @@ -52,7 +56,7 @@ public: PipeWriter& operator=(const PipeReader&&) = delete; void send_message(std::string msg) { - send_msg_pipe_writer(&this->pwriter, msg.c_str()); + pipeio_send_msg(&this->pwriter, msg.c_str()); } private: @@ -60,10 +64,13 @@ private: }; -class PipeIO : public PipeReader, public PipeWriter { +class PipeIO { public: - PipeIO(const char* in_pipe_path, const char* out_pipe_path) - :PipeReader(in_pipe_path), PipeWriter(out_pipe_path) {} + PipeReader reader; + PipeWriter writer; + + PipeIO(const std::string& in_pipe_path, const std::string& out_pipe_path) + :reader(in_pipe_path), writer(out_pipe_path) {} PipeIO(PipeReader&) = delete; PipeIO(PipeReader&&) = delete; diff --git a/clients/c_cpp/test.c b/clients/c_cpp/test.c deleted file mode 100644 index 020ec3a..0000000 --- a/clients/c_cpp/test.c +++ /dev/null @@ -1,11 +0,0 @@ - #include "pipe_io.h" - - -int main() { - pipe_io pipeio = new_pipe_io("in", "out"); - const char* line; - while ((line = read_line_pipe_io(&pipeio))) { - send_msg_pipe_io(&pipeio, line); - } - close_pipe_io(&pipeio); -} diff --git a/clients/c_cpp/test.cpp b/clients/c_cpp/test.cpp deleted file mode 100644 index 4878391..0000000 --- a/clients/c_cpp/test.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include -#include "pipe_io.hpp" - - -class EchoPipeIO : public PipeIO { - using PipeIO::PipeIO; - - virtual void handle_message(std::string msg) override { - this->send_message(msg); - } -}; - - -int main() { - EchoPipeIO echo_pipe_io("in", "out"); - echo_pipe_io.run(); -} diff --git a/clients/csharp/Test.cs b/clients/csharp/Example.cs similarity index 65% rename from clients/csharp/Test.cs rename to clients/csharp/Example.cs index 2129ced..503e8e3 100644 --- a/clients/csharp/Test.cs +++ b/clients/csharp/Example.cs @@ -7,8 +7,8 @@ class Program { using (var t = new PipeIO("in", "out")) { - t.reader.OnMessage += (String msg) => t.writer.SendMessage(msg); - t.reader.Run(); + t.Reader.OnMessage += (String msg) => t.Writer.SendMessage(msg); + t.Reader.Run(); } } } diff --git a/clients/csharp/PipeIO.cs b/clients/csharp/PipeIO.cs index 820a647..1ba7e61 100644 --- a/clients/csharp/PipeIO.cs +++ b/clients/csharp/PipeIO.cs @@ -65,19 +65,19 @@ namespace Pipe.IO public class PipeIO : IDisposable { - public PipeReader reader; - public PipeWriter writer; + public PipeReader Reader; + public PipeWriter Writer; public PipeIO(String in_pipe_path, String out_pipe_path) { - this.reader = new PipeReader(in_pipe_path); - this.writer = new PipeWriter(out_pipe_path); + this.Reader = new PipeReader(in_pipe_path); + this.Writer = new PipeWriter(out_pipe_path); } public void Dispose() { - this.reader.Dispose(); - this.writer.Dispose(); + this.Reader.Dispose(); + this.Writer.Dispose(); } } } diff --git a/clients/go/test.go b/clients/go/example.go similarity index 73% rename from clients/go/test.go rename to clients/go/example.go index 8ea1eb5..8558d67 100644 --- a/clients/go/test.go +++ b/clients/go/example.go @@ -13,8 +13,8 @@ func main() { } defer pipeio.Close() - pipeio.HandleMessage(func(msg []byte) { + pipeio.Reader.SetMessageHandler(func(msg []byte) { pipeio.Writer.SendMessage(msg) }) - pipeio.Run() + pipeio.Reader.Run() } diff --git a/clients/go/pipeio/pipeio.go b/clients/go/pipeio/pipeio.go index 83f2403..c93e49e 100644 --- a/clients/go/pipeio/pipeio.go +++ b/clients/go/pipeio/pipeio.go @@ -9,8 +9,11 @@ import ( type pipeReader struct { pipe *os.File scanner *bufio.Scanner + messageHandler messageHandlerFunc } +type messageHandlerFunc func([]byte) + func NewPipeReader(pipePath string) (*pipeReader, error) { pipe, err := os.Open(pipePath) scanner := bufio.NewScanner(pipe) @@ -21,9 +24,28 @@ func NewPipeReader(pipePath string) (*pipeReader, error) { return &pipeReader{ pipe: pipe, scanner: scanner, + messageHandler: func([]byte){}, }, nil } +func (preader *pipeReader) Close() { + preader.pipe.Close() +} + +func (preader *pipeReader) SetMessageHandler(fun messageHandlerFunc) { + preader.messageHandler = fun +} + +func (preader *pipeReader) Run() { + for { + msg := preader.RecvMessage() + if msg == nil { + break + } + preader.messageHandler(msg) + } +} + func (preader *pipeReader) RecvMessage() []byte { if preader.scanner.Scan() { return preader.scanner.Bytes() @@ -31,10 +53,6 @@ func (preader *pipeReader) RecvMessage() []byte { return nil } -func (preader *pipeReader) Close() { - preader.pipe.Close() -} - type pipeWriter struct { pipe *os.File @@ -60,11 +78,8 @@ func (pwriter *pipeWriter) SendMessage(msg []byte) { type pipeIO struct { Reader pipeReader Writer pipeWriter - handleMessage handleMessageFunc } -type handleMessageFunc func([]byte) - func NewPipeIO(inPipePath, outPipePath string) (*pipeIO, error) { reader, err := NewPipeReader(inPipePath) if err != nil { @@ -77,7 +92,6 @@ func NewPipeIO(inPipePath, outPipePath string) (*pipeIO, error) { return &pipeIO{ Reader: *reader, Writer: *writer, - handleMessage: func([]byte){}, }, nil } @@ -85,17 +99,3 @@ func (pipeio *pipeIO) Close() { pipeio.Reader.Close() pipeio.Writer.Close() } - -func (pipeio *pipeIO) Run() { - for { - msg := pipeio.Reader.RecvMessage() - if msg == nil { - break - } - pipeio.handleMessage(msg) - } -} - -func (pipeio *pipeIO) HandleMessage(fun handleMessageFunc) { - pipeio.handleMessage = fun -} diff --git a/clients/java/Example.java b/clients/java/Example.java new file mode 100644 index 0000000..359e615 --- /dev/null +++ b/clients/java/Example.java @@ -0,0 +1,13 @@ +public class Example { + public static void main(String[] args) { + try (PipeIO pipeio = new PipeIO("in", "out")) { + pipeio.reader.setMessageHandler(new MessageHandler(){ + @Override + public void call(String msg) { + pipeio.writer.sendMessage(msg); + } + }); + pipeio.reader.run(); + } + } +} diff --git a/clients/java/MessageHandler.java b/clients/java/MessageHandler.java new file mode 100644 index 0000000..7af755e --- /dev/null +++ b/clients/java/MessageHandler.java @@ -0,0 +1,3 @@ +public interface MessageHandler { + public void call(String msg); +} diff --git a/clients/java/PipeIO.java b/clients/java/PipeIO.java index b9e8702..f7b5920 100644 --- a/clients/java/PipeIO.java +++ b/clients/java/PipeIO.java @@ -2,25 +2,16 @@ import java.io.IOException; public class PipeIO implements AutoCloseable { - protected PipeReader reader; - protected PipeWriter writer; + public PipeReader reader; + public PipeWriter writer; - public PipeIO(String in_pipe_path, String out_pipe_path) throws IOException { + public PipeIO(String in_pipe_path, String out_pipe_path) { this.reader = new PipeReader(in_pipe_path); this.writer = new PipeWriter(out_pipe_path); } - public void close() throws IOException { + public void close() { this.reader.close(); this.writer.close(); } - - public void run() throws IOException { - String msg; - while ((msg = this.reader.recvMessage()) != null) { - this.handleMessage(msg); - } - } - - public void handleMessage(String msg) throws IOException {} } diff --git a/clients/java/PipeReader.java b/clients/java/PipeReader.java index b83f11b..e59d918 100644 --- a/clients/java/PipeReader.java +++ b/clients/java/PipeReader.java @@ -1,21 +1,50 @@ import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; +import java.io.UncheckedIOException; import java.lang.AutoCloseable; public class PipeReader implements AutoCloseable { private BufferedReader pipe; + private MessageHandler messageHandler; - public PipeReader(String pipe_path) throws IOException { - this.pipe = new BufferedReader(new FileReader(pipe_path)); + public PipeReader(String pipe_path) { + try { + this.pipe = new BufferedReader(new FileReader(pipe_path)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + this.messageHandler = new MessageHandler(){ + @Override + public void call(String msg) {} + }; } - public void close() throws IOException { - this.pipe.close(); + public void close() { + try { + this.pipe.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } - public String recvMessage() throws IOException { - return this.pipe.readLine(); + public void setMessageHandler(MessageHandler handler) { + this.messageHandler = handler; + } + + public void run() { + String msg; + while ((msg = this.recvMessage()) != null) { + this.messageHandler.call(msg); + } + } + + public String recvMessage() { + try { + return this.pipe.readLine(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } } diff --git a/clients/java/PipeWriter.java b/clients/java/PipeWriter.java index 1329a38..a232ebe 100644 --- a/clients/java/PipeWriter.java +++ b/clients/java/PipeWriter.java @@ -1,22 +1,35 @@ import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; +import java.io.UncheckedIOException; import java.lang.AutoCloseable; public class PipeWriter implements AutoCloseable { private BufferedWriter pipe; - public PipeWriter(String pipe_path) throws IOException { - this.pipe = new BufferedWriter(new FileWriter(pipe_path)); + public PipeWriter(String pipe_path) { + try { + this.pipe = new BufferedWriter(new FileWriter(pipe_path)); + } catch(IOException e) { + throw new UncheckedIOException(e); + } } - public void close() throws IOException { - this.pipe.close(); + public void close() { + try { + this.pipe.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } - public void sendMessage(String msg) throws IOException { - this.pipe.write(msg + "\n"); - this.pipe.flush(); + public void sendMessage(String msg) { + try { + this.pipe.write(msg + "\n"); + this.pipe.flush(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } } diff --git a/clients/java/Test.java b/clients/java/Test.java deleted file mode 100644 index 9f936de..0000000 --- a/clients/java/Test.java +++ /dev/null @@ -1,22 +0,0 @@ -import java.io.IOException; - - -public class Test extends PipeIO { - public Test(String in_pipe_path, String out_pipe_path) throws IOException { - super(in_pipe_path, out_pipe_path); - } - - @Override - public void handleMessage(String msg) throws IOException { - this.writer.sendMessage(msg); - } - - public static void main(String[] args) { - try(Test test = new Test("in", "out")) { - test.run(); - } - catch (IOException e) { - e.printStackTrace(); - } - } -}