1
/*      Copyright (C) 2004 Garrett A. Kajmowicz
 
 
3
        This file is part of the uClibc++ Library.
 
 
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.
 
 
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.
 
 
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
 
 
25
#ifndef __STD_HEADER_ISTREAM_HELPERS
 
 
26
#define __STD_HEADER_ISTREAM_HELPERS 1
 
 
28
#pragma GCC visibility push(default)
 
 
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
 
 
45
        template <class C, class traits> _UCXXEXPORT 
 
 
46
                basic_string<C, traits> _readToken(basic_istream<C, traits>& stream)
 
 
48
                basic_string<C, traits> temp;
 
 
49
                typename traits::int_type c;
 
 
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));
 
 
60
                        stream.setstate(ios_base::eofbit|ios_base::failbit);
 
 
65
        template <class C, class traits> _UCXXEXPORT 
 
 
66
                basic_string<C, traits> _readTokenDecimal(basic_istream<C, traits>& stream)
 
 
68
                basic_string<C, traits> temp;
 
 
69
                typename traits::int_type c;
 
 
71
                        c = stream.rdbuf()->sgetc();
 
 
72
                        if(c != traits::eof() && isspace(c) == false && (
 
 
76
                                ((c == '-' || c == '+') && temp.size() == 0) )
 
 
78
                                stream.rdbuf()->sbumpc();
 
 
79
                                temp.append(1, traits::to_char_type(c));
 
 
85
                        stream.setstate(ios_base::eofbit|ios_base::failbit);
 
 
90
#ifdef __UCLIBCXX_EXPAND_ISTREAM_CHAR__
 
 
92
        template <> _UCXXEXPORT string _readToken<char, char_traits<char> >(istream & stream);
 
 
97
        template <class traits, class charT, class dataType> class _UCXXEXPORT __istream_readin{
 
 
99
                static void readin(basic_istream<charT,traits>& stream, dataType & var);
 
 
102
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, bool>{
 
 
104
                inline static void readin(basic_istream<char, traits >& stream, bool & var)
 
 
106
                        basic_string<char, traits > temp;
 
 
107
                        temp = _readToken( stream);
 
 
108
                        if(temp == "true" || temp == "True" || temp == "TRUE" || temp == "1"){
 
 
117
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, short>{
 
 
119
                inline static void readin(basic_istream<char, traits >& stream, short & var)
 
 
121
                        basic_string<char, traits > temp;
 
 
123
                        if(stream.flags() & ios_base::dec){
 
 
124
                                temp = _readTokenDecimal( stream);
 
 
125
                                sscanf(temp.c_str(), "%hd", &var );
 
 
127
                                temp = _readToken( stream);
 
 
128
                                if( stream.flags() & ios_base::oct){
 
 
129
                                        sscanf(temp.c_str(), "%ho", (unsigned short int *)(&var) );
 
 
130
                                }else if(stream.flags() & ios_base::hex){
 
 
131
                                        if(stream.flags() & ios_base::uppercase){
 
 
132
                                                sscanf(temp.c_str(), "%hX", (unsigned short int *)(&var) );
 
 
134
                                                sscanf(temp.c_str(), "%hx", (unsigned short int *)(&var) );
 
 
137
                                        sscanf(temp.c_str(), "%hi", &var);
 
 
144
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, unsigned short>{
 
 
146
                inline static void readin(basic_istream<char, traits >& stream, unsigned short & var)
 
 
148
                        basic_string<char, traits > temp;
 
 
150
                        if(stream.flags() & ios_base::dec){
 
 
151
                                temp = _readTokenDecimal( stream);
 
 
152
                                sscanf(temp.c_str(), "%hu", &var );
 
 
154
                                temp = _readToken( stream);
 
 
155
                                if( stream.flags() & ios_base::oct){
 
 
156
                                        sscanf(temp.c_str(), "%ho", &var);
 
 
157
                                }else if(stream.flags() & ios_base::hex){
 
 
158
                                        if(stream.flags() & ios_base::uppercase){
 
 
159
                                                sscanf(temp.c_str(), "%hX", &var );
 
 
161
                                                sscanf(temp.c_str(), "%hx", &var);
 
 
164
                                        sscanf(temp.c_str(), "%hi", (signed short int*)(&var) );
 
 
170
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, int>{
 
 
172
                inline static void readin(basic_istream<char, traits >& stream, int & var)
 
 
174
                        basic_string<char, traits > temp;
 
 
176
                        if(stream.flags() & ios_base::dec){
 
 
177
                                temp = _readTokenDecimal( stream);
 
 
178
                                sscanf(temp.c_str(), "%d", &var );
 
 
180
                                temp = _readToken( stream);
 
 
181
                                if( stream.flags() & ios_base::oct){
 
 
182
                                        sscanf(temp.c_str(), "%o", (unsigned int *)(&var) );
 
 
183
                                }else if(stream.flags() & ios_base::hex){
 
 
184
                                        if(stream.flags() & ios_base::uppercase){
 
 
185
                                                sscanf(temp.c_str(), "%X", (unsigned int *)(&var) );
 
 
187
                                                sscanf(temp.c_str(), "%x", (unsigned int *)(&var) );
 
 
190
                                        sscanf(temp.c_str(), "%i", &var);
 
 
196
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, unsigned int>{
 
 
198
                inline static void readin(basic_istream<char, traits >& stream, unsigned int & var)
 
 
200
                        basic_string<char, traits > temp;
 
 
202
                        if(stream.flags() & ios_base::dec){
 
 
203
                                temp = _readTokenDecimal( stream);
 
 
204
                                sscanf(temp.c_str(), "%u", &var );
 
 
206
                                temp = _readToken( stream);
 
 
207
                                if( stream.flags() & ios_base::oct){
 
 
208
                                        sscanf(temp.c_str(), "%o", (unsigned int *)(&var) );
 
 
209
                                }else if(stream.flags() & ios_base::hex){
 
 
210
                                        if(stream.flags() & ios_base::uppercase){
 
 
211
                                                sscanf(temp.c_str(), "%X", (unsigned int *)(&var) );
 
 
213
                                                sscanf(temp.c_str(), "%x", (unsigned int *)(&var) );
 
 
216
                                        sscanf(temp.c_str(), "%i", (int *)(&var) );
 
 
224
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, long int>{
 
 
226
                inline static void readin(basic_istream<char, traits >& stream, long int & var)
 
 
228
                        basic_string<char, traits > temp;
 
 
230
                        if(stream.flags() & ios_base::dec){
 
 
231
                                temp = _readTokenDecimal( stream);
 
 
232
                                sscanf(temp.c_str(), "%ld", &var );
 
 
234
                                temp = _readToken( stream);
 
 
235
                                if( stream.flags() & ios_base::oct){
 
 
236
                                        sscanf(temp.c_str(), "%lo", (unsigned long int *)(&var) );
 
 
237
                                }else if(stream.flags() & ios_base::hex){
 
 
238
                                        if(stream.flags() & ios_base::uppercase){
 
 
239
                                                sscanf(temp.c_str(), "%lX", (unsigned long int *)(&var) );
 
 
241
                                                sscanf(temp.c_str(), "%lx", (unsigned long int *)(&var) );
 
 
244
                                        sscanf(temp.c_str(), "%li", (long int *)(&var) );
 
 
252
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, unsigned long int>{
 
 
254
                inline static void readin(basic_istream<char, traits >& stream, unsigned long int & var)
 
 
256
                        basic_string<char, traits > temp;
 
 
258
                        if(stream.flags() & ios_base::dec){
 
 
259
                                temp = _readTokenDecimal( stream);
 
 
260
                                sscanf(temp.c_str(), "%lu", &var );
 
 
262
                                temp = _readToken( stream);
 
 
263
                                if( stream.flags() & ios_base::oct){
 
 
264
                                        sscanf(temp.c_str(), "%lo", &var );
 
 
265
                                }else if(stream.flags() & ios_base::hex){
 
 
266
                                        if(stream.flags() & ios_base::uppercase){
 
 
267
                                                sscanf(temp.c_str(), "%lX", &var );
 
 
269
                                                sscanf(temp.c_str(), "%lx", &var);
 
 
272
                                        sscanf(temp.c_str(), "%li", (long int *)(&var) );
 
 
279
#ifdef __UCLIBCXX_HAS_FLOATS__
 
 
281
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, float>{
 
 
283
                inline static void readin(basic_istream<char, traits >& stream, float & var)
 
 
285
                        basic_string<char, traits > temp;
 
 
286
                        temp = _readTokenDecimal( stream);
 
 
287
#if defined (__AVR__) 
 
 
288
                        var = strtod(temp.c_str(), NULL);
 
 
290
                        sscanf(temp.c_str(), "%g", &var);
 
 
296
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, double>{
 
 
298
                inline static void readin(basic_istream<char, traits >& stream, double & var)
 
 
300
                        basic_string<char, traits > temp;
 
 
301
                        temp = _readTokenDecimal( stream);
 
 
302
#if defined (__AVR__)
 
 
303
                        var = strtod(temp.c_str(), NULL);
 
 
305
                        sscanf(temp.c_str(), "%lg", &var);
 
 
310
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, long double>{
 
 
312
                inline static void readin(basic_istream<char, traits >& stream, long double & var)
 
 
314
                        basic_string<char, traits > temp;
 
 
315
                        temp = _readTokenDecimal( stream);
 
 
316
#if defined (__AVR__)
 
 
317
                        var = strtod(temp.c_str(), NULL);
 
 
319
                        sscanf(temp.c_str(), "%Lg", &var);
 
 
324
#endif  // ifdef __UCLIBCXX_HAS_FLOATS__
 
 
326
        template <class traits> class _UCXXEXPORT __istream_readin<traits, char, void*>{
 
 
328
                inline static void readin(basic_istream<char, traits >& stream, void* & var)
 
 
330
                        basic_string<char, traits > temp;
 
 
331
                        temp = _readToken( stream);
 
 
332
                        sscanf(temp.c_str(), "%p", &var);
 
 
337
        template<class charT, class traits> void __skipws(basic_istream<charT,traits>& is){
 
 
338
                const typename basic_istream<charT,traits>::int_type eof = traits::eof();
 
 
339
                typename basic_istream<charT,traits>::int_type c;
 
 
340
                //While the next character normally read doesn't equal eof
 
 
341
                //and that character is a space, advance to the next read position
 
 
342
                //Thus itterating through all whitespace until we get to the meaty stuff
 
 
344
                        !traits::eq_int_type((c = is.rdbuf()->sgetc()), eof)
 
 
348
                        is.rdbuf()->sbumpc();
 
 
350
                if(traits::eq_int_type(c, eof)){
 
 
351
                        is.setstate(ios_base::eofbit);
 
 
356
#pragma GCC visibility pop