diff options
-rw-r--r-- | include/streambuf | 165 | ||||
-rw-r--r-- | src/Android.mk | 1 | ||||
-rw-r--r-- | src/streambuf.cpp | 73 | ||||
-rw-r--r-- | tests/Android.mk | 1 | ||||
-rw-r--r-- | tests/test_streambuf.cpp | 78 |
5 files changed, 318 insertions, 0 deletions
diff --git a/include/streambuf b/include/streambuf new file mode 100644 index 0000000..f83dd2f --- /dev/null +++ b/include/streambuf @@ -0,0 +1,165 @@ +/* -*- c++ -*- */ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANDROID_ASTL_STREAMBUF__ +#define ANDROID_ASTL_STREAMBUF__ + +#include <char_traits.h> + +namespace std { + +/** + * Basic implementation of streambuf. The STL standard defines a + * basic_streambuf template that gets specialized for char and + * wchar. Since Android supports only char, we don't use a template + * here. + * Only output ops are supported. + * There are only 2 public entry points: + * - sputc + * - sputn + */ + +class streambuf +{ + public: + typedef char_traits traits_type; + typedef traits_type::char_type char_type; + typedef traits_type::int_type int_type; + typedef streampos pos_type; + typedef streamoff off_type; + + public: + virtual ~streambuf(); + + /** + * Entry points for derived buffer functions. The public + * version pubfoo dispatch to the protected foo member + * functions. + */ + int pubsync() { return this->sync(); } + + /** + * Entry point for all single-character output functions. If a + * write position is available (buffer not full), stores c at that + * position, incr the position and return + * traits.::to_int_type(c). If no position is available returns + * overflow(c). + */ + int_type sputc(char_type c) { + int_type ret; + + if (this->pptr() < this->epptr()) { + *this->pptr() = c; + this->pbump(1); + return traits_type::to_int_type(c); + } else { + ret = this->overflow(traits_type::to_int_type(c)); + } + return ret; + } + + /** + * Write str[0] to str[n-1] to output sequence. Stops if sputc + * would return traits_type::eof(). + * @param str A buffer area. + * @param nnum Maximum number of characters to write. + * @return The number of characters written. + */ + streamsize sputn(const char_type* str, streamsize num) { + return this->xsputn(str, num); + } + + protected: + streambuf(); + + + /** + * Access to the put area. + * - pbase() returns the beginning pointer for the output sequence. + * - pptr() returns the next pointer for the output sequence. + * - epptr() returns the end pointer for the output sequence. + * - pbump(int) Advance the write postion in the output sequence. + */ + char_type* pbase() const { return mPutBeg; } + char_type* pptr() const { return mPutCurr; } + char_type* epptr() const { return mPutEnd; } + void pbump(int num) { + if (mPutCurr + num > mPutCurr && mPutCurr + num <= mPutEnd) { + mPutCurr += num; + } + } + + /** + * Set the 3 write pointers. + */ + void setp(char_type* beg, char_type* end) { + if (end >= beg) { + mPutBeg = mPutCurr = beg; + mPutEnd = end; + } + } + + /** + * Sync buffer array. Provided by derived class. + */ + virtual int sync() { return 0; } + + /** + * See sputn. Provided by derived class. + */ + virtual streamsize xsputn(const char_type* str, streamsize num); + + /** + * Consumes one char from the buffer, writes to the controlled + * sequence if possible. This is called when the buffer is + * full. Typically the impl will flush the buffer, write the + * character 'c'. + * Provided by derived class. + * @return traits::eof() in case of error, anything else otherwise. + */ + virtual int_type overflow(int_type /* c */ = traits_type::eof()) + { return traits_type::eof(); } + + /** + * Minimal abstraction for an internal buffer. + * - put == output == write + */ + char_type* mPutBeg; // Start of put area. + char_type* mPutCurr; // Current put area. + char_type* mPutEnd; // End of put area. + + private: + // No copy constructors. + streambuf(const streambuf& sb); + streambuf& operator=(const streambuf&) { return *this; } +}; + +} // namespace std + +#endif diff --git a/src/Android.mk b/src/Android.mk index e555dab..c6c3d54 100644 --- a/src/Android.mk +++ b/src/Android.mk @@ -22,6 +22,7 @@ astl_common_src_files := \ ios_base.cpp \ ios_pos_types.cpp \ ostream.cpp \ + streambuf.cpp \ string.cpp # Build the target lib diff --git a/src/streambuf.cpp b/src/streambuf.cpp new file mode 100644 index 0000000..0acebb3 --- /dev/null +++ b/src/streambuf.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <streambuf> +#include <algorithm> // for min +namespace std { + +// Implementation of the streambuf, common stuff for all the stream buffers. +streambuf::streambuf() + : mPutBeg(0), mPutCurr(0), mPutEnd(0) { } + +streambuf::streambuf(const streambuf& sb) + : mPutBeg(sb.mPutBeg), mPutCurr(sb.mPutCurr), mPutEnd(sb.mPutEnd) { } + +streambuf::~streambuf() {} + +streamsize streambuf::xsputn(const char_type* str, streamsize num) { + streamsize written = 0; + + while (written < num) { + const streamsize avail = this->epptr() - this->pptr(); + if (avail) { + const streamsize remaining = num - written; + const streamsize len = std::min(avail, remaining); + traits_type::copy(this->pptr(), str, len); + written += len; + str += len; + this->pbump(len); + } + + if (written < num) { + // Indicate to the impl that we overflown. Either the impl + // can increase its buffer and consume one character (in + // which case eof() is not returned) or it can't and we + // stop here. + int_type c = this->overflow(traits_type::to_int_type(*str)); + if (!traits_type::eq_int_type(c, traits_type::eof())) { + ++written; + ++str; + } else { + break; + } + } + } + return written; +} + +} // namespace std diff --git a/tests/Android.mk b/tests/Android.mk index 88dd282..5de2eb7 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -70,6 +70,7 @@ sources := \ test_limits.cpp \ test_memory.cpp \ test_set.cpp \ + test_streambuf.cpp \ test_string.cpp \ test_type_traits.cpp \ test_uninitialized.cpp \ diff --git a/tests/test_streambuf.cpp b/tests/test_streambuf.cpp new file mode 100644 index 0000000..cc58abc --- /dev/null +++ b/tests/test_streambuf.cpp @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "../include/streambuf" +#ifndef ANDROID_ASTL_STREAMBUF__ +#error "Wrong header included!!" +#endif +#include "common.h" + +#include <char_traits.h> + +namespace android { +using std::char_traits; + +class streambuf: public std::streambuf { + public: + streambuf() { + setp(mBuffer, mBuffer + sizeof(mBuffer)); + char_traits::assign(mBuffer, sizeof(mBuffer), 'X'); + } + + char mBuffer[5]; +}; + +bool testSputc() { + streambuf buf; + + EXPECT_TRUE(buf.sputc('A') == 65); + EXPECT_TRUE(buf.sputc('B') == 66); + EXPECT_TRUE(buf.sputc('C') == 67); + EXPECT_TRUE(buf.sputc('D') == 68); + EXPECT_TRUE(buf.sputc('E') == 69); + EXPECT_TRUE(buf.sputc('F') == char_traits::eof()); + EXPECT_TRUE(buf.sputc('G') == char_traits::eof()); + return true; +} + +bool testSputn() { + streambuf buf; + + EXPECT_TRUE(buf.sputn("ABCDE", 5) == 5); + EXPECT_TRUE(buf.sputn("F", 1) == 0); + return true; +} + +} // namespace android + +int main(int argc, char **argv){ + FAIL_UNLESS(testSputc); + FAIL_UNLESS(testSputn); + return kPassed; +} |