summaryrefslogtreecommitdiff
path: root/Build/source/libs/pplib/pplib-src/doc/ppnew.rst
blob: 4a0a3b42887566fa20480afa087207a9a1fc2e04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

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.