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