Compare commits

...

112 Commits

Author SHA1 Message Date
lda 2c6d5194d2 Set an error message with MatrixErrorCreate whenever applicable (#45)
Closes #6.

Co-authored-by: Jordan Bancino <jordan@bancino.net>
Reviewed-on: #45
Co-authored-by: lda <lda@freetards.xyz>
Co-committed-by: lda <lda@freetards.xyz>
2023-12-02 10:24:08 -05:00
Jordan Bancino 0a91a0c40b Remove site files & update README with current site.
The website is now managed in Grav.
2023-11-21 09:16:50 -05:00
Jordan Bancino d3dcf334f0 Update change log. 2023-11-21 09:14:03 -05:00
lda 3dae19e82d Refactor code to comply with #8 (#39)
Reviewed-on: #39
Co-authored-by: lda <lda@freetards.xyz>
Co-committed-by: lda <lda@freetards.xyz>
2023-11-21 09:11:45 -05:00
Jordan Bancino 2d30719be4 Implement Registration Token Administrator API (#43)
This pull request fully implements and documents all of the registration token administrator API endpoints.

**NOTE:** There is a memory leak when listing all of the registration tokens. Debug this before merging.
 
~~Closes~~ Supersedes #37.

Closes #26.

This pull request is based off of #37, which addresses #26. This pull makes a number of improvements to the logic, organization, and behavior of the API endpoints.

Co-authored-by: hatkid <daichi93100@gmail.com>
Co-authored-by: LoaD Accumulator <lda@freetards.xyz>
Co-authored-by: LoaD Accumulator <lda@noreply.git.telodendria.io>
Co-authored-by: lda <lda@freetards.xyz>
Co-authored-by: Load Accumulator <lda@freetards.xyz>
Reviewed-on: #43
2023-11-10 09:30:53 -05:00
Jordan Bancino 503bfb6104 Suppress warnings of unused variables.
I will use them eventually when I implement all these functions.

I'm probably going to start CI work here soon, so I don't want warnings showing up in the logs unless they're important.
2023-11-08 15:17:27 -05:00
Jordan Bancino 77800e4117 Housekeeping tasks with documentation and versioning. 2023-11-08 14:30:45 -05:00
Jordan Bancino db4ae0408c Fix admin endpoint names in documentation 2023-11-08 11:21:20 -05:00
Jordan Bancino edee1288d8 Remove unused global variables. 2023-11-08 09:45:49 -05:00
Jordan Bancino 4b90800a2b Fix leak in RouteConfig, update documentation.
Closes #15.
2023-11-07 01:26:26 -05:00
Jordan Bancino 6e7f170768 Start working on #15. 2023-11-06 20:42:39 -05:00
Jordan Bancino 1f02f3c2a2 Allow customization of compiler in configure. 2023-11-04 15:56:57 -04:00
Jordan Bancino 582c79b608 Schema are now generated out-of-tree.
Closes #40.
2023-11-04 15:28:20 -04:00
Jordan Bancino 42a901b7f5 Update docs/dev/rationale.md 2023-11-01 20:35:48 -04:00
Jordan Bancino 1fee47a628 Use `Makefile`s instead of a custom script (#38)
This pull request also requires the use of the external [Cytoplasm](/Telodendria/Cytoplasm) repository by removing the in-tree copy of Cytoplasm. The increased modularity requires a little more complex build process, but is overall better. Closes #19

The appropriate documentation has been updated. Closes #18

---

Please review the developer certificate of origin:

1. The contribution was created in whole or in part by me, and I have
the right to submit it under the open source licenses of the
Telodendria project; or
1. The contribution is based upon a previous work that, to the best of
my knowledge, is covered under an appropriate open source license and
I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under the
Telodendria project license; or
1. The contribution was provided directly to me by some other person
who certified (1), (2), or (3), and I have not modified it.
1. I understand and agree that this project and the contribution are
made public and that a record of the contribution&mdash;including all
personal information I submit with it&mdash;is maintained indefinitely
and may be redistributed consistent with this project or the open
source licenses involved.

- [x] I have read the Telodendria Project development certificate of
origin, and I certify that I have permission to submit this patch
under the conditions specified in it.

Reviewed-on: #38
2023-11-01 12:27:45 -04:00
Jordan Bancino 6377689a83 Update docs/CHANGELOG.md 2023-11-01 12:16:03 -04:00
Jordan Bancino 23237f97b5 Format source code and apply license. 2023-09-28 19:16:45 -04:00
Jordan Bancino 82ae2d4e41 Update 'docs/CHANGELOG.md' 2023-09-25 16:18:35 -04:00
Jordan Bancino 7d3d84d969 Move Admin routes to /_telodendria/admin/v1 (with version number)
Closes #16.
2023-09-25 16:10:44 -04:00
Jordan Bancino bf1ce839d0 If HOST_NAME_MAX is undefined, use _POSIX_HOST_NAME_MAX.
Probably good enough. Closes #2
2023-09-25 16:02:09 -04:00
Jordan Bancino f8d3e54fec Use int instead of char in EvalExpr.
Closes #5
2023-09-25 15:58:43 -04:00
lda cb41716bf3 Implement #27 (#36)
Implements #27.

Co-authored-by: LoaD Accumulator <lda@freetards.xyz>
Co-authored-by: Jordan Bancino <jordan@bancino.net>
Reviewed-on: Telodendria/telodendria#36
Co-authored-by: LoaD Accumulator <lda@noreply.git.telodendria.io>
Co-committed-by: LoaD Accumulator <lda@noreply.git.telodendria.io>
2023-09-25 09:39:21 -04:00
Jordan Bancino 6247085df1 Add change log entry for #35. 2023-09-11 11:01:50 -04:00
lda 0172fa083b Fixes issue #33 related to a memory issue, and format some code. (#35)
Fixes #33.

Co-authored-by: LoaD Accumulator <lda@freetards.xyz>
Reviewed-on: Telodendria/telodendria#35
Co-authored-by: LoaD Accumulator <lda@noreply.git.telodendria.io>
Co-committed-by: LoaD Accumulator <lda@noreply.git.telodendria.io>
2023-09-11 10:57:16 -04:00
Jordan Bancino 0b820b80f7 Convert configuration documentation. 2023-09-09 17:43:43 -04:00
Jordan Bancino 6dcfa7dc02 Remove `send-patch` and `tp`. See #20. 2023-09-09 16:58:47 -04:00
Jordan Bancino 024482d4e8 Put the finishing touches on `CONTRIBUTING.md`. 2023-09-09 16:57:52 -04:00
Jordan Bancino 7a091c5b93 Add contributing documentation. 2023-09-09 16:50:38 -04:00
Jordan Bancino 9e8523d92e Fix issue config. 2023-09-09 15:39:12 -04:00
Jordan Bancino 419017bcc9 Don't allow blank issues. 2023-09-09 15:36:58 -04:00
Jordan Bancino 1a009e87c3 Fix a few small bugs in Gitea templates. 2023-09-09 15:32:43 -04:00
Jordan Bancino 08594e0fb1 Add Gitea issue templates. 2023-09-09 15:28:33 -04:00
Jordan Bancino 56508afe4c Merge branch 'master' of https://git.telodendria.io/telodendria/telodendria 2023-09-09 00:12:07 -04:00
Jordan Bancino ac3582ddeb Fix table rendering in stats.md 2023-09-09 00:12:00 -04:00
Jordan Bancino 61f7ab1040 Fix table rendering in stats.md 2023-09-09 00:11:32 -04:00
Jordan Bancino a672c05112 Finish moving over current Administrator API documentation. 2023-09-09 00:03:09 -04:00
Jordan Bancino 09023089f5 Another typo. 2023-09-08 23:27:55 -04:00
Jordan Bancino 6d6fd1645c Fix typo in privileges.md. 2023-09-08 23:27:14 -04:00
Jordan Bancino 043c2e9e33 Add privileges documentation. 2023-09-08 23:26:47 -04:00
Jordan Bancino 9e2f047e82 Fix typo in docs/user/admin/README.md 2023-09-08 17:23:06 -04:00
Jordan Bancino c78d075a93 Add admin documentation home page. 2023-09-08 17:22:24 -04:00
Jordan Bancino e4a217550f Add logo and center title. 2023-09-08 16:40:33 -04:00
Jordan Bancino d50372a91a Add technical rationale document. 2023-09-08 16:34:27 -04:00
Jordan Bancino fa3b5e95bd Add a nice README which will serve as the basis for the website. 2023-09-08 16:04:48 -04:00
Jordan Bancino 7033a1f0b1 Add repository structure documentation. 2023-09-08 12:12:07 -04:00
Jordan Bancino f6c54cbc7f Add setup documentation. 2023-09-08 11:58:54 -04:00
Jordan Bancino 3cb04417ff Add porting instructions. 2023-09-07 21:53:22 -04:00
Jordan Bancino 93e6582db5 Add usage and install documentation. 2023-09-07 21:10:46 -04:00
Jordan Bancino ee62d31c68 Add documentation home page. 2023-09-07 20:23:40 -04:00
Jordan Bancino 4bd527aa9a Remove old change log. 2023-09-07 20:06:12 -04:00
Jordan Bancino 79ce36c860 Add `CHANGELOG.md` 2023-09-07 19:53:56 -04:00
Jordan Bancino be3ee54bd8 Merge pull request 'added git ignore and removed cvs ignore files' (#29) from array-in-a-matrix/telodendria:master into master
Reviewed-on: Telodendria/telodendria#29
2023-09-06 14:37:29 -04:00
array-in-a-matrix 5367ffca96 replaced .cvsignore with .gitignore 2023-09-06 11:45:44 -04:00
Jordan Bancino c5b2fcf586 Convert Cytoplasm README to markdown. 2023-09-05 22:10:33 -04:00
Jordan Bancino 2b43a93524 Break proposals/admin.7 into multiple issues.
Closes #17
2023-09-05 21:54:26 -04:00
Jordan Bancino fd28f97449 Finish remaining issues in TODO.txt and add docs/ROADMAP.md. 2023-09-05 21:30:09 -04:00
Jordan Bancino 745a208f14 Move over some more issues. 2023-09-05 19:31:46 -04:00
Jordan Bancino 8843b34ba6 Merge branch 'master' of https://git.telodendria.io/telodendria/telodendria 2023-09-05 17:11:13 -04:00
Jordan Bancino b059f966f1 Make progress toward migrating TODO.txt to issues.
Still have a ways to go, but wanted to save my progress.
2023-09-05 17:09:58 -04:00
Jordan Bancino 8bf8afd91d Merge pull request '[MOD] Make the README(Markdown) file reflect the current situation.' (#11) from lda/telodendria:lda-dev into master
Reviewed-on: Telodendria/telodendria#11
2023-09-05 16:34:04 -04:00
lda 6db3f3c612
[MOD] Make the README(Markdown) file reflect the current situation.
Signed-off-by: LoaD Accumulator <lda@freetards.xyz>
2023-09-05 22:25:39 +02:00
Jordan Bancino fd1172ff56 Summarize Matrix room activity in TODO.txt
I really want to get back to work on Telodendria. I need to find some
more time for it.
2023-09-04 13:35:28 +00:00
Jordan Bancino 468656eee6 Apply #72 2023-09-04 13:30:22 +00:00
Jordan Bancino b625655439 Fix memory leak in some generated code. 2023-08-17 18:09:53 +00:00
Jordan Bancino dab666c969 Update documentation on UtilServerTs(). 2023-08-17 18:09:20 +00:00
Jordan Bancino 36413b4dca Ignore special case in Int64Str. This is hack but good enough for now. 2023-08-13 12:33:18 +00:00
Jordan Bancino 1c32e18c74 Json now uses Int64 for integers.
This should fix all timestamp errors on 32-bit systems in Cytoplasm and
Telodendria.
2023-08-13 03:11:40 +00:00
Jordan Bancino 2382638005 Make all timestamps use UInt64. 2023-08-12 23:02:06 +00:00
Jordan Bancino 38a303da91 Allow forcing the emulation mode for testing purposes. 2023-08-12 21:51:51 +00:00
Jordan Bancino 2f76d5b9ae Add signed 64-bit integer support. 2023-08-12 19:59:16 +00:00
Jordan Bancino 93c4b6bfc4 Add 64-bit emulation for platforms that don't have a native 64-bit type. 2023-08-12 16:30:24 +00:00
Jordan Bancino d565640455 Add schema for PDUs v1 and v3, the only unique PDU formats.
All other room versions use one of these two PDU formats.
2023-08-10 00:08:33 +00:00
Jordan Bancino bc71a7ec01 Add admin privilege to manage room aliases. 2023-08-09 15:50:03 +00:00
Jordan Bancino 69d28f39d1 Begin working on room aliases.
These endpoints will help me build out some functionality that will be
needed when actually implementing rooms.
2023-08-09 15:19:45 +00:00
Jordan Bancino e0af88145e Add RouteCreateRoom stub. 2023-08-08 15:11:50 +00:00
Jordan Bancino 6ef965d1e0 Apply patch to make MatrixErrorCreate() take a custom message. 2023-08-05 19:26:03 +00:00
Jordan Bancino 28d9e1cb3b Add RoomCreateRequest schema. 2023-08-05 15:00:52 +00:00
Jordan Bancino 78302d6320 Print admin registration token to configured log, not default stdout.
If Telodendria is started as a daemon and is logging to the syslog, we
want the token to show up in the syslog.
2023-08-05 14:12:02 +00:00
Jordan Bancino 6ec87b8d76 Properly exclude Schema directories from showing up in CVS. 2023-08-05 14:03:08 +00:00
Jordan Bancino 5f3220372e Implement filter validation by using j2s. 2023-08-05 13:46:23 +00:00
Jordan Bancino 77d71989df Don't install configuration files. 2023-08-04 21:15:49 +00:00
Jordan Bancino e9600a21e9 Add support for arrays of primitives. 2023-08-04 20:47:36 +00:00
Jordan Bancino 942d2aad18 Fix memory leaks and remove logging messages. 2023-08-01 22:36:52 +00:00
Jordan Bancino aeaa8487c3 Add leaky Cytoplasm JSON -> Struct code generator.
It is basically complete, I just have to finish cleaning up some of the
memory leaks and remove the log messages.
2023-08-01 20:23:19 +00:00
Jordan Bancino ed37afe564 Add [time] to interpolate dates and times using strftime(). 2023-07-29 18:27:35 +00:00
Jordan Bancino 2e193d4bcf Format code. 2023-07-29 18:27:17 +00:00
Jordan Bancino d22baf440f Update TODO. 2023-07-29 15:50:45 +00:00
Jordan Bancino c467d0913d Add tp, a simple but powerful text preprocessor.
I might rename it, and I have yet to document it in a man page, but I have
found this extremely useful so I thought I'd give it a home here.
2023-07-29 00:04:42 +00:00
Jordan Bancino 68b644a4f2 Add HashMapKeys() and HashMapValues() functions for convenience. 2023-07-18 00:15:29 +00:00
Jordan Bancino b65394ab50 Add basic Graph API.
This is going to be useful with state resolution and dependency ordering,
both of which will be crutial components of Telodendria.
2023-07-16 01:12:56 +00:00
Jordan Bancino a958c4a529 Apply #71: Add ArrayUnique() function. 2023-07-15 22:27:24 +00:00
Jordan Bancino c96ac30f28 Fix Unicode handling in Json, don't sign-extend bytes in Stream. 2023-07-15 17:57:21 +00:00
Jordan Bancino a4330123b9 Add EventRedact() prototype. 2023-07-09 23:18:18 +00:00
Jordan Bancino b1c23ee53a Begin prototyping state resolution API. 2023-07-07 03:15:13 +00:00
Jordan Bancino bc8283f844 Begin prototyping room API. 2023-07-07 02:56:09 +00:00
Jordan Bancino 5f34b846ee Fix stable release version scheme (more details in an upcoming newsletter) 2023-07-01 20:18:59 +00:00
Jordan Bancino 3054a80906 Fix Unicode handling. 2023-06-21 02:49:58 +00:00
Jordan Bancino 539fde773f Fix CanonicalJson and ArraySort. 2023-06-21 02:37:56 +00:00
Jordan Bancino 1fa07d2d3c Update TODO. 2023-06-18 03:25:03 +00:00
Jordan Bancino 80da024e4e Update change log. 2023-06-18 03:19:12 +00:00
Jordan Bancino e3badbd55c Format source code. 2023-06-18 02:53:52 +00:00
Jordan Bancino 861d4146c0 Add Filter API to validate filters and process events. 2023-06-18 02:53:06 +00:00
Jordan Bancino f9e1250d47 Begin working on filtering. 2023-06-17 19:09:06 +00:00
Jordan Bancino 4e184102cb Add Sha1 implementation. 2023-06-17 17:36:46 +00:00
Jordan Bancino 8bda70b1fb Refactor Sha API to return raw bytes, added Sha1() function. 2023-06-17 17:36:11 +00:00
Jordan Bancino 8f0d197480 Bump version: v0.3.0 -> v0.4.0 2023-06-16 16:01:19 +00:00
Jordan Bancino b9641e89d6 Update TODO 2023-06-13 14:06:05 +00:00
Jordan Bancino 1381a31cbd Update TODO. 2023-06-13 14:05:34 +00:00
Jordan Bancino c3287c1674 Update TODO. 2023-06-12 18:00:26 +00:00
Jordan Bancino 071a86114c Apply #70: Add StrLower() function. 2023-06-12 14:10:59 +00:00
Jordan Bancino 1f14169284 Apply #70: Fix warnings of unused variables. 2023-06-12 14:10:08 +00:00
Jordan Bancino 2f946848cb Telodendria Bot can now send messages again.
The problem here is that some Matrix homeservers reject requests that don't
have a Content-Length. http was not sending a Content-Length because it was
reading from standard input. By reading from an actual file, we can actually
easily get the size of the file to send as the Content-Length.
2023-06-12 14:01:56 +00:00
170 changed files with 4694 additions and 20761 deletions

View File

@ -1,6 +0,0 @@
build
data
.env
*.patch
*.log
vgcore.*

View File

@ -0,0 +1,49 @@
name: Bug Report
about: File a bug report regarding Telodendria, its website, or its documentation.
body:
- type: markdown
attributes:
value: |
You are submitting a bug report. Please be sure to fill out the
title with a brief description of the bug.
- type: dropdown
attributes:
label: Type
description: Select the type of issue.
options:
- Memory Leak
- Crash
- Unexpected Error Message
- Documentation
- Website
- Other
validations:
required: true
- type: textarea
attributes:
label: Description
description: |
Please give a thorough and detailed description of the bug you
are reporting. Provide all the information you have, and do
some investigating to ensure you are providing a legitimate
issue report that is well thought out. **Include details on
how to reproduce the issue, or explicitly state that you were
unable to reproduce it.**
validations:
required: true
- type: textarea
attributes:
label: Log Output
description: |
Please copy and paste the relevant sections of the log output,
or the entire log if it is not unreasonably large. The logs
will be automatically formatted, no code block is necessary.
render: shell
validations:
required: true
- type: markdown
attributes:
value: |
Please attach any additional files that may aid in our
investigation of this issue, including screenshots, debugging
session stack traces and dumps, etc.

View File

@ -0,0 +1,7 @@
blank_issues_enabled: false
contact_links:
- name: General Matrix Room
url: "https://matrix.to/#/#telodendria-general:bancino.net"
about: |
General discussion on Telodendria happens in this Matrix room. You
may get quicker feedback from there.

View File

@ -0,0 +1,18 @@
name: Feature Request
about: Request a new feature or enhancement be added to Telodendria.
title: "[Feature] "
body:
- type: markdown
attributes:
value: |
You are submitting a feature request. Please be sure to fill
out the title with a brief description of the feature you are
requesting.
- type: textarea
attributes:
label: Description
description: |
Please give a thorough and detailed description of the feature
you are requesting.
validations:
required: true

View File

@ -0,0 +1,25 @@
---
Please review the developer certificate of origin:
1. The contribution was created in whole or in part by me, and I have
the right to submit it under the open source licenses of the
Telodendria project; or
1. The contribution is based upon a previous work that, to the best of
my knowledge, is covered under an appropriate open source license and
I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under the
Telodendria project license; or
1. The contribution was provided directly to me by some other person
who certified (1), (2), or (3), and I have not modified it.
1. I understand and agree that this project and the contribution are
made public and that a record of the contribution&mdash;including all
personal information I submit with it&mdash;is maintained indefinitely
and may be redistributed consistent with this project or the open
source licenses involved.
- [ ] I have read the Telodendria Project development certificate of
origin, and I certify that I have permission to submit this patch
under the conditions specified in it.

18
.gitignore vendored Normal file
View File

@ -0,0 +1,18 @@
# Telodendria .gitignore
build
out
data
Makefile
*-leaked.txt
.env
*.patch
*.orig
*.log
vgcore.*
*.core
contrib/.vagrant
src/Schema
src/include/Schema
man/mandoc.db

View File

@ -1,3 +0,0 @@
build
out
*-leaked.txt

28
Cytoplasm/.indent.pro vendored
View File

@ -1,28 +0,0 @@
-bad
-bap
-bbb
-nbc
-bl
-c36
-cd36
-ncdb
-nce
-ci8
-cli1
-d0
-di1
-ndj
-ei
-fc1
-i4
-ip
-l72
-lc72
-lp
-npcs
-psl
-sc
-nsob
-nut
-nv

View File

@ -1,158 +0,0 @@
Cytoplasm (libcytoplasm)
========================================================================
Cytoplasm is a general-purpose C library and runtime stub for
creating high-level (particularly networked and multi-threaded) C
applications. It allows applications to take advantage of the speed,
flexibility, and simplicity of the C programming language, while
providing helpful code to perform various complex tasks. Cytoplasm
provides high-level data structures, a basic logging facility, an
HTTP client and server, and more.
Cytoplasm aims not to only do one thing well, but to do many things
good enough. The primary target of Cytoplasm is simple, yet higher
level C applications that have to perform relatively complex tasks,
but don't want to pull in a large number of dependencies.
Cytoplasm is extremely opinionated on the way programs using it are
written. It strives to create a comprehensive and tightly-integrated
programming environment, while also maintaining C programming
correctness. It doesn't do any macro magic or make C look like
anything other than C. It is written entirely in C89, and depends
only on a POSIX environment. This differentiates it from other
general-purpose libraries that often require modern compilers and
non-standard language and environment features. Cytoplasm is intended
to be extremely portable and simple, while still providing some of
the functionality expected in higher-level programming languages
in a platform-agnostic manner. In the case of TLS, Cytoplasm wraps
low-level TLS libraries to offer a single, unified interface to TLS
so that programs do not have to care about the underlying
implementation.
Cytoplasm is probably not suitable for embedded programming. It makes
liberal use of the heap, and while data structures are designed to
conserve memory where possible and practical, minimal memory usage
is not really a design goal for Cytoplasm, although Cytoplasm takes
care not to use any more memory than it absolutely needs. Cytoplasm
also wraps a few standard libraries with additional logic and
checking. While this ensures better runtime safetly, this inevitably
adds a little overhead.
Originally a part of Telodendria (https://telodendria.io), a Matrix
homeserver written in C, Cytoplasm was split off into its own project
due to the desire of some Telodendria developers to use Telodendria's
code in other projects. Cytoplasm is still a Telodendria project,
and is maintained along side of Telodendria itself, even living in
the same CVS module, but it is designed specifically to be distributed
and used totally independent of Telodendria.
The name "Cytoplasm" was chosen for a few reasons. It plays off the
precedent set up by the Matrix organization in naming projects after
the parts of a neuron. It also speaks to the function of Cytoplasm.
The cytoplasm of a cell is the supporting material. It is what gives
the cell its shape, and it facilitates the movement of materials
to the other cell parts. Likewise, Cytoplasm aims to provide a
support mechanism for C applications that have to perform complex
tasks.
Cytoplasm also starts with a C, which I think is a nice touch for C
libraries. It's also fun to say and unique enough that searching for
"libcytoplasm" should bring you to this project and not some other
one.
Building
------------------------------------------------------------------------
If your operating system or software distribution provides a pre-built
package of Cytoplasm, you should prefer to use that instead of
building it from source.
Cytoplasm aims to have zero dependencies beyond what is mandated
by POSIX. You only need the standard math and pthread libraries to
build it. TLS support can optionally be enabled by setting the
TLS_IMPL environment variable. The supported TLS implementations
are as follows:
* OpenSSL
* LibreSSL
If TLS support is not enabled, all APIs that use it should fall
back to non-TLS behavior in a sensible manner. For example, if TLS
support is not enabled, then the HTTP client API will simply return
an error if a TLS connection is requested.
Cytoplasm uses a custom build script instead of Make, for the sake
of portability. To build everything, just run the script:
$ sh make.sh
This will produce the following out/ directory:
out/
lib/
libcytoplasm.so - The Cytoplasm shared library.
libcytoplasm.a - The Cytoplasm static library.
cytoplasm.o - The Cytoplasm runtime stub.
bin/
hdoc - The documentation generator tool.
man/ - All Cytoplasm API documentation.
Usage
------------------------------------------------------------------------
Cytoplasm provides the typical .so and .a files, which can be used
to link programs with it in the usual way. However, Cytoplasm also
provides a minimal runtime environment that is intended to be used
with the library. As such, it also provides a runtime stub, which
is intended to be linked in with programs using Cytoplasm. This
stub is responsible for setting up and tearing down some Cytoplasm
APIs. While it isn't required by any means, it makes Cytoplasm a
lot easier to use for programmers by abstracting out all of the
common logic that most programs will want to use.
Here is the canonical Hello World written with Cytoplasm:
#include <Log.h>
int Main(void)
{
Log(LOG_INFO, "Hello World!");
return 0;
}
If this file is Hello.c, then you can compile it by doing something
like this:
$ cc -o hello Hello.c cytoplasm.o -lcytoplasm
This command assumes that the runtime stub resides in the current
working directory, and that libcytoplasm.so is in your library path.
If you're using the version of Cytoplasm installed by your operating
system or software distribution, consult the documentation for the
location of the runtime stub. It may be located in
/usr/local/libexec or some other similar location. If you've built
Cytoplasm from source and wish to link to it from there, you may wish
to do something like this:
$ export CYTOPLASM=/path/to/Cytoplasm/out/lib
$ cc -o hello Hello.c "${CYTOPLASM}/cytoplasm.o" \
"-L${CYTOPLASM}" -lcytoplasm
As you may have noticed, C programs using Cytoplasm's runtime stub
don't write the main() function. Instead, they use Main(). The main()
function is provided by the runtime stub. The full form of Main()
expected by the stub is as follows:
int Main(Array *args, HashMap *env);
The first argument is a Cytoplasm array of the command line
arguments, and the second is a Cytoplasm hash map of environment
variables. Most linkers will let programs omit the env argument,
or both arguments if you don't need either. The return value of
Main() is returned to the operating system.
Note that both arguments to Main may be treated like any other
array or hash map. However, do not invoke ArrayFree() or HashMapFree()
on the passed pointers, because memory is cleaned up after Main()
returns.

View File

@ -1,28 +0,0 @@
#include <Array.h>
#include <HashMap.h>
#include <Log.h>
int
Main(Array * args, HashMap * env)
{
size_t i;
char *key;
char *val;
Log(LOG_INFO, "Hello World!");
Log(LOG_INFO, "Arguments: %lu", ArraySize(args));
for (i = 0; i < ArraySize(args); i++)
{
Log(LOG_INFO, " [%ld] %s", i, ArrayGet(args, i));
}
Log(LOG_INFO, "Environment:");
while (HashMapIterate(env, &key, (void **) &val))
{
Log(LOG_INFO, " %s = %s", key, val);
}
return 0;
}

View File

@ -1,328 +0,0 @@
#!/usr/bin/env sh
addprefix() {
prefix="$1"
shift
for thing in "$@"; do
echo "${prefix}${thing}"
done
unset prefix
unset thing
}
: "${NAME:=Cytoplasm}"
: "${LIB_NAME:=$(echo ${NAME} | tr '[A-Z]' '[a-z]')}"
: "${VERSION:=0.3.0}"
: "${CVS_TAG:=${NAME}-$(echo ${VERSION} | sed 's/\./_/g')}"
: "${SRC:=src}"
: "${TOOLS:=tools}"
: "${EXAMPLES:=examples}"
: "${BUILD:=build}"
: "${OUT:=out}"
: "${STUB:=RtStub}"
: "${LICENSE:=LICENSE.txt}"
: "${CC:=cc}"
: "${AR:=ar}"
: "${DEFINES:=-D_DEFAULT_SOURCE -DLIB_NAME=\"${NAME}\" -DLIB_VERSION=\"${VERSION}\"}"
: "${INCLUDE:=${SRC}/include}"
: "${CFLAGS:=-Wall -Wextra -pedantic -std=c89 -O3 -pipe}"
: "${LD_EXTRA:=-flto -fdata-sections -ffunction-sections -s -Wl,-gc-sections}"
: "${LDFLAGS:=-lm -pthread}"
if [ "${DEBUG}" = "1" ]; then
CFLAGS="${CFLAGS} -O0 -g"
LD_EXTRA=""
fi
if [ -n "${TLS_IMPL}" ]; then
case "${TLS_IMPL}" in
"LIBRESSL")
TLS_LIBS="-ltls -lcrypto -lssl"
;;
"OPENSSL")
TLS_LIBS="-lcrypto -lssl"
;;
*)
echo "Unrecognized TLS implementation: ${TLS_IMPL}"
echo "Consult Tls.h for supported implementations."
echo "Note that the TLS_ prefix is omitted in TLS_IMPL."
exit 1
;;
esac
DEFINES="${DEFINES} -DTLS_IMPL=TLS_${TLS_IMPL}"
LDFLAGS="${LDFLAGS} ${TLS_LIBS}"
fi
CFLAGS="${CFLAGS} ${DEFINES} $(addprefix -I$(pwd)/ ${INCLUDE})"
LDFLAGS="${LDFLAGS} ${LD_EXTRA}"
# Check the modificiation time of a file. This is used to do
# incremental builds; we only want to rebuild files that have
# have changed.
mod_time() {
if [ -n "$1" ] && [ -f "$1" ]; then
case "$(uname)" in
Linux | CYGWIN_NT* | Haiku)
stat -c %Y "$1"
;;
*BSD | DragonFly | Minix)
stat -f %m "$1"
;;
*)
# Platform unknown, force rebuilding the whole
# project every time.
echo "0"
;;
esac
else
echo "0"
fi
}
# Substitute shell variables in a stream with their actual value
# in this shell.
setsubst() {
SED="/tmp/sed-$RANDOM.txt"
(
set | while IFS='=' read -r var val; do
val=$(echo "$val" | cut -d "'" -f 2- | rev | cut -d "'" -f 2- | rev)
echo "s|\\\${$var}|$val|g"
done
echo "s|\\\${[a-zA-Z_]*}||g"
echo "s|'''|'|g"
) >"$SED"
sed -f "$SED" $@
rm "$SED"
}
recipe_docs() {
export LD_LIBRARY_PATH="${OUT}/lib"
mkdir -p "${OUT}/man/man3"
for header in $(find ${INCLUDE} -name '*.h'); do
basename=$(basename "$header")
man=$(echo "${OUT}/man/man3/$basename" | sed -e 's/\.h$/\.3/')
if [ $(mod_time "$header") -ge $(mod_time "$man") ]; then
echo "DOC $basename"
if ! "${OUT}/bin/hdoc" -D "Os=${NAME}" -i "$header" -o "$man"; then
rm "$man"
exit 1
fi
fi
done
if which makewhatis 2>&1 > /dev/null; then
makewhatis "${OUT}/man"
fi
}
recipe_libs() {
echo "-lm -pthread ${TLS_LIBS}"
}
recipe_build() {
mkdir -p "${BUILD}" "${OUT}/bin" "${OUT}/lib"
cd "${SRC}"
echo "CC = ${CC}"
echo "CFLAGS = ${CFLAGS}"
echo "LDFLAGS = ${LDFLAGS}"
echo
do_rebuild=0
objs=""
for src in $(find . -name '*.c' | cut -d '/' -f 2-); do
obj=$(echo "${BUILD}/$src" | sed -e 's/\.c$/\.o/')
if [ $(basename "$obj" .o) != "${STUB}" ]; then
objs="$objs $obj"
fi
if [ $(mod_time "$src") -ge $(mod_time "../$obj") ]; then
echo "CC $(basename $obj)"
obj_dir=$(dirname "../$obj")
mkdir -p "$obj_dir"
if ! $CC $CFLAGS -fPIC -c -o "../$obj" "$src"; then
exit 1
fi
do_rebuild=1
fi
done
cd ..
if [ $do_rebuild -eq 1 ] || [ ! -f "${OUT}/lib/lib${LIB_NAME}.a" ]; then
echo "AR lib${LIB_NAME}.a"
if ! $AR rcs "${OUT}/lib/lib${LIB_NAME}.a" $objs; then
exit 1
fi
fi
if [ $do_rebuild -eq 1 ] || [ ! -f "${OUT}/lib/lib${LIB_NAME}.so" ]; then
echo "LD lib${LIB_NAME}.so"
if ! $CC -shared -o "${OUT}/lib/lib${LIB_NAME}.so" $objs ${LDFLAGS}; then
exit 1
fi
fi
cp "${BUILD}/${STUB}.o" "${OUT}/lib/${LIB_NAME}.o"
for src in $(find "${TOOLS}" -name '*.c'); do
out=$(basename "$src" .c)
out="${OUT}/bin/$out"
if [ $(mod_time "$src") -ge $(mod_time "$out") ] || [ $do_rebuild -eq 1 ]; then
echo "CC $(basename $out)"
mkdir -p "$(dirname $out)"
if ! $CC $CFLAGS -o "$out" "$src" "${OUT}/lib/${LIB_NAME}.o" "-L${OUT}/lib" "-l${LIB_NAME}" ${LDFLAGS}; then
exit 1
fi
fi
done
recipe_docs
}
recipe_examples() {
for src in $(find "${EXAMPLES}" -name '*.c'); do
out=$(basename "$src" .c)
out="${OUT}/bin/$out"
if [ $(mod_time "$src") -ge $(mod_time "$out") ]; then
echo "CC $(basename $out)"
mkdir -p "$(dirname $out)"
if ! $CC $CFLAGS -o "$out" "$src" "${OUT}/lib/${LIB_NAME}.o" "-L${OUT}/lib" "-l${LIB_NAME}" ${LDFLAGS}; then
exit 1
fi
fi
done
}
recipe_clean() {
rm -r "${BUILD}" "${OUT}"
}
# Update copyright comments in sources and header files.
recipe_license() {
find . -name '*.[ch]' | while IFS= read -r src; do
if [ -t 1 ]; then
printf "LICENSE %s%*c\r" $(basename "$src") "16" " "
fi
srcHeader=$(grep -n -m 1 '^ \*/' "$src" | cut -d ':' -f 1)
head "-n$srcHeader" "$src" |
diff -u -p - "${LICENSE}" |
patch "$src" | grep -v "^Hmm"
done
if [ -t 1 ]; then
printf "%*c\n" "50" " "
fi
}
# Format source code files by running indent(1) on them.
recipe_format() {
find . -name '*.c' | while IFS= read -r src; do
if [ -t 1 ]; then
printf "FMT %s%*c\r" $(basename "$src") "16" " "
fi
if indent "$src"; then
rm $(basename "$src").BAK
fi
done
if [ -t 1 ]; then
printf "%*c\n" "50" " "
fi
}
# Generate a release tarball, checksum and sign it, and push it to
# the web root.
recipe_release() {
# Tag the release at this point in time.
cvs tag "$CVS_TAG"
mkdir -p "${OUT}/release"
cd "${OUT}/release"
# Generate the release tarball.
cvs export "-r$CVS_TAG" "${NAME}"
mv "${NAME}" "${NAME}-v${VERSION}"
tar -czf "${NAME}-v${VERSION}.tar.gz" "${NAME}-v${VERSION}"
rm -r "${NAME}-v${VERSION}"
# Checksum the release tarball.
sha256 "${NAME}-v${VERSION}.tar.gz" > "${NAME}-v${VERSION}.tar.gz.sha256"
# Sign the release tarball.
if [ ! -z "${SIGNIFY_SECRET}" ]; then
signify -S -s "${SIGNIFY_SECRET}" \
-m "${NAME}-v${VERSION}.tar.gz" \
-x "${NAME}-v${VERSION}.tar.gz.sig"
else
echo "Warning: SIGNIFY_SECRET not net."
echo "The built tarball will not be signed."
fi
}
recipe_patch() {
# If the user has not set their MXID, try to deduce one from
# their system.
if [ -z "$MXID" ]; then
MXID="@${USER}:$(hostname)"
fi
# If the user has not set their EDITOR, use a safe default.
# (vi should be available on any POSIX system)
if [ -z "$EDITOR" ]; then
EDITOR=vi
fi
NORMALIZED_MXID=$(echo "$MXID" | sed -e 's/@//g' -e 's/:/-/g')
PATCH_FILE="${NORMALIZED_MXID}_$(date +%s).patch"
# Generate the actual patch file
# Here we write some nice headers, and then do a cvs diff.
(
printf 'From: "%s" <%s>\n' "$DISPLAY_NAME" "$MXID"
echo "Date: $(date)"
echo "Subject: "
echo
cvs -q diff -uNp $PATCHSET | grep -v '^\? '
) >"$PATCH_FILE"
"$EDITOR" "$PATCH_FILE"
echo "$PATCH_FILE"
}
recipe_diff() {
tmp_patch="/tmp/${NAME}-$(date +%s).patch"
cvs -q diff -uNp $PATCHSET >"$tmp_patch"
if [ -z "$PAGER" ]; then
PAGER="less -F"
fi
$PAGER "$tmp_patch"
rm "$tmp_patch"
}
# Execute the user-specified recipes.
for recipe in $@; do
recipe_$recipe
done
# If no recipe was provided, run a build.
if [ -z "$1" ]; then
recipe_build
fi

