engine/script/src/script_json.cpp
/** Convert a JSON document to Lua table. (See dmScript::JsonToLua)
     * @note Doesn't free the document upon error
     * @note Doesn't reset the Lua stack upon error
     * @return <0 if it fails. >=0 if it succeeds (index of next JSON node to handle)
     */
Convert a JSON document to Lua table. (See dmScript::JsonToLua)
@note Doesn't free the document upon error
@note Doesn't reset the Lua stack upon error
@return <0 if it fails. >=0 if it succeeds (index of next JSON node to handle)
Convert a JSON document to Lua table . ( See dmScript :: JsonToLua ) @note Doesn ' t free the document upon error @note Doesn ' t reset the Lua stack upon error @return <0 if it fails . > = 0 if it succeeds ( index of next JSON node to handle )
static int JsonToLuaInternal(lua_State* L, dmJson::Document* doc, int index, char* error_str_out, size_t error_str_size)
    {
        const uint32_t buffer_len = 3 + DBL_MANT_DIG - DBL_MIN_EXP + 1;
        if (index >= doc->m_NodeCount)
        {
            dmSnPrintf(error_str_out, error_str_size, "Unexpected JSON index, unable to parse content.");
            return -1;
        }
        const dmJson::Node& n = doc->m_Nodes[index];
        const char* json = doc->m_Json;
        uint32_t l = n.m_End - n.m_Start;
        switch (n.m_Type)
        {
        case dmJson::TYPE_PRIMITIVE:
            if (l == 4 && memcmp(json + n.m_Start, "null", 4) == 0)
            {
                lua_pushnil(L);
            }
            else if (l == 4 && memcmp(json + n.m_Start, "true", 4) == 0)
            {
                lua_pushboolean(L, 1);
            }
            else if (l == 5 && memcmp(json + n.m_Start, "false", 5) == 0)
            {
                lua_pushboolean(L, 0);
            }
            else
            {
                char buffer[buffer_len] = { 0 };
                memcpy(buffer, json + n.m_Start, dmMath::Min(buffer_len - 1, l));
                uint32_t bytes_read = 0;
                double value = 0.0f;
                int result = sscanf(buffer, "%lf%n", &value, &bytes_read);
#if defined(__NX__)
                if (result == 1 && bytes_read == l+1 && value == 0)
                {
                    bytes_read--;
                }
#endif
                if (result == 1 && bytes_read == dmMath::Min(buffer_len - 1, l))
                {
                    lua_pushnumber(L, value);
                }
                else
                {
                    dmSnPrintf(error_str_out, error_str_size, "Invalid JSON primitive: %s", buffer);
                    return -1;
                }
            }
            return index + 1;
        case dmJson::TYPE_STRING:
            lua_pushlstring(L, json + n.m_Start, l);
            return index + 1;
        case dmJson::TYPE_ARRAY:
            lua_createtable(L, n.m_Size, 0);
            ++index;
            for (int i = 0; i < n.m_Size; ++i)
            {
                index = JsonToLuaInternal(L, doc, index, error_str_out, error_str_size);
                if (index < 0)
                    return -1;
                lua_rawseti(L, -2, i+1);
            }
            return index;
        case dmJson::TYPE_OBJECT:
            if ((n.m_Size % 2) == 0)
            {
                lua_createtable(L, 0, n.m_Size);
                ++index;
                for (int i = 0; i < n.m_Size; i += 2)
                {
                    index = JsonToLuaInternal(L, doc, index, error_str_out, error_str_size);
                    if (index < 0)
                        return -1;
                    index = JsonToLuaInternal(L, doc, index, error_str_out, error_str_size);
                    if (index < 0)
                        return -1;
                    lua_rawset(L, -3);
                }
                return index;
            }
            else
            {
                char buffer[buffer_len] = { 0 };
                memcpy(buffer, json + n.m_Start, dmMath::Min(buffer_len - 1, l));
                dmSnPrintf(error_str_out, error_str_size, "Incomplete JSON object: %s", buffer);
                return -1;
            }
        }
        dmSnPrintf(error_str_out, error_str_size, "Unsupported JSON type (%d), unable to parse content.", n.m_Type);
        return -1;
    }
