File: CODINGSTYLE.txt

package info (click to toggle)
libpodofo 0.9.6%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 6,228 kB
  • sloc: cpp: 61,697; ansic: 347; sh: 96; makefile: 15
file content (333 lines) | stat: -rw-r--r-- 12,559 bytes parent folder | download | duplicates (5)
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
This document tries to give an overview of the codingstyle used in PoDoFo.
To keep the code consistent every commit should apply to this codingstyle.

The codingstyle of PoDoFo is in no way perfect and is in parts not even the
preferred codingstyle of the maintainers. But consistency is more important
than personal preferences and most parts of the style can be applied through
simple editor settings.

       2006 Dominik Seichter <domseichter@web.de> 

0. Overall Rule
===============

    Documentation is an important part of PoDoFo. Every class and method
    should include appropriate documentation in Doxygen format so that
    automatic API documentation can be generated and the code can be
    easily understand by everyone.

    The comments are most important in the header files, though additional
    information may also be included in the source itself if necessary.  

1. Code formatting
==================

1.1 Indentation

     The code is indented by 4 spaces. No tabs and no discussion ;)
     EMACS users might apply those settings:
         (setq tab-width 4)                    ;; the the preferred tab-width
         (setq indent-tabs-mode nil)           ;; indent using spaces instead of tabs
         (setq c-basic-offset tab-width)

1.2 Brackets

    Brackets always start in a new line of their own. The only exception are
    class and struct declarations and try and catch blocks.

    Example:

    if( true ) 
    {
         // do something
    }

    but 

    class MyClass {

    };

    If only one line follows after an if or while statement, no brackets are
    needed, however they may be used if the author feels that there is a 
    possibility for future expansion in that area.


1.3 Inline functions

    Inline functions are declared in the class definition in the header file.
    They are implemented in the header file after the class definition.  
    The author may choose to either implement them directly at the same location
    as the declaration or may place them at the end of the header file (preferred).

2. Naming
=========

2.1 Variables

    Someone started to use hungarian notation in PoDoFo. Well, the maintainer
    thinks this was one of the worst ideas he ever had... . Nontheless, the
    point is consistency and not personall preference. 

    PoDoFo uses hungarian notation for the following types:

    enum typenames	  should start with an			E
    enum variables	  should start with an			e
    struture typesnames	  should start with a			T
    struture variables	  should start with a			t
    pointer		  should start with a			p
    strings		  should start with a			s
    c-strings		  should start with			psz
(pointer zero terminated)
    numbers		  should start with a			n
    long's		  should start with a			l
    bool's		  should start with a			b
    references            often  start with a                   r

    Example:

    bool  bDecision;
    long  lValue;
    char* pszString;
    int   nNumber;

2.2 Member variables

    Member variables in classes are additionally prefixed with "m_".

    Examples:

    class MyClass {

    private:
    bool m_bMemberVar;

    };

2.3 Methods

    All methods start with an uppercase letter and every new word is
    capitalized again.

    MyClass::FunctionWithLongName( long lParameter );

    Properties are set using a function with the prefix "Set", and retrieved with
    a "Get".   Also, unless there is a good reason not to - all "Getters" should be
    marked as const.

    MyClass::SetProperty( long lValue );
    long MyClass::GetProperty() const;

    Additionally, please use the prefixes "Has" and "Is" when appropriate.
    E.g.

    PdfDictionary::HasKey();
    PdfDocument::IsLinearized();

    Avoid the throw() qualifier (see 3.5).

2.4 NULL-Pointers

    NULL Pointers are initialized in the code with the constant NULL. Please
    do not use 0 or 0L but use NULL.

3. General Guidelines
===================

3.1 Casting

    C++ style casting is strongly preferred, and the use of C-style casts will
    generate warnings on gcc builds. Use, as appropriate,
        static_cast<>
        const_cast<>
        reinterpret_cast<>
    Dynamic casting and typeid are not presently used in PoDoFo.

    const_cast<> should be avoided unless it is absolutely required, especially
    for `const char *' variables that might ever take a string literal value.

3.2 Local variable declaration

    Local variables should always be declared closest to their point of use,
    and should be declared `const' wherever possible.

    For example:

    Thing f()
    {
       Thing ret;
       // blah blah blah
       ret = DoSomething();
       // blah blah blah
       return ret;
    }

    would be better written as:

    Thing f()
    {
       // blah blah blah
       Thing ret ( DoSomething() );
       // blah blah blah
       return ret;
    }

    Remember your const pointers:

    char * x;               Pointer to char
    const char * x;         Pointer to const char
    char * const x;         Const pointer to char
    const char * const x;   Const pointer to const char

3.3 Static arrays

    Static data should be declared as an array of const char rather than a
    pointer to const char whereever possible. This will help the compiler put
    it in the static read only data section of the compiled object, resulting
    in a smaller memory footprint, faster load times, and hardware protection
    against accidental writes to the data.

    const char myStaticData[] = "This is the right way".
    const char * myStaticData = "Avoid this way".

    Two dimensional arrays may be specified in a similar way - see
    s_szPdfVersions in PdfDefines.{cpp,h} . It's usually better to waste a few
    bytes by padding the array to the length of the longest member and get it
    into the readonly data section of the executable than it is to use an array
    of pointers to char and save a few bytes. Which is best is, however, dependent
    on what "a few bytes" is in a given situation.

