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