Move length-encoded integer/string functions to maxsql
This commit is contained in:
		@ -211,4 +211,14 @@ private:
 | 
			
		||||
    mutable ConversionError                  m_error;       /**< Error information */
 | 
			
		||||
    std::unordered_map<std::string, int64_t> m_col_indexes; /**< Map of column name -> index */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** Length-encoded integers */
 | 
			
		||||
size_t   leint_bytes(const uint8_t* ptr);
 | 
			
		||||
uint64_t leint_value(const uint8_t* c);
 | 
			
		||||
uint64_t leint_consume(uint8_t** c);
 | 
			
		||||
 | 
			
		||||
/** Length-encoded strings */
 | 
			
		||||
char* lestr_consume_dup(uint8_t** c);
 | 
			
		||||
char* lestr_consume(uint8_t** c, size_t* size);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <maxsql/mariadb.hh>
 | 
			
		||||
#include <maxscale/buffer.hh>
 | 
			
		||||
#include <maxscale/mysql_utils.hh>
 | 
			
		||||
#include <maxscale/protocol/mysql.hh>
 | 
			
		||||
@ -40,7 +41,7 @@ public:
 | 
			
		||||
     */
 | 
			
		||||
    LEncInt(uint8_t* pData)
 | 
			
		||||
    {
 | 
			
		||||
        m_value = mxs_leint_value(pData);
 | 
			
		||||
        m_value = leint_value(pData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -52,8 +53,8 @@ public:
 | 
			
		||||
     */
 | 
			
		||||
    LEncInt(uint8_t** ppData)
 | 
			
		||||
    {
 | 
			
		||||
        size_t nBytes = mxs_leint_bytes(*ppData);
 | 
			
		||||
        m_value = mxs_leint_value(*ppData);
 | 
			
		||||
        size_t nBytes = leint_bytes(*ppData);
 | 
			
		||||
        m_value = leint_value(*ppData);
 | 
			
		||||
        *ppData += nBytes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -229,7 +230,7 @@ public:
 | 
			
		||||
        // NULL is sent as 0xfb. See https://dev.mysql.com/doc/internals/en/com-query-response.html
 | 
			
		||||
        if (*pData != 0xfb)
 | 
			
		||||
        {
 | 
			
		||||
            m_pString = mxs_lestr_consume(&pData, &m_length);
 | 
			
		||||
            m_pString = lestr_consume(&pData, &m_length);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
@ -250,7 +251,7 @@ public:
 | 
			
		||||
        // NULL is sent as 0xfb. See https://dev.mysql.com/doc/internals/en/com-query-response.html
 | 
			
		||||
        if (**ppData != 0xfb)
 | 
			
		||||
        {
 | 
			
		||||
            m_pString = mxs_lestr_consume(ppData, &m_length);
 | 
			
		||||
            m_pString = lestr_consume(ppData, &m_length);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@
 | 
			
		||||
#include <errmsg.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <maxbase/alloc.h>
 | 
			
		||||
#include <maxbase/assert.h>
 | 
			
		||||
#include <maxbase/format.hh>
 | 
			
		||||
 | 
			
		||||
@ -333,4 +334,121 @@ bool QueryResult::ConversionError::error() const
 | 
			
		||||
{
 | 
			
		||||
    return !m_target_type.empty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Calculate the length of a length-encoded integer in bytes
 | 
			
		||||
 *
 | 
			
		||||
 * @param ptr Start of the length encoded value
 | 
			
		||||
 * @return Number of bytes before the actual value
 | 
			
		||||
 */
 | 
			
		||||
size_t leint_bytes(const uint8_t* ptr)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t val = *ptr;
 | 
			
		||||
    if (val < 0xfb)
 | 
			
		||||
    {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    else if (val == 0xfc)
 | 
			
		||||
    {
 | 
			
		||||
        return 3;
 | 
			
		||||
    }
 | 
			
		||||
    else if (val == 0xfd)
 | 
			
		||||
    {
 | 
			
		||||
        return 4;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        return 9;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Converts a length-encoded integer to @c uint64_t
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://dev.mysql.com/doc/internals/en/integer.html
 | 
			
		||||
 * @param c Pointer to the first byte of a length-encoded integer
 | 
			
		||||
 * @return The value converted to a standard unsigned integer
 | 
			
		||||
 */
 | 
			
		||||
uint64_t leint_value(const uint8_t* c)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t sz = 0;
 | 
			
		||||
    if (*c < 0xfb)
 | 
			
		||||
    {
 | 
			
		||||
        sz = *c;
 | 
			
		||||
    }
 | 
			
		||||
    else if (*c == 0xfc)
 | 
			
		||||
    {
 | 
			
		||||
        memcpy(&sz, c + 1, 2);
 | 
			
		||||
    }
 | 
			
		||||
    else if (*c == 0xfd)
 | 
			
		||||
    {
 | 
			
		||||
        memcpy(&sz, c + 1, 3);
 | 
			
		||||
    }
 | 
			
		||||
    else if (*c == 0xfe)
 | 
			
		||||
    {
 | 
			
		||||
        memcpy(&sz, c + 1, 8);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        mxb_assert(*c == 0xff);
 | 
			
		||||
        MXB_ERROR("Unexpected length encoding '%x' encountered when reading length-encoded integer.", *c);
 | 
			
		||||
    }
 | 
			
		||||
    return sz;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts a length-encoded integer into a standard unsigned integer
 | 
			
		||||
 * and advances the pointer to the next unrelated byte.
 | 
			
		||||
 *
 | 
			
		||||
 * @param c Pointer to the first byte of a length-encoded integer
 | 
			
		||||
 */
 | 
			
		||||
uint64_t leint_consume(uint8_t** c)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t rval = leint_value(*c);
 | 
			
		||||
    *c += leint_bytes(*c);
 | 
			
		||||
    return rval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Consume and duplicate a length-encoded string
 | 
			
		||||
 *
 | 
			
		||||
 * Converts a length-encoded string to a C string and advances the pointer to
 | 
			
		||||
 * the first byte after the string. The caller is responsible for freeing
 | 
			
		||||
 * the returned string.
 | 
			
		||||
 * @param c Pointer to the first byte of a valid packet.
 | 
			
		||||
 * @return The newly allocated string or NULL if memory allocation failed
 | 
			
		||||
 */
 | 
			
		||||
char* lestr_consume_dup(uint8_t** c)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t slen = leint_consume(c);
 | 
			
		||||
    char* str = (char*)MXS_MALLOC((slen + 1) * sizeof(char));
 | 
			
		||||
 | 
			
		||||
    if (str)
 | 
			
		||||
    {
 | 
			
		||||
        memcpy(str, *c, slen);
 | 
			
		||||
        str[slen] = '\0';
 | 
			
		||||
        *c += slen;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Consume a length-encoded string
 | 
			
		||||
 *
 | 
			
		||||
 * Converts length-encoded strings to character strings and advanced
 | 
			
		||||
 * the pointer to the next unrelated byte.
 | 
			
		||||
 * @param c Pointer to the start of the length-encoded string
 | 
			
		||||
 * @param size Pointer to a variable where the size of the string is stored
 | 
			
		||||
 * @return Pointer to the start of the string
 | 
			
		||||
 */
 | 
			
		||||
char* lestr_consume(uint8_t** c, size_t* size)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t slen = leint_consume(c);
 | 
			
		||||
    *size = slen;
 | 
			
		||||
    char* start = (char*) *c;
 | 
			
		||||
    *c += slen;
 | 
			
		||||
    return start;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user