C++实现的一个类ostringstream的类

嫌ostringsteam过大,一些功能也不知道怎么用的,小生只好自己实现了一个功能类似的类,基本的常用的功能类似,只是为了我自己用起来更方便,更好驾驭,内置一个一级缓冲区(栈上,用户可以定义大小),用户可以定义缓冲区递增的幅度。在知情(已知不会内存越界)的情况下可以直接对缓冲区进行写入操作,代码没有针对char和wchar_t来做,当然也没有考虑线程安全,有兴趣的朋友可以自己修改。代码在VC8下面通过,如果不是VC8的话,里面有几个后面带"_s"函数自己修改一下,如果有bug,请不吝赐教。

源代码下载:http://www.cppblog.com/Files/PeakGao/ostrbuf.rar

/**
    Created 2007.6.7 by PeakGao
    Email: peakgao163@163.com
*/


#ifndef __OSTRBUF_H__
#define __OSTRBUF_H__

#include 
<stdlib.h>

namespace base{

/*
    示例
    
    @code

    int dosomething(char* dest_buf, int max_size)
    {
        char buf[] = "some thing some thing some thing some thing ";
        int actualCpySize = max_size / 2 + 1;
        memcpy(dest_buf, buf, actualCpySize);
        return actualCpySize;
    }

    void test_ostrbuf()
    {
        ostrbuf osb;

        // 如果怕缓冲区不够,先直接设置一下
        //osb.reserve(1024);

        // 这些操作类似ostream的功能
        osb<<(uint)0xffffffff<<","<<(int)0x80000001<<endl;// endl即换行符
        osb<<99<<","<<(short)14<<","<<-15<<endl;
        osb<<(int64)0x8000000000000001<<","<<(uint64)0xffffffffffffffff<<endl;
        osb<<15.1367891024f<<","<<9999.123456789<<endl;

         // 将一个字符串的子串写入
        osb<<ostrbuf::substr("我们你们他们abcdefg", 12)<<endl;

        // 定制的格式化
        osb<<ostrbuf::formatf("%02.6f", 3.1415926f)<<endl;
        osb<<_fi("%04d", 25)<<endl; // 这种写法更简洁
        osb<<_fi("%X", 255)<<endl;


        // 直接操作缓冲区示例(在不知情的情况下不推荐这样操作,知情的情况下,也不错,很方便,至少少了字符串拷贝操作)
        osb.grow(64);    // 可能需要128字节空间,这个数值必须正确才能防止缓存越界
        int off = dosomething(osb.cur(), 64); // dosomething 已经完全抛开了 ostrbuf 类,不受任何拘束,危险!
        osb.seek(off);    // 手动将位置seek到正确位置
        osb<<ends;        // 因上面的 dosomething 没有在缓冲区最后加入'\0',这里不能忘记,除了像 dosomething 这样直接对缓冲区进行写外,其他的操作都会自动加'\0'

        std::cout<<osb.c_str();
    }

    //结果:
    4294967295,-2147483647
    99,14,-15
    -9223372036854775807,18446744073709551615
    15.136789,9999.123457
    我们你们他们
    3.141593
    0025
    FF
    some thing some thing some thing 

    @endcode
*/


/**
    字符串输出缓冲,功能类似ostream,但更加简洁

    @param _GrowBytes 缓冲区的递增大小
    @param _ArrSize 内部的字符数组的大小,当该字符数组容量不够时,才new出真正的缓冲区
*/

template 
<int _GrowBytes, int _ArrSize = 64>
class basic_ostrbuf
{
private:
    
enum {_MyGrowBytes = _GrowBytes > 0 ? ((_GrowBytes + 7& ~7) : 256};
    
enum {_MyArrSize = _ArrSize > 0 ? ((_ArrSize + 7& ~7) : 64};
    
enum {_LongMaxLength = 16, _Int64MaxLength = 24, _DoubleMaxLength = 48}// 留有余地,8字节对齐

    
char*    _buf;                /// 缓冲区
    size_t    _pos;                /// 当前写入位置
    size_t    _cap;                /// 缓冲区容量
    char    _arr[_MyArrSize];    /// 字符数组,当操作小缓冲区时,可以利用他,这样就没必要new内存


    
/// 用于用户自定义的格式化,基于sprintf函数的格式化功能

public:
    template
<class T>
    
struct format 
    
{
        
const char* _f;
        T _v;
        format(
const char* f, const T& v) : _f(f), _v(v) { }
    }
;

