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

atoms/buffer.hh

Go to the documentation of this file.
00001 
00009 #ifndef ATOMS_BUFFER_HH
00010 #define ATOMS_BUFFER_HH
00011 
00012 #include <atoms/gen.hh>
00013 #include <stdlib.h>
00014 #include <locale>
00015 #include <atoms/stream.hh>
00016 
00017 namespace atoms {
00018 
00052 class Buffer {
00053 public:
00054     Buffer() : markSet(false), position(0), limit(0), capacity(0), buf(NULL) {}
00055 
00060     ~Buffer() {
00061         assert(!markSet);
00062         free(buf);
00063     }
00064 
00080     size_t readAndAppend(Stream *s, size_t min);
00081     size_t readAndAppend(const boost::shared_ptr<Stream> &s, size_t min) {
00082         return readAndAppend(s.get(), min);
00083     }
00085 
00093     void append(const void *src, size_t n);
00094 
00095     template <typename internT, typename externT, typename stateT>
00096     void append(const internT *from, const internT *fromEnd, stateT&,
00097                 const std::codecvt<internT,externT,stateT>&);
00098 
00107     void replace(const void *src, size_t p, size_t n);
00108 
00119     size_t writeAndShift(Stream *s, size_t max);
00120     size_t writeAndShift(const boost::shared_ptr<Stream> &s, size_t max) {
00121         return writeAndShift(s.get(), max);
00122     }
00124 
00133     void shift(void *dest, size_t n);
00134 
00139     size_t truncate(size_t n);
00140 
00142     size_t getSize() const { return limit - position; }
00143 
00145     size_t getCapacity() const { return capacity; }
00146 
00148     size_t getRollbackSize() const { return position; }
00149 
00156     void setMark() {
00157         assert(!markSet);
00158         mark = position;
00159         markSet = true;
00160     }
00161 
00167     void rollback() {
00168         assert(markSet);
00169         position = mark;
00170         markSet = false;
00171     }
00172 
00176     void rollback(size_t n) {
00177         assert(n <= position);
00178         position -= n;
00179         if (position <= mark) {
00180             markSet = false;
00181         }
00182     }
00183 
00189     void clear() {
00190         assert(markSet);
00191         markSet = false;
00192     }
00193 private:
00198     void prepareForAppend(size_t n);
00199 
00207     size_t mark;
00208     bool markSet;
00210 
00212     size_t position;
00213 
00218     size_t limit;
00219 
00221     size_t capacity;
00222 
00227     char *buf;
00228 
00230     static size_t MINIMUM_ALLOCATION;
00231 
00232     static DebugLogger LOGGER;
00233 };
00234 
00235 template <typename internT, typename externT, typename stateT>
00236 void Buffer::append(const internT *from, const internT *fromEnd, stateT &state,
00237                     const std::codecvt<internT,externT,stateT> &cvt) {
00238     using namespace std;
00239     size_t oldSize = getSize();
00240     std::codecvt_base::result r;
00241     try {
00242         const internT *fromNext = from;
00243         externT *to, *toEnd, *toNext;
00244         do {
00245             // Make sure we have at least a little space.
00246             prepareForAppend(sizeof(externT));
00247 
00248             // And try the conversion.
00249             to = toNext = reinterpret_cast<externT*>(&buf[limit]);
00250             toEnd = reinterpret_cast<externT*>(&buf[capacity]);
00251             r = cvt.out(state, from, fromEnd, from, to, toEnd, to);
00252             limit += (toNext - to) * sizeof(externT);
00253             from = fromNext;
00254         } while (r == codecvt_base::partial && to == toEnd) ;
00255     } catch (std::bad_alloc&) {
00256         // On allocation failure, leave the buffer as it was.
00257         limit = position + oldSize;
00258         throw;
00259     }
00260     if (r == codecvt_base::error) {
00261         // If there's an error converting to the locale, throw an exception
00262         // and leave the buffer as before.
00263         limit = position + oldSize;
00264         throw Error("Invalid character conversion.");
00265     }
00266     if (r == codecvt_base::noconv) {
00267         append(from, sizeof(internT) * (fromEnd - from));
00268         return;
00269     }
00270     assert(r == codecvt_base::ok);
00271 }
00272 
00273 } // namespace atoms
00274 #endif // !ATOMS_BUFFER_HH

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