问题描述:
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