Beispiel #1
0
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
{
    if (!cJSON_IsObject(patch))
    {
        /* scalar value, array or NULL, just duplicate */
        cJSON_Delete(target);
        return cJSON_Duplicate(patch, 1);
    }

    if (!cJSON_IsObject(target))
    {
        cJSON_Delete(target);
        target = cJSON_CreateObject();
    }

    patch = patch->child;
    while (patch)
    {
        if (cJSON_IsNull(patch))
        {
            /* NULL is the indicator to remove a value, see RFC7396 */
            cJSON_DeleteItemFromObject(target, patch->string);
        }
        else
        {
            cJSON *replaceme = cJSON_DetachItemFromObject(target, patch->string);
            cJSON_AddItemToObject(target, patch->string, cJSONUtils_MergePatch(replaceme, patch));
        }
        patch = patch->next;
    }
    return target;
}
Beispiel #2
0
static cJSON *merge_patch(cJSON *target, const cJSON * const patch, const cJSON_bool case_sensitive)
{
    cJSON *patch_child = NULL;

    if (!cJSON_IsObject(patch))
    {
        /* scalar value, array or NULL, just duplicate */
        cJSON_Delete(target);
        return cJSON_Duplicate(patch, 1);
    }

    if (!cJSON_IsObject(target))
    {
        cJSON_Delete(target);
        target = cJSON_CreateObject();
    }

    patch_child = patch->child;
    while (patch_child != NULL)
    {
        if (cJSON_IsNull(patch_child))
        {
            /* NULL is the indicator to remove a value, see RFC7396 */
            if (case_sensitive)
            {
                cJSON_DeleteItemFromObjectCaseSensitive(target, patch_child->string);
            }
            else
            {
                cJSON_DeleteItemFromObject(target, patch_child->string);
            }
        }
        else
        {
            cJSON *replace_me = NULL;
            cJSON *replacement = NULL;

            if (case_sensitive)
            {
                replace_me = cJSON_DetachItemFromObjectCaseSensitive(target, patch_child->string);
            }
            else
            {
                replace_me = cJSON_DetachItemFromObject(target, patch_child->string);
            }

            replacement = merge_patch(replace_me, patch_child, case_sensitive);
            if (replacement == NULL)
            {
                return NULL;
            }

            cJSON_AddItemToObject(target, patch_child->string, replacement);
        }
        patch_child = patch_child->next;
    }
    return target;
}
Beispiel #3
0
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to)
{
    cJSON *patch = NULL;
    if (!to)
    {
        /* patch to delete everything */
        return cJSON_CreateNull();
    }
    if (!cJSON_IsObject(to) || !cJSON_IsObject(from))
    {
        return cJSON_Duplicate(to, 1);
    }

    cJSONUtils_SortObject(from);
    cJSONUtils_SortObject(to);

    from = from->child;
    to = to->child;
    patch = cJSON_CreateObject();
    while (from || to)
    {
        int compare = from ? (to ? strcmp(from->string, to->string) : -1) : 1;
        if (compare < 0)
        {
            /* from has a value that to doesn't have -> remove */
            cJSON_AddItemToObject(patch, from->string, cJSON_CreateNull());
            from = from->next;
        }
        else if (compare > 0)
        {
            /* to has a value that from doesn't have -> add to patch */
            cJSON_AddItemToObject(patch, to->string, cJSON_Duplicate(to, 1));
            to = to->next;
        }
        else
        {
            /* object key exists in both objects */
            if (cJSONUtils_Compare(from, to))
            {
                /* not identical --> generate a patch */
                cJSON_AddItemToObject(patch, to->string, cJSONUtils_GenerateMergePatch(from, to));
            }
            /* next key in the object */
            from = from->next;
            to = to->next;
        }
    }
    if (!patch->child)
    {
        cJSON_Delete(patch);
        return NULL;
    }

    return patch;
}
Beispiel #4
0
CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target)
{
    size_t child_index = 0;
    cJSON *current_child = 0;

    if (object == target)
    {
        /* found */
        return (char*)cJSONUtils_strdup((const unsigned char*)"");
    }

    /* recursively search all children of the object or array */
    for (current_child = object->child; current_child != NULL; (void)(current_child = current_child->next), child_index++)
    {
        unsigned char *target_pointer = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(current_child, target);
        /* found the target? */
        if (target_pointer != NULL)
        {
            if (cJSON_IsArray(object))
            {
                /* reserve enough memory for a 64 bit integer + '/' and '\0' */
                unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + 20 + sizeof("/"));
                /* check if conversion to unsigned long is valid
                 * This should be eliminated at compile time by dead code elimination
                 * if size_t is an alias of unsigned long, or if it is bigger */
                if (child_index > ULONG_MAX)
                {
                    cJSON_free(target_pointer);
                    return NULL;
                }
                sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* /<array_index><path> */
                cJSON_free(target_pointer);

                return (char*)full_pointer;
            }

            if (cJSON_IsObject(object))
            {
                unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + pointer_encoded_length((unsigned char*)current_child->string) + 2);
                full_pointer[0] = '/';
                encode_string_as_pointer(full_pointer + 1, (unsigned char*)current_child->string);
                strcat((char*)full_pointer, (char*)target_pointer);
                cJSON_free(target_pointer);

                return (char*)full_pointer;
            }

            /* reached leaf of the tree, found nothing */
            cJSON_free(target_pointer);
            return NULL;
        }
    }

    /* not found */
    return NULL;
}
Beispiel #5
0
CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
{
    size_t c = 0;
    cJSON *obj = 0;

    if (object == target)
    {
        /* found */
        return (char*)cJSONUtils_strdup((const unsigned char*)"");
    }

    /* recursively search all children of the object */
    for (obj = object->child; obj; (void)(obj = obj->next), c++)
    {
        unsigned char *found = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(obj, target);
        if (found)
        {
            if (cJSON_IsArray(object))
            {
                /* reserve enough memory for a 64 bit integer + '/' and '\0' */
                unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + 23);
                /* check if conversion to unsigned long is valid
                 * This should be eliminated at compile time by dead code elimination
                 * if size_t is an alias of unsigned long, or if it is bigger */
                if (c > ULONG_MAX)
                {
                    free(found);
                    return NULL;
                }
                sprintf((char*)ret, "/%lu%s", (unsigned long)c, found); /* /<array_index><path> */
                free(found);

                return (char*)ret;
            }
            else if (cJSON_IsObject(object))
            {
                unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + cJSONUtils_PointerEncodedstrlen((unsigned char*)obj->string) + 2);
                *ret = '/';
                cJSONUtils_PointerEncodedstrcpy(ret + 1, (unsigned char*)obj->string);
                strcat((char*)ret, (char*)found);
                free(found);

                return (char*)ret;
            }

            /* reached leaf of the tree, found nothing */
            free(found);
            return NULL;
        }
    }

    /* not found */
    return NULL;
}
Beispiel #6
0
/* detach an item at the given path */
static cJSON *detach_path(cJSON *object, const unsigned char *path, const cJSON_bool case_sensitive)
{
    unsigned char *parent_pointer = NULL;
    unsigned char *child_pointer = NULL;
    cJSON *parent = NULL;
    cJSON *detached_item = NULL;

    /* copy path and split it in parent and child */
    parent_pointer = cJSONUtils_strdup(path);
    if (parent_pointer == NULL) {
        goto cleanup;
    }

    child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); /* last '/' */
    if (child_pointer == NULL)
    {
        goto cleanup;
    }
    /* split strings */
    child_pointer[0] = '\0';
    child_pointer++;

    parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive);
    decode_pointer_inplace(child_pointer);

    if (cJSON_IsArray(parent))
    {
        size_t index = 0;
        if (!decode_array_index_from_pointer(child_pointer, &index))
        {
            goto cleanup;
        }
        detached_item = detach_item_from_array(parent, index);
    }
    else if (cJSON_IsObject(parent))
    {
        detached_item = cJSON_DetachItemFromObject(parent, (char*)child_pointer);
    }
    else
    {
        /* Couldn't find object to remove child from. */
        goto cleanup;
    }