    typedef format
<float>                    formatf;
    typedef format
<double>                    formatd;
    typedef format
<int>                        formati;
    typedef format
<__int64>                    formati64;
    typedef std::pair
<const char*, size_t>    substr;

    
// 构造(析构)
public:
    basic_ostrbuf() : _buf(_arr), _pos(
0), _cap(_MyArrSize) { _arr[0= 0; }
    
~basic_ostrbuf() if (_buf != _arr) delete[] _buf; }

    
// 基本方法
public:
    
void clear()
    
{
        grow(
1);
        _pos 
= 0;
        _buf[_pos] 
= 0;
    }


    
char* str() const                return _buf; }
    
const char* c_str() const        return _buf; }
    size_t length() 
const            return _pos; }
    size_t capacity() 
const            return _cap; }
    
char* cur() const                return _buf + _pos;}
    
void seek(int offset)
    
{
        
int new_pos = (int)_pos + offset;
        
if (new_pos >= (int)_cap) new_pos = (int)_cap - 1;
        
if (new_pos < 0) new_pos = 0;
        _pos 
= (size_t)new_pos;
    }


    
/// 预定一个用户设定的缓冲大小(对于大缓冲或已知大小的缓冲,用这种方法可以减少new/delete的次数)
    void reserve(size_t length)
    
{
        
if (length >= _cap)
            grow(length 
- _pos);
    }


    
// operator<<
public:
    
/// 用于endl和ends
    basic_ostrbuf& operator<<(basic_ostrbuf& (__cdecl * fn)(basic_ostrbuf&)) 
    
{
        
return ((*fn)(*this));
    }


    
/// 输入另一个对象
    basic_ostrbuf& operator<<(const basic_ostrbuf& other)
    
{
        
return push(other.c_str(), other.length());
    }



    
/// 输入字符串
    basic_ostrbuf& operator<<(const char* str)
    
{
        
return (str ? push(str, strlen(str)) : (*this));
    }

    
/// 输入一个子串
    basic_ostrbuf& operator<<(const substr& str)
    
{
        
return push(str.first, str.second);
    }

    
/// 输入std::string对象
    basic_ostrbuf& operator<<(const std::string& str)
    
{
        
return push(str.c_str(), str.length());
    }

    
/// 输入一个字符
    
/// 注:这里c当字符处理,不当0-255的数字处理,0-255的数字,需要转换为short,int,long等进行处理

    basic_ostrbuf& operator<<(char c)
    
{
        
return put(c);
    }


    
/// 导入数字
    basic_ostrbuf& operator<<(short int si)
    
{
        
return operator<<(long(si));
    }

    basic_ostrbuf
& operator<<(unsigned short int usi)
    
{
        
return operator<<(unsigned long(usi));
    }

    basic_ostrbuf
& operator<<(int i)
    
{
#ifdef INT_64_BITS
        
return operator<<(__int64(i));
#else
        
return operator<<(long(i));
#endif
    }

    basic_ostrbuf
& operator<<(unsigned int ui)
    
{
#ifdef INT_64_BITS
        
return operator<<(unsigned __int64(ui));
#else
        
return operator<<(unsigned long(ui));
#endif
    }

    basic_ostrbuf
& operator<<(long l)
    
{
        grow(_LongMaxLength);
        _ltoa_s(l, cur(), _LongMaxLength, 
10);
        _pos 
+= strlen(cur());
        
return (*this);
    }

    basic_ostrbuf
& operator<<(unsigned long ul)
    
{
        grow(_LongMaxLength);
        _ultoa_s(ul, cur(), _LongMaxLength, 
10);
        _pos 
+= strlen(cur());
        
return (*this);
    }

    basic_ostrbuf
& operator<<(__int64 i64)
    
{
        grow(_Int64MaxLength);
        _i64toa_s(i64, cur(), _Int64MaxLength, 
10);
        _pos 
+= strlen(cur());
        
return (*this);
    }

    basic_ostrbuf
