void CRedisClient::hmget(const string &key, const CRedisClient::VecString &fields, CResult &result)
{
    _socket.clearBuffer();
    Command cmd( "HMGET" );
    cmd << key;

    VecString::const_iterator it = fields.begin();
    VecString::const_iterator end = fields.end();
    for ( ; it != end; ++it )
    {
        cmd << *it;
    }

    _sendCommand( cmd );
    _getReply( result );

    ReplyType type = result.getType();
    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_ARRAY != type )
    {
        throw ProtocolErr( "HMGET: data recved is not arry" );
    }
}
uint64_t CRedisClient::hgetall(const string &key, CRedisClient::MapString &values)
{
    CResult result;
    hgetall( key, result );
    ReplyType type = result.getType();

    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_ARRAY != type )
    {
        throw ProtocolErr( "HGETALL: data recv is not arry" );
    }

    CResult::ListCResult::const_iterator it = result.getArry().begin();
    CResult::ListCResult::const_iterator it2 = it;
    CResult::ListCResult::const_iterator end = result.getArry().end();

    for ( ; it != end; ++it )
    {
        it2 = it++;		// the next element is value.
        values.insert( MapString::value_type( *it2, *it ) );
    }
    return values.size();
}
void CRedisClient::flushdb()
{
    Command cmd( "FLUSHDB" );
    string status;
    _getStatus( cmd, status );
    if ( "OK"!=status)
        throw ProtocolErr( "FLUSHDB: data recved is not OK" );
}
void CRedisClient::configResetstat()
{
    Command cmd( "CONFIG" );
    cmd<<"RESETSTAT";
    string status;
    _getStatus( cmd, status );
    if ( "OK"!=status)
        throw ProtocolErr( "CONFIG RESETSTAT: data recved is not OK" );
}
void CRedisClient::slaveof(const string& host,const UInt16 port)
{
    Command cmd( "SLAVEOF" );
    cmd<<host<<port;
    string status;
    _getStatus( cmd, status );
    std::cout<<status<<std::endl;
    if (('O'==status[0])&&('K'==status[1]))
            return;
        throw ProtocolErr( "SLAVEOF: data recved is not OK" );
}
void CRedisClient::_set(const std::string &key,const std::string &value)
{
    CResult result;
    _set( key, value, result );

    if ( result.getType() == REDIS_REPLY_ERROR )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( result.getType() == REDIS_REPLY_STATUS )
    {
        if ( result.getStatus() == "OK" )
        {
            return;
        }else
        {
            throw ProtocolErr( "SET: data recved is not OK" );
        }
    }else
    {
        throw ProtocolErr( "SET: data recved is not status" );
    }
}
void CRedisClient::hmset(const string &key, const CRedisClient::MapString &pairs)
{
    CResult result;
    hmset( key, pairs ,result );

    ReplyType type = result.getType();
    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_STATUS != type )
    {
        throw ProtocolErr( "HMSET: data recved is not status" );
    }
}
bool CRedisClient::hscan(const string &key, int64_t cursor, VecString& values,const string &match, uint64_t count )
{
    static uint64_t lastCur = 0;
    uint64_t realCur = 0;
    CResult result;

    if ( cursor >= 0 )
    {
        realCur = cursor;
    }else
    {
        realCur = lastCur;
    }

    hscan( key, realCur, match, count, result );
    ReplyType type = result.getType() ;
    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_ARRAY != type )
    {
         throw ProtocolErr( "HSCAN: data recved is not arry" );
    }
    CResult::ListCResult::const_iterator it = result.getArry().begin();

    if ( REDIS_REPLY_STRING != it->getType() )
    {
        throw ProtocolErr( "HSCAN: first ele is not string" );
    }

    lastCur = _valueFromString<uint64_t>( it->getString() );
    ++it;

    _getValueFromArry( it->getArry(), values );

    return ( lastCur == 0 ? false : true );
}
uint64_t CRedisClient::hlen(const string &key)
{
   CResult result;
   hlen( key, result );

   ReplyType type = result.getType();
   if ( REDIS_REPLY_ERROR == type )
   {
        throw ReplyErr( result.getErrorString() );
   }else if ( REDIS_REPLY_INTEGERER != type )
   {
        throw ProtocolErr( "HLEN: data recved is not intergerer" );
   }
   return result.getInt();
}
float CRedisClient::hincrbyfloat(const string &key, const string &field, float increment)
{
    CResult result;
    hincrbyfloat( key, field, increment,result );

    ReplyType type = result.getType();
    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_STRING != type )
    {
        throw ProtocolErr( "HINCRBYFLOAT: data recved is not string" );
    }
    return _valueFromString<float>(  result.getString() );
}
uint64_t CRedisClient::hincrby(const string &key, const string &field, uint64_t increment)
{
    CResult result;
    hincrby( key, field, increment,result );

    ReplyType type = result.getType();
    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_INTEGERER != type )
    {
        throw ProtocolErr( "HINCRBY: data recved is not intgerer" );
    }
    return result.getInt();
}
bool CRedisClient::hsetnx(const string &key, const string &field, const string &value)
{
    CResult result;
    hsetnx( key, field, value,result );

    ReplyType type = result.getType();
    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_INTEGERER != type )
    {
        throw ProtocolErr( "HSETNX: data recved is not intergerer" );
    }
    return ( result.getInt()==1?true:false );
}
bool CRedisClient::hexists(const string &key, const string &field)
{
    CResult result;
    hexists( key, field, result );

    ReplyType type = result.getType();

    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_INTEGERER != type )
    {
        throw ProtocolErr( "HEXISTS: data recv is not intgerer" );
    }
    return result.getInt();
}
uint64_t CRedisClient::hdel( const string &key, const CRedisClient::VecString &fields )
{
    CResult result;
    hdel( key, fields, result );

    ReplyType type = result.getType();

    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_INTEGERER != type )
    {
        throw ProtocolErr( "HDEL: data recv is not intgerer" );
    }
    return result.getInt();
}
uint64_t CRedisClient::hkeys(const string &key, CRedisClient::VecString &values)
{
    CResult result;
    hkeys( key, result );

    ReplyType type = result.getType();
   if ( REDIS_REPLY_ERROR == type )
   {
       throw ReplyErr( result.getErrorString() );
   }else if ( REDIS_REPLY_ARRAY != type )
   {
        throw ProtocolErr("HKEYS: data recved is not arry");
   }

   _getValueFromArry( result.getArry(), values );
   return values.size();
}
uint8_t CRedisClient::hset(const std::string &key, const std::string &field, const std::string &value)
{
    CResult result;

   hset( key, field, value, result );
   ReplyType type = result.getType();
   if ( type == REDIS_REPLY_ERROR )
   {
        throw ReplyErr( result.getErrorString() );
   }

   if ( type != REDIS_REPLY_INTEGERER )
   {
       throw ProtocolErr( "HSET: data recved is not integerer" );
   }
   return result.getInt();
}
bool CRedisClient::setXX(const std::string &key, const std::string &value)
{
    CResult result;
    _set( key, value, result,"XX" );

    if ( result.getType() == REDIS_REPLY_ERROR )
    {
       throw ReplyErr( result.getErrorString() );
    } else if ( result.getType() == REDIS_REPLY_NIL )
    {
        return false;
    }else if ( result.getType() == REDIS_REPLY_STATUS )
    {
        return true;
    }else
    {
        throw ProtocolErr( "SET: data recved is not status" );
    }
}
uint64_t CRedisClient::hvals(const string &key, CRedisClient::VecString &values)
{
    CResult result;
    hvals( key, result );

    ReplyType type = result.getType();
    if ( REDIS_REPLY_ERROR == type )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( REDIS_REPLY_ARRAY != type )
    {
        throw ProtocolErr( "HVALS: data recved is not arry");
    }
    CResult::ListCResult::const_iterator it = result.getArry().begin();
    CResult::ListCResult::const_iterator end = result.getArry().end();
    for ( ; it != end; ++it )
    {
        values.push_back( static_cast<string>(*it) );
    }
    return values.size();
}
bool CRedisClient::get( const std::string &key, std::string &value )
{
    value.clear();
    CResult result;
    get( key, result );

    ReplyType type = result.getType();
    if ( type == REDIS_REPLY_ERROR )
    {
        throw ReplyErr( result.getErrorString() );
    }else if ( type == REDIS_REPLY_NIL )
    {
        return false;
    }else if ( type == REDIS_REPLY_STRING )
    {
        value = result.getString();
        return true;
    }else
    {
        throw ProtocolErr( "GET: data recved is not string" );
    }
}
bool CRedisClient::setEX(const std::string &key, const std::string &value, long time, SET_OPTION opt )
{
    string suffix;
    if ( DEFAULT == opt )
    {
        suffix.clear();
    }
    else if ( NX == opt )
    {
        suffix = "NX";
    }else if ( XX == opt )
    {
        suffix = "XX";
    }else
    {
        return false;
    }

    CResult result;
    _set( key, value, result,"EX", time,suffix );

    if ( result.getType() == REDIS_REPLY_ERROR )
    {
        throw ReplyErr( result.getErrorString() );
    }
    else if ( result.getType() == REDIS_REPLY_STATUS )
    {
       return true;
    }else if ( result.getType() == REDIS_REPLY_NIL )
    {
        return false;
    }else
    {
        throw ProtocolErr( "SET: data recved is not status" );
    }
}