cleanup:
    if (parent_pointer != NULL)
    {
        cJSON_free(parent_pointer);
    }

    return detached_item;
}
static void
treasure_create_json_object_for_type_A_test(void)
{
    struct rnd *rnd = rnd_alloc_fake_min();
    struct treasure treasure;
    treasure_initialize(&treasure);
    struct treasure_type *treasure_type = treasure_type_by_letter('A');
    treasure_type_generate(treasure_type, rnd, &treasure);
    struct cJSON *json_object = treasure_create_json_object(&treasure);

    assert(cJSON_IsObject(json_object));

    char *json_string = cJSON_PrintUnformatted(json_object);
    char const *expected = "{"
                           "\"struct\":\"treasure\","
                           "\"rev\":0,"
                           "\"type\":\"A\","
                           "\"coins\":{"
                               "\"struct\":\"coins\","
                               "\"rev\":0,"
                               "\"pp\":100,"
                               "\"gp\":1000,"
                               "\"ep\":1000,"
                               "\"sp\":1000,"
                               "\"cp\":1000"
                           "},"
                           "\"gems\":["
                               "{\"struct\":\"gem\",\"rev\":0,\"size\":\"very small\",\"type\":\"ornamental\",\"kind\":\"azurite\",\"colors\":\"mottled deep blue\",\"value_percent_modifier\":0,\"value_rank_modifier\":7},"
                               "{\"struct\":\"gem\",\"rev\":0,\"size\":\"very small\",\"type\":\"ornamental\",\"kind\":\"azurite\",\"colors\":\"mottled deep blue\",\"value_percent_modifier\":0,\"value_rank_modifier\":7},"
                               "{\"struct\":\"gem\",\"rev\":0,\"size\":\"very small\",\"type\":\"ornamental\",\"kind\":\"azurite\",\"colors\":\"mottled deep blue\",\"value_percent_modifier\":0,\"value_rank_modifier\":7},"
                               "{\"struct\":\"gem\",\"rev\":0,\"size\":\"very small\",\"type\":\"ornamental\",\"kind\":\"azurite\",\"colors\":\"mottled deep blue\",\"value_percent_modifier\":0,\"value_rank_modifier\":7}"
                           "],"
                           "\"jewelry\":["
                               "{\"struct\":\"jewelry\",\"rev\":0,\"has_gems\":false,\"form\":\"anklet\",\"material\":\"ivory\",\"workmanship_bonus\":12,\"exceptional_stone_bonus\":0,\"value_in_cp\":400000},"
                               "{\"struct\":\"jewelry\",\"rev\":0,\"has_gems\":false,\"form\":\"anklet\",\"material\":\"ivory\",\"workmanship_bonus\":12,\"exceptional_stone_bonus\":0,\"value_in_cp\":400000},"
                               "{\"struct\":\"jewelry\",\"rev\":0,\"has_gems\":false,\"form\":\"anklet\",\"material\":\"ivory\",\"workmanship_bonus\":12,\"exceptional_stone_bonus\":0,\"value_in_cp\":400000}"
                           "],"
                           "\"maps\":["
                               "{\"struct\":\"treasure_map\",\"rev\":0,\"is_false\":true,\"treasure\":{\"struct\":\"treasure\",\"rev\":0,\"type\":null,\"coins\":{\"struct\":\"coins\",\"rev\":0,\"pp\":0,\"gp\":0,\"ep\":0,\"sp\":0,\"cp\":0},\"gems\":[],\"jewelry\":[],\"maps\":[],\"magic_items\":[]},\"true_description\":\"false map to treasure of (no treasure) in nearby labyrinth to the north\"},"
                               "{\"struct\":\"treasure_map\",\"rev\":0,\"is_false\":true,\"treasure\":{\"struct\":\"treasure\",\"rev\":0,\"type\":null,\"coins\":{\"struct\":\"coins\",\"rev\":0,\"pp\":0,\"gp\":0,\"ep\":0,\"sp\":0,\"cp\":0},\"gems\":[],\"jewelry\":[],\"maps\":[],\"magic_items\":[]},\"true_description\":\"false map to treasure of (no treasure) in nearby labyrinth to the north\"},"
                               "{\"struct\":\"treasure_map\",\"rev\":0,\"is_false\":true,\"treasure\":{\"struct\":\"treasure\",\"rev\":0,\"type\":null,\"coins\":{\"struct\":\"coins\",\"rev\":0,\"pp\":0,\"gp\":0,\"ep\":0,\"sp\":0,\"cp\":0},\"gems\":[],\"jewelry\":[],\"maps\":[],\"magic_items\":[]},\"true_description\":\"false map to treasure of (no treasure) in nearby labyrinth to the north\"}"
                           "],"
                           "\"magic_items\":[]"
                           "}";
    assert(str_eq(expected, json_string));

    free(json_string);
    cJSON_Delete(json_object);

    treasure_finalize(&treasure);
    rnd_free(rnd);
}
static int GLua_JSON_IsObject( lua_State *L )
{
	// Check and make sure we're using a valid index
	if( !FJSON_ValidateNode( L, 1 ) )
	{
		lua_pushnil(L);
		return 1;
	}

	cJSON *node = FJSON_RetrieveNode( L, 1 );
	lua_pushboolean( L, cJSON_IsObject( node ) );

	return 1;
}
void
treasure_map_initialize_from_json_object(struct treasure_map *treasure_map,
                                         struct cJSON *json_object)
{
    treasure_map_initialize(treasure_map);

