From patchwork Sat Sep 23 06:54:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Ovtchenkov X-Patchwork-Id: 817769 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-462818-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="vyjjUXER"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xzhN93zPbz9s9Y for ; Sat, 23 Sep 2017 17:11:18 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:from:date:subject:to:cc; q=dns; s=default; b=Fgyt6uB Uhbspm8o8gdXConaYSqQY515qoZ+qHjzxbt7VNjDSKcnbqMPZPOZ1iDWkwP9WJnp K3NRMFRq3/aNHLG0LtDNWtrxn8zlsbSI+Z0qznb8UqZCLpALXCobMHx9wRG7eiTD lpJVRVKI5lLwOrGBBz+VRsqwXPuse2zKtHjU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:from:date:subject:to:cc; s=default; bh=InDhz0y3HvrD3 MH5aulf7qJ5nUI=; b=vyjjUXERCK2ksriNPQ/rBlQQzKIlpe5A0EuLKrRupcrKF MJ0YhuLWJ0NdXLMYh/4hrJLuhPVtDJYcf/axnhSE+IK/myxlsFcuOB9nZXAlaZZo aDEE0B6UhaVME3wVoa7eKTmA2W3LMNpueDcgBcqIY6pcwWPC34i2NbPQiVf1pE= Received: (qmail 12540 invoked by alias); 23 Sep 2017 07:10:59 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 12514 invoked by uid 89); 23 Sep 2017 07:10:57 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-22.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_INFOUSMEBIZ, KAM_LAZY_DOMAIN_SECURITY, RDNS_DYNAMIC autolearn=ham version=3.3.2 spammy=H*m:info, H*MI:info, life, H*F:D*info X-Spam-User: qpsmtpd, 2 recipients X-HELO: void-ptr.info Received: from pppoe.185.44.68.223.lanport.ru (HELO void-ptr.info) (185.44.68.223) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 23 Sep 2017 07:10:55 +0000 Received: from ptr by void-ptr.info with local (Exim 4.72) (envelope-from ) id 1dveaR-0006O7-My; Sat, 23 Sep 2017 10:10:51 +0300 Message-Id: From: Petr Ovtchenkov Date: Sat, 23 Sep 2017 09:54:03 +0300 Subject: [PATCH] libstdc++: istreambuf_iterator keep attached streambuf To: libstdc++@gcc.gnu.org Cc: gcc-patches@gcc.gnu.org X-IsSubscribed: yes istreambuf_iterator should not forget about attached streambuf when it reach EOF. Checks in debug mode has no infuence more on character extraction in istreambuf_iterator increment operators. In this aspect behaviour in debug and non-debug mode is similar now. Test for detached srteambuf in istreambuf_iterator: When istreambuf_iterator reach EOF of istream, it should not forget about attached streambuf. From fact "EOF in stream reached" not follow that stream reach end of life and input operation impossible more. --- libstdc++-v3/include/bits/streambuf_iterator.h | 41 +++++++-------- .../24_iterators/istreambuf_iterator/3.cc | 61 ++++++++++++++++++++++ 2 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/3.cc diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h index f0451b1..45c3d89 100644 --- a/libstdc++-v3/include/bits/streambuf_iterator.h +++ b/libstdc++-v3/include/bits/streambuf_iterator.h @@ -136,12 +136,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION istreambuf_iterator& operator++() { - __glibcxx_requires_cond(!_M_at_eof(), + __glibcxx_requires_cond(_M_sbuf, _M_message(__gnu_debug::__msg_inc_istreambuf) ._M_iterator(*this)); if (_M_sbuf) { +#ifdef _GLIBCXX_DEBUG_PEDANTIC + int_type _tmp = +#endif _M_sbuf->sbumpc(); +#ifdef _GLIBCXX_DEBUG_PEDANTIC + __glibcxx_requires_cond(!traits_type::eq_int_type(_tmp,traits_type::eof()), + _M_message(__gnu_debug::__msg_inc_istreambuf) + ._M_iterator(*this)); +#endif _M_c = traits_type::eof(); } return *this; @@ -151,14 +159,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION istreambuf_iterator operator++(int) { - __glibcxx_requires_cond(!_M_at_eof(), + _M_get(); + __glibcxx_requires_cond(_M_sbuf + && !traits_type::eq_int_type(_M_c,traits_type::eof()), _M_message(__gnu_debug::__msg_inc_istreambuf) ._M_iterator(*this)); istreambuf_iterator __old = *this; if (_M_sbuf) { - __old._M_c = _M_sbuf->sbumpc(); + _M_sbuf->sbumpc(); _M_c = traits_type::eof(); } return __old; @@ -177,18 +187,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_get() const { const int_type __eof = traits_type::eof(); - int_type __ret = __eof; - if (_M_sbuf) - { - if (!traits_type::eq_int_type(_M_c, __eof)) - __ret = _M_c; - else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()), - __eof)) - _M_c = __ret; - else - _M_sbuf = 0; - } - return __ret; + if (_M_sbuf && traits_type::eq_int_type(_M_c, __eof)) + _M_c = _M_sbuf->sgetc(); + return _M_c; } bool @@ -339,7 +340,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename __is_iterator_type::streambuf_type streambuf_type; typedef typename traits_type::int_type int_type; - if (__first._M_sbuf && !__last._M_sbuf) + if (__first._M_sbuf && (__last == istreambuf_iterator<_CharT>())) { streambuf_type* __sb = __first._M_sbuf; int_type __c = __sb->sgetc(); @@ -374,7 +375,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename __is_iterator_type::streambuf_type streambuf_type; typedef typename traits_type::int_type int_type; - if (__first._M_sbuf && !__last._M_sbuf) + if (__first._M_sbuf && (__last == istreambuf_iterator<_CharT>())) { const int_type __ival = traits_type::to_int_type(__val); streambuf_type* __sb = __first._M_sbuf; @@ -395,11 +396,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else __c = __sb->snextc(); } - - if (!traits_type::eq_int_type(__c, traits_type::eof())) - __first._M_c = __c; - else - __first._M_sbuf = 0; + __first._M_c = __c; } return __first; } diff --git a/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/3.cc b/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/3.cc new file mode 100644 index 0000000..803ede4 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/3.cc @@ -0,0 +1,61 @@ +// { dg-options "-std=gnu++17" } + +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, 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 General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include +#include +#include + +void test03() +{ + using namespace std; + bool test __attribute__((unused)) = true; + + std::stringstream s; + char b[] = "c2ee3d09-43b3-466d-b490-db35999a22cf"; + char r[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + char q[] = "3c4852d6-d47b-4f46-b05e-b5edc1aa440e"; + // 012345678901234567890123456789012345 + // 0 1 2 3 + s << b; + VERIFY( !s.fail() ); + + istreambuf_iterator i(s); + copy_n(i, 36, r); + ++i; // EOF reached + VERIFY(i == std::istreambuf_iterator()); + + VERIFY(memcmp(b, r, 36) == 0); + + s << q; + VERIFY(!s.fail()); + + copy_n(i, 36, r); + ++i; // EOF reached + VERIFY(i == std::istreambuf_iterator()); + + VERIFY(memcmp(q, r, 36) == 0); +} + +int main() +{ + test03(); + return 0; +}