Changeset 6371c5bf in mainline


Ignore:
Timestamp:
2018-07-05T21:41:19Z (6 years ago)
Author:
Dzejrou <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
91ba048
Parents:
e7462e6
git-author:
Dzejrou <dzejrou@…> (2017-12-04 15:52:38)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:19)
Message:

cpp: added basic unformatted input to std::istream

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/impl/istream.hpp

    re7462e6 r6371c5bf  
    3030#define LIBCPP_ISTREAM
    3131
     32#include <ios>
    3233#include <iosfwd>
     34#include <limits>
     35#include <locale>
     36#include <ostream>
    3337#include <utility>
    3438
     
    5761                : gcount_{0}
    5862            {
    59                 basic_ios::init(sb);
    60             }
    61 
    62             virtual ~basic_stream()
     63                printf("ISTREAM\n");
     64                basic_ios<Char, Traits>::init(sb);
     65            }
     66
     67            virtual ~basic_istream()
    6368            { /* DUMMY BODY */ }
    6469
     
    8287                            if (!noskipws && ((is.flags() & ios_base::skipws) != 0))
    8388                            {
    84                                 // TODO: implement when we have istream_iterator and locale,
    85                                 //       skip whitespace using is.locale()
     89                                const auto& ct = use_facet<ctype<Char>>(is.getloc());
     90                                while (true)
     91                                {
     92                                    auto i = is.rdbuf()->sgetc();
     93                                    if (Traits::eq_int_type(i, Traits::eof()))
     94                                    {
     95                                        is.setstate(ios_base::failbit | ios_base::eofbit);
     96                                        break;
     97                                    }
     98
     99                                    auto c = Traits::to_char_type(i);
     100                                    if (!ct.is(c, ct.space))
     101                                        break;
     102                                    else
     103                                        is.rdbuf()->sbumpc();
     104                                }
    86105                            }
    87106                        }
     107
     108                        if (is.good())
     109                            ok_ = true;
    88110                    }
    89111
     
    101123                    using traits_type = Traits;
    102124                    bool ok_;
    103             }
     125            };
    104126
    105127            /**
     
    107129             */
    108130
    109             basic_istream<Char, Traits> operator>>(
     131            basic_istream<Char, Traits>& operator>>(
    110132                basic_istream<Char, Traits>& (*pf)(basic_istream<Char, Traits>&)
    111133            )
    112134            {
    113                 // TODO: implement
    114             }
    115 
    116             basic_istream<Char, Traits> operator>>(
     135                return pf(*this);
     136            }
     137
     138            basic_istream<Char, Traits>& operator>>(
    117139                basic_ios<Char, Traits>& (*pf)(basic_ios<Char, Traits>&)
    118140            )
    119141            {
    120                 // TODO: implement
    121             }
    122 
    123             basic_istream<Char, Traits> operator>>(
     142                pf(*this);
     143
     144                return *this;
     145            }
     146
     147            basic_istream<Char, Traits>& operator>>(
    124148                ios_base& (*pf)(ios_base&)
    125149            )
    126150            {
    127                 // TODO: implement
    128             }
    129 
    130             basic_istream<Char, Traits> operator>>(bool& x)
    131             {
    132                 // TODO: implement
    133             }
    134 
    135             basic_istream<Char, Traits> operator>>(short& x)
    136             {
    137                 // TODO: implement
    138             }
    139 
    140             basic_istream<Char, Traits> operator>>(unsigned short& x)
    141             {
    142                 // TODO: implement
    143             }
    144 
    145             basic_istream<Char, Traits> operator>>(int& x)
    146             {
    147                 // TODO: implement
    148             }
    149 
    150             basic_istream<Char, Traits> operator>>(unsigned int& x)
    151             {
    152                 // TODO: implement
    153             }
    154 
    155             basic_istream<Char, Traits> operator>>(long& x)
    156             {
    157                 // TODO: implement
    158             }
    159 
    160             basic_istream<Char, Traits> operator>>(unsigned long& x)
    161             {
    162                 // TODO: implement
    163             }
    164 
    165             basic_istream<Char, Traits> operator>>(long long& x)
    166             {
    167                 // TODO: implement
    168             }
    169 
    170             basic_istream<Char, Traits> operator>>(unsigned long long& x)
    171             {
    172                 // TODO: implement
    173             }
    174 
    175             basic_istream<Char, Traits> operator>>(float& x)
    176             {
    177                 // TODO: implement
    178             }
    179 
    180             basic_istream<Char, Traits> operator>>(double& x)
    181             {
    182                 // TODO: implement
    183             }
    184 
    185             basic_istream<Char, Traits> operator>>(long double& x)
    186             {
    187                 // TODO: implement
    188             }
    189 
    190             basic_istream<Char, Traits> operator>>(void*& p)
    191             {
    192                 // TODO: implement
    193             }
    194 
    195             basic_istream<Char, Traits> operator>>(basic_streambuf<Char, Traits>* sb)
     151                pf(*this);
     152
     153                return *this;
     154            }
     155
     156            basic_istream<Char, Traits>& operator>>(bool& x)
     157            {
     158                // TODO: implement
     159            }
     160
     161            basic_istream<Char, Traits>& operator>>(short& x)
     162            {
     163                // TODO: implement
     164            }
     165
     166            basic_istream<Char, Traits>& operator>>(unsigned short& x)
     167            {
     168                // TODO: implement
     169            }
     170
     171            basic_istream<Char, Traits>& operator>>(int& x)
     172            {
     173                // TODO: implement
     174            }
     175
     176            basic_istream<Char, Traits>& operator>>(unsigned int& x)
     177            {
     178                // TODO: implement
     179            }
     180
     181            basic_istream<Char, Traits>& operator>>(long& x)
     182            {
     183                // TODO: implement
     184            }
     185
     186            basic_istream<Char, Traits>& operator>>(unsigned long& x)
     187            {
     188                // TODO: implement
     189            }
     190
     191            basic_istream<Char, Traits>& operator>>(long long& x)
     192            {
     193                // TODO: implement
     194            }
     195
     196            basic_istream<Char, Traits>& operator>>(unsigned long long& x)
     197            {
     198                // TODO: implement
     199            }
     200
     201            basic_istream<Char, Traits>& operator>>(float& x)
     202            {
     203                // TODO: implement
     204            }
     205
     206            basic_istream<Char, Traits>& operator>>(double& x)
     207            {
     208                // TODO: implement
     209            }
     210
     211            basic_istream<Char, Traits>& operator>>(long double& x)
     212            {
     213                // TODO: implement
     214            }
     215
     216            basic_istream<Char, Traits>& operator>>(void*& p)
     217            {
     218                // TODO: implement
     219            }
     220
     221            basic_istream<Char, Traits>& operator>>(basic_streambuf<Char, Traits>* sb)
    196222            {
    197223                // TODO: implement
     
    200226            /**
    201227             * 27.7.2.3, unformatted input:
     228             * TODO: Once we have exceptions, implement
     229             *       27.7.2.3 paragraph 1.
    202230             */
    203231
     
    209237            int_type get()
    210238            {
    211                 // TODO: implement
     239                gcount_ = 0;
     240                sentry sen{*this, true};
     241
     242                if (sen)
     243                {
     244                    auto res = this->rdbuf()->sbumpc();
     245                    if (!traits_type::eq_int_type(res, traits_type::eof()))
     246                    {
     247                        gcount_ = 1;
     248                        return res;
     249                    }
     250
     251                    this->setstate(ios_base::failbit | ios_base::eofbit);
     252                }
     253
     254                return traits_type::eof();
    212255            }
    213256
    214257            basic_istream<Char, Traits>& get(char_type& c)
    215258            {
    216                 // TODO: implement
     259                auto res = get();
     260                if (res != traits_type::eof())
     261                    c = traits_type::to_char_type(res);
     262
     263                return this;
     264            }
     265
     266            basic_istream<Char, Traits>& get(char_type* s, streamsize n, char_type delim)
     267            {
     268                gcount_ = 0;
     269                sentry sen{*this, true};
     270
     271                if (sen && n > 0)
     272                {
     273                    while(gcount_ < n - 1)
     274                    {
     275                        auto c = this->rdbuf()->sbumpc();
     276
     277                        if (traits_type::eq_int_type(c, traits_type::eof()))
     278                        {
     279                            this->setstate(ios_base::eofbit);
     280                            break;
     281                        }
     282
     283                        s[gcount_++] = traits_type::to_char_type(c);
     284
     285                        auto peek = traits_type::to_char_type(this->rdbuf()->sgetc());
     286                        if (traits_type::eq(peek, delim))
     287                            break;
     288                    }
     289
     290                    if (gcount_ == 0)
     291                        this->setstate(ios_base::failbit);
     292                    s[n] = char_type{};
     293                }
     294
     295                return *this;
    217296            }
    218297
    219298            basic_istream<Char, Traits>& get(char_type* s, streamsize n)
    220299            {
    221                 // TODO: implement
    222             }
    223 
    224             basic_istream<Char, Traits>& get(char_type* s, streamsize n, char_type delim)
    225             {
    226                 // TODO: implement
     300                return get(s, n, this->widen('\n'));
    227301            }
    228302
    229303            basic_istream<Char, Traits>& get(basic_streambuf<Char, Traits>& sb)
    230304            {
    231                 // TODO: implement
     305                get(sb, this->widen('\n'));
    232306            }
    233307
    234308            basic_istream<Char, Traits>& get(basic_streambuf<Char, Traits>& sb, char_type delim)
    235309            {
    236                 // TODO: implement
     310                gcount_ = 0;
     311                sentry sen{*this, true};
     312
     313                if (sen)
     314                {
     315                    while (true)
     316                    {
     317                        auto i = this->rdbuf()->sgetc();
     318                        if (traits_type::eq_int_type(i, traits_type::eof()))
     319                        {
     320                            this->setstate(ios_base::eofbit);
     321                            break;
     322                        }
     323
     324                        auto c = traits_type::to_char_type(i);
     325                        if (traits_type::eq(c, delim))
     326                            break;
     327
     328                        auto insert_ret = sb.sputc(c);
     329                        if (traits_type::eq_int_type(insert_ret, traits_type::eof()))
     330                            break;
     331
     332                        this->rdbuf()->sbumpc();
     333                        ++gcount_;
     334                    }
     335
     336                    if (gcount_ == 0)
     337                        this->setstate(ios_base::failbit);
     338                }
     339
     340                return *this;
    237341            }
    238342
    239343            basic_istream<Char, Traits>& getline(char_type* s, streamsize n)
    240344            {
    241                 // TODO: implement
     345                return getline(s, n, this->widen('\n'));
    242346            }
    243347
    244348            basic_istream<Char, Traits>& getline(char_type* s, streamsize n, char_type delim)
    245349            {
    246                 // TODO: implement
     350                gcount_ = 0;
     351                sentry sen{*this, true};
     352
     353                if (sen)
     354                {
     355                    while (true)
     356                    { // We have exactly specified order of checks, easier to do them in the body.
     357                        auto c = this->rdbuf()->sbumpc();
     358
     359                        if (traits_type::eq_int_type(c, traits_type::eof()))
     360                        {
     361                            this->setstate(ios_base::eofbit);
     362                            break;
     363                        }
     364
     365                        if (traits_type::eq_int_type(c, traits_type::to_int_type(delim)))
     366                            break;
     367
     368                        if (n < 1 || gcount_ >= n - 1)
     369                        {
     370                            this->setstate(ios_base::failbit);
     371                            break;
     372                        }
     373
     374                        s[gcount_++] = traits_type::to_char_type(c);
     375                    }
     376
     377                    if (gcount_ == 0)
     378                        this->setstate(ios_base::failbit);
     379                    if (n > 0)
     380                        s[gcount_] = char_type{};
     381                }
     382
     383                return *this;
    247384            }
    248385
    249386            basic_istream<Char, Traits>& ignore(streamsize n = 1, int_type delim = traits_type::eof())
    250387            {
    251                 // TODO: implement
     388                sentry sen{*this, true};
     389
     390                if (sen)
     391                {
     392                    streamsize i{};
     393                    while (n == numeric_limits<streamsize>::max() || i < n)
     394                    {
     395                        auto c = this->rdbuf()->sbumpc();
     396
     397                        if (traits_type::eq_int_type(c, traits_type::eof()))
     398                        {
     399                            this->setstate(ios_base::eofbit);
     400                            break;
     401                        }
     402
     403                        if (traits_type::eq_int_type(c, delim))
     404                            break;
     405                    }
     406                }
    252407            }
    253408
    254409            int_type peek()
    255410            {
    256                 // TODO: implement
     411                sentry sen{*this, true};
     412
     413                if (!this->good())
     414                    return traits_type::eof();
     415                else
     416                    return this->rdbuf()->sgetc();
    257417            }
    258418
    259419            basic_istream<Char, Traits>& read(char_type* s, streamsize n)
    260420            {
    261                 // TODO: implement
     421                gcount_ = 0;
     422                sentry sen{*this, true};
     423
     424                if (!this->good())
     425                {
     426                    this->setstate(ios_base::failbit);
     427                    return *this;
     428                }
     429
     430                while (gcount_ < n)
     431                {
     432                    auto c = this->rdbuf()->sbumpc();
     433                    if (traits_type::eq_int_type(c, traits_type::eof()))
     434                    {
     435                        this->setstate(ios_base::failbit | ios_base::eofbit);
     436                        break;
     437                    }
     438
     439                    s[gcount_++] = traits_type::to_char_type(c);
     440                }
    262441            }
    263442
    264443            streamsize readsome(char_type* s, streamsize n)
    265444            {
    266                 // TODO: implement
     445                gcount_ = 0;
     446                sentry sen{*this, true};
     447
     448                if (!this->good())
     449                {
     450                    this->setstate(ios_base::failbit);
     451                    return streamsize{};
     452                }
     453
     454                auto avail = this->rdbuf()->in_avail();
     455                if (avail == -1)
     456                {
     457                    this->setstate(ios_base::eofbit);
     458                    return streamsize{};
     459                } else if (avail > 0)
     460                {
     461                    auto count = (avail < n ? avail : n);
     462                    while (gcount_ < count)
     463                        s[gcount_++] = traits_type::to_char_type(this->rdbuf()->sbumpc());
     464                }
     465
     466                return gcount_;
    267467            }
    268468
    269469            basic_istream<Char, Traits>& putback(char_type c)
    270470            {
    271                 // TODO: implement
     471                clear(this->rdstate() & (~ios_base::eofbit));
     472
     473                gcount_ = 0;
     474                sentry sen{*this, true};
     475
     476                if (!this->good())
     477                {
     478                    this->setstate(ios_base::failbit);
     479                    return *this;
     480                }
     481
     482                if (this->rdbuf())
     483                {
     484                    auto ret = this->rdbuf()->sputbackc(c);
     485                    if (traits_type::eq_int_type(ret, traits_type::eof()))
     486                        this->setstate(ios_base::badbit);
     487                }
     488                else
     489                    this->setstate(ios_base::badbit);
     490
     491                return *this;
    272492            }
    273493
    274494            basic_istream<Char, Traits>& unget()
    275495            {
    276                 // TODO: implement
     496                clear(this->rdstate() & (~ios_base::eofbit));
     497
     498                gcount_ = 0;
     499                sentry sen{*this, true};
     500
     501                if (!this->good())
     502                {
     503                    this->setstate(ios_base::failbit);
     504                    return *this;
     505                }
     506
     507                if (this->rdbuf())
     508                {
     509                    auto ret = this->rdbuf()->sungetc();
     510                    if (traits_type::eq_int_type(ret, traits_type::eof()))
     511                        this->setstate(ios_base::badbit);
     512                }
     513                else
     514                    this->setstate(ios_base::badbit);
     515
     516                return *this;
    277517            }
    278518
    279519            int sync()
    280520            {
    281                 // TODO: implement
     521                sentry s{*this, true};
     522
     523                if (this->rdbuf())
     524                {
     525                    auto ret = this->rdbuf()->pubsync();
     526                    if (ret == -1)
     527                    {
     528                        this->setstate(ios_base::badbit);
     529                        return -1;
     530                    }
     531                    else
     532                        return 0;
     533                }
     534                else
     535                    return -1;
    282536            }
    283537
    284538            pos_type tellg()
    285539            {
    286                 // TODO: implement
     540                sentry s{*this, true};
     541
     542                if (this->fail())
     543                    return pos_type(-1);
     544                else
     545                    return this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in);
    287546            }
    288547
    289548            basic_istream<Char, Traits>& seekg(pos_type pos)
    290549            {
    291                 // TODO: implement
    292             }
    293 
    294             basic_istream<Char, Traits>& seekg(off_type off, ios_base::seekdir way)
    295             {
    296                 // TODO: implement
     550                this->clear(this->rdstate() & (~ios_base::eofbit));
     551
     552                sentry sen{*this, true};
     553
     554                if (!this->fail())
     555                    this->rdbuf()->pubseekoff(pos, ios_base::in);
     556                else
     557                    this->setstate(ios_base::failbit);
     558
     559                return *this;
     560            }
     561
     562            basic_istream<Char, Traits>& seekg(off_type off, ios_base::seekdir dir)
     563            {
     564                sentry sen{*this, true};
     565
     566                if (!this->fail())
     567                    this->rdbuf()->pubseekoff(off, dir, ios_base::in);
     568                else
     569                    this->setstate(ios_base::failbit);
     570
     571                return *this;
    297572            }
    298573
     
    306581                gcount_ = rhs.gcout_;
    307582
    308                 basic_ios::move(rhs);
     583                basic_ios<Char, Traits>::move(rhs);
    309584
    310585                rhs.gcount_ = 0;
     
    324599            }
    325600
    326             void swap(basic_stream& rhs)
    327             {
    328                 basic_ios::swap(rhs);
    329                 swap(gcoung_, rhs.gcount_);
     601            void swap(basic_istream& rhs)
     602            {
     603                basic_ios<Char, Traits>::swap(rhs);
     604                swap(gcount_, rhs.gcount_);
    330605            }
    331606    };
     
    377652    }
    378653
     654    /**
     655     * 27.7.2.4, standard basic_istream manipulators:
     656     */
     657
     658    template<class Char, class Traits = char_traits<Char>>
     659    basic_istream<Char, Traits>& ws(basic_istream<Char, Traits>& is)
     660    {
     661        using sentry = typename basic_istream<Char, Traits>::sentry;
     662        sentry sen{is, true};
     663
     664        if (sen)
     665        {
     666            const auto& ct = use_facet<ctype<Char>>(is.getloc());
     667            while (true)
     668            {
     669                auto i = is.rdbuf()->sgetc();
     670                if (Traits::eq_int_type(i, Traits::eof()))
     671                {
     672                    is.setstate(ios_base::eofbit);
     673                    break;
     674                }
     675
     676                auto c = Traits::to_char_type(i);
     677                if (!ct.is(c, ct.space))
     678                    break;
     679                else
     680                    is.rdbuf()->sbumpc();
     681            }
     682        }
     683
     684        return is;
     685    }
     686
    379687    using istream  = basic_istream<char>;
    380688    using wistream = basic_istream<wchar_t>;
    381689
     690    /**
     691     * 27.7.2.5, class template basic_iostream:
     692     */
     693
    382694    template<class Char, class Traits>
    383695    class basic_iostream;
     
    386698    using wiostream = basic_iostream<wchar_t>;
    387699
    388     template<class Char, class Traits = char_traits<Char>>
    389     basic_istream<Char, Traits>& ws(basic_istream<Char, Traits>& is);
    390 
    391     template<class Char, class Tratis = char_traits<Char>>
    392     basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is, T& x);
     700    /**
     701     * 27.7.2.6, rvalue stream extraction:
     702     */
     703
     704    template<class Char, class Traits, class T>
     705    basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>&& is, T& x)
     706    {
     707        is >> x;
     708
     709        return is;
     710    }
    393711}
    394712
Note: See TracChangeset for help on using the changeset viewer.