    if ( ! cJSON_IsObject(json_object)) return;
    if ( ! json_object_has_struct_member(json_object, "treasure_map")) return;

    treasure_map->is_false = json_object_get_bool_value(json_object, "is_false", false);

    struct cJSON *treasure = cJSON_GetObjectItemCaseSensitive(json_object, "treasure");
    treasure_initialize_from_json_object(&treasure_map->treasure, treasure);

    treasure_map->true_description = json_object_alloc_string_value(json_object, "true_description", NULL);
}
Beispiel #10
0
CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON *object, const char *pointer)
{
    /* follow path of the pointer */
    while ((*pointer++ == '/') && object)
    {
        if (cJSON_IsArray(object))
        {
            size_t which = 0;
            /* parse array index */
            while ((*pointer >= '0') && (*pointer <= '9'))
            {
                which = (10 * which) + (size_t)(*pointer++ - '0');
            }
            if (*pointer && (*pointer != '/'))
            {
                /* not end of string or new path token */
                return NULL;
            }
            if (which > INT_MAX)
            {
                return NULL;
            }
            object = cJSON_GetArrayItem(object, (int)which);
        }
        else if (cJSON_IsObject(object))
        {
            object = object->child;
            /* GetObjectItem. */
            while (object && cJSONUtils_Pstrcasecmp((unsigned char*)object->string, (const unsigned char*)pointer))
            {
                object = object->next;
            }
            /* skip to the next path token or end of string */
            while (*pointer && (*pointer != '/'))
            {
                pointer++;
            }
        }
        else
        {
            return NULL;
        }
    }

    return object;
}
Beispiel #11
0
static cJSON *cJSONUtils_PatchDetach(cJSON *object, const unsigned char *path)
{
    unsigned char *parentptr = NULL;
    unsigned char *childptr = NULL;
    cJSON *parent = NULL;
    cJSON *ret = NULL;

    /* copy path and split it in parent and child */
    parentptr = cJSONUtils_strdup(path);
    if (parentptr == NULL) {
        return NULL;
    }

    childptr = (unsigned char*)strrchr((char*)parentptr, '/'); /* last '/' */
    if (childptr == NULL)
    {
        free(parentptr);
        return NULL;
    }
    /* split strings */
    *childptr++ = '\0';

    parent = cJSONUtils_GetPointer(object, (char*)parentptr);
    cJSONUtils_InplaceDecodePointerString(childptr);

    if (!parent)
    {
        /* Couldn't find object to remove child from. */
        ret = NULL;
    }
    else if (cJSON_IsArray(parent))
    {
        ret = cJSON_DetachItemFromArray(parent, atoi((char*)childptr));
    }
    else if (cJSON_IsObject(parent))
    {
        ret = cJSON_DetachItemFromObject(parent, (char*)childptr);
    }
    free(parentptr);

    /* return the detachted item */
    return ret;
}
Beispiel #12
0
static cJSON *get_item_from_pointer(cJSON * const object, const char * pointer, const cJSON_bool case_sensitive)
{
    cJSON *current_element = object;
    /* follow path of the pointer */
    while ((pointer[0] == '/') && (current_element != NULL))
    {
        pointer++;
        if (cJSON_IsArray(current_element))
        {
            size_t index = 0;
            if (!decode_array_index_from_pointer((const unsigned char*)pointer, &index))
            {
                return NULL;
            }

            current_element = get_array_item(current_element, index);
        }
        else if (cJSON_IsObject(current_element))
        {
            current_element = current_element->child;
            /* GetObjectItem. */
            while ((current_element != NULL) && !compare_pointers((unsigned char*)current_element->string, (const unsigned char*)pointer, case_sensitive))
            {
                current_element = current_element->next;
            }
            /* skip to the next path token or end of string */
            while ((pointer[0] != '\0') && (pointer[0] != '/'))
            {
                pointer++;
            }
        }
        else
        {
            return NULL;
        }
    }

    return current_element;
}
static void BG_ParseDamage ( weaponFireModeStats_t *fireModeStats, cJSON *damageNode, qboolean secondary )
{
    if ( !damageNode )
    {
        return;
    }
    
    if ( !secondary && cJSON_IsNumber (damageNode) )
    {
        fireModeStats->baseDamage = (short)cJSON_ToIntegerOpt (damageNode, 0);
    }
    else if ( cJSON_IsObject (damageNode) )
    {
        damageSettings_t darea;
        cJSON *node = NULL;
        qhandle_t areaHandle = 0;
        
        memset (&darea, 0, sizeof (darea));
        
        node = cJSON_GetObjectItem (damageNode, "damageradius");
        if ( node )
        {
            cJSON *child = NULL;
            const char *s = NULL;
            
            darea.radial = qtrue;
            
            child = cJSON_GetObjectItem (node, "start");
            darea.radiusParams.startRadius = (float)cJSON_ToNumber (child);
            
            child = cJSON_GetObjectItem (node, "end");
            darea.radiusParams.endRadius = (float)cJSON_ToNumber (child);
            
            child = cJSON_GetObjectItem (node, "parm");
            darea.radiusParams.generic1 = cJSON_ToInteger (child);
            
            child = cJSON_GetObjectItem (node, "falloff");
            s = cJSON_ToStringOpt (child, "constant");
            if ( Q_stricmp (s, "constant") == 0 )
                darea.radiusParams.damageFunc = DF_CONSTANT;
            else if ( Q_stricmp (s, "linear") == 0 )
                darea.radiusParams.damageFunc = DF_LINEAR;
            else if ( Q_stricmp (s, "gaussian") == 0 )
                darea.radiusParams.damageFunc = DF_GAUSSIAN;
            else
            {
                darea.radiusParams.damageFunc = DF_CONSTANT;
                Com_Printf ("Unknown damage falloff type used: %s. Defaulting to linear falloff.\n", s);
            }
                
            child = cJSON_GetObjectItem (node, "function");
            s = cJSON_ToStringOpt (child, "constant");
            if ( Q_stricmp (s, "linear") == 0 )
                darea.radiusParams.radiusFunc = RF_LINEAR;
            else if ( Q_stricmp (s, "nonlinear") == 0 )
                darea.radiusParams.radiusFunc = RF_NONLINEAR;
            else if ( Q_stricmp (s, "clamp") == 0 )
                darea.radiusParams.radiusFunc = RF_CLAMP;
            else if ( Q_stricmp (s, "wave") == 0 )
                darea.radiusParams.radiusFunc = RF_WAVE;
            else if ( Q_stricmp (s, "constant") == 0 )
                darea.radiusParams.radiusFunc = RF_CONSTANT;
            else
            {
                darea.radiusParams.radiusFunc = RF_CONSTANT;
                Com_Printf ("Unknown radius function used: %s; Defaulting to constant radius.\n", s);
            }
        }
        
        node = cJSON_GetObjectItem (damageNode, "duration");
        darea.lifetime = cJSON_ToIntegerOpt (node, 0);
        
        node = cJSON_GetObjectItem (damageNode, "delay");
        darea.delay = cJSON_ToIntegerOpt (node, 0);
        
        node = cJSON_GetObjectItem (damageNode, "damage");
        darea.damage = cJSON_ToIntegerOpt (node, 0);
        fireModeStats->baseDamage = darea.damage;
        
        node = cJSON_GetObjectItem (damageNode, "damagedelay");
        darea.damageDelay = cJSON_ToIntegerOpt (node, 0);
        
        node = cJSON_GetObjectItem (damageNode, "penetration");
        switch ( cJSON_ToIntegerOpt (node, 0) )
        {
            default:
            case 0: darea.penetrationType = PT_NONE; break;
            case 1: darea.penetrationType = PT_SHIELD; break;
            case 2: darea.penetrationType = PT_SHIELD_ARMOR; break;
            case 3: darea.penetrationType = PT_SHIELD_ARMOR_BUILDING; break;
        }
        
        node = cJSON_GetObjectItem (damageNode, "damagetype");
        if ( node )
        {
            int i = 0;
            const char *types[NUM_DAMAGE_TYPES];
            int numTypes = cJSON_ReadStringArray (node, NUM_DAMAGE_TYPES, types);
            
            for ( i = 0; i < numTypes; i++ )
            {
                if ( Q_stricmp (types[i], "annihilate") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_ANNIHILATION);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "concussion") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_CONCUSSION);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "cut") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_CUT);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "disintegrate") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_DISINTEGRATE);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "electric") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_ELECTRIC);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "explosion") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_EXPLOSION);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "fire") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= ( 1 << DT_FIRE );
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "freeze") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_FREEZE);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "implosion") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_IMPLOSION);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "stun") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_STUN);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "carbonite") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_CARBONITE);
                    darea.damageType = dType;
				}
                else
				{
                    Com_Printf ("Unknown damage type used: %s.\n", types[i]);
				}
            }
        }
        
        areaHandle = JKG_RegisterDamageSettings (&darea);
        if ( !secondary )
        {
            fireModeStats->damageTypeHandle = areaHandle;
        }
        else
        {
            fireModeStats->secondaryDmgHandle = areaHandle;
        }
    }
}
Beispiel #14
0
static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_sensitive)
{
    cJSON *path = NULL;
    cJSON *value = NULL;
    cJSON *parent = NULL;
    enum patch_operation opcode = INVALID;
    unsigned char *parent_pointer = NULL;
    unsigned char *child_pointer = NULL;
    int status = 0;

    path = get_object_item(patch, "path", case_sensitive);
    if (!cJSON_IsString(path))
    {
        /* malformed patch. */
        status = 2;
        goto cleanup;
    }

    opcode = decode_patch_operation(patch, case_sensitive);
    if (opcode == INVALID)
    {
        status = 3;
        goto cleanup;
    }
    else if (opcode == TEST)
    {
        /* compare value: {...} with the given path */
        status = !compare_json(get_item_from_pointer(object, path->valuestring, case_sensitive), get_object_item(patch, "value", case_sensitive), case_sensitive);
        goto cleanup;
    }

    /* special case for replacing the root */
    if (path->valuestring[0] == '\0')
    {
        if (opcode == REMOVE)
        {
            static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL};

            overwrite_item(object, invalid);

            status = 0;
            goto cleanup;
        }

        if ((opcode == REPLACE) || (opcode == ADD))
        {
            value = get_object_item(patch, "value", case_sensitive);
            if (value == NULL)
            {
                /* missing "value" for add/replace. */
                status = 7;
                goto cleanup;
            }

            value = cJSON_Duplicate(value, 1);
            if (value == NULL)
            {
                /* out of memory for add/replace. */
                status = 8;
                goto cleanup;
            }

            overwrite_item(object, *value);

            /* delete the duplicated value */
            cJSON_free(value);
            value = NULL;

            /* the string "value" isn't needed */
            if (object->string != NULL)
            {
                cJSON_free(object->string);
                object->string = NULL;
            }

            status = 0;
            goto cleanup;
        }
    }

    if ((opcode == REMOVE) || (opcode == REPLACE))
    {
        /* Get rid of old. */
        cJSON *old_item = detach_path(object, (unsigned char*)path->valuestring, case_sensitive);
        if (old_item == NULL)
        {
            status = 13;
            goto cleanup;
        }
        cJSON_Delete(old_item);
        if (opcode == REMOVE)
        {
            /* For Remove, this job is done. */
            status = 0;
            goto cleanup;
        }
    }

    /* Copy/Move uses "from". */
    if ((opcode == MOVE) || (opcode == COPY))
    {
        cJSON *from = get_object_item(patch, "from", case_sensitive);
        if (from == NULL)
        {
            /* missing "from" for copy/move. */
            status = 4;
            goto cleanup;
        }

        if (opcode == MOVE)
        {
            value = detach_path(object, (unsigned char*)from->valuestring, case_sensitive);
        }
        if (opcode == COPY)
        {
            value = get_item_from_pointer(object, from->valuestring, case_sensitive);
        }
        if (value == NULL)
        {
            /* missing "from" for copy/move. */
            status = 5;
            goto cleanup;
        }
        if (opcode == COPY)
        {
            value = cJSON_Duplicate(value, 1);
        }
        if (value == NULL)
        {
            /* out of memory for copy/move. */
            status = 6;
            goto cleanup;
        }
    }
    else /* Add/Replace uses "value". */
    {
        value = get_object_item(patch, "value", case_sensitive);
        if (value == NULL)
        {
            /* missing "value" for add/replace. */
            status = 7;
            goto cleanup;
        }
        value = cJSON_Duplicate(value, 1);
        if (value == NULL)
        {
            /* out of memory for add/replace. */
            status = 8;
            goto cleanup;
        }
    }

    /* Now, just add "value" to "path". */

    /* split pointer in parent and child */
    parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring);
    child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/');
    if (child_pointer != NULL)
    {
        child_pointer[0] = '\0';
        child_pointer++;
    }
    parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive);
    decode_pointer_inplace(child_pointer);

    /* add, remove, replace, move, copy, test. */
    if ((parent == NULL) || (child_pointer == NULL))
    {
        /* Couldn't find object to add to. */
        status = 9;
        goto cleanup;
    }
    else if (cJSON_IsArray(parent))
    {
        if (strcmp((char*)child_pointer, "-") == 0)
        {
            cJSON_AddItemToArray(parent, value);
            value = NULL;
        }
        else
        {
            size_t index = 0;
            if (!decode_array_index_from_pointer(child_pointer, &index))
            {
                status = 11;
                goto cleanup;
            }

            if (!insert_item_in_array(parent, index, value))
            {
                status = 10;
                goto cleanup;
            }
            value = NULL;
        }
    }
    else if (cJSON_IsObject(parent))
    {
        cJSON_DeleteItemFromObject(parent, (char*)child_pointer);
        cJSON_AddItemToObject(parent, (char*)child_pointer, value);
        value = NULL;
    }

