beatbox-puredata/purest_json/manual/Contributing-and-Code-Docum...

844 lines
25 KiB
HTML
Raw Normal View History

2024-09-18 21:11:11 -03:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
Contributing and Code Documentation
</title>
<style>
/* Page tweaks */
.preview-page {
margin-top: 64px;
margin-bottom: 21px;
}
/* User-content tweaks */
.timeline-comment-wrapper > .timeline-comment:after,
.timeline-comment-wrapper > .timeline-comment:before {
content: none;
}
/* User-content overrides */
.discussion-timeline.wide {
width: 920px;
}
</style>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
<div class="preview-page" data-autorefresh-url="" id="preview-page">
<main id="js-repo-pjax-container">
<div class="clearfix new-discussion-timeline container-xl px-3 px-md-4 px-lg-5">
<div class="repository-content">
<div class="clearfix">
<div class="Layout Layout--flowRow-until-md Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end">
<div class="Layout-main">
<div class="Box md Box--responsive" id="readme">
<div class="Box-header d-flex border-bottom-0 flex-items-center flex-justify-between color-bg-default rounded-top-2">
<div class="d-flex flex-items-center">
<h2 class="Box-title">
Contributing and Code Documentation
</h2>
</div>
</div>
<div class="Box-body px-5 pb-5">
<article class="markdown-body entry-content container-lg" id="grip-content">
<p>
If you want to contribute to the development of the software, every help is much appreciated.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#bugs-and-wishes" id="user-content-bugs-and-wishes">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Bugs And Wishes
</h2>
<p>
If you found any bugs in the software or would like a feature implemented, please open a new issue on
<a href="https://github.com/residuum/PuRestJson/issues">
the bug tracker
</a>
or send an email to
<a href="mailto:purest-json-bugs@ix.residuum.org">
purest-json-bugs@ix.residuum.org
</a>
.
</p>
<h2>
<a aria-hidden="true" class="anchor" href="#development" id="user-content-development">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Development
</h2>
<p>
Feel free to fork the project and submit pull requests, if you want to implement some features or fix some bugs. If possible, please open a new issue on
<a href="https://github.com/residuum/PuRestJson/issues">
the bug tracker
</a>
, so that noone else tries to fix or implement the same issue.
</p>
<p>
If you need some help with writing externals for Pd, read the
<a href="http://iem.at/pd/externals-HOWTO/" rel="nofollow">
excellent how-to on that subject
</a>
.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#code-structure" id="user-content-code-structure">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Code structure
</h3>
<p>
The whole project in written in C99. C code is in subfolder
<code>
src/
</code>
. Every object and the library itself has a .c and a corresponding .h file.
<code>
purest_json.c
</code>
is only used to setup the library.
<code>
#define
</code>
s are done only in the .h files.
<code>
purest_json.h
</code>
is
<code>
#include
</code>
d in all objects.
</p>
<p>
Every object contains functions with a structure of
<code>
&lt;OBJECT&gt;_&lt;FUNCTION&gt;
</code>
with the exception of setup functions. Only functions that Pd needs to call are exported, and only exported functions are declared in the .h file, all other functions are static.
</p>
<p>
Shared functions used by more than one object are in directory
<code>
src/inc
</code>
. The functions are prefixed with the name of the file, e.g.
<code>
ctw.c
</code>
includes functions named
<code>
ctw_&lt;FUNCTION&gt;
</code>
.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#order-of-functions-and-declarations-in-c-files" id="user-content-order-of-functions-and-declarations-in-c-files">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Order of Functions And Declarations in .c Files
</h3>
<ol>
<li>
<code>
#include
</code>
s
</li>
<li>
<code>
t_class
</code>
declaration
</li>
<li>
<code>
struct
</code>
declarations
</li>
<li>
prototypes for static functions
</li>
<li>
implementation of static functions
</li>
<li>
setup functions
</li>
<li>
functions reacting to messages
</li>
<li>
constructor function
</li>
<li>
destructor function
</li>
</ol>
<h3>
<a aria-hidden="true" class="anchor" href="#names-of-setup-functions" id="user-content-names-of-setup-functions">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Names of Setup Functions
</h3>
<p>
When Pd tries to load an object, it is looking for the file with the correct platform specific suffix (.pd_linux, .pd_darwin, .dll, .pd_freebsd) and the same name, e.g. to create
<code>
[json-encode]
</code>
, Pd on Windows looks for a file
<code>
json-encode.dll
</code>
.
</p>
<p>
In this library file, Pd looks for a setup function according, depending on the name of the object:
</p>
<ul>
<li>
If the name contains a special character, that cannot be used in a C symbol (
<code>
-
</code>
,
<code>
~
</code>
,
<code>
.
</code>
, etc.), then this special character is converted to a hex representation using
<code>
sprintf(symname+i, "0x%02x", c);
</code>
where
<code>
c
</code>
is the special character. This resulting name is prefixed by
<code>
setup_
</code>
. So the function for creating
<code>
[json-encode]
</code>
must be called
<code>
setup_json0x2dencode
</code>
.
</li>
<li>
If the name can be converted to a C symbol, then the setup function must be the object name suffixed with
<code>
_setup
</code>
. So the function for creating
<code>
[urlparams]
</code>
must be called
<code>
urlparams_setup
</code>
.
</li>
</ul>
<h3>
<a aria-hidden="true" class="anchor" href="#names-of-other-exported-functions" id="user-content-names-of-other-exported-functions">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Names of Other Exported Functions
</h3>
<p>
If an object has a hyphen (
<code>
-
</code>
) in its name, then this is replaced by an underscore (
<code>
_
</code>
)
</p>
<ul>
<li>
Creation functions:
<code>
&lt;OBJECT&gt;_new
</code>
, e.g.
<code>
rest_new
</code>
.
</li>
<li>
Destruction functions:
<code>
&lt;OBJECT&gt;_free
</code>
, e.g.
<code>
rest_free
</code>
. Not every object needs to clean up on destruction, do not create this function then.
</li>
<li>
Generic message functions: If the function should be called based on the type of content, then the corresponding function is
<code>
&lt;OBJECT&gt;_&lt;TYPE&gt;
</code>
, e.g.
<code>
json_decode_symbol
</code>
,
<code>
json_encode_bang
</code>
.
</li>
<li>
HTTP request messages
<code>
[GET(
</code>
,
<code>
[POST(
</code>
,
<code>
[PUT(
</code>
,
<code>
[DELETE(
</code>
,
<code>
[HEAD(
</code>
,
<code>
[PATCH(
</code>
,
<code>
[TRACE(
</code>
, and
<code>
[OPTIONS(
</code>
:
<code>
&lt;OBJECT&gt;_command
</code>
, e.g.
<code>
[GET(
</code>
on
<code>
[rest]
</code>
calls
<code>
rest_command
</code>
.
</li>
<li>
Message functions: Every
<code>
[MESSAGE(
</code>
for the object has a corresponding function
<code>
&lt;OBJECT&gt;_&lt;MESSAGE&gt;
</code>
, e.g.
<code>
[cancel(
</code>
on
<code>
[oauth]
</code>
calls the function
<code>
oauth_cancel
</code>
.
</li>
</ul>
<h3>
<a aria-hidden="true" class="anchor" href="#names-of-static-functions" id="user-content-names-of-static-functions">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Names of Static Functions
</h3>
<p>
Static functions are prefixed with the name of the corresponding file without the .c extension, and an underscore. Function prototypes are declared in .c files before implemtations. Sometimes, the object names are abbreviated:
</p>
<ul>
<li>
<code>
json-decode.c
</code>
=&gt;
<code>
jdec_
</code>
</li>
<li>
<code>
json-encode.c
</code>
=&gt;
<code>
jenc_
</code>
</li>
<li>
<code>
oauth.c
</code>
=&gt;
<code>
oauth_
</code>
</li>
<li>
<code>
rest.c
</code>
=&gt;
<code>
rest_
</code>
</li>
<li>
<code>
urlparams.c
</code>
=&gt;
<code>
urlp_
</code>
</li>
</ul>
<h3>
<a aria-hidden="true" class="anchor" href="#content-of-included-files" id="user-content-content-of-included-files">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Content of Included Files
</h3>
<p>
All .c files that do not have a matching .h file contain only static functions and are
<code>
#include
</code>
d in files defining the objects. These source files are in subfolder
<code>
src/inc/
</code>
. They have the following properties:
</p>
<h4>
<a aria-hidden="true" class="anchor" href="#ctwc" id="user-content-ctwc">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
ctw.c
</h4>
<p>
ctw is short for
<strong>
c
</strong>
url
<strong>
t
</strong>
hread
<strong>
w
</strong>
rapper. As the name suggests, it contain functions for using threading for making requests with libcurl.
</p>
<p>
This file is used in
<code>
[oauth]
</code>
and
<code>
[rest]
</code>
. In both objects, a
<code>
struct _ctw
</code>
is the first member, so that casting is possible.
</p>
<p>
All functions are prefixed with
<code>
ctw_
</code>
.
</p>
<h4>
<a aria-hidden="true" class="anchor" href="#kvpc" id="user-content-kvpc">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
kvp.c
</h4>
<p>
kvp is short for
<strong>
k
</strong>
ey
<strong>
v
</strong>
alue
<strong>
p
</strong>
air. Three structs are defined in this file,
<code>
struct _v
</code>
,
<code>
struct _kvp
</code>
, and
<code>
struct _kvp_store
</code>
.
<code>
struct _kvp
</code>
is a key value pair, while
<code>
struct _kvp_store
</code>
includes a hash table of key value pair.
<code>
struct _v
</code>
is a value, containing a union of
<code>
t_float
</code>
,
<code>
char *
</code>
and
<code>
int
</code>
to distinguish between floats, strings and integers for JSON.
</p>
<p>
This file is used in
<code>
[json-encode]
</code>
and
<code>
[urlparams]
</code>
. In both objects, a
<code>
struct _kvp_store
</code>
is the first member, so that casting is possible.
</p>
<p>
All functions are prefixed with
<code>
kvp_
</code>
.
</p>
<h4>
<a aria-hidden="true" class="anchor" href="#stringc" id="user-content-stringc">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
string.c
</h4>
<p>
Utility functions for creating and freeing memory for
<code>
char *
</code>
and the corresponding
<code>
size_t
</code>
.
</p>
<p>
This file is used in
<code>
[json-decode]
</code>
,
<code>
[json-encode]
</code>
,
<code>
[oauth]
</code>
,
<code>
[rest]
</code>
, and
<code>
[urlparams]
</code>
.
</p>
<p>
All functions are prefixed with
<code>
string_
</code>
.
</p>
<h4>
<a aria-hidden="true" class="anchor" href="#strlistc" id="user-content-strlistc">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
strlist.c
</h4>
<p>
Utility functions for creating and freeing memory for a linked list of
<code>
char *
</code>
and the corresponding
<code>
size_t
</code>
.
</p>
<p>
This file is used in
<code>
[oauth]
</code>
and
<code>
[rest]
</code>
.
</p>
<p>
All functions are prefixed with
<code>
strlist_
</code>
.
</p>
<h3>
<a aria-hidden="true" class="anchor" href="#reasons-for-using-c99" id="user-content-reasons-for-using-c99">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Reasons for using C99
</h3>
<ul>
<li>
Variadic macros
</li>
<li>
In older implementations
<code>
json_object_object_foreach
</code>
requires C99:
<a href="https://github.com/json-c/json-c/pull/73">
https://github.com/json-c/json-c/pull/73
</a>
</li>
<li>
C99 forces the memory layout for using casting to structs:
<a href="http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf" rel="nofollow">
§ 6.2.5, 20 of the standard
</a>
:
</li>
</ul>
<blockquote>
<p>
A structure type describes a sequentially allocated nonempty set of member objects
(and, in certain circumstances, an incomplete array), each of which has an optionally
specified name and possibly distinct type.
</p>
</blockquote>
<h3>
<a aria-hidden="true" class="anchor" href="#special-cases" id="user-content-special-cases">
<span aria-hidden="true" class="octicon octicon-link">
</span>
</a>
Special Cases
</h3>
<ul>
<li>
<code>
static char *string_remove_backslashes(char *source_string, size_t *memsize)
</code>
in
<code>
string.c
</code>
is surrounded by a
<code>
#ifndef NO_BACKSLASHES
</code>
. This function is not needed for
<code>
[urlparams]
</code>
, and therefore this is used to not get warnings on compilation.
</li>
<li>
There are only a few platform specific
<code>
#define
</code>
s, those are all declared in
<code>
purest_json.h
</code>
.
</li>
<li>
<code>
[json-encode]
</code>
can contain arrays, while
<code>
[urlparams]
</code>
cannot, so a
<code>
#define
</code>
is used in
<code>
kvp.c
</code>
to remove array functions and struct members for
<code>
[urlparams]
</code>
.
</li>
</ul>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script>
function showCanonicalImages() {
var images = document.getElementsByTagName('img');
if (!images) {
return;
}
for (var index = 0; index < images.length; index++) {
var image = images[index];
if (image.getAttribute('data-canonical-src') && image.src !== image.getAttribute('data-canonical-src')) {
image.src = image.getAttribute('data-canonical-src');
}
}
}
function scrollToHash() {
if (location.hash && !document.querySelector(':target')) {
var element = document.getElementById('user-content-' + location.hash.slice(1));
if (element) {
element.scrollIntoView();
}
}
}
function autorefreshContent(eventSourceUrl) {
var initialTitle = document.title;
var contentElement = document.getElementById('grip-content');
var source = new EventSource(eventSourceUrl);
var isRendering = false;
source.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if (msg.updating) {
isRendering = true;
document.title = '(Rendering) ' + document.title;
} else {
isRendering = false;
document.title = initialTitle;
contentElement.innerHTML = msg.content;
showCanonicalImages();
}
}
source.onerror = function(e) {
if (e.readyState === EventSource.CLOSED && isRendering) {
isRendering = false;
document.title = initialTitle;
}
}
}
window.onhashchange = function() {
scrollToHash();
}
window.onload = function() {
scrollToHash();
}
showCanonicalImages();
var autorefreshUrl = document.getElementById('preview-page').getAttribute('data-autorefresh-url');
if (autorefreshUrl) {
autorefreshContent(autorefreshUrl);
}
</script>
</body>
</html>