View File

@ -1,51 +0,0 @@
.Dd $Mdocdate: May 21 2023 $
.Dt HDOC 1
.Os Cytoplasm
.Sh NAME
.Nm hdoc
.Nd Generate documentation from a C header file.
.Sh SYNOPSIS
.Nm
.Op Fl i Ar file
.Op Fl o Ar file
.Op Fl D Ar key=value
.Sh DESCRIPTION
.Nm
is an extremely simple documentation generator that generates
a BSD man page from a specially-formatted C header file.
See
.Xr hdoc 5
for details on the format of this header file.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl i Ar file
The input C header file to read from. If this option is omitted,
then the standard input is read.
.It Fl o Ar file
The output BSD man page file to write. If this option is omitted,
then the standard output is written.
.It Fl D Ar key=value
Set the register
.Ar key
to
.Ar value .
.Nm
registers are used in various places, and can be set in either
the header file, or on the command line. Setting registers that
should be the same in all headers is best done from the command
line for maintainability purposes, but header-specific values
should be set in the header file itself.
.Pp
Registers are explained in more detail in
.Xr hdoc 5 .
.El
.Sh RETURN VALUE
.Pp
.Nm
returns a success value if the header is well-formed and the
man page is successfully generated. It returns an error code in
all other scenarios.
.Sh SEE ALSO
.Xr hdoc 5 ,
.Xr HeaderParser 3

