mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
doc: Move conventions to STYLE; ircd: Add additional README related.
This commit is contained in:
parent
1898cb307d
commit
8ccdd8568f
4 changed files with 111 additions and 72 deletions
50
doc/STYLE.md
50
doc/STYLE.md
|
@ -280,3 +280,53 @@ other words, if you have a prototype like `foo(const std::string &message)` you
|
|||
`message` because std::string is common and *what* the string is for is otherwise opaque.
|
||||
OTOH, if you have `foo(const options &options, const std::string &message)` one should skip
|
||||
the name for `options &` as it just adds redundant text to the prototype.
|
||||
|
||||
### Conventions
|
||||
|
||||
These are things you should know when mulling over the code as a whole.
|
||||
Importantly, knowing these things will help you avoid various gotchas and not
|
||||
waste your time debugging little surprises. You may or may not agree with some
|
||||
of these choices (specifically the lack of choices in many cases) but that's
|
||||
why they're explicitly discussed here.
|
||||
|
||||
#### Null termination
|
||||
|
||||
- We don't rely on null terminated strings. We always carry around two points
|
||||
of data to indicate such vectoring. Ideally this is a pair of pointers
|
||||
indicating the `begin`/`end` like an STL iterator range. `string_view` et al
|
||||
and the `buffer::` suite work this way.
|
||||
|
||||
- Null terminated strings can still be used and we even still create them in
|
||||
many places on purpose just because we can.
|
||||
|
||||
- Null terminated creations use the BSD `strl*` style and *not* the `strn*`
|
||||
style. Take note of this. When out of buffer space, such an `strl*` style
|
||||
will *always* add a null to the end of the buffer. Since we almost always
|
||||
have vectoring data and don't really need this null, a character of the string
|
||||
may be lost. This can happen when creating a buffer tight to the length of an
|
||||
expected string without a `+ 1`. This is actually the foundation of a case
|
||||
to move *back* to `strn*` style but it's not prudent at this time.
|
||||
|
||||
- Anything named `print*` like `print(mutable_buffer, T)` always composes null
|
||||
terminated output into the buffer. These functions usually return a size_t
|
||||
which count characters printed *not including null*. They may return a
|
||||
`string_view`/`const_buffer` of that size (never viewing the null).
|
||||
|
||||
#### assert() volatility
|
||||
|
||||
- Consider any code inside a runtime `assert()` statement to **entirely**
|
||||
disappear in optimized builds. Some implementations of `assert()` may only
|
||||
elide the boolean check and thus preserve the inner statement and the effects
|
||||
of its execution. We do not rely on this. Do not use `assert()` to check
|
||||
return values of statements that need to be executed in optimized builds.
|
||||
|
||||
- Furthermore, consider the **assert statement itself to be physically erased**
|
||||
from the code during optimized builds. Thus the following is a big mistake:
|
||||
|
||||
```
|
||||
if(foo)
|
||||
assert(!bar);
|
||||
|
||||
if(baz)
|
||||
bam();
|
||||
```
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
# IRCd Library API
|
||||
|
||||
### Getting Around
|
||||
#### Project Namespaces
|
||||
|
||||
##### libircd headers are organized into several aggregate "stacks"
|
||||
* `IRCD_` Preprocessor #define and macro namespace.
|
||||
* `RB_` Preprocessor #define and macro namespace (legacy / low-level).
|
||||
* `ircd_` C namespace and demangled bindings.
|
||||
* `ircd::` C++ namespace scope.
|
||||
|
||||
#### What To Include
|
||||
|
||||
##### libircd headers are organized into several aggregates groups
|
||||
|
||||
As a C++ project there are a lot of header files. Header files depend on other
|
||||
header files. We don't expect the developer of a compilation unit to figure out
|
||||
|
@ -10,75 +17,32 @@ an exact list of header files necessary to include for that unit. Instead we
|
|||
have aggregated groups of header files which are then precompiled. These
|
||||
aggregations are mostly oriented around a specific project dependency.
|
||||
|
||||
- Standard Include stack <ircd/ircd.h> is the main header group. This stack
|
||||
> Note: The term 'stack' may be found in place of the preferred term 'group'
|
||||
in other documentation.
|
||||
|
||||
- Standard Include group `<ircd/ircd.h>` is the main header group. This group
|
||||
involves the standard library and most of libircd. This is what an embedder
|
||||
will be working with. These headers will expose our own interfaces wrapping
|
||||
3rd party dependencies which are not included there. Note that the actual file
|
||||
to properly include this stack is <ircd/ircd.h> (not stdinc.h).
|
||||
3rd party dependencies which are not included there.
|
||||
|
||||
- Boost ASIO include stack <ircd/asio.h> is a header group exposing the
|
||||
There are actually two files in play here: `<ircd/stdinc.h>` and `<ircd/ircd.h>`.
|
||||
We have to offer two different pre-compilations: one with `-fPIC`
|
||||
and one without. Therefor the contents are in `<ircd/stdinc.h>` and the
|
||||
preprocessor determination for which is in `<ircd/ircd.h>`.
|
||||
|
||||
- Boost ASIO include group `<ircd/asio.h>` is a header group exposing the
|
||||
boost::asio library. We only involve this header in compilation units working
|
||||
directly with asio for networking et al. Involving this header file slows down
|
||||
compilation compared with the standard stack.
|
||||
compilation compared with the standard group.
|
||||
|
||||
- Boost Spirit include stack <ircd/spirit.h> is a header group exposing the
|
||||
- Boost Spirit include group `<ircd/spirit.h>` is a header group exposing the
|
||||
spirit parser framework to compilation units which involve formal grammars.
|
||||
Involving this header is a *monumental* slowdown when compiling.
|
||||
|
||||
- JavaScript include stack <ircd/js/js.h> is a header group exposing symbols
|
||||
- JavaScript include group `<ircd/js/js.h>` is a header group exposing symbols
|
||||
from the SpiderMonkey JS engine. Alternatively, <ircd/js.h> is part of the
|
||||
standard include stack which includes any wrapping to hide SpiderMonkey.
|
||||
standard include group which includes any wrapping to hide SpiderMonkey.
|
||||
|
||||
- MAPI include stack <ircd/mapi.h> is the standard header group for modules.
|
||||
This stack is an extension to the standard include stack but has specific
|
||||
- MAPI include group `<ircd/mapi.h>` is the standard header group for modules.
|
||||
This group is an extension to the standard include group but has specific
|
||||
tools for pluggable modules which are not part of the libircd core.
|
||||
|
||||
### Conventions
|
||||
|
||||
These are things you should know when mulling over the code as a whole.
|
||||
Importantly, knowing these things will help you avoid various gotchas and not
|
||||
waste your time debugging little surprises. You may or may not agree with some
|
||||
of these choices (specifically the lack of choices in many cases) but that's
|
||||
why they're explicitly discussed here.
|
||||
|
||||
#### Null termination
|
||||
|
||||
- We don't rely on null terminated strings. We always carry around two points
|
||||
of data to indicate such vectoring. Ideally this is a pair of pointers
|
||||
indicating the `begin`/`end` like an STL iterator range. `string_view` et al
|
||||
and the `buffer::` suite work this way.
|
||||
|
||||
- Null terminated strings can still be used and we even still create them in
|
||||
many places on purpose just because we can.
|
||||
|
||||
- Null terminated creations use the BSD `strl*` style and *not* the `strn*`
|
||||
style. Take note of this. When out of buffer space, such an `strl*` style
|
||||
will *always* add a null to the end of the buffer. Since we almost always
|
||||
have vectoring data and don't really need this null, a character of the string
|
||||
may be lost. This can happen when creating a buffer tight to the length of an
|
||||
expected string without a `+ 1`. This is actually the foundation of a case
|
||||
to move *back* to `strn*` style but it's not prudent at this time.
|
||||
|
||||
- Anything named `print*` like `print(mutable_buffer, T)` always composes null
|
||||
terminated output into the buffer. These functions usually return a size_t
|
||||
which count characters printed *not including null*. They may return a
|
||||
`string_view`/`const_buffer` of that size (never viewing the null).
|
||||
|
||||
#### assert() volatility
|
||||
|
||||
- Consider any code inside a runtime `assert()` statement to **entirely**
|
||||
disappear in optimized builds. Some implementations of `assert()` may only
|
||||
elide the boolean check and thus preserve the inner statement and the effects
|
||||
of its execution. We do not rely on this. Do not use `assert()` to check
|
||||
return values of statements that need to be executed in optimized builds.
|
||||
|
||||
- Furthermore, consider the **assert statement itself to be physically erased**
|
||||
from the code during optimized builds. Thus the following is a big mistake:
|
||||
|
||||
```
|
||||
if(foo)
|
||||
assert(!bar);
|
||||
|
||||
if(baz)
|
||||
bam();
|
||||
```
|
||||
|
|
|
@ -20,16 +20,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IRCd's namespacing is as follows:
|
||||
//
|
||||
// IRCD_ #define and macro namespace
|
||||
// RB_ #define and macro namespace (legacy, low-level)
|
||||
// ircd_ C namespace and demangled bindings
|
||||
// ircd:: C++ namespace
|
||||
//
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Standard includes
|
||||
|
|
|
@ -1,3 +1,38 @@
|
|||
# IRCd Library Definitions
|
||||
|
||||
This directory contains definitions and linkage for `libircd`
|
||||
|
||||
### Overview
|
||||
|
||||
`libircd` is designed specifically as a shared object library. The purpose of its
|
||||
shared'ness is to facilitate IRCd's modular design: IRCd ships with many other
|
||||
shared objects which introduce the "business logic" and features of the daemon. If
|
||||
`libircd` was not a shared object, every single module would have to include large
|
||||
amounts of duplicate code drawn from the static library. This would be a huge drag
|
||||
on both compilation and the runtime performance.
|
||||
|
||||
```
|
||||
(module) (module)
|
||||
| |
|
||||
| |
|
||||
V V
|
||||
|-------------|
|
||||
---------------------- | | < ---- (module)
|
||||
| | | |
|
||||
| User's executable | <---- | libircd |
|
||||
| | | |
|
||||
---------------------- | | < ---- (module)
|
||||
|-------------|
|
||||
^ ^
|
||||
| |
|
||||
| |
|
||||
(module) (module)
|
||||
|
||||
```
|
||||
|
||||
The user (which we may also refer to as the "embedder" elsewhere in
|
||||
documentation) only deals directly with `libircd` and not the modules.
|
||||
`libircd` is generally loaded with its symbols bound globally in the executable
|
||||
and on most platforms cannot be unloaded (or even loaded) manually and has not
|
||||
been tested to do so. As an aside, we do not summarily dismiss the idea of
|
||||
reload capability and would like to see it made possible.
|
||||
|
|
Loading…
Reference in a new issue