static int JsonToLuaInternal ( lua_State * L , dmJson :: Document * doc , int index , char * error_str_out , size_t error_str_size ) { const uint32_t buffer_len = 3 + DBL_MANT_DIG - DBL_MIN_EXP + 1 ; if ( index >= doc -> m_NodeCount ) { dmSnPrintf ( error_str_out , error_str_size , " " ) ; return -1 ; } const dmJson :: Node & n = doc -> m_Nodes [ index ] ; const char * json = doc -> m_Json ; uint32_t l = n . m_End - n . m_Start ; switch ( n . m_Type ) { case dmJson :: TYPE_PRIMITIVE : if ( l == 4 && memcmp ( json + n . m_Start , " " , 4 ) == 0 ) { lua_pushnil ( L ) ; } else if ( l == 4 && memcmp ( json + n . m_Start , " " , 4 ) == 0 ) { lua_pushboolean ( L , 1 ) ; } else if ( l == 5 && memcmp ( json + n . m_Start , " " , 5 ) == 0 ) { lua_pushboolean ( L , 0 ) ; } else { char buffer [ buffer_len ] = { 0 } ; memcpy ( buffer , json + n . m_Start , dmMath :: Min ( buffer_len - 1 , l ) ) ; uint32_t bytes_read = 0 ; double value = 0.0f ; int result = sscanf ( buffer , " " , & value , & bytes_read ) ; #if defined ( __NX__ ) if ( result == 1 && bytes_read == l + 1 && value == 0 ) { bytes_read -- ; } #endif if ( result == 1 && bytes_read == dmMath :: Min ( buffer_len - 1 , l ) ) { lua_pushnumber ( L , value ) ; } else { dmSnPrintf ( error_str_out , error_str_size , " " , buffer ) ; return -1 ; } } return index + 1 ; case dmJson :: TYPE_STRING : lua_pushlstring ( L , json + n . m_Start , l ) ; return index + 1 ; case dmJson :: TYPE_ARRAY : lua_createtable ( L , n . m_Size , 0 ) ; ++ index ; for ( int i = 0 ; i < n . m_Size ; ++ i ) { index = JsonToLuaInternal ( L , doc , index , error_str_out , error_str_size ) ; if ( index < 0 ) return -1 ; lua_rawseti ( L , -2 , i + 1 ) ; } return index ; case dmJson :: TYPE_OBJECT : if ( ( n . m_Size % 2 ) == 0 ) { lua_createtable ( L , 0 , n . m_Size ) ; ++ index ; for ( int i = 0 ; i < n . m_Size ; i += 2 ) { index = JsonToLuaInternal ( L , doc , index , error_str_out , error_str_size ) ; if ( index < 0 ) return -1 ; index = JsonToLuaInternal ( L , doc , index , error_str_out , error_str_size ) ; if ( index < 0 ) return -1 ; lua_rawset ( L , -3 ) ; } return index ; } else { char buffer [ buffer_len ] = { 0 } ; memcpy ( buffer , json + n . m_Start , dmMath :: Min ( buffer_len - 1 , l ) ) ; dmSnPrintf ( error_str_out , error_str_size , " " , buffer ) ; return -1 ; } } dmSnPrintf ( error_str_out , error_str_size , " " , n . m_Type ) ; return -1 ; }
Convert a JSON document to Lua table.
Convert a JSON document to Lua table .
// The maximum length of a IEEE 754 double (+ \0) // for some reason, if the value happens to be a 0, or -0 it seems the sscanf code is stepping // one character too far. However, as long as the result is ok, // and since the last character is a \0 , we'll let it slide // {1 2 3} is a valid object according to the jsmn parser, we need // to protect against this to avoid reading random memory.