View File

@ -1,195 +0,0 @@
.Dd $Mdocdate: May 21 2023 $
.Dt HDOC 5
.Os Cytoplasm
.Sh NAME
.Nm hdoc
.Nd C header file format accepted by the documentation generator.
.Sh DESCRIPTION
.Pp
.Nm
uses an extremely primitive parser to generate documentation from
C header files. As such, the format accepted by
.Nm
is rather strict and may not be suitable for other projects beyond
of Cytoplasm. This document describes what
.Nm
considers to be a valid C header file, and how that header file can
be annotated to produce a nicely-formatted man page.
.Pp
At the very top level, a C header is a sequences of tokens that
represent the following:
.Bl -bullet -offset indent
.It
An ANSI C89 comment.
.It
A preprocessor directive.
.It
A typedef declaration.
.It
A constant or other global variable declaration.
.It
A function declaration.
.El
.Pp
Note that global variables and functions
.Em must
be marked with
.Ar extern ,
otherwise the parser will fail to recognize them. This is by
design; a header should make everything extern by default,
because it does not actually implement or declare anything.
.Pp
Preprocessor directives are completely ignored. Regular C
comments are also ignored.
.Nm
is primarily concerned with type declarations, global
variables, and functions. It also inspects specially-formatted
C comments, which are used to annotate these elements of the
header. The format of these comments is described here.
.Pp
There are two types of special comments recognized, the first
of which is called the ``main'' comment block, as it documents
the header itself, not the declarations contained in it. Main
comment blocks also control the behavior of the parser and the
resulting man page by setting registers. The format of the
main comment block, which typically appears only once at the
top of the header, although this is not a requirement, is as
follows:
.Bl -bullet -offset indent
.It
The comment should start with a ``triple star,'' like this:
.Bd -literal -offset indent
/***
*
*/
.Ed
.It
Any lines that start with a ``@'' are parser directives that
set registers. The name of the register to set follows
immediately after the ``@'' sigil, and continues until the first
whitespace. The rest of the line is the value of the register.
A list of registers recognized by
.Nm
is as follows. These registers control the man page output,
and the last value set is the one that is used:
.Bl -tag -width Ds
.It \&Nm
The name register. The name of the man page will be set to the
contents of this register. It defaults to ``Unnmamed.''
.It \&Dd
The date register. The date of the man page will be set to the
contents of this register. If left unset, it defaults to the
current date.
.It \&Os
The operating system register. The Os value, which appears in
the bottom left and right corners of the man page, will be set
to the contents of this register. If left unset, it is not
output.
.It \&Nd
The description register. The description of the man page will
be set to the contents of this register. It defaults to
``No description.''
.It \&Xr
The cross reference register. The SEE ALSO section of the man
page will list the specified cross references, which are to be
separated by a single space. The section shall be omitted,
because it is set automatically to the same section that the
current man page will belong to. This limitation may be removed
in the future.
.El
.Pp
These registers control the parser itself, modifying its
behavior as soon as the appear in the file:
.Bl -tag -width Ds
.It ignore-typedefs
Don't throw an error for an undocumented type declaration.
The value doesn't matter; as soon as this register shows
up, it's set. In most cases, it should not be used, however,
it may be helpful in a few scenarios, such as when there are
multiple typedefs that do the same thing, but are controlled
by preprocessor macros.
.It suppress-warnings
Don't issue a warning for invalid or unrecognized top-level
tokens. They will instead be ignored until the next
recognized top-level token is found. The value doesn't
matter; as soon as this register shows up, it is set. In most
cases, it should not be used, however it may be helpful in a
few scenarios, such as when function declarations are generated
by preprocessor directives and thus don't follow the standard
form.
.El
.It
Any other lines in the main block are output to the DESCRIPTION
section of the main page. This description may contain mdoc
directives in it, as the lines are copied verbatim. If multiple
main comment blocks appear in a single header, their description
lines are appended in the order they appear.
.El
.Pp
Declaration documentation comments are created as follows:
.Bl -bullet -offset indent
.It
The comment should start with a ``double star,'' like this:
.Bd -literal -offset indent
/**
*
*/
.Ed
.It
The contents of the comment are copied verbatim into the output,
so the comment may contain mdoc directives.
.It
The comment must appear before a declaration. If multiple
documentation comments appear before a declaration, the last
one before the declaration is used.
.El
.Pp
The generated man page includes the name and description of the
header, a synopsis section that lists all of the functions in
the header, a description section that contains all the non-register
lines of the main comment blocks, and then all of the documentation
for each function, with the function prototype displayed as a
subsection header, and the documentation displayed under it.
.Sh EXAMPLES
.Pp
Consider the following simple C header:
.Bd -literal -offset indent
#include <stdio.h>
extern void SayHello(FILE *);
.Ed
.Pp
To annotate this header in the manner
.Nm
expects, do something like this:
.Bd -literal -offset indent
/***
* @Nm Hello
* @Nd Say hello.
* @Dd May 17 2023
*
* .Nm
* provides functionality to write hello world messages
* into standard C file descriptors.
*
* @Xr fputs fprintf
*/
#include <stdio.h>
/**
* This function writes "hello world" to the given file
* descriptor.
* .Pp
* There really isn't much more to be said about it.
*/
extern void SayHello(FILE *);
.Ed
.Pp
This example shows how mdoc directives can be placed in
documentation comments. Note that the triple-star comment
documents the header itself, and the double-star comment
documents the type declaration or function definition
below it.
.Sh SEE ALSO
.Xr hdoc 5 ,
.Xr HeaderParser 3

