#pragma once /** @file @brief stream and line stream class @author MITSUNARI Shigeo(@herumi) */ #ifndef CYBOZU_DONT_USE_STRING #include #include #endif #include #include namespace cybozu { namespace stream_local { template struct is_convertible { typedef char yes; typedef int no; static no test(...); static yes test(const To*); static const bool value = sizeof(test(static_cast(0))) == sizeof(yes); }; template struct enable_if { typedef T type; }; template struct enable_if {}; #ifndef CYBOZU_DONT_USE_STRING /* specialization for istream */ template size_t readSome_inner(void *buf, size_t size, InputStream& is, typename enable_if::value>::type* = 0) { if (size > 0x7fffffff) size = 0x7fffffff; is.read(static_cast(buf), size); const int64_t readSize = is.gcount(); if (readSize < 0) return 0; if (size == 1 && readSize == 0) is.clear(); return static_cast(readSize); } /* generic version for size_t readSome(void *, size_t) */ template size_t readSome_inner(void *buf, size_t size, InputStream& is, typename enable_if::value>::type* = 0) { return is.readSome(buf, size); } #else template size_t readSome_inner(void *buf, size_t size, InputStream& is) { return is.readSome(buf, size); } #endif #ifndef CYBOZU_DONT_USE_EXCEPTION /* specialization for ostream */ template void writeSub(OutputStream& os, const void *buf, size_t size, typename enable_if::value>::type* = 0) { if (!os.write(static_cast(buf), size)) throw cybozu::Exception("stream:writeSub") << size; } #endif #ifndef CYBOZU_DONT_USE_STRING /* generic version for void write(const void*, size_t), which writes all data */ template void writeSub(OutputStream& os, const void *buf, size_t size, typename enable_if::value>::type* = 0) { os.write(buf, size); } template void writeSub(bool *pb, OutputStream& os, const void *buf, size_t size, typename enable_if::value>::type* = 0) { *pb = !!os.write(static_cast(buf), size); } /* generic version for void write(const void*, size_t), which writes all data */ template void writeSub(bool *pb, OutputStream& os, const void *buf, size_t size, typename enable_if::value>::type* = 0) { os.write(pb, buf, size); } #else template void writeSub(bool *pb, OutputStream& os, const void *buf, size_t size) { os.write(pb, buf, size); } #endif } // stream_local /* make a specializaiton of class to use new InputStream, OutputStream */ template struct InputStreamTag { static size_t readSome(void *buf, size_t size, InputStream& is) { return stream_local::readSome_inner(buf, size, is); } static bool readChar(char *c, InputStream& is) { return readSome(c, 1, is) == 1; } }; template struct OutputStreamTag { static void write(OutputStream& os, const void *buf, size_t size) { stream_local::writeSub(os, buf, size); } }; class MemoryInputStream { const char *p_; size_t size_; size_t pos; public: MemoryInputStream(const void *p, size_t size) : p_(static_cast(p)), size_(size), pos(0) {} size_t readSome(void *buf, size_t size) { if (size > size_ - pos) size = size_ - pos; memcpy(buf, p_ + pos, size); pos += size; return size; } size_t getPos() const { return pos; } }; class MemoryOutputStream { char *p_; size_t size_; size_t pos; public: MemoryOutputStream(void *p, size_t size) : p_(static_cast(p)), size_(size), pos(0) {} void write(bool *pb, const void *buf, size_t size) { if (size > size_ - pos) { *pb = false; return; } memcpy(p_ + pos, buf, size); pos += size; *pb = true; } #ifndef CYBOZU_DONT_USE_EXCEPTION void write(const void *buf, size_t size) { bool b; write(&b, buf, size); if (!b) throw cybozu::Exception("MemoryOutputStream:write") << size << size_ << pos; } #endif size_t getPos() const { return pos; } }; #ifndef CYBOZU_DONT_USE_STRING class StringInputStream { const std::string& str_; size_t pos; StringInputStream(const StringInputStream&); void operator=(const StringInputStream&); public: explicit StringInputStream(const std::string& str) : str_(str), pos(0) {} size_t readSome(void *buf, size_t size) { const size_t remainSize = str_.size() - pos; if (size > remainSize) size = remainSize; memcpy(buf, &str_[pos], size); pos += size; return size; } size_t getPos() const { return pos; } }; class StringOutputStream { std::string& str_; StringOutputStream(const StringOutputStream&); void operator=(const StringOutputStream&); public: explicit StringOutputStream(std::string& str) : str_(str) {} void write(bool *pb, const void *buf, size_t size) { str_.append(static_cast(buf), size); *pb = true; } void write(const void *buf, size_t size) { str_.append(static_cast(buf), size); } size_t getPos() const { return str_.size(); } }; #endif template size_t readSome(void *buf, size_t size, InputStream& is) { return stream_local::readSome_inner(buf, size, is); } template void write(OutputStream& os, const void *buf, size_t size) { stream_local::writeSub(os, buf, size); } template void write(bool *pb, OutputStream& os, const void *buf, size_t size) { stream_local::writeSub(pb, os, buf, size); } template void read(bool *pb, void *buf, size_t size, InputStream& is) { char *p = static_cast(buf); while (size > 0) { size_t readSize = cybozu::readSome(p, size, is); if (readSize == 0) { *pb = false; return; } p += readSize; size -= readSize; } *pb = true; } #ifndef CYBOZU_DONT_USE_EXCEPTION template void read(void *buf, size_t size, InputStream& is) { bool b; read(&b, buf, size, is); if (!b) throw cybozu::Exception("stream:read"); } #endif template bool readChar(char *c, InputStream& is) { return readSome(c, 1, is) == 1; } template void writeChar(OutputStream& os, char c) { cybozu::write(os, &c, 1); } template void writeChar(bool *pb, OutputStream& os, char c) { cybozu::write(pb, os, &c, 1); } } // cybozu