1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 //
3 // Rstreambuf.h: Rcpp R/C++ interface class library -- stream buffer
4 //
5 // Copyright (C) 2011 - 2020  Dirk Eddelbuettel, Romain Francois and Jelmer Ypma
6 // Copyright (C) 2021         Dirk Eddelbuettel, Romain Francois, Jelmer Ypma and Iñaki Ucar
7 //
8 // This file is part of Rcpp.
9 //
10 // Rcpp is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // Rcpp is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.
22 
23 #ifndef RCPP__IOSTREAM__RSTREAMBUF_H
24 #define RCPP__IOSTREAM__RSTREAMBUF_H
25 
26 #include <cstdio>
27 #include <streambuf>
28 
29 namespace Rcpp {
30 
31     template <bool OUTPUT>
32     class Rstreambuf : public std::streambuf {
33     public:
Rstreambuf()34         Rstreambuf(){}
35 
36     protected:
37         virtual std::streamsize xsputn(const char *s, std::streamsize n);
38 
39         virtual int overflow(int c = traits_type::eof());
40 
41         virtual int sync();
42     };
43 
44     template <bool OUTPUT>
45     class Rostream : public std::ostream {
46         typedef Rstreambuf<OUTPUT> Buffer;
47         Buffer buf;
48     public:
Rostream()49         Rostream() : std::ostream( &buf ) {}
50     };
51 							// #nocov start
xsputn(const char * s,std::streamsize num)52     template <> inline std::streamsize Rstreambuf<true>::xsputn(const char *s, std::streamsize num) {
53         Rprintf("%.*s", num, s);
54         return num;
55     }
xsputn(const char * s,std::streamsize num)56     template <> inline std::streamsize Rstreambuf<false>::xsputn(const char *s, std::streamsize num) {
57         REprintf("%.*s", num, s);
58         return num;
59     }
60 
overflow(int c)61     template <> inline int Rstreambuf<true>::overflow(int c) {
62         if (c != traits_type::eof()) {
63             char_type ch = traits_type::to_char_type(c);
64             return xsputn(&ch, 1) == 1 ? c : traits_type::eof();
65         }
66         return c;
67     }
overflow(int c)68     template <> inline int Rstreambuf<false>::overflow(int c) {
69         if (c != traits_type::eof()) {
70             char_type ch = traits_type::to_char_type(c);
71             return xsputn(&ch, 1) == 1 ? c : traits_type::eof();
72         }
73         return c;
74     }
75 
sync()76     template <> inline int Rstreambuf<true>::sync() {
77         ::R_FlushConsole();
78         return 0;
79     }
sync()80     template <> inline int Rstreambuf<false>::sync() {
81         ::R_FlushConsole();
82         return 0;
83     }								// #nocov end
84 
85 #ifdef RCPP_USE_GLOBAL_ROSTREAM
86     extern Rostream<true>&  Rcout;
87     extern Rostream<false>& Rcerr;
88 #else
89     static Rostream<true>   Rcout;
90     static Rostream<false>  Rcerr;
91 #endif
92 
93 }
94 
95 #endif
96