cleanup:
    if (value != NULL)
    {
        cJSON_Delete(value);
    }
    if (parent_pointer != NULL)
    {
        cJSON_free(parent_pointer);
    }

    return status;
}
Beispiel #15
0
static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
{
    cJSON *op = NULL;
    cJSON *path = NULL;
    cJSON *value = NULL;
    cJSON *parent = NULL;
    int opcode = 0;
    unsigned char *parentptr = NULL;
    unsigned char *childptr = NULL;

    op = cJSON_GetObjectItem(patch, "op");
    path = cJSON_GetObjectItem(patch, "path");
    if (!op || !path)
    {
        /* malformed patch. */
        return 2;
    }

    /* decode operation */
    if (!strcmp(op->valuestring, "add"))
    {
        opcode = 0;
    }
    else if (!strcmp(op->valuestring, "remove"))
    {
        opcode = 1;
    }
    else if (!strcmp(op->valuestring, "replace"))
    {
        opcode = 2;
    }
    else if (!strcmp(op->valuestring, "move"))
    {
        opcode = 3;
    }
    else if (!strcmp(op->valuestring, "copy"))
    {
        opcode = 4;
    }
    else if (!strcmp(op->valuestring, "test"))
    {
        /* compare value: {...} with the given path */
        return cJSONUtils_Compare(cJSONUtils_GetPointer(object, path->valuestring), cJSON_GetObjectItem(patch, "value"));
    }
    else
    {
        /* unknown opcode. */
        return 3;
    }

    /* Remove/Replace */
    if ((opcode == 1) || (opcode == 2))
    {
        /* Get rid of old. */
        cJSON_Delete(cJSONUtils_PatchDetach(object, (unsigned char*)path->valuestring));
        if (opcode == 1)
        {
            /* For Remove, this is job done. */
            return 0;
        }
    }

    /* Copy/Move uses "from". */
    if ((opcode == 3) || (opcode == 4))
    {
        cJSON *from = cJSON_GetObjectItem(patch, "from");
        if (!from)
        {
            /* missing "from" for copy/move. */
            return 4;
        }

        if (opcode == 3)
        {
            /* move */
            value = cJSONUtils_PatchDetach(object, (unsigned char*)from->valuestring);
        }
        if (opcode == 4)
        {
            /* copy */
            value = cJSONUtils_GetPointer(object, from->valuestring);
        }
        if (!value)
        {
            /* missing "from" for copy/move. */
            return 5;
        }
        if (opcode == 4)
        {
            value = cJSON_Duplicate(value, 1);
        }
        if (!value)
        {
            /* out of memory for copy/move. */
            return 6;
        }
    }
    else /* Add/Replace uses "value". */
    {
        value = cJSON_GetObjectItem(patch, "value");
        if (!value)
        {
            /* missing "value" for add/replace. */
            return 7;
        }
        value = cJSON_Duplicate(value, 1);
        if (!value)
        {
            /* out of memory for add/replace. */
            return 8;
        }
    }

    /* Now, just add "value" to "path". */

    /* split pointer in parent and child */
    parentptr = cJSONUtils_strdup((unsigned char*)path->valuestring);
    childptr = (unsigned char*)strrchr((char*)parentptr, '/');
    if (childptr)
    {
        *childptr++ = '\0';
    }
    parent = cJSONUtils_GetPointer(object, (char*)parentptr);
    cJSONUtils_InplaceDecodePointerString(childptr);

    /* add, remove, replace, move, copy, test. */
    if (!parent)
    {
        /* Couldn't find object to add to. */
        free(parentptr);
        cJSON_Delete(value);
        return 9;
    }
    else if (cJSON_IsArray(parent))
    {
        if (!strcmp((char*)childptr, "-"))
        {
            cJSON_AddItemToArray(parent, value);
        }
        else
        {
            cJSON_InsertItemInArray(parent, atoi((char*)childptr), value);
        }
    }
    else if (cJSON_IsObject(parent))
    {
        cJSON_DeleteItemFromObject(parent, (char*)childptr);
        cJSON_AddItemToObject(parent, (char*)childptr, value);
    }
    else
    {
        cJSON_Delete(value);
    }
    free(parentptr);

    return 0;
}
Beispiel #16
0
static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive)
{
    cJSON *from_child = NULL;
    cJSON *to_child = NULL;
    cJSON *patch = NULL;
    if (to == NULL)
    {
        /* patch to delete everything */
        return cJSON_CreateNull();
    }
    if (!cJSON_IsObject(to) || !cJSON_IsObject(from))
    {
        return cJSON_Duplicate(to, 1);
    }

    sort_object(from, case_sensitive);
    sort_object(to, case_sensitive);

    from_child = from->child;
    to_child = to->child;
    patch = cJSON_CreateObject();
    while (from_child || to_child)
    {
        int diff;
        if (from_child != NULL)
        {
            if (to_child != NULL)
            {
                diff = strcmp(from_child->string, to_child->string);
            }
            else
            {
                diff = -1;
            }
        }
        else
        {
            diff = 1;
        }

        if (diff < 0)
        {
            /* from has a value that to doesn't have -> remove */
            cJSON_AddItemToObject(patch, from_child->string, cJSON_CreateNull());

            from_child = from_child->next;
        }
        else if (diff > 0)
        {
            /* to has a value that from doesn't have -> add to patch */
            cJSON_AddItemToObject(patch, to_child->string, cJSON_Duplicate(to_child, 1));

            to_child = to_child->next;
        }
        else
        {
            /* object key exists in both objects */
            if (!compare_json(from_child, to_child, case_sensitive))
            {
                /* not identical --> generate a patch */
                cJSON_AddItemToObject(patch, to_child->string, cJSONUtils_GenerateMergePatch(from_child, to_child));
            }

            /* next key in the object */
            from_child = from_child->next;
            to_child = to_child->next;
        }
    }
    if (patch->child == NULL)
    {
        /* no patch generated */
        cJSON_Delete(patch);
        return NULL;
    }

    return patch;
}
static void
treasure_create_json_object_test(void)
{
    struct rnd *rnd = rnd_alloc_fake_median();
    struct treasure treasure;
    treasure_initialize(&treasure);
    treasure_generate_magic_items(&treasure, rnd, 3, ANY_MAGIC_ITEM);
    struct cJSON *json_object = treasure_create_json_object(&treasure);

    assert(cJSON_IsObject(json_object));

    char *json_string = cJSON_PrintUnformatted(json_object);
    char const *expected = "{"
                           "\"struct\":\"treasure\","
                           "\"rev\":0,"
                           "\"type\":null,"
                           "\"coins\":{"
                               "\"struct\":\"coins\","
                               "\"rev\":0,"
                               "\"pp\":0,"
                               "\"gp\":0,"
                               "\"ep\":0,"
                               "\"sp\":0,"
                               "\"cp\":0"
                           "},"
                           "\"gems\":[],"
                           "\"jewelry\":[],"
                           "\"maps\":[],"
                           "\"magic_items\":["
                               "{"
                                   "\"struct\":\"magic_item\","
                                   "\"rev\":0,"
                                   "\"experience_points\":2000,"
                                   "\"true_description\":\"cloak of protection +2\","
                                   "\"true_details\":[],"
                                   "\"true_value_in_cp\":4000000,"
                                   "\"type\":\"miscellaneous\""
                               "},"
                               "{"
                                   "\"struct\":\"magic_item\","
                                   "\"rev\":0,"
                                   "\"experience_points\":2000,"
                                   "\"true_description\":\"cloak of protection +2\","
                                   "\"true_details\":[],"
                                   "\"true_value_in_cp\":4000000,"
                                   "\"type\":\"miscellaneous\""
                               "},"
                               "{"
                                   "\"struct\":\"magic_item\","
                                   "\"rev\":0,"
                                   "\"experience_points\":2000,"
                                   "\"true_description\":\"cloak of protection +2\","
                                   "\"true_details\":[],"
                                   "\"true_value_in_cp\":4000000,"
                                   "\"type\":\"miscellaneous\""
                               "}"
                           "]"
                           "}";
    assert(str_eq(expected, json_string));

    free(json_string);
    cJSON_Delete(json_object);

    treasure_finalize(&treasure);
    rnd_free(rnd);
}