1.x vs 2.x — pplib 0.1 documentation

# 1.x vs 2.x

## Allocation

Allocation mechanisms has been revised. All objects are still allocated from a private storage (called heap), but now the heap serves properly aligned memory chunks. Implementation of the heap is (hopefully) platform independent, so all `ARM_COMPLIANT` checks has been removed. Some details work differently on 32/64-bit machines, this distinction seems inevitable. Allocation related code has been moved to `util/utilmem*.c` files.

[There are actually 3 different allocators - heap, stock, and pool - each of which has 4 variants for 1, 2, 4 and 8 bytes alignment. So far `pplib` uses only the heap, but I want to have this part in a single place for a while. More notes about allocators in `utilmemallc.h`.]

`pplib` uses two heaps:

- bytes heap - providing 2-bytes aligned memory chunks for byte data
- structures heap - providing 8-bytes aligned chunks for all structures

2-bytes alignment of byte data is caused by implementation details / limits, `pplib` doesn’t make a use of it (could be unaligned as well). All the structures are stored in 8-bytes aligned chunks on both 32 and 64-bit machines (in some structures we use `double` and `int64_t`, which generally needs 8-bytes).

## Strings And Names

So far, both `ppname` and `ppstring` were aliases to `char *` with an extra structure hidden just below the data address. The idea was to make a string or name usable whenever chars array can, at the cost of some pointers trickery. Both names and strings keep an information about pdf-encoded data, as well as plain bytes data. I implemented this feature once `pplib 1.0` was almost done, and to avoid a revolution, I made that with yet another trick. This all was dirty and caused lots of alignment issues.

Now `ppstring` and `ppname` are structures, keeping data and size members, pretty much like `pparray`:

    struct ppname {
      ppbyte *data;
      size_t size;
      ppname *alterego;
      int flags;
    };

    struct ppstring {
      ppbyte *data;
      size_t size;
      ppstring *alterego;
      int flags;
    };

Data member is a pointer to (2-bytes aligned) bytes array – `ppbyte *`. `ppbyte` is an alias to `char`. `pplib` makes no assumptions about `ppbyte` signedness. [I’d prefer to have `uint8_t`, but better keep that in sync with `ppdict_get_*` suite, which accepts `char *`. Using `"string literals"` with `ppdict_get` function is the most common case, I guess.]

`ppname_size()` and `ppstring_size() `` now have trivial ``ppname_data()` and `ppstring_data()` counterparts:

    #define ppname_size(name) ((name)->size)
    #define ppname_data(name) ((name)->data)

    #define ppstring_size(string) ((string)->size)
    #define ppstring_data(string) ((string)->data)

Switching between encoded / decoded variants is made via explicit `alterego` member. If encoded and decoded forms are identical, then `self->alfterego == self` (never NULL). Helper functions for that:

    PPAPI ppname * ppname_decoded (ppname *name);
    PPAPI ppname * ppname_encoded (ppname *name);

    PPAPI ppbyte * ppname_decoded_data (ppname *name);
    PPAPI ppbyte * ppname_encoded_data (ppname *name);

    PPAPI ppstring * ppstring_decoded (ppstring *string);
    PPAPI ppstring * ppstring_encoded (ppstring *string);

    PPAPI ppbyte * ppstring_decoded_data (ppstring *string);
    PPAPI ppbyte * ppstring_encoded_data (ppstring *string);

Since `ppname` and `ppstring` are now structures, all API functions returning name/string or taking name/string as an argument, now take a pointer to name/string. Watch out for `ppdict_get_*` functions suite. They still accept `const char *` key as an argument, but `ppname` type can no longer be used there:

    ppname key;
    ppdict_get_something(dict, key);      // wrong
    ppdict_get_something(dict, key.data); // ok

    ppname *pkey;
    ppdict_get_something(dict, (const char *)pkey); // wrong
    ppdict_get_something(dict, pkey->data);         // ok

Consequently, functions / macros that used pointer to `ppname` (`ppdict_first()` / `ppdict_next()`), now needs `ppname **pname`.

## Cleanups

Some of unused utils were removed. There is still some code in utils part that is not used by the library, but I need this tollbox in many other places and don’t want to maintain two versions.

Some unification in integer types; `size_t` seems to be the best choice for and integer representing machine word (`unsigned long` is not long enough on windows), less utils dependencies, less compiler warnings.