|  | @@ -533,54 +533,100 @@ static cJSON_bool insert_item_in_array(cJSON *array, size_t which, cJSON *newite
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  enum patch_operation { INVALID, ADD, REMOVE, REPLACE, MOVE, COPY, TEST };
 |  |  enum patch_operation { INVALID, ADD, REMOVE, REPLACE, MOVE, COPY, TEST };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
 |  | 
 | 
											
												
													
														|  | 
 |  | +static enum patch_operation decode_patch_operation(const cJSON * const patch)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  | -    cJSON *op = NULL;
 |  | 
 | 
											
												
													
														|  | -    cJSON *path = NULL;
 |  | 
 | 
											
												
													
														|  | -    cJSON *value = NULL;
 |  | 
 | 
											
												
													
														|  | -    cJSON *parent = NULL;
 |  | 
 | 
											
												
													
														|  | -    enum patch_operation opcode = INVALID;
 |  | 
 | 
											
												
													
														|  | -    unsigned char *parentptr = NULL;
 |  | 
 | 
											
												
													
														|  | -    unsigned char *childptr = NULL;
 |  | 
 | 
											
												
													
														|  | 
 |  | +    cJSON *operation = cJSON_GetObjectItem(patch, "op");
 | 
											
												
													
														|  | 
 |  | +    if (!cJSON_IsString(operation))
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        return INVALID;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    op = cJSON_GetObjectItem(patch, "op");
 |  | 
 | 
											
												
													
														|  | -    path = cJSON_GetObjectItem(patch, "path");
 |  | 
 | 
											
												
													
														|  | -    if (!cJSON_IsString(op) || !cJSON_IsString(path))
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if (strcmp(operation->valuestring, "add") == 0)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        /* malformed patch. */
 |  | 
 | 
											
												
													
														|  | -        return 2;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        return ADD;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    /* decode operation */
 |  | 
 | 
											
												
													
														|  | -    if (!strcmp(op->valuestring, "add"))
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if (strcmp(operation->valuestring, "remove") == 0)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        opcode = ADD;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        return REMOVE;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    else if (!strcmp(op->valuestring, "remove"))
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (strcmp(operation->valuestring, "replace") == 0)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        opcode = REMOVE;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        return REPLACE;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    else if (!strcmp(op->valuestring, "replace"))
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (strcmp(operation->valuestring, "move") == 0)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        opcode = REPLACE;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        return MOVE;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    else if (!strcmp(op->valuestring, "move"))
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (strcmp(operation->valuestring, "copy") == 0)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        opcode = MOVE;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        return COPY;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    else if (!strcmp(op->valuestring, "copy"))
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (strcmp(operation->valuestring, "test") == 0)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        opcode = COPY;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        return TEST;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    else if (!strcmp(op->valuestring, "test"))
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    return INVALID;
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +/* overwrite and existing item with another one and free resources on the way */
 | 
											
												
													
														|  | 
 |  | +static void overwrite_item(cJSON * const root, const cJSON replacement)
 | 
											
												
													
														|  | 
 |  | +{
 | 
											
												
													
														|  | 
 |  | +    if (root == NULL)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        /* compare value: {...} with the given path */
 |  | 
 | 
											
												
													
														|  | -        return cJSONUtils_Compare(cJSONUtils_GetPointer(object, path->valuestring), cJSON_GetObjectItem(patch, "value"));
 |  | 
 | 
											
												
													
														|  | 
 |  | +        return;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    else
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (root->string != NULL)
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        cJSON_free(root->string);
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    if (root->valuestring != NULL)
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        cJSON_free(root->valuestring);
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    if (root->child != NULL)
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        cJSON_Delete(root->child);
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    memcpy(root, &replacement, sizeof(cJSON));
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +static int cJSONUtils_ApplyPatch(cJSON *object, const cJSON *patch)
 | 
											
												
													
														|  | 
 |  | +{
 | 
											
												
													
														|  | 
 |  | +    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 = cJSON_GetObjectItem(patch, "path");
 | 
											
												
													
														|  | 
 |  | +    if (!cJSON_IsString(path))
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        /* unknown opcode. */
 |  | 
 | 
											
												
													
														|  | -        return 3;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        /* malformed patch. */
 | 
											
												
													
														|  | 
 |  | +        status = 2;
 | 
											
												
													
														|  | 
 |  | +        goto cleanup;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    opcode = decode_patch_operation(patch);
 | 
											
												
													
														|  | 
 |  | +    if (opcode == INVALID)
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        status = 3;
 | 
											
												
													
														|  | 
 |  | +        goto cleanup;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    else if (opcode == TEST)
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        /* compare value: {...} with the given path */
 | 
											
												
													
														|  | 
 |  | +        status = cJSONUtils_Compare(cJSONUtils_GetPointer(object, path->valuestring), cJSON_GetObjectItem(patch, "value"));
 | 
											
												
													
														|  | 
 |  | +        goto cleanup;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      /* special case for replacing the root */
 |  |      /* special case for replacing the root */
 | 
											
										
											
												
													
														|  | @@ -588,73 +634,47 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  |          if (opcode == REMOVE)
 |  |          if (opcode == REMOVE)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  | -            /* remove possible children */
 |  | 
 | 
											
												
													
														|  | -            if (object->child != NULL)
 |  | 
 | 
											
												
													
														|  | -            {
 |  | 
 | 
											
												
													
														|  | -                cJSON_Delete(object->child);
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | 
 |  | +            static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL};
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            /* remove other allocated resources */
 |  | 
 | 
											
												
													
														|  | -            if (object->string != NULL)
 |  | 
 | 
											
												
													
														|  | -            {
 |  | 
 | 
											
												
													
														|  | -                cJSON_free(object->string);
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            if (object->valuestring != NULL)
 |  | 
 | 
											
												
													
														|  | -            {
 |  | 
 | 
											
												
													
														|  | -                cJSON_free(object->valuestring);
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            /* make it invalid */
 |  | 
 | 
											
												
													
														|  | -            memset(object, '\0', sizeof(cJSON));
 |  | 
 | 
											
												
													
														|  | 
 |  | +            overwrite_item(object, invalid);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            return 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            status = 0;
 | 
											
												
													
														|  | 
 |  | +            goto cleanup;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          if ((opcode == REPLACE) || (opcode == ADD))
 |  |          if ((opcode == REPLACE) || (opcode == ADD))
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  | -            /* remove possible children */
 |  | 
 | 
											
												
													
														|  | -            if (object->child != NULL)
 |  | 
 | 
											
												
													
														|  | -            {
 |  | 
 | 
											
												
													
														|  | -                cJSON_Delete(object->child);
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            /* remove other allocated resources */
 |  | 
 | 
											
												
													
														|  | -            if (object->string != NULL)
 |  | 
 | 
											
												
													
														|  | -            {
 |  | 
 | 
											
												
													
														|  | -                cJSON_free(object->string);
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            if (object->valuestring != NULL)
 |  | 
 | 
											
												
													
														|  | -            {
 |  | 
 | 
											
												
													
														|  | -                cJSON_free(object->valuestring);
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  |              value = cJSON_GetObjectItem(patch, "value");
 |  |              value = cJSON_GetObjectItem(patch, "value");
 | 
											
												
													
														|  |              if (value == NULL)
 |  |              if (value == NULL)
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  |                  /* missing "value" for add/replace. */
 |  |                  /* missing "value" for add/replace. */
 | 
											
												
													
														|  | -                return 7;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                status = 7;
 | 
											
												
													
														|  | 
 |  | +                goto cleanup;
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              value = cJSON_Duplicate(value, 1);
 |  |              value = cJSON_Duplicate(value, 1);
 | 
											
												
													
														|  |              if (value == NULL)
 |  |              if (value == NULL)
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  |                  /* out of memory for add/replace. */
 |  |                  /* out of memory for add/replace. */
 | 
											
												
													
														|  | -                return 8;
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            /* the string "value" isn't needed */
 |  | 
 | 
											
												
													
														|  | -            if (value->string != NULL)
 |  | 
 | 
											
												
													
														|  | -            {
 |  | 
 | 
											
												
													
														|  | -                cJSON_free(value->string);
 |  | 
 | 
											
												
													
														|  | -                value->string = NULL;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                status = 8;
 | 
											
												
													
														|  | 
 |  | +                goto cleanup;
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            /* copy over the value object */
 |  | 
 | 
											
												
													
														|  | -            memcpy(object, value, sizeof(cJSON));
 |  | 
 | 
											
												
													
														|  | 
 |  | +            overwrite_item(object, *value);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              /* delete the duplicated value */
 |  |              /* delete the duplicated value */
 | 
											
												
													
														|  |              cJSON_free(value);
 |  |              cJSON_free(value);
 | 
											
												
													
														|  | 
 |  | +            value = NULL;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -            return 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /* the string "value" isn't needed */
 | 
											
												
													
														|  | 
 |  | +            if (object->string != NULL)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                cJSON_free(object->string);
 | 
											
												
													
														|  | 
 |  | +                object->string = NULL;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            status = 0;
 | 
											
												
													
														|  | 
 |  | +            goto cleanup;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -664,13 +684,15 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
 | 
											
												
													
														|  |          cJSON *old_item = cJSONUtils_PatchDetach(object, (unsigned char*)path->valuestring);
 |  |          cJSON *old_item = cJSONUtils_PatchDetach(object, (unsigned char*)path->valuestring);
 | 
											
												
													
														|  |          if (old_item == NULL)
 |  |          if (old_item == NULL)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  | -            return 13;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            status = 13;
 | 
											
												
													
														|  | 
 |  | +            goto cleanup;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          cJSON_Delete(old_item);
 |  |          cJSON_Delete(old_item);
 | 
											
												
													
														|  |          if (opcode == REMOVE)
 |  |          if (opcode == REMOVE)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              /* For Remove, this job is done. */
 |  |              /* For Remove, this job is done. */
 | 
											
												
													
														|  | -            return 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            status = 0;
 | 
											
												
													
														|  | 
 |  | +            goto cleanup;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -678,10 +700,11 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
 | 
											
												
													
														|  |      if ((opcode == MOVE) || (opcode == COPY))
 |  |      if ((opcode == MOVE) || (opcode == COPY))
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  |          cJSON *from = cJSON_GetObjectItem(patch, "from");
 |  |          cJSON *from = cJSON_GetObjectItem(patch, "from");
 | 
											
												
													
														|  | -        if (!from)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        if (from == NULL)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              /* missing "from" for copy/move. */
 |  |              /* missing "from" for copy/move. */
 | 
											
												
													
														|  | -            return 4;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            status = 4;
 | 
											
												
													
														|  | 
 |  | +            goto cleanup;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          if (opcode == MOVE)
 |  |          if (opcode == MOVE)
 | 
											
										
											
												
													
														|  | @@ -692,93 +715,103 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              value = cJSONUtils_GetPointer(object, from->valuestring);
 |  |              value = cJSONUtils_GetPointer(object, from->valuestring);
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  | -        if (!value)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        if (value == NULL)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              /* missing "from" for copy/move. */
 |  |              /* missing "from" for copy/move. */
 | 
											
												
													
														|  | -            return 5;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            status = 5;
 | 
											
												
													
														|  | 
 |  | +            goto cleanup;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          if (opcode == COPY)
 |  |          if (opcode == COPY)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              value = cJSON_Duplicate(value, 1);
 |  |              value = cJSON_Duplicate(value, 1);
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  | -        if (!value)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        if (value == NULL)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              /* out of memory for copy/move. */
 |  |              /* out of memory for copy/move. */
 | 
											
												
													
														|  | -            return 6;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            status = 6;
 | 
											
												
													
														|  | 
 |  | +            goto cleanup;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |      else /* Add/Replace uses "value". */
 |  |      else /* Add/Replace uses "value". */
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  |          value = cJSON_GetObjectItem(patch, "value");
 |  |          value = cJSON_GetObjectItem(patch, "value");
 | 
											
												
													
														|  | -        if (!value)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        if (value == NULL)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              /* missing "value" for add/replace. */
 |  |              /* missing "value" for add/replace. */
 | 
											
												
													
														|  | -            return 7;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            status = 7;
 | 
											
												
													
														|  | 
 |  | +            goto cleanup;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          value = cJSON_Duplicate(value, 1);
 |  |          value = cJSON_Duplicate(value, 1);
 | 
											
												
													
														|  | -        if (!value)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        if (value == NULL)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              /* out of memory for add/replace. */
 |  |              /* out of memory for add/replace. */
 | 
											
												
													
														|  | -            return 8;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            status = 8;
 | 
											
												
													
														|  | 
 |  | +            goto cleanup;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      /* Now, just add "value" to "path". */
 |  |      /* Now, just add "value" to "path". */
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      /* split pointer in parent and child */
 |  |      /* split pointer in parent and child */
 | 
											
												
													
														|  | -    parentptr = cJSONUtils_strdup((unsigned char*)path->valuestring);
 |  | 
 | 
											
												
													
														|  | -    childptr = (unsigned char*)strrchr((char*)parentptr, '/');
 |  | 
 | 
											
												
													
														|  | -    if (childptr)
 |  | 
 | 
											
												
													
														|  | 
 |  | +    parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring);
 | 
											
												
													
														|  | 
 |  | +    child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/');
 | 
											
												
													
														|  | 
 |  | +    if (child_pointer != NULL)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        *childptr++ = '\0';
 |  | 
 | 
											
												
													
														|  | 
 |  | +        child_pointer[0] = '\0';
 | 
											
												
													
														|  | 
 |  | +        child_pointer++;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    parent = cJSONUtils_GetPointer(object, (char*)parentptr);
 |  | 
 | 
											
												
													
														|  | -    cJSONUtils_InplaceDecodePointerString(childptr);
 |  | 
 | 
											
												
													
														|  | 
 |  | +    parent = cJSONUtils_GetPointer(object, (char*)parent_pointer);
 | 
											
												
													
														|  | 
 |  | +    cJSONUtils_InplaceDecodePointerString(child_pointer);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      /* add, remove, replace, move, copy, test. */
 |  |      /* add, remove, replace, move, copy, test. */
 | 
											
												
													
														|  | -    if ((parent == NULL) || (childptr == NULL))
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if ((parent == NULL) || (child_pointer == NULL))
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  |          /* Couldn't find object to add to. */
 |  |          /* Couldn't find object to add to. */
 | 
											
												
													
														|  | -        free(parentptr);
 |  | 
 | 
											
												
													
														|  | -        cJSON_Delete(value);
 |  | 
 | 
											
												
													
														|  | -        return 9;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        status = 9;
 | 
											
												
													
														|  | 
 |  | +        goto cleanup;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |      else if (cJSON_IsArray(parent))
 |  |      else if (cJSON_IsArray(parent))
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        if (!strcmp((char*)childptr, "-"))
 |  | 
 | 
											
												
													
														|  | 
 |  | +        if (strcmp((char*)child_pointer, "-") == 0)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              cJSON_AddItemToArray(parent, value);
 |  |              cJSON_AddItemToArray(parent, value);
 | 
											
												
													
														|  | 
 |  | +            value = NULL;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          else
 |  |          else
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              size_t index = 0;
 |  |              size_t index = 0;
 | 
											
												
													
														|  | -            if (!decode_array_index_from_pointer(childptr, &index))
 |  | 
 | 
											
												
													
														|  | 
 |  | +            if (!decode_array_index_from_pointer(child_pointer, &index))
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  | -                free(parentptr);
 |  | 
 | 
											
												
													
														|  | -                cJSON_Delete(value);
 |  | 
 | 
											
												
													
														|  | -                return 11;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                status = 11;
 | 
											
												
													
														|  | 
 |  | +                goto cleanup;
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              if (!insert_item_in_array(parent, index, value))
 |  |              if (!insert_item_in_array(parent, index, value))
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  | -                free(parentptr);
 |  | 
 | 
											
												
													
														|  | -                cJSON_Delete(value);
 |  | 
 | 
											
												
													
														|  | -                return 10;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                status = 10;
 | 
											
												
													
														|  | 
 |  | +                goto cleanup;
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  | 
 |  | +            value = NULL;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |      else if (cJSON_IsObject(parent))
 |  |      else if (cJSON_IsObject(parent))
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        cJSON_DeleteItemFromObject(parent, (char*)childptr);
 |  | 
 | 
											
												
													
														|  | -        cJSON_AddItemToObject(parent, (char*)childptr, value);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        cJSON_DeleteItemFromObject(parent, (char*)child_pointer);
 | 
											
												
													
														|  | 
 |  | +        cJSON_AddItemToObject(parent, (char*)child_pointer, value);
 | 
											
												
													
														|  | 
 |  | +        value = NULL;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    else
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +cleanup:
 | 
											
												
													
														|  | 
 |  | +    if (value != NULL)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  |          cJSON_Delete(value);
 |  |          cJSON_Delete(value);
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    free(parentptr);
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if (parent_pointer != NULL)
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        cJSON_free(parent_pointer);
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    return 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +    return status;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches)
 |  |  CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches)
 |