问题描述:
1.c++封装的用来存储key, value对的内存池;
2.key 用字符串表达,value可以是各种类型。目前value只支持六种类型,后面会继续扩展;
3.key value pair 内存结构是:key length(1byte) | key string | value type | value |。注意中间|是为了表达区分而加上的,实际内存中并没有。注意当value 是char* 对象是,value前面四个字节表达它的长度;
4.这个类写的很仓促,目前呈现给大家的仅仅是一个雏形,后面会扩展一个使用的iterator class,使得使用更加简单化,更加直观;
程序代码:
#ifndef _KEY_VALUE_STREAM_H_
#define _KEY_VALUE_STREAM_H_
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>
/*
* stream buffer can be used to store key value pair
*
*/
class KeyValueStream
{
public:
static const int INIT_BUFFER_SIZE = 1024;
enum ValueType
{
CharType,
IntType,
floatType,
doubleType,
StringType,
TimeType
};
typedef struct tagStreamBuffer
{
char* buffer;
size_t size;
size_t used;
tagStreamBuffer* prev;
tagStreamBuffer():buffer(0),size(0),used(0), prev(0)
{
}
}StreamBuffer, *pStreamBuffer;
/*
*
*
*/
explicit KeyValueStream( size_t bytes = INIT_BUFFER_SIZE ):m_streamBuffer(0), m_pairCount(0),
m_headStreamBuffer( new StreamBuffer)
{
Init( bytes );
*m_headStreamBuffer = *m_streamBuffer;
}
/*
*
*
*/
~KeyValueStream()
{
Clear();
}
/*
* Clear all buffer
*
*/
void Clear()
{
pStreamBuffer cur = m_streamBuffer;
pStreamBuffer prev = 0;
while( cur )
{
prev = cur->prev;
free( cur );
cur = prev;
}
delete m_headStreamBuffer;
m_headStreamBuffer = 0;
}
/*
* Insert key number pair to buffer
*
*/
void InsertNumber( const char* key, int number )
{
InsertKey( key );
void* buf = GetBuffer( sizeof(int) + 1 );
*(char*)buf = IntType;
*(int*)((char*)buf + 1) = number;
m_pairCount++;
}
/*
*Insert key char pair to buffer
*
*/
void InsertChar( const char* key, char c )
{
InsertKey( key );
void* buf = GetBuffer( sizeof(char) + 1 );
*(char*)buf = CharType;
*(char*)((char*)buf + 1) = c;
m_pairCount++;
}
/*
*Insert key string pair to buffer
*
*/
void InsertString( const char* key, const char* str )
{
InsertKey( key );
size_t len = strlen( str );
void* buf = GetBuffer( len + 4 + 1 );
*(char*)buf = StringType;
*(int*)((char*)buf + 1) = len;
memcpy( (char*)buf + 5, str, len );
m_pairCount++;
}
/*
*Insert key time pair to buffer
*
*/
void InsertTime( const char* key, time_t time )
{
InsertKey( key );
void* buf = GetBuffer( sizeof(time_t) + 1 );
*(char*)buf = TimeType;
*(time_t*)((char*)buf + 1) = time;
m_pairCount++;
}
/*
*Insert key float pair to buffer
*
*/
void InsertFloat( const char* key, float number )
{
InsertKey( key );
void* buf = GetBuffer( sizeof(float) + 1 );
*(char*)buf = floatType;
*(float*)((char*)buf + 1) = number;
m_pairCount++;
}
/*
*Insert key double pair to buffer
*
*/
void InsertDouble( const char* key, double number )
{
InsertKey( key );
void* buf = GetBuffer( sizeof(double) + 1 );
*(char*)buf = doubleType;
*(double*)((char*)buf + 1) = number;
m_pairCount++;
}
/*
*get number value by key from buffer
*
*/
int GetNumber( const char* key )
{
void* buf = GetValueByKey( key, strlen(key) );
assert( *(char*)buf == IntType );
return *(int*)((char*)buf + 1);
}
/*
*get char value by key from buffer
*
*/
char GetChar( const char* key )
{
void* buf = GetValueByKey( key, strlen(key) );
assert( *(char*)buf == CharType );
return *(char*)((char*)buf + 1);
}
/*
*get string value by key from buffer
*
*/
const char* GetString( const char* key )
{
void* buf = GetValueByKey( key, strlen(key) );
assert( *(char*)buf == StringType );
return (const char*)((char*)buf + 1 + 4);
}
/*
*get time value by key from buffer
*
*/
time_t GetTime( const char* key )
{
void* buf = GetValueByKey( key, strlen(key) );
assert( *(char*)buf == TimeType );
return *(time_t*)((char*)buf + 1);
}
/*
*get float value by key from buffer
*
*/
float GetFloat( const char* key )
{
void* buf = GetValueByKey( key, strlen(key) );
assert( *(char*)buf == floatType );
return *(float*)((char*)buf + 1);
}
/*
*get double value by key from buffer
*
*/
double GetDouble( const char* key )
{
void* buf = GetValueByKey( key, strlen(key) );
assert( *(char*)buf == doubleType );
return *(double*)((char*)buf + 1);
}
/*
*implement get value by key
*
*/
void* GetValueByKey( const char* key, size_t len )
{
char* buf = m_headStreamBuffer->buffer;
char* endBuf = m_headStreamBuffer->buffer + m_streamBuffer->size;
StreamBuffer* curStreamBuf = m_headStreamBuffer;
while( buf )
{
if( buf >= endBuf )
{
buf = (char*)curStreamBuf->prev;
curStreamBuf = curStreamBuf->prev;
}
if( *buf == len )
{
if( !strncmp( buf + 1, key, len ) )
{
return buf + 1 + *buf;
}
}
//else
{
char keyLen = *buf;
char type = *(char*)((char*)buf + 1 + keyLen);
int valueLen = 0;
switch( type )
{
case IntType:
valueLen = sizeof(int) + 1;
break;
case CharType:
valueLen = sizeof(char) + 1;
break;
case floatType:
valueLen = sizeof(float) + 1;
break;
case doubleType:
valueLen = sizeof(double) + 1;
break;
case TimeType:
valueLen = sizeof(time_t) + 1;
break;
case StringType:
valueLen = *(int*)((char*)buf + 1 + keyLen + 1);
break;
default:
break;
}
buf += 1 + keyLen + valueLen;
if( type == StringType)
buf += 5;
}
}
return NULL;
}
private:
/*
* implement key to buffer
*
*/
void InsertKey( const char* key )
{
size_t len = strlen(key);
len++;
void* buf = GetBuffer( len );
*(char*)buf = len - 1;
memcpy( (char*)buf + 1, key, len - 1 );
}
/*
* allocate new buffer given size
*
*/
void* GetBuffer( size_t bytes )
{
if( m_streamBuffer->used + bytes > m_streamBuffer->size )
{
Init( bytes );
}
void* ptr = m_streamBuffer->buffer;
m_streamBuffer->buffer += bytes;
m_streamBuffer->used += bytes;
return ptr;
}
/*
*init
*/
void Init( size_t bytes )
{
if( bytes < INIT_BUFFER_SIZE )
bytes = INIT_BUFFER_SIZE;
StreamBuffer* newBuf = (StreamBuffer*)malloc( sizeof(StreamBuffer) + bytes );
assert( newBuf );
newBuf->buffer = (char*)(newBuf + 1);
newBuf->size = bytes;
newBuf->used = 0;
newBuf->prev = 0;
newBuf->prev = m_streamBuffer;
m_streamBuffer = newBuf;
}
private:
StreamBuffer* m_streamBuffer;
size_t m_pairCount;
StreamBuffer* m_headStreamBuffer;
};
/*
* Test interface
*
*/
void TestKeyValueStream()
{
KeyValueStream stream;
stream.InsertChar( "char", 'a' );
stream.InsertNumber( "number", 1 );
stream.InsertNumber( "number1", 2 );
stream.InsertNumber( "number2", 3 );
stream.InsertNumber( "number3", 4 );
stream.InsertFloat( "float", 1.3 );
stream.InsertDouble( "double", 1.33 );
stream.InsertString( "string", "comefromechina");
time_t timer;
time(&timer);
stream.InsertTime("time", timer );
assert( stream.GetChar("char") == 'a');
assert( stream.GetNumber("number") == 1);
assert( stream.GetNumber("number1") == 2);
assert( stream.GetNumber("number2") == 3);
assert( stream.GetNumber("number3") == 4);
assert( (stream.GetFloat("float") - 1.3) < 0.0000001 );
assert( (stream.GetDouble("double") - 1.33) < 0.000001);
assert( !strncmp( stream.GetString("string"), "comefromechina", strlen("comefromechina")));
assert( stream.GetTime("time") == timer );
}
#endif