3.4 Use of temporary objects

    Where possible, it can be better to use a temporary rather than
    storing a named object, eg:

    DoSomething( PdfName("blah") );

    rather than

    PdfName n("blah");
    DoSomething( n );

    as this makes it easier for the compiler to optimise the call, may reduce
    the stack size of the function, etc. Don't forget to consider the lifetime
    of the temporary, however.

3.5 The `throw' qualifier

    Under no circumstances use exception specifiers, even the empty exception
    specifier `throw()'. C++ checked exceptions - when implemented according
    to the standard - are essentially useless and may actually be costly. If
    you want to tell the compiler a method will not throw (as an optimisation)
    use a macro for __declspec(nothrow) instead. podofoapi provides
    appropriate macros for use in podofo. (Note that VC++ treats throw() as
    __declspec(nothrow) in violation of the standard, but that's all the more
    reason to just use __declspec(nothrow)).

    see:
    http://msdn2.microsoft.com/en-us/library/49147z04.aspx
    http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Function-Attributes.html

3.6 Exported API

    PoDoFo draws a distinction between exported and private API on some
    platforms (currently Windows DLL builds and gcc 4 with
    PODOFO_USE_VISIBILITY). To do this it uses some macros defined in
    podofoapi.h to tell the compiler what's public API that should appear
    in the DLL/shared library's symbol table. The rest is not exported.

    This may have several positive effects depending on the particular
    platform and compiler. It can result in a smaller binary, better link
    times, help the compiler optimise better, and ensure that API intended to
    be private to PoDoFo _cannot_ be called from outside it.

    If you add new classes to PoDoFo, annotate them with PODOFO_API
    as shown in podofoapi.h if they're intended as public API. If an outside
    user will ever need to reference those symbols directly (by constructing
    the class, calling its methods, etc) they're public.

    Note that classes that only inherit and implement an abstract interface
    (adding no other public methods intended for use outside PoDoFo) that're
    only constructed through a factory or through other PoDoFo classes need
    not be exported.

    If you have a class that needs to be exported as public API, but it has
    quite a few methods that do not need to be externally visible (private
    helper methods etc), you can annotate those with the PODOFO_LOCAL macro as
    shown in podofoapi.h . This omits just those methods from the symbol
    table. Note that if the methods are accessed via public or protected
    inline functions it is not safe to make them private.

    If in doubt, ask for help on podofo-users. It also helps to build PoDoFo
    as a DLL (Windows) or, on UNIX platforms, use gcc4 and enable visibility
    support. This will help catch cases where you forgot to export required
    API.

3.7 Memory allocations in inlined methods

    It's not safe to (directly) allocate or free
    heap memory in an inlined function, because it only works if the same
    runtime library is used in the shared library and the executable linking
    to the library. Using malloc and/or new in inlined methods will lead to
    crashes on MS Windows systems. It might be undetected on Linux systems
    (even though it is bad style on Linux, too), because most processes and
    libraries use the same runtime library on a Linux system.

    There's also no point inlining functions that call new / delete /
    malloc / free, because the memory allocation is dramatically more
    expensive than a mere function call is.

    Using STL classes that may perform allocations internally is fine since
    they tend to carry their own std::allocator instance (or reference,
    anyway) around with them.

3.8 Visibility of 3rd party headers

    If at all possible, it's desirable not to expose the use of 3rd party
    headers in the PoDoFo headers. Rather than including headers for required
    libraries, try to forward-declare required types and then include the
    header in the implementation (.cpp) files. If the header is widely used,
    you might want to put it in PdfDefinesPrivate.h . Widely used forward
    declarations can go in Pdf3rdPtyForwardDecl.h .

    Avoiding exposing used 3rd party headers means that users' build systems
    don't need to know how to find those headers, and means that users' programs
    don't get their namespaces polluted by unrelated symbols from libjpeg,
    zlib, libtiff, freetype, etc etc etc. As some headers (*cough*freetype*cough*)
    aren't trivial to reliably locate, this can really simplify the build of
    tools that use PoDoFo.

    This applies to some system headers too. <windows.h> for example is a
    difficult and quirky header. Its behaviour is strongly affected by
    a variety of preprocessor definitions and it scatters macros everywhere.
    We shouldn't be exposing it to library users, because it's quite likely
    they'll need to include it with different macro parameters, and theirs
    may conflict with ours or vice versa.

    If you need to include a 3rd party header to make something a direct
    member, consider making it a member by pointer instead, initializing
    it in the object's ctor and destroying it it the dtor. That way you
    don't need to include the 3rd party's header to get access to their
    type sizes in the PoDoFo headers, only in the .cpp files. See, for example,
    PdfMutex.h .

4. Structure
============

4.1 Project structure

The PoDoFo project is structure as follows. 

There are two libraries: podofo-base and podofo-doc. Podofo-base contains
everythign needed to work with reading, writing and modifying PDF files and
there objects. It should have a minimal set of dependencies. Podofo-doc
provides a rich interface, which also allows to easily create PDF files using
the PdfPainter and PdfFont infrastructure. 

Additionally, there are two more projects. The test/ subdirectory contains
tests for both libraries. All new tests shall go to the test/unit/
sub-projects to provide unit-tests for PoDoFo. Utility programs that come with
PoDoFo go into the tools/ subdirectory. These tools provide a direct benefit
for end users who want to work with PDF files on the commandline and are also
a nice way to showcase the features of the PoDoFo libraries to new
developers.