Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

atoms/buffer.cc

Go to the documentation of this file.
00001 
00009 #include <atoms/buffer.hh>
00010 #include <string.h>
00011 #include <algorithm>
00012 #include <limits>
00013 #include <boost/shared_ptr.hpp>
00014 #include <atoms/stream.hh>
00015 #include <atoms/error.hh>
00016 
00017 using namespace std;
00018 using namespace boost;
00019 
00020 namespace atoms {
00021 
00022 size_t Buffer::MINIMUM_ALLOCATION = 1024;
00023 DebugLogger Buffer::LOGGER("org.atoms.slamb.Buffer");
00024 //size_t Buffer::MINIMUM_ALLOCATION = 1;
00025 
00026 size_t Buffer::readAndAppend(Stream *s, size_t min) {
00027     assert(s != NULL);
00028     prepareForAppend(min);
00029     size_t actuallyRead = s->read(buf + limit, capacity - limit);
00030     assert(0 < actuallyRead && actuallyRead <= capacity - limit);
00031     limit += actuallyRead;
00032     return actuallyRead;
00033 }
00034 
00035 void Buffer::append(const void *src, size_t n) {
00036     assert(src != NULL);
00037     prepareForAppend(n);
00038     memcpy(buf + limit, src, n);
00039     limit += n;
00040 }
00041 
00042 void Buffer::replace(const void *src, size_t p, size_t n) {
00043     assert(src != NULL);
00044     assert(p <= limit - position);
00045     size_t excess = 0;
00046     if (p + n > limit - position) {
00047         excess = (p + n) - (limit - position);
00048         prepareForAppend(excess);
00049     }
00050     memcpy(buf + position + p, src, n);
00051     limit += excess;
00052 }
00053 
00054 size_t Buffer::writeAndShift(Stream *s, size_t max) {
00055     assert(s != NULL);
00056     assert(limit - position >= max);
00057     size_t actuallyWritten = s->write(buf + position, max);
00058     position += actuallyWritten;
00059     return actuallyWritten;
00060 }
00061 
00062 void Buffer::shift(void *dest, size_t n) {
00063     assert(limit - position >= n);
00064     if (dest != NULL)
00065         memcpy(dest, buf + position, n);
00066     position += n;
00067 }
00068 
00069 size_t Buffer::truncate(size_t n) {
00070     assert(limit - position >= n);
00071     size_t numTruncated = limit - position - n;
00072     limit -= numTruncated;
00073     return numTruncated;
00074 }
00075 
00076 void Buffer::prepareForAppend(size_t n) {
00077     if (!markSet)
00078         mark = position;
00079     size_t currentBytesToKeep = limit - mark;
00080     size_t bytesNeeded = currentBytesToKeep + n;
00081     if (bytesNeeded < currentBytesToKeep) {
00082         // Overflow; don't try to expand into less space.
00083         throw std::bad_alloc();
00084     }
00085     if (bytesNeeded > capacity) {
00086         // We need to reallocate.
00087         size_t newCapacity = max(MINIMUM_ALLOCATION, capacity);
00088         if (bytesNeeded>static_cast<size_t>(numeric_limits<ssize_t>::max())) {
00089             // The powers of two logic will loop infinitely.
00090             // This is too big to bother trying, anyway.
00091             throw std::bad_alloc();
00092         }
00093         while (newCapacity < bytesNeeded)
00094             newCapacity <<= 1;
00095         LOGGER.log(DebugLogger::lInfo, "Expanding buffer %p to %zu bytes",
00096                    this, newCapacity);
00097         char *newBuf = reinterpret_cast<char*>(realloc(buf, newCapacity));
00098         if (newBuf == NULL)
00099             throw std::bad_alloc();
00100         buf = newBuf;
00101         capacity = newCapacity;
00102     }
00103     if (bytesNeeded > capacity - mark) {
00104         // We need to move the important buffer contents
00105         memmove(buf, buf + mark, currentBytesToKeep);
00106         limit -= mark;
00107         position -= mark;
00108         mark = 0;
00109     }
00110 }
00111 
00112 } // namespace atoms

Generated on Wed Jun 15 01:20:34 2005 for atoms++ by doxygen 1.3.5