File: acbuf.h

package info (click to toggle)
apt-cacher-ng 0.7.27-1~bpo70+1
  • links: PTS
  • area: main
  • in suites: wheezy-backports
  • size: 1,740 kB
  • sloc: cpp: 13,987; sh: 519; perl: 442; ansic: 414; makefile: 77
file content (132 lines) | stat: -rw-r--r-- 5,395 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

#ifndef _acbuf_H
#define _acbuf_H

#include <limits.h>
#include <string.h>
#include <stdio.h>
#include "meta.h"

/*! \brief Helper class to maintain a memory buffer, i.e. a continuous block of bytes.
 * It also encapsulates some typical operations on it.
 */

class acbuf
{
    public:
        inline acbuf() : r(0), w(0), m_nCapacity(0), m_buf(NULL) {};
    	virtual ~acbuf() { free(m_buf); m_buf=NULL; }
    	inline bool empty() const { return w==r;}
    	//! Count of the data inside
        inline unsigned int size() const { return w-r;}
        //! Returns capacity
        inline unsigned int freecapa() const { return m_nCapacity-w; }
        inline unsigned int totalcapa() const { return m_nCapacity; }
        //! Erase all characters after a certain position  
        inline void erase(size_t pos) { w=r+pos; if(r==w) clear(); }
        //! Invalidate data on the beginning, move reading position  
        inline void drop(size_t count) {  r+=count; if(r==w) clear(); }
        //! Mark externally appended data as valid, move writing position
        inline void got(size_t count) { w+=count;}
        //! for the worst case, move data to beginning to make space to read a complete new header
        inline void move() { if(0==r) return; memmove(m_buf, m_buf+r, w+1-r); w-=r; r=0; }
        //! Return pointer where to append data
        inline char *wptr() { return m_buf+w;};
        //! Return pointer to read valid data from
        inline const char *rptr() const { return m_buf+r; }
        //! like rptr but appends a NULL terminator
        inline const char *c_str() const { m_buf[w]=0x0; return rptr();}
        //! Equivalent to drop(size()), drops all data
        inline void clear() {w=r=0;}
        
        //! Allocate needed memory
        bool setsize(unsigned int capa);
        bool initFromFile(const char *path);

        /*!
         * Writes to a (non-blocking) file descriptor, cares about EAGAIN and updates
         * position indexes. Optional chunklen variable specifies
         * the maximum of data to write.
         *
         * \param fd File descriptor to write to
         * \param maxlen Maximum amount of data to write
         * \return Number of written bytes, negative on failures, see write(2)
         */
        int syswrite(int fd, unsigned int maxlen=UINT_MAX);

        /*
         * Reads from a file descriptor and append to buffered data, update position indexes.
         * \param fd File descriptor
         * \return Number of read bytes, negative on failures, see read(2)
         */
        int sysread(int fd);


    protected:
        size_t r, w, m_nCapacity; // read/write positions, size
        char *m_buf;
    	acbuf(const acbuf&); // don't copy me
    	acbuf& operator=(const acbuf&);

//        friend class maintenance::tFmtSendObj;

};

/* This is a light-weight and less cumbersome implementation of ostringstream.
 *
 * What it also makes possible: use itself as a string, use alternative add() operators
 * for strings which can also specify the length, and it runs faster with zero-terminated strings.
 */
class tSS : public acbuf
{
public:
// map char array to buffer pointer and size
#define _SZ2PS(x) x, (sizeof(x)-1)
	inline tSS & operator<<(const char *val) { return add(val); }
	inline tSS & operator<<(const mstring& val) { return add(val); };
	inline tSS & operator<<(const acbuf& val) { return add(val.rptr(), val.size()); };

#define __tss_nbrfmt(x, h, y) { add(fmtbuf, sprintf(fmtbuf, m_fmtmode == hex ? h : x, y)); return *this; }
	inline tSS & operator<<(int val) __tss_nbrfmt("%d", "%x", val);
	inline tSS & operator<<(unsigned int val) __tss_nbrfmt("%u", "%x", val);
	inline tSS & operator<<(long val) __tss_nbrfmt("%ld", "%lx", val);
	inline tSS & operator<<(unsigned long val) __tss_nbrfmt("%lu", "%lx", val);
	inline tSS & operator<<(long long val) __tss_nbrfmt("%lld", "%llx", val);
	inline tSS & operator<<(unsigned long long val) __tss_nbrfmt("%llu", "%llx", val);
#ifdef DEBUG
	inline tSS & operator<<(void* val) __tss_nbrfmt("ptr:%llu", "ptr:0x%llx", (long long unsigned) val);
#endif

    enum fmtflags {	hex, dec };
    inline tSS & operator<<(fmtflags mode) { m_fmtmode=mode; return *this;}

    operator mstring() const { return mstring(rptr(), size()); }
    inline size_t length() const { return size();}
    inline const char * data() const { return rptr();}

    inline tSS() : m_fmtmode(dec){}
    inline tSS(size_t sz) : m_fmtmode(dec) { setsize(sz); }
    inline tSS(const tSS &src) : acbuf(), m_fmtmode(src.m_fmtmode) { add(src.data(), src.size()); }
    tSS & addEscaped(const char *fmt);
    inline tSS & operator<<(const char c) { reserve(size()+1); *(wptr())=c; got(1); return *this;}


protected:
    char fmtbuf[22];
	fmtflags m_fmtmode;
	inline void reserve(size_t minCapa) { minCapa+=(r+1); if(m_nCapacity>=minCapa) return;
	char *p=(char*)realloc(m_buf, MYSTD::max(m_nCapacity, minCapa*2));
	if(!p) throw MYSTD::bad_alloc(); m_nCapacity=minCapa*2; m_buf=p; }

	inline tSS & add(const mstring& val) { return add(val.data(), val.size());}
	inline tSS & appDosNL() { return add("\r\n", 2);}
	inline tSS & add(const char *data, size_t len)
	{ reserve(size()+len); memcpy(wptr(), data, len); got(len); return *this;}
	inline tSS & add(const char *val)
	{ if(val) return add(val, strlen(val)); else return add("(null)", 6); }

};

void _AddFooter(tSS &msg);

#endif