/* Copyright (C) 2004 Garrett A. Kajmowicz This file is part of the uClibc++ Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #ifndef __STD_HEADER_OSTREAM_HELPERS #define __STD_HEADER_OSTREAM_HELPERS 1 #pragma GCC visibility push(default) namespace std{ /* We are making the following template class for serveral reasons. Firstly, * we want to keep the main ostream code neat and tidy. Secondly, we want it * to be easy to do partial specialization of the ostream code so that it can * be expanded and put into the library. This will allow us to make application * code smaller at the expense of increased library size. This is a fair * trade-off when there are multiple applications being compiled. Also, this * feature will be used optionally via configuration options. It will also * allow us to keep the code bases in sync, dramatically simplifying the * maintenance required. We specialized for char because wchar and others * require different scanf functions */ template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const dataType n); }; template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const signed long int n) { char buffer[20]; const char * c_ld = "%ld"; const char * c_lo = "%lo"; const char * c_lX = "%lX"; const char * c_lx = "%lx"; const char * c_hashlo = "%#lo"; const char * c_hashlX = "%#lX"; const char * c_hashlx = "%#lx"; const char * formatString=0; if( stream.flags() & ios_base::dec){ formatString = c_ld; }else if( stream.flags() & ios_base::oct){ if( stream.flags() & ios_base::showbase){ formatString = c_hashlo; }else{ formatString = c_lo; } }else if (stream.flags() & ios_base::hex){ if(stream.flags() & ios_base::showbase){ if(stream.flags() & ios_base::uppercase){ formatString = c_hashlX; }else{ formatString = c_hashlx; } }else{ if(stream.flags() & ios_base::uppercase){ formatString = c_lX; }else{ formatString = c_lx; } } } stream.write(buffer, snprintf(buffer, 20, formatString, n) ); if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const unsigned long int n) { char buffer[20]; const char * c_lo = "%lo"; const char * c_lu = "%lu"; const char * c_lX = "%lX"; const char * c_lx = "%lx"; const char * c_hashlo = "%#lo"; const char * c_hashlX = "%#lX"; const char * c_hashlx = "%#lx"; const char * formatString=0; if( stream.flags() & ios_base::dec){ formatString = c_lu; }else if( stream.flags() & ios_base::oct){ if( stream.flags() & ios_base::showbase){ formatString = c_hashlo; }else{ formatString = c_lo; } }else if (stream.flags() & ios_base::hex){ if(stream.flags() & ios_base::showbase){ if(stream.flags() & ios_base::uppercase){ formatString = c_hashlX; }else{ formatString = c_hashlx; } }else{ if(stream.flags() & ios_base::uppercase){ formatString = c_lX; }else{ formatString = c_lx; } } } stream.write(buffer, snprintf(buffer, 20, formatString, n)); if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; #ifndef __STRICT_ANSI__ template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const signed long long int n) { char buffer[28]; const char * lld = "%lld"; const char * llo = "%llo"; const char * llX = "%llX"; const char * llx = "%llx"; const char * hashllo = "%#llo"; const char * hashllX = "%#llX"; const char * hashllx = "%#llx"; const char * formatString=0; if( stream.flags() & ios_base::dec){ formatString = lld; }else if( stream.flags() & ios_base::oct){ if( stream.flags() & ios_base::showbase){ formatString = hashllo; }else{ formatString = llo; } }else if (stream.flags() & ios_base::hex){ if(stream.flags() & ios_base::showbase){ if(stream.flags() & ios_base::uppercase){ formatString = hashllX; }else{ formatString = hashllx; } }else{ if(stream.flags() & ios_base::uppercase){ formatString = llX; }else{ formatString = llx; } } } stream.write(buffer, snprintf(buffer, 27, formatString, n) ); if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const unsigned long long int n) { char buffer[28]; const char * llo = "%llo"; const char * llu = "%llu"; const char * llX = "%llX"; const char * llx = "%llx"; const char * hashllo = "%#llo"; const char * hashllX = "%#llX"; const char * hashllx = "%#llx"; const char * formatString=0; if( stream.flags() & ios_base::dec){ formatString = llu; }else if( stream.flags() & ios_base::oct){ if( stream.flags() & ios_base::showbase){ formatString = hashllo; }else{ formatString = llo; } }else if (stream.flags() & ios_base::hex){ if(stream.flags() & ios_base::showbase){ if(stream.flags() & ios_base::uppercase){ formatString = hashllX; }else{ formatString = hashllx; } }else{ if(stream.flags() & ios_base::uppercase){ formatString = llX; }else{ formatString = llx; } } } stream.write(buffer, snprintf(buffer, 27, formatString, n) ); if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; #endif //__STRICT_ANSI__ template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, double f) { char buffer[32]; int length; #ifdef __AVR__ // this is lifted from the Arduino Print class char *ptr=buffer; // Handle negative numbers if (f < 0.0) { *ptr++='-'; f = -f; } int digits=stream.precision(); // Round correctly so that print(1.999, 2) prints as "2.00" double rounding = 0.5; for (uint8_t i=0; i 0) *ptr++='.'; // Extract digits from the remainder one at a time while (digits-- > 0) { remainder *= 10.0; int toPrint = int(remainder); itoa(toPrint,ptr,10); while(*ptr) ptr++; remainder -= toPrint; } length=ptr-buffer; #else if(stream.flags() & ios_base::scientific){ if(stream.flags() & ios_base::uppercase){ length = snprintf(buffer, 32, "%*.*E", static_cast(stream.width()),static_cast(stream.precision()), f); }else{ length = snprintf(buffer, 32, "%*.*e", static_cast(stream.width()),static_cast(stream.precision()), f); } } else if(stream.flags() & ios_base::fixed){ length = snprintf(buffer, 32, "%*.*f",static_cast(stream.width()),static_cast(stream.precision()), f); } else { length = snprintf(buffer, 32, "%*.*g",static_cast(stream.width()),static_cast(stream.precision()), f); } #endif stream.write(buffer, length); if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const long double f) { char buffer[32]; int length; if(stream.flags() & ios_base::scientific){ if(stream.flags() & ios_base::uppercase){ length = snprintf(buffer, 32, "%*.*LE", static_cast(stream.width()), static_cast(stream.precision()), f); }else{ length = snprintf(buffer, 32, "%*.*Le", static_cast(stream.width()), static_cast(stream.precision()), f); } } else if(stream.flags() & ios_base::fixed){ length = snprintf(buffer, 32, "%*.*Lf", static_cast(stream.width()), static_cast(stream.precision()), f); } else { length = snprintf(buffer, 32, "%*.*Lg", static_cast(stream.width()), static_cast(stream.precision()), f); } stream.write(buffer, length); if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; #ifdef __UCLIBCXX_HAS_WCHAR__ template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const signed long int n) { wchar_t buffer[20]; if( stream.flags() & ios_base::dec){ stream.write(buffer, swprintf(buffer, 20, L"%ld", n)); }else if( stream.flags() & ios_base::oct){ if( stream.flags() & ios_base::showbase){ stream.write(buffer, swprintf(buffer, 20, L"%#lo", n)); }else{ stream.write(buffer, swprintf(buffer, 20, L"%lo", n) ); } }else if (stream.flags() & ios_base::hex){ if(stream.flags() & ios_base::showbase){ if(stream.flags() & ios_base::uppercase){ stream.write(buffer, swprintf(buffer, 20, L"%#lX", n) ); }else{ stream.write(buffer, swprintf(buffer, 20, L"%#lx", n) ); } }else{ if(stream.flags() & ios_base::uppercase){ stream.write(buffer, swprintf(buffer, 20, L"%lX", n) ); }else{ stream.write(buffer, swprintf(buffer, 20, L"%lx", n) ); } } } if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const unsigned long int n) { wchar_t buffer[20]; if( stream.flags() & ios_base::dec){ stream.write(buffer, swprintf(buffer, 20, L"%lu", n)); }else if( stream.flags() & ios_base::oct){ if( stream.flags() & ios_base::showbase){ stream.write(buffer, swprintf(buffer, 20, L"%#lo", n)); }else{ stream.write(buffer, swprintf(buffer, 20, L"%lo", n) ); } }else if (stream.flags() & ios_base::hex){ if(stream.flags() & ios_base::showbase){ if(stream.flags() & ios_base::uppercase){ stream.write(buffer, swprintf(buffer, 20, L"%#lX", n) ); }else{ stream.write(buffer, swprintf(buffer, 20, L"%#lx", n) ); } }else{ if(stream.flags() & ios_base::uppercase){ stream.write(buffer, swprintf(buffer, 20, L"%lX", n) ); }else{ stream.write(buffer, swprintf(buffer, 20, L"%lx", n) ); } } } if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; #ifndef __STRICT_ANSI__ template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const signed long long int n) { wchar_t buffer[28]; if( stream.flags() & ios_base::dec){ stream.write(buffer, swprintf(buffer, 27, L"%lld", n)); }else if( stream.flags() & ios_base::oct){ if( stream.flags() & ios_base::showbase){ stream.write(buffer, swprintf(buffer, 27, L"%#llo", n)); }else{ stream.write(buffer, swprintf(buffer, 27, L"%llo", n) ); } }else if (stream.flags() & ios_base::hex){ if(stream.flags() & ios_base::showbase){ if(stream.flags() & ios_base::uppercase){ stream.write(buffer, swprintf(buffer, 27, L"%#llX", n) ); }else{ stream.write(buffer, swprintf(buffer, 27, L"%#llx", n) ); } }else{ if(stream.flags() & ios_base::uppercase){ stream.write(buffer, swprintf(buffer, 27, L"%llX", n) ); }else{ stream.write(buffer, swprintf(buffer, 27, L"%llx", n) ); } } } if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const unsigned long long int n) { wchar_t buffer[28]; if( stream.flags() & ios_base::dec){ stream.write(buffer, swprintf(buffer, 27, L"%llu", n)); }else if( stream.flags() & ios_base::oct){ if( stream.flags() & ios_base::showbase){ stream.write(buffer, swprintf(buffer, 27, L"%#llo", n)); }else{ stream.write(buffer, swprintf(buffer, 27, L"%llo", n) ); } }else if (stream.flags() & ios_base::hex){ if(stream.flags() & ios_base::showbase){ if(stream.flags() & ios_base::uppercase){ stream.write(buffer, swprintf(buffer, 27, L"%#llX", n) ); }else{ stream.write(buffer, swprintf(buffer, 27, L"%#llx", n) ); } }else{ if(stream.flags() & ios_base::uppercase){ stream.write(buffer, swprintf(buffer, 27, L"%llX", n) ); }else{ stream.write(buffer, swprintf(buffer, 27, L"%llx", n) ); } } } if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; #endif //__STRICT_ANSI__ template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const double f) { wchar_t buffer[32]; wchar_t format_string[32]; if(stream.flags() & ios_base::scientific){ if(stream.flags() & ios_base::uppercase){ swprintf(format_string, 32, L"%%%u.%uE", static_cast(stream.width()), static_cast(stream.precision())); }else{ swprintf(format_string, 32, L"%%%u.%ue", static_cast(stream.width()), static_cast(stream.precision())); } } else if(stream.flags() & ios_base::fixed){ swprintf(format_string, 32, L"%%%u.%uf", static_cast(stream.width()), static_cast(stream.precision())); } else { swprintf(format_string, 32, L"%%%u.%ug", static_cast(stream.width()), static_cast(stream.precision())); } stream.write(buffer, swprintf(buffer, 32, format_string, f) ); if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; template class _UCXXEXPORT __ostream_printout{ public: static void printout(basic_ostream& stream, const long double f) { wchar_t buffer[32]; wchar_t format_string[32]; if(stream.flags() & ios_base::scientific){ if(stream.flags() & ios_base::uppercase){ swprintf(format_string, 32, L"%%%u.%uLE", static_cast(stream.width()), static_cast(stream.precision())); }else{ swprintf(format_string, 32, L"%%%u.%uLe", static_cast(stream.width()), static_cast(stream.precision())); } } else if(stream.flags() & ios_base::fixed){ swprintf(format_string, 32, L"%%%u.%uLf", static_cast(stream.width()), static_cast(stream.precision())); } else { swprintf(format_string, 32, L"%%%u.%uLg", static_cast(stream.width()), static_cast(stream.precision())); } stream.write(buffer, swprintf(buffer, 32, format_string, f) ); if(stream.flags() & ios_base::unitbuf){ stream.flush(); } } }; #endif //__UCLIBCXX_HAS_WCHAR__ } #pragma GCC visibility pop #endif