Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*      Copyright (C) 2004 Garrett A. Kajmowicz
  2.  
  3.         This file is part of the uClibc++ Library.
  4.  
  5.         This library is free software; you can redistribute it and/or
  6.         modify it under the terms of the GNU Lesser General Public
  7.         License as published by the Free Software Foundation; either
  8.         version 2.1 of the License, or (at your option) any later version.
  9.  
  10.         This library is distributed in the hope that it will be useful,
  11.         but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.         Lesser General Public License for more details.
  14.  
  15.         You should have received a copy of the GNU Lesser General Public
  16.         License along with this library; if not, write to the Free Software
  17.         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. #include <ios>
  21. #include <cctype>
  22.  
  23. #include <string>
  24.  
  25. #ifndef __STD_HEADER_ISTREAM_HELPERS
  26. #define __STD_HEADER_ISTREAM_HELPERS 1
  27.  
  28. #pragma GCC visibility push(default)
  29.  
  30. namespace std{
  31.  
  32.  
  33.         /* We are making the following template class for serveral reasons.  Firstly,
  34.          * we want to keep the main istream code neat and tidy.  Secondly, we want it
  35.          * to be easy to do partial specialization of the istream code so that it can
  36.          * be expanded and put into the library.  This will allow us to make application
  37.          * code smaller at the expense of increased library size.  This is a fair
  38.          * trade-off when there are multiple applications being compiled.  Also, this
  39.          * feature will be used optionally via configuration options.  It will also
  40.          * allow us to keep the code bases in sync, dramatically simplifying the
  41.          * maintenance required.  We specialized for char because wchar and others
  42.          * require different scanf functions
  43.          */
  44.  
  45.         template <class C, class traits> _UCXXEXPORT
  46.                 basic_string<C, traits> _readToken(basic_istream<C, traits>& stream)
  47.         {
  48.                 basic_string<C, traits> temp;
  49.                 typename traits::int_type c;
  50.                 while(true){
  51.                         c = stream.rdbuf()->sgetc();
  52.                         if(c != traits::eof() && isspace(c) == false){
  53.                                 stream.rdbuf()->sbumpc();
  54.                                 temp.append(1, traits::to_char_type(c));
  55.                         }else{
  56.                                 break;
  57.                         }
  58.                 }
  59.                 if (temp.size() == 0)
  60.                         stream.setstate(ios_base::eofbit|ios_base::failbit);
  61.  
  62.                 return temp;
  63.         }
  64.  
  65.         template <class C, class traits> _UCXXEXPORT
  66.                 basic_string<C, traits> _readTokenDecimal(basic_istream<C, traits>& stream)
  67.         {
  68.                 basic_string<C, traits> temp;
  69.                 typename traits::int_type c;
  70.                 while(true){
  71.                         c = stream.rdbuf()->sgetc();
  72.                         if(c != traits::eof() && isspace(c) == false && (
  73.                                 isdigit(c) ||
  74.                                 c == '.' ||
  75.                                 c == ',' ||
  76.                                 ((c == '-' || c == '+') && temp.size() == 0) )
  77.                         ){
  78.                                 stream.rdbuf()->sbumpc();
  79.                                 temp.append(1, traits::to_char_type(c));
  80.                         }else{
  81.                                 break;
  82.                         }
  83.                 }
  84.                 if (temp.size() == 0)
  85.                         stream.setstate(ios_base::eofbit|ios_base::failbit);
  86.  
  87.                 return temp;
  88.         }
  89.  
  90. #ifdef __UCLIBCXX_EXPAND_ISTREAM_CHAR__
  91.  
  92.         template <> _UCXXEXPORT string _readToken<char, char_traits<char> >(istream & stream);
  93.  
  94. #endif
  95.  
  96.  
  97.         template <class traits, class charT, class dataType> class _UCXXEXPORT __istream_readin{
  98.         public:
  99.                 static void readin(basic_istream<charT,traits>& stream, dataType & var);
  100.         };
  101.  
  102.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, bool>{
  103.         public:
  104.                 inline static void readin(basic_istream<char, traits >& stream, bool & var)
  105.                 {
  106.                         /* 22.4.2.1.2.4 */
  107.                         basic_string<char, traits > temp;
  108.                         temp = _readToken( stream);
  109.                         if (stream.flags() & ios_base::boolalpha) {
  110.                                 if (temp == "true") // truename()
  111.                                         var = true;
  112.                                 else {
  113.                                         var = false;
  114.                                         if (temp != "false") // falsename()
  115.                                                 stream.setstate(ios_base::failbit);
  116.                                 }
  117.                         } else {
  118.                                 long int i = 0;
  119.                                 int ret;
  120.                                 if (stream.flags() & ios_base::dec) {
  121.                                         ret = sscanf(temp.c_str(), "%ld", &i );
  122.                                 } else {
  123.                                         if (stream.flags() & ios_base::oct) {
  124.                                                 ret = sscanf(temp.c_str(), "%lo", (unsigned long int *)(&i));
  125.                                         } else if (stream.flags() & ios_base::hex) {
  126.                                                 if (stream.flags() & ios_base::uppercase) {
  127.                                                         ret = sscanf(temp.c_str(), "%lX", (unsigned long int *)(&i));
  128.                                                 } else {
  129.                                                         ret = sscanf(temp.c_str(), "%lx", (unsigned long int *)(&i));
  130.                                                 }
  131.                                         } else {
  132.                                                 ret = sscanf(temp.c_str(), "%li", &i);
  133.                                         }
  134.                                 }
  135.                                 if (ret != 1 || i >> 1)
  136.                                         stream.setstate(ios_base::failbit);
  137.                                 var = ret == 1 && bool(i);
  138.                         }
  139.                 }
  140.         };
  141.  
  142.  
  143.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, short>{
  144.         public:
  145.                 inline static void readin(basic_istream<char, traits >& stream, short & var)
  146.                 {
  147.                         basic_string<char, traits > temp;
  148.  
  149.                         if(stream.flags() & ios_base::dec){
  150.                                 temp = _readTokenDecimal( stream);
  151.                                 sscanf(temp.c_str(), "%hd", &var );
  152.                         }else{
  153.                                 temp = _readToken( stream);
  154.                                 if( stream.flags() & ios_base::oct){
  155.                                         sscanf(temp.c_str(), "%ho", (unsigned short int *)(&var) );
  156.                                 }else if(stream.flags() & ios_base::hex){
  157.                                         if(stream.flags() & ios_base::uppercase){
  158.                                                 sscanf(temp.c_str(), "%hX", (unsigned short int *)(&var) );
  159.                                         }else{
  160.                                                 sscanf(temp.c_str(), "%hx", (unsigned short int *)(&var) );
  161.                                         }
  162.                                 }else{
  163.                                         sscanf(temp.c_str(), "%hi", &var);
  164.                                 }
  165.                         }
  166.                 }
  167.         };
  168.  
  169.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, unsigned short>{
  170.         public:
  171.                 inline static void readin(basic_istream<char, traits >& stream, unsigned short & var)
  172.                 {
  173.                         basic_string<char, traits > temp;
  174.  
  175.                         if(stream.flags() & ios_base::dec){
  176.                                 temp = _readTokenDecimal( stream);
  177.                                 sscanf(temp.c_str(), "%hu", &var );
  178.                         }else{
  179.                                 temp = _readToken( stream);
  180.                                 if( stream.flags() & ios_base::oct){
  181.                                         sscanf(temp.c_str(), "%ho", &var);
  182.                                 }else if(stream.flags() & ios_base::hex){
  183.                                         if(stream.flags() & ios_base::uppercase){
  184.                                                 sscanf(temp.c_str(), "%hX", &var );
  185.                                         }else{
  186.                                                 sscanf(temp.c_str(), "%hx", &var);
  187.                                         }
  188.                                 }else{
  189.                                         sscanf(temp.c_str(), "%hi", (signed short int*)(&var) );
  190.                                 }
  191.                         }
  192.                 }
  193.         };
  194.  
  195.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, int>{
  196.         public:
  197.                 inline static void readin(basic_istream<char, traits >& stream, int & var)
  198.                 {
  199.                         basic_string<char, traits > temp;
  200.  
  201.                         if(stream.flags() & ios_base::dec){
  202.                                 temp = _readTokenDecimal( stream);
  203.                                 sscanf(temp.c_str(), "%d", &var );
  204.                         }else{
  205.                                 temp = _readToken( stream);
  206.                                 if( stream.flags() & ios_base::oct){
  207.                                         sscanf(temp.c_str(), "%o", (unsigned int *)(&var) );
  208.                                 }else if(stream.flags() & ios_base::hex){
  209.                                         if(stream.flags() & ios_base::uppercase){
  210.                                                 sscanf(temp.c_str(), "%X", (unsigned int *)(&var) );
  211.                                         }else{
  212.                                                 sscanf(temp.c_str(), "%x", (unsigned int *)(&var) );
  213.                                         }
  214.                                 }else{
  215.                                         sscanf(temp.c_str(), "%i", &var);
  216.                                 }
  217.                         }
  218.                 }
  219.         };
  220.  
  221.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, unsigned int>{
  222.         public:
  223.                 inline static void readin(basic_istream<char, traits >& stream, unsigned int & var)
  224.                 {
  225.                         basic_string<char, traits > temp;
  226.  
  227.                         if(stream.flags() & ios_base::dec){
  228.                                 temp = _readTokenDecimal( stream);
  229.                                 sscanf(temp.c_str(), "%u", &var );
  230.                         }else{
  231.                                 temp = _readToken( stream);
  232.                                 if( stream.flags() & ios_base::oct){
  233.                                         sscanf(temp.c_str(), "%o", (unsigned int *)(&var) );
  234.                                 }else if(stream.flags() & ios_base::hex){
  235.                                         if(stream.flags() & ios_base::uppercase){
  236.                                                 sscanf(temp.c_str(), "%X", (unsigned int *)(&var) );
  237.                                         }else{
  238.                                                 sscanf(temp.c_str(), "%x", (unsigned int *)(&var) );
  239.                                         }
  240.                                 }else{
  241.                                         sscanf(temp.c_str(), "%i", (int *)(&var) );
  242.                                 }
  243.                         }
  244.  
  245.                 }
  246.         };
  247.  
  248.  
  249.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, long int>{
  250.         public:
  251.                 inline static void readin(basic_istream<char, traits >& stream, long int & var)
  252.                 {
  253.                         basic_string<char, traits > temp;
  254.  
  255.                         if(stream.flags() & ios_base::dec){
  256.                                 temp = _readTokenDecimal( stream);
  257.                                 sscanf(temp.c_str(), "%ld", &var );
  258.                         }else{
  259.                                 temp = _readToken( stream);
  260.                                 if( stream.flags() & ios_base::oct){
  261.                                         sscanf(temp.c_str(), "%lo", (unsigned long int *)(&var) );
  262.                                 }else if(stream.flags() & ios_base::hex){
  263.                                         if(stream.flags() & ios_base::uppercase){
  264.                                                 sscanf(temp.c_str(), "%lX", (unsigned long int *)(&var) );
  265.                                         }else{
  266.                                                 sscanf(temp.c_str(), "%lx", (unsigned long int *)(&var) );
  267.                                         }
  268.                                 }else{
  269.                                         sscanf(temp.c_str(), "%li", (long int *)(&var) );
  270.                                 }
  271.                         }
  272.  
  273.                 }
  274.         };
  275.  
  276.  
  277.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, unsigned long int>{
  278.         public:
  279.                 inline static void readin(basic_istream<char, traits >& stream, unsigned long int & var)
  280.                 {
  281.                         basic_string<char, traits > temp;
  282.  
  283.                         if(stream.flags() & ios_base::dec){
  284.                                 temp = _readTokenDecimal( stream);
  285.                                 sscanf(temp.c_str(), "%lu", &var );
  286.                         }else{
  287.                                 temp = _readToken( stream);
  288.                                 if( stream.flags() & ios_base::oct){
  289.                                         sscanf(temp.c_str(), "%lo", &var );
  290.                                 }else if(stream.flags() & ios_base::hex){
  291.                                         if(stream.flags() & ios_base::uppercase){
  292.                                                 sscanf(temp.c_str(), "%lX", &var );
  293.                                         }else{
  294.                                                 sscanf(temp.c_str(), "%lx", &var);
  295.                                         }
  296.                                 }else{
  297.                                         sscanf(temp.c_str(), "%li", (long int *)(&var) );
  298.                                 }
  299.                         }
  300.                 }
  301.         };
  302.  
  303.  
  304. #ifdef __UCLIBCXX_HAS_FLOATS__
  305.  
  306.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, float>{
  307.         public:
  308.                 inline static void readin(basic_istream<char, traits >& stream, float & var)
  309.                 {
  310.                         basic_string<char, traits > temp;
  311.                         temp = _readTokenDecimal( stream);
  312.  
  313.                         sscanf(temp.c_str(), "%g", &var);
  314.                 }
  315.         };
  316.  
  317.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, double>{
  318.         public:
  319.                 inline static void readin(basic_istream<char, traits >& stream, double & var)
  320.                 {
  321.                         basic_string<char, traits > temp;
  322.                         temp = _readTokenDecimal( stream);
  323.                         sscanf(temp.c_str(), "%lg", &var);
  324.                 }
  325.         };
  326.  
  327.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, long double>{
  328.         public:
  329.                 inline static void readin(basic_istream<char, traits >& stream, long double & var)
  330.                 {
  331.                         basic_string<char, traits > temp;
  332.                         temp = _readTokenDecimal( stream);
  333.                         sscanf(temp.c_str(), "%Lg", &var);
  334.                 }
  335.         };
  336.  
  337. #endif  // ifdef __UCLIBCXX_HAS_FLOATS__
  338.  
  339.         template <class traits> class _UCXXEXPORT __istream_readin<traits, char, void*>{
  340.         public:
  341.                 inline static void readin(basic_istream<char, traits >& stream, void* & var)
  342.                 {
  343.                         basic_string<char, traits > temp;
  344.                         temp = _readToken( stream);
  345.                         sscanf(temp.c_str(), "%p", &var);
  346.                 }
  347.         };
  348.  
  349.  
  350.         template<class charT, class traits> void __skipws(basic_istream<charT,traits>& is){
  351.                 const typename basic_istream<charT,traits>::int_type eof = traits::eof();
  352.                 typename basic_istream<charT,traits>::int_type c;
  353.                 //While the next character normally read doesn't equal eof
  354.                 //and that character is a space, advance to the next read position
  355.                 //Thus itterating through all whitespace until we get to the meaty stuff
  356.                 while (
  357.                         !traits::eq_int_type((c = is.rdbuf()->sgetc()), eof)
  358.                         && isspace(c)
  359.                 ) {
  360.                         is.rdbuf()->sbumpc();
  361.                 }
  362.                 if(traits::eq_int_type(c, eof)){
  363.                         is.setstate(ios_base::eofbit);
  364.                 }
  365.         }
  366. }
  367.  
  368. #pragma GCC visibility pop
  369.  
  370. #endif
  371.  
  372.  
  373.  
  374.