View File

@ -1,118 +0,0 @@
/*
* Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <Args.h>
#include <Memory.h>
#include <Log.h>
#include <Str.h>
#include <ctype.h>
#include <string.h>
void
ArgParseStateInit(ArgParseState * state)
{
state->optPos = 1;
state->optErr = 1;
state->optInd = 1;
state->optOpt = 0;
state->optArg = NULL;
}
int
ArgParse(ArgParseState * state, Array * args, const char *optStr)
{
const char *arg;
arg = ArrayGet(args, state->optInd);
if (arg && StrEquals(arg, "--"))
{
state->optInd++;
return -1;
}
else if (!arg || arg[0] != '-' || !isalnum((unsigned char) arg[1]))
{
return -1;
}
else
{
const char *opt = strchr(optStr, arg[state->optPos]);
state->optOpt = arg[state->optPos];
if (!opt)
{
if (state->optErr && *optStr != ':')
{
Log(LOG_ERR, "Illegal option: %c", ArrayGet(args, 0), state->optOpt);
}
if (!arg[++state->optPos])
{
state->optInd++;
state->optPos = 1;
}
return '?';
}
else if (opt[1] == ':')
{
if (arg[state->optPos + 1])
{
state->optArg = (char *) arg + state->optPos + 1;
state->optInd++;
state->optPos = 1;
return state->optOpt;
}
else if (ArrayGet(args, state->optInd + 1))
{
state->optArg = (char *) ArrayGet(args, state->optInd + 1);
state->optInd += 2;
state->optPos = 1;
return state->optOpt;
}
else
{
if (state->optErr && *optStr != ':')
{
Log(LOG_ERR, "Option requires an argument: %c", state->optOpt);
}
if (!arg[++state->optPos])
{
state->optInd++;
state->optPos = 1;
}
return *optStr == ':' ? ':' : '?';
}
}
else
{
if (!arg[++state->optPos])
{
state->optInd++;
state->optPos = 1;
}
return state->optOpt;
}
}
}

View File

@ -1,339 +0,0 @@
/*
* Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <Array.h>
#ifndef ARRAY_BLOCK
#define ARRAY_BLOCK 16
#endif
#include <stddef.h>
#include <Memory.h>
struct Array
{
void **entries; /* An array of void pointers, to
* store any data */
size_t allocated; /* Elements allocated on the heap */
size_t size; /* Elements actually filled */
};
int
ArrayAdd(Array * array, void *value)
{
if (!array)
{
return 0;
}
return ArrayInsert(array, array->size, value);
}
Array *
ArrayCreate(void)
{
Array *array = Malloc(sizeof(Array));
if (!array)
{
return NULL;
}
array->size = 0;
array->allocated = ARRAY_BLOCK;
array->entries = Malloc(sizeof(void *) * ARRAY_BLOCK);
if (!array->entries)
{
Free(array);
return NULL;
}
return array;
}
void *
ArrayDelete(Array * array, size_t index)
{
size_t i;
void *element;
if (!array || array->size <= index)
{
return NULL;
}
element = array->entries[index];
for (i = index; i < array->size - 1; i++)
{
array->entries[i] = array->entries[i + 1];
}
array->size--;
return element;
}
void
ArrayFree(Array * array)
{
if (array)
{
Free(array->entries);
Free(array);
}
}
void *
ArrayGet(Array * array, size_t index)
{
if (!array)
{
return NULL;
}
if (index >= array->size)
{
return NULL;
}
return array->entries[index];
}
extern int
ArrayInsert(Array * array, size_t index, void *value)
{
size_t i;
if (!array || !value || index > array->size)
{
return 0;
}
if (array->size >= array->allocated)
{
void **tmp;
size_t newSize = array->allocated + ARRAY_BLOCK;
tmp = array->entries;
array->entries = Realloc(array->entries,
sizeof(void *) * newSize);