& operator<<(unsigned __int64 ui64)
    
{
        grow(_Int64MaxLength);
        _ui64toa_s(ui64, cur(), _Int64MaxLength, 
10);
        _pos 
+= strlen(cur());
        
return (*this);
    }

    basic_ostrbuf
& operator<<(float f)
    
{
        grow(_DoubleMaxLength);
        sprintf_s(cur(), _DoubleMaxLength, 
"%f", f);
        _pos 
+= strlen(cur());
        
return (*this);
    }

    basic_ostrbuf
& operator<<(double d)
    
{
        grow(_DoubleMaxLength);
        sprintf_s(cur(), _DoubleMaxLength, 
"%f", d);
        _pos 
+= strlen(cur());
        
return (*this);
    }


    
/// 定制的格式化
    template<class T>
    basic_ostrbuf
& operator<<(const format<T>& val)
    
{
        grow(_DoubleMaxLength);
        sprintf_s(cur(), _DoubleMaxLength, val._f, val._v);
        _pos 
+= strlen(cur());
        
return (*this);
    }

public:
    
void grow(size_t len)
    
{
        
if (_pos + len >= _cap)
        
{
            
// 计算新的尺寸,并8字节对齐
            size_t new_size = _pos + len + 1;
            size_t new_cap 
= _cap ? _cap : _MyGrowBytes;
            
while (new_cap < new_size)
                new_cap 
+= _MyGrowBytes;
            new_cap 
= (new_cap + 7& ~7;

            
char* new_buf = new char[new_cap];
            
if (_pos > 0)
            
{
                memcpy(new_buf, _buf, _pos 
+ 1);
                
if (_buf != _arr)
                    delete[] _buf;
            }

            
else
                new_buf[
0= 0;

            _buf 
= new_buf;
            _cap 
= new_cap;
        }

    }

    basic_ostrbuf
& put(char c)
    
{
        grow(
1);
        _buf[_pos] 
= c;
        
if (c != 0)
            _buf[
++_pos] = 0;
        
return (*this);
    }

    basic_ostrbuf
& push(const char* str, size_t len)
    
{
        
if (str && len > 0)
        
{
            grow(len);
            memcpy(_buf 
+ _pos, str, len);
            _buf[_pos 
+= len] = 0;
        }

        
return (*this);
    }

}
;



/// 字符串终止
template<int _GrowBytes, int _ArrSize>
inline basic_ostrbuf
<_GrowBytes, _ArrSize>& _cdecl ends(basic_ostrbuf<_GrowBytes, _ArrSize>& osb)
{
    
return osb.put('\0');
}


/// 换行
template<int _GrowBytes, int _ArrSize>
inline basic_ostrbuf
<_GrowBytes, _ArrSize>& _cdecl endl(basic_ostrbuf<_GrowBytes, _ArrSize>& osb)
{
    
return osb.put('\n');
}


#if 0
/*
    示例:用户自定义类型的定制方法,定义后可以这样处理你的自定义类型:
    YourType  yt;
    ostrbuf<<yt;
*/

template
<int _GrowBytes, int _ArrSize>
inline basic_ostrbuf
<_GrowBytes, _ArrSize>& _cdecl operator<<(basic_ostrbuf<_GrowBytes, _ArrSize>& osb, const YourType& val)
{
    
if (val.c_str())
        osb.push(val.c_str(), val.length());
    
return osb;
}

#endif


typedef basic_ostrbuf
<25664>        ostrbuf;


// 为了方便使用,作这样的 typedef
typedef ostrbuf::formatf    _ff;
typedef ostrbuf::formatd    _fd;
typedef ostrbuf::formati    _fi;
typedef ostrbuf::formati64    _fi64;
typedef ostrbuf::substr        _ss;

}
 // namespace

#endif // __OSTRBUF_H__

posted on 2007-06-07 16:30 PeakGao 阅读(2230) 评论(0)  编辑 收藏 引用 所属分类: C++技术


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2007年6月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(9)

随笔分类(67)

随笔档案(65)

搜索

最新评论

阅读排行榜

评论排行榜