You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/06/21 03:48:31 UTC
svn commit: r415868 - in /incubator/stdcxx/trunk/include: fstream fstream.cc
Author: sebor
Date: Tue Jun 20 18:48:31 2006
New Revision: 415868
URL: http://svn.apache.org/viewvc?rev=415868&view=rev
Log:
2006-06-20 Martin Sebor <se...@roguewave.com>
STDCXX-7
* fstream (xsputn): Declared.
* fstream (xsputn): Overrode the base class virtual function and
optimized to avoid unnecessary writes when the size of the array
argument exceeds the amount of space available in the internal
character buffer.
(overflow): Moved most of the body of the function to xsputn()
and called it.
Modified:
incubator/stdcxx/trunk/include/fstream
incubator/stdcxx/trunk/include/fstream.cc
Modified: incubator/stdcxx/trunk/include/fstream
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/include/fstream?rev=415868&r1=415867&r2=415868&view=diff
==============================================================================
--- incubator/stdcxx/trunk/include/fstream (original)
+++ incubator/stdcxx/trunk/include/fstream Tue Jun 20 18:48:31 2006
@@ -245,6 +245,10 @@
// 27.8.1.4, p16 - in input mode, repopulates buffer from file
virtual int sync ();
+ // overridden for efficiency
+ virtual _RWSTD_STREAMSIZE
+ xsputn (const char_type*, _RWSTD_STREAMSIZE);
+
private:
basic_filebuf*
@@ -259,7 +263,7 @@
// write unshift sequence to file (multibyte, state-dependent encondings)
bool _C_unshift ();
-
+
void *_C_file; // underlying FILE ptr or file descriptor
pos_type _C_cur_pos; // offset/state in file corresponding to
// end of buffer, and actual pos in file
Modified: incubator/stdcxx/trunk/include/fstream.cc
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/include/fstream.cc?rev=415868&r1=415867&r2=415868&view=diff
==============================================================================
--- incubator/stdcxx/trunk/include/fstream.cc (original)
+++ incubator/stdcxx/trunk/include/fstream.cc Tue Jun 20 18:48:31 2006
@@ -7,16 +7,22 @@
*
***************************************************************************
*
- * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
- * Software division. Licensed under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0. Unless required by
- * applicable law or agreed to in writing, software distributed under
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License
- * for the specific language governing permissions and limitations under
- * the License.
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 1994-2006 Rogue Wave Software.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*
**************************************************************************/
@@ -329,137 +335,199 @@
this->setg (0, 0, 0); // invalidate the get area
- const char_type* __from_beg; // pointer to start of sequence to write
- const char_type* __from_end; // pointer to end of sequence to write
+ const bool __unbuf = this->_C_is_unbuffered ();
const char_type __c_to_char = traits_type::to_char_type (__c);
- if (this->_C_is_unbuffered ()) {
- __from_beg = &__c_to_char;
- __from_end = __from_beg + 1;
+ if (this->pptr () == 0 && !__unbuf) {
+ // put area not valid yet - just need to initialize it
+ this->setp (this->_C_buffer, this->_C_buf_end ());
}
- else {
- __from_beg = this->_C_buffer;
- __from_end = this->pptr ();
+ else if ( this->pptr () == this->epptr ()
+ || this->_C_is_eof (__c)
+ || __unbuf) {
+
+ const char_type* __buf;
+ _RWSTD_STREAMSIZE __nchars;
+
+ if (__unbuf) {
+ __buf = &__c_to_char;
+ __nchars = 1;
+ }
+ else {
+ // call xsputn() with a special value to have it flush
+ // the controlled sequence to the file
+ __buf = _RWSTD_REINTERPRET_CAST (char_type*, this);
+ __nchars = this->pptr () - this->pbase ();
+ }
+
+ if (__nchars != basic_filebuf::xsputn (__buf, __nchars))
+ return traits_type::eof (); // error while writing
}
- if (this->pptr () == 0 && !this->_C_is_unbuffered ()) {
+ // now that there's room in the buffer, call sputc() recursively
+ // to actually place the character in the buffer (unless we're
+ // in unbuffered mode because we just wrote it out)
+ if (!this->_C_is_eof (__c) && !__unbuf)
+ this->sputc (__c_to_char);
+
+ this->_C_out_last (true); // needed by close ()
+
+ return traits_type::not_eof (__c);
+}
+
+
+template <class _CharT, class _Traits>
+_RWSTD_STREAMSIZE
+basic_filebuf<_CharT, _Traits>::
+xsputn (const char_type* __buf, _RWSTD_STREAMSIZE __nchars)
+{
+ _RWSTD_ASSERT (0 != __buf || 0 == __nchars);
+ _RWSTD_ASSERT (this->_C_is_valid ());
+
+ if (0 == __nchars)
+ return 0; // not an error
+
+ if (__nchars < 0 || !this->_C_is_out () || !is_open ())
+ return -1; // error
+
+ if (0 == this->pptr () && !this->_C_is_unbuffered ())
// put area not valid yet - just need to initialize it
this->setp (this->_C_buffer, this->_C_buf_end ());
+
+ const _RWSTD_STREAMSIZE __navail = this->epptr () - this->pptr ();
+
+ const char_type* const __special =
+ _RWSTD_REINTERPRET_CAST (char_type*, this);
+
+ if (__buf == __special) {
+ __buf = this->pbase ();
}
- else if ( this->pptr () == this->epptr ()
- || this->_C_is_eof (__c)
- || this->_C_is_unbuffered ()) {
+ else if (__nchars <= __navail) {
+ // the amount of available space is big enough
- // flush put area to file,
- // performing code conversion if necessary
+ // append the contents of the buffer to the controlled sequence
+ traits_type::copy (this->pptr (), __buf, __nchars);
- typedef _TYPENAME traits_type::state_type _StateT;
+ this->pbump (__nchars);
- _RWSTD_STREAMSIZE __nwrote = 0; // num chars to write
- _StateT __state = _C_cur_pos.state (); // state of stream
+ return __nchars;
+ }
+ else {
+ // call self recursively to flush the controlled sequence first
+ const _RWSTD_STREAMSIZE __nwrite = this->pptr () - this->pbase ();
- _C_beg_pos = _C_cur_pos;
+ // return -1 on error to flush the controlled sequence
+ if (__nwrite != basic_filebuf::xsputn (__special, __nwrite))
+ return -1;
+ }
- typedef codecvt<char_type, char, _StateT> _Codecvt;
+ // flush buffer to file, performing code conversion if necessary
- const _Codecvt &__cvt = _USE_FACET (_Codecvt, this->getloc ());
+ _RWSTD_ASSERT (this->_C_is_valid ());
+ _RWSTD_ASSERT (this->_C_is_out ());
+ _RWSTD_ASSERT (is_open ());
- if (__cvt.always_noconv ()) {
+ const char_type* const __end = __buf + __nchars;
- // no conversion
+ typedef _TYPENAME traits_type::state_type _StateT;
- __nwrote = __from_end - __from_beg;
+ _RWSTD_STREAMSIZE __nwrote = 0; // num chars to write
+ _StateT __state = _C_cur_pos.state (); // state of stream
- const _RWSTD_STREAMSIZE __nbytes = sizeof (char_type) * __nwrote;
+ _C_beg_pos = _C_cur_pos;
- if (__nbytes != _RW::__rw_fwrite (_C_file, this->_C_state,
- __from_beg, __nbytes))
- return traits_type::eof (); // error while writing
- }
- else {
+ typedef codecvt<char_type, char, _StateT> _Codecvt;
- // conversion required: we do this a chunk at a time
- // to avoid dynamic allocation of memory
+ const _Codecvt &__cvt = _USE_FACET (_Codecvt, this->getloc ());
- char __xbuf [_RWSTD_DEFAULT_BUFSIZE];
- char* __xbuf_end = __xbuf + sizeof __xbuf;
- char* __to_next = 0;
- const char_type* __from_next = 0;
-
- for (const char_type* __base = __from_beg;
- __from_next != __from_end;
- __base = __from_next) {
-
- const codecvt_base::result __res =
- __cvt.out (__state, __base, __from_end, __from_next,
- __xbuf, __xbuf_end, __to_next);
+ if (__cvt.always_noconv ()) {
- _RWSTD_STREAMSIZE __nbytes =
- sizeof (char_type) * (__from_end - __base);
+ // no conversion
- switch (__res) {
- case codecvt_base::error:
- // write out the sequence successfully converted up
- // to the point of the error in the internal sequence
- // and fail
- _RW::__rw_fwrite (_C_file, this->_C_state,
- __base, __nbytes);
- return traits_type::eof ();
+ __nwrote = __end - __buf;
- case codecvt_base::noconv:
- // write the entire sequence
- if (__nbytes != _RW::__rw_fwrite (_C_file, this->_C_state,
- __base, __nbytes))
- return traits_type::eof ();
+ const _RWSTD_STREAMSIZE __nbytes = sizeof (char_type) * __nwrote;
- __nwrote += __from_end - __base
- + _C_crlf_intern_count (__base, __from_end);
+ if (__nbytes != _RW::__rw_fwrite (_C_file, this->_C_state,
+ __buf, __nbytes))
+ return -1; // error while writing
+ }
+ else {
- __from_next = __from_end; // effectively 'break'
- break;
+ // perform codeset conversion in chunks to avoid dynamic
+ // memory allocation
- default:
- _RWSTD_ASSERT ( codecvt_base::ok == __res
- || codecvt_base::partial == __res);
+ char __xbuf [_RWSTD_DEFAULT_BUFSIZE];
+ char* __xbuf_end = __xbuf + sizeof __xbuf;
+ char* __to_next = 0;
+ const char_type* __from_next = 0;
+
+ for (const char_type* __base = __buf; __from_next != __end;
+ __base = __from_next) {
+
+ const codecvt_base::result __res =
+ __cvt.out (__state, __base, __end, __from_next,
+ __xbuf, __xbuf_end, __to_next);
+
+ _RWSTD_STREAMSIZE __nbytes =
+ sizeof (char_type) * (__end - __base);
+
+ switch (__res) {
+ case codecvt_base::error:
+ // write out the sequence successfully converted up
+ // to the point of the error in the internal sequence
+ // and fail
+ _RW::__rw_fwrite (_C_file, this->_C_state, __base, __nbytes);
+ return traits_type::eof ();
- // a partial conversion will result if there's
- // not enough space in the conversion buffer to
- // hold the converted sequence, but we're O.K.
- // since we'll be passing any remaining unconverted
- // characters (starting at __from_next) in the next
- // iteration
-
- __nbytes = __to_next - __xbuf;
-
- if (__nbytes != _RW::__rw_fwrite (_C_file, this->_C_state,
- __xbuf, __nbytes))
- return traits_type::eof ();
+ case codecvt_base::noconv:
+ // write the entire sequence
+ if (__nbytes != _RW::__rw_fwrite (_C_file, this->_C_state,
+ __base, __nbytes))
+ return traits_type::eof ();
- __nwrote += __nbytes
- + _C_crlf_extern_count (__xbuf, __to_next);
- }
+ __nwrote += __end - __base
+ + _C_crlf_intern_count (__base, __end);
+
+ __from_next = __end; // effectively 'break'
+ break;
+
+ default:
+ _RWSTD_ASSERT ( codecvt_base::ok == __res
+ || codecvt_base::partial == __res);
+
+ // partial conversion will result if there isn't enough
+ // space in the conversion buffer to hold the converted
+ // sequence, but we're O.K. since we'll be passing any
+ // remaining unconverted characters (starting at
+ // __from_next) in the next iteration
+
+ __nbytes = __to_next - __xbuf;
+
+ if (__nbytes != _RW::__rw_fwrite (_C_file, this->_C_state,
+ __xbuf, __nbytes))
+ return -1;
+
+ __nwrote += __nbytes
+ + _C_crlf_extern_count (__xbuf, __to_next);
}
}
-
- // adjust the current position in the file
- _C_cur_pos += __nwrote;
- _C_cur_pos.state (__state);
-
- // reset the put area
- if (!this->_C_is_unbuffered ())
- this->setp (this->_C_buffer, this->_C_buf_end ());
}
- // now that there's room in the buffer, call sputc() recursively
- // to actually place the character in the buffer (unless we're
- // in unbuffered mode because we just wrote it out)
- if (!this->_C_is_eof (__c) && !this->_C_is_unbuffered ())
- this->sputc (__c_to_char);
+ // adjust the current position in the file
+ _C_cur_pos += __nwrote;
+ _C_cur_pos.state (__state);
+
+ // reset the put area
+ if (!this->_C_is_unbuffered ())
+ this->setp (this->_C_buffer, this->_C_buf_end ());
this->_C_out_last (true); // needed by close ()
- return traits_type::not_eof (__c);
+ // return the number of characters (not bytes) in the buffer
+ // successfully written to the file
+ return __nchars;
}