Skip to content

Clean up the cJSON struct #63

@FSMaxB

Description

@FSMaxB

Currently theres three ways the cJSON struct can be improved:

  1. Get rid of valueint
  2. Use a union for valuestring and valuedouble
  3. Using good names for the elements

If you don't think this is a good idea, please tell me why.

Let me explain:

Getting rid of valueint

  • Having both valueint and valuedouble introduces unnecessary complexity in cJSON.
  • Having both valueint and valuedouble increases the chance of misuse by users of the library
  • With an IEEE754 compliant floating point implementation, valueint is not bringing any extra value on platforms that have integers smaller than 32 bit
    • double can store integers up to 53 bits (> 32)
    • even if you have a 64 bit integer, this code prevents it from being useful, because it only works if the integer fits into the double type completely.
    • that means, that even on a floating point implementation that is not IEEE754 compliant, the range of supported numbers is completely bounded by the implementation of double, cJSON will never print an exact value of an integer bigger than the biggest exact integer that can be represented by double
  • The valueint is using between 2-8 bytes that are completely wasted
    • it might be even more because of alignment, if we have a processor that requires 8 byte alignment and has a 64 bit pointer type and a 32 bit integer type, the struct will look like this
      • next: 8 byte
      • prev 8 byte
      • child 8 byte
      • type 4 byte
      • 4 byte padding
      • valuestring 8 byte
      • valueint 4 byte
      • 4 byte padding
      • valuedouble 8 byte
      • string 8 byte
      • even though valueint has only 4 bytes, it takes up 8 bytes in the struct

Using a union of valuestring and valuedouble

As an instance of the cJSON struct can only be either a string type or a number type, not both at the same time. Therefore they can be stored at the same place in memory.

New version of the cJSON struct

typedef struct cJSON
{
    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *next;
    struct cJSON *previous;
    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
    struct cJSON *child;
    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
    char *name;
    union {
        /* The item's string, if type==cJSON_String */
        char *string;
        /* The item's number, if type==cJSON_Number */
        double number;
    }
    /* The type of the item, as above. */
    int type;
} cJSON;
  • renamed prev -> previous
  • valueint removed
  • renamed valuedouble -> number
  • renamed string -> name
  • renamed valuestring -> string
  • put string and number in a union
  • reorder the elements in the struct

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions