├── .astylerc ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CMakeLists.txt ├── Doxyfile ├── LICENSE ├── README.md ├── TODO ├── apps └── test │ └── main.c ├── cmake ├── enable_cmp0048.cmake ├── libpng-libm-unix.patch └── zlib.patch ├── docs ├── bmfont.md ├── composite.md └── stream.md ├── include ├── base │ ├── debug.h │ ├── result.h │ ├── types.h │ └── utils.h ├── databases │ ├── digest-db.h │ ├── filename-db.h │ ├── pickle-reader-hash.h │ ├── pickle-writer-hash.h │ ├── pickle.h │ └── tag-db.h ├── datastruct │ ├── atom.h │ ├── bitarr.h │ ├── bitfifo.h │ ├── bitvec.h │ ├── cache.h │ ├── hash.h │ ├── hlist.h │ ├── list.h │ ├── ntree.h │ └── vector.h ├── fortify │ ├── fortify.h │ └── ufortify.h ├── framebuf │ ├── bitmap-set.h │ ├── bitmap.h │ ├── bmfont.h │ ├── colour.h │ ├── composite.h │ ├── pixelfmt.h │ └── screen.h ├── geom │ ├── box.h │ ├── layout.h │ ├── packer.h │ └── point.h ├── io │ ├── path.h │ ├── stream-mem.h │ ├── stream-mtfcomp.h │ ├── stream-packbits.h │ ├── stream-stdio.h │ └── stream.h ├── test │ ├── all-tests.h │ └── txtscr.h └── utils │ ├── array.h │ ├── barith.h │ ├── bsearch.h │ ├── bytesex.h │ ├── fxp.h │ ├── maths.h │ ├── pack.h │ └── primes.h ├── libraries ├── databases │ ├── digest-db │ │ └── digest-db.c │ ├── filename-db │ │ └── filename-db.c │ ├── pickle │ │ ├── delete.c │ │ ├── hash-reader.c │ │ ├── hash-writer.c │ │ ├── pickle.c │ │ ├── test │ │ │ └── pickle-test.c │ │ └── unpickle.c │ └── tag-db │ │ ├── tag-db.c │ │ └── test │ │ └── tag-db-test.c ├── datastruct │ ├── atom │ │ ├── create.c │ │ ├── delete-block.c │ │ ├── delete.c │ │ ├── destroy.c │ │ ├── for-block.c │ │ ├── get.c │ │ ├── impl.h │ │ ├── new.c │ │ ├── set.c │ │ └── test │ │ │ └── atom-test.c │ ├── bitarr │ │ ├── count.c │ │ └── test │ │ │ └── bitarr-test.c │ ├── bitfifo │ │ ├── bitfifo.c │ │ └── test │ │ │ └── bitfifo-test.c │ ├── bitvec │ │ ├── and.c │ │ ├── clear-all.c │ │ ├── clear.c │ │ ├── count.c │ │ ├── create.c │ │ ├── destroy.c │ │ ├── ensure.c │ │ ├── eq.c │ │ ├── get.c │ │ ├── impl.h │ │ ├── length.c │ │ ├── next.c │ │ ├── or.c │ │ ├── set-all.c │ │ ├── set.c │ │ ├── test │ │ │ └── bitvec-test.c │ │ └── toggle.c │ ├── cache │ │ ├── cache.c │ │ └── test │ │ │ └── cache-test.c │ ├── hash │ │ ├── count.c │ │ ├── create.c │ │ ├── destroy.c │ │ ├── impl.h │ │ ├── insert.c │ │ ├── lookup-node.c │ │ ├── lookup.c │ │ ├── remove.c │ │ ├── test │ │ │ └── hash-test.c │ │ ├── walk-cont.c │ │ └── walk.c │ ├── hlist │ │ ├── append.c │ │ ├── copy.c │ │ ├── free.c │ │ ├── impl.h │ │ ├── length.c │ │ ├── list.c │ │ ├── map.c │ │ ├── pop.c │ │ ├── push.c │ │ ├── reverse.c │ │ └── to-array.c │ ├── list │ │ ├── add-head.c │ │ ├── find.c │ │ ├── init.c │ │ ├── remove.c │ │ ├── test │ │ │ └── list-test.c │ │ └── walk.c │ ├── ntree │ │ ├── copy.c │ │ ├── delete.c │ │ ├── depth.c │ │ ├── first-child.c │ │ ├── free.c │ │ ├── get-data.c │ │ ├── impl.h │ │ ├── insert-after.c │ │ ├── insert-before.c │ │ ├── insert.c │ │ ├── last-child.c │ │ ├── max-height.c │ │ ├── n-nodes.c │ │ ├── new.c │ │ ├── next-sibling.c │ │ ├── nth-child.c │ │ ├── parent.c │ │ ├── prepend.c │ │ ├── prev-sibling.c │ │ ├── set-data.c │ │ ├── test │ │ │ └── ntree-test.c │ │ ├── unlink.c │ │ └── walk.c │ └── vector │ │ ├── clear.c │ │ ├── create.c │ │ ├── destroy.c │ │ ├── ensure.c │ │ ├── get.c │ │ ├── impl.h │ │ ├── insert.c │ │ ├── length.c │ │ ├── set-length.c │ │ ├── set-width.c │ │ ├── set.c │ │ ├── test │ │ └── vector-test.c │ │ └── width.c ├── fortify │ ├── CMakeLists.txt │ └── fortify.c ├── framebuf │ ├── bitmap │ │ ├── bitmap.c │ │ ├── load.c │ │ └── save.c │ ├── bmfont │ │ ├── bmfont.c │ │ └── test │ │ │ └── bmfont-test.c │ ├── colour │ │ └── colour.c │ ├── composite │ │ ├── composite.c │ │ └── test │ │ │ └── composite-test.c │ ├── pixelfmt │ │ └── log2bpp.c │ └── screen │ │ └── screen.c ├── geom │ ├── box │ │ ├── clipped.c │ │ ├── contains-box.c │ │ ├── contains-point.c │ │ ├── could-hold.c │ │ ├── grow.c │ │ ├── intersection.c │ │ ├── intersects.c │ │ ├── is-empty.c │ │ ├── reset.c │ │ ├── round.c │ │ ├── round4.c │ │ ├── test │ │ │ └── box-test.c │ │ ├── translated.c │ │ └── union.c │ ├── layout │ │ ├── layout.c │ │ └── test │ │ │ └── layout-test.c │ └── packer │ │ ├── impl.h │ │ ├── packer.c │ │ └── test │ │ └── packer-test.c ├── io │ ├── path │ │ └── path.c │ └── stream │ │ ├── stream-mem.c │ │ ├── stream-mtfcomp.c │ │ ├── stream-packbitscomp.c │ │ ├── stream-packbitsdecomp.c │ │ ├── stream-stdio.c │ │ ├── stream.c │ │ └── test │ │ └── stream-test.c ├── test │ └── txtscr │ │ └── txtscr.c └── utils │ ├── array │ ├── delelem.c │ ├── delelems.c │ ├── grow.c │ ├── shrink.c │ ├── squeeze.c │ ├── stretch.c │ └── test │ │ └── array-test.c │ ├── barith │ └── barith.c │ ├── bsearch │ ├── bsearch-impl.h │ ├── bsearch-int.c │ ├── bsearch-short.c │ ├── bsearch-uint.c │ ├── bsearch-ushort.c │ └── test │ │ └── bsearch-test.c │ ├── bytesex │ ├── rev-l-block.c │ ├── rev-l-m.c │ ├── rev-l.c │ ├── rev-s-block.c │ ├── rev-s-m.c │ ├── rev-s-pair-m.c │ ├── rev-s-pair.c │ ├── rev-s.c │ └── util.h │ ├── fxp │ ├── smull-fxp16.c │ └── umull-fxp16.c │ ├── maths │ ├── degs-to-rads.c │ └── gcd.c │ ├── pack │ ├── pack.c │ └── unpack.c │ └── primes │ └── primes.c ├── pngusr-ro.dfa ├── pngusr-rw.dfa └── resources ├── bmfonts ├── digits-font.png ├── gliderrider-font.png ├── henry-font.png ├── ms-sans-serif.png ├── tall-font.png └── tiny-font.png └── composite ├── A.png └── B.png /.astylerc: -------------------------------------------------------------------------------- 1 | # .astylerc 2 | 3 | --align-pointer=name 4 | --convert-tabs 5 | --indent=spaces=2 6 | --max-continuation-indent=120 7 | --mode=c 8 | --pad-header 9 | --pad-oper 10 | --style=allman 11 | --unpad-paren 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # CI build for DPTLib 3 | # 4 | 5 | name: DPTLib 6 | on: [push] 7 | jobs: 8 | build: 9 | name: ${{ matrix.config.name }} 10 | runs-on: ${{ matrix.config.os }} 11 | strategy: 12 | matrix: 13 | config: 14 | - { name: "Ubuntu build", os: "ubuntu-latest", install: "sudo apt-get install cmake ninja-build" } 15 | - { name: "Windows build", os: "windows-latest", install: "choco install cmake ninja" } 16 | - { name: "macOS build", os: "macos-latest", install: "brew install cmake ninja" } 17 | steps: 18 | - uses: actions/checkout@v4 19 | - run: ${{ matrix.config.install }} 20 | - run: | 21 | mkdir build 22 | cd build 23 | cmake -GNinja .. 24 | cmake --build . 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Additional 32 | *.d 33 | *.orig 34 | xcuserdata 35 | tags 36 | *.plist 37 | doxydocs 38 | *.swp 39 | build 40 | build.ninja/ 41 | build.xcode/ 42 | .DS_Store 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, David Thomas 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * Add attributions (e.g. the packbits compressor is inspired by libtiff). 2 | * Apply inlining to bytesex and anything else that might benefit. 3 | * Big Doxygen pass to improve documentation. 4 | * Drop array squeeze/stretch duplicate functions. 5 | * Reinstate Fortify, or use Robin's one. 6 | -------------------------------------------------------------------------------- /cmake/enable_cmp0048.cmake: -------------------------------------------------------------------------------- 1 | cmake_policy(SET CMP0048 NEW) 2 | -------------------------------------------------------------------------------- /cmake/libpng-libm-unix.patch: -------------------------------------------------------------------------------- 1 | diff -ur a/CMakeLists.txt b/CMakeLists.txt 2 | --- a/CMakeLists.txt 2019-04-14 20:10:32.000000000 +0200 3 | +++ b/CMakeLists.txt 2019-09-06 14:14:39.425498139 +0200 4 | @@ -44,7 +44,7 @@ 5 | endif() 6 | 7 | if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU) 8 | - find_library(M_LIBRARY m) 9 | + set(M_LIBRARY m) 10 | else() 11 | # libm is not needed and/or not available 12 | set(M_LIBRARY "") 13 | -------------------------------------------------------------------------------- /cmake/zlib.patch: -------------------------------------------------------------------------------- 1 | --- a/CMakeLists.txt 2 | +++ b/CMakeLists.txt 3 | @@ -1,4 +1,4 @@ 4 | -cmake_minimum_required(VERSION 2.4.4) 5 | +cmake_minimum_required(VERSION 3.0.0) 6 | set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) 7 | 8 | project(zlib C) 9 | -------------------------------------------------------------------------------- /docs/bmfont.md: -------------------------------------------------------------------------------- 1 | [DPTLib](https://github.com/dpt/DPTLib) > framebuf > bmfont 2 | =========================================================== 3 | "bmfont" is a sub-library of DPTLib for drawing proportionally spaced bitmap fonts. It reads font definitions from PNG files like this: 4 | 5 | ![Henry Font](../resources/bmfonts/henry-font.png) 6 | 7 | or this: 8 | 9 | ![Digits Font](../resources/bmfonts/digits-font.png) 10 | 11 | or even this: 12 | 13 | ![Tiny Font](../resources/bmfonts/tiny-font.png) 14 | 15 | ...which have the glyphs laid out in a grid, with extra lines inserted, that define the advance widths. 16 | 17 | - It can draw to 4bpp and 32bpp format screens at the time of writing. 18 | - It supports both opaque and transparent backgrounds. 19 | - Its rendering should be reasonably quick. 20 | 21 | PNG Font Format 22 | --------------- 23 | The PNG should be 32 characters wide: bmfont works out the character dimensions from the total PNG size. 24 | 25 | It should be a four colour PNG where pixels of value 1 are font definitions and pixels of value 2 are advance widths. Note: An 8bpp 4-palette-entry image won't do, it must be 4bpp. 26 | 27 | Setup 28 | ----- 29 | #### Make a bitmap and a screen: 30 | 1. `bitmap_init()` to create a `bitmap_t` for your destination buffer. 31 | 2. `screen_for_bitmap()` to create a `screen_t` from the `bitmap_t`. 32 | 33 | #### Open a font: 34 | `bmfont_create()` to load a font from a PNG, returning a font handle. 35 | 36 | Measuring 37 | --------- 38 | Use `bmfont_measure()` to measure and determine split points for runs of text: 39 | 40 | ``` C 41 | result_t bmfont_measure(bmfont_t *bmfont, 42 | const char *text, 43 | int textlen, 44 | bmfont_width_t target_width, 45 | int *split_point, 46 | bmfont_width_t *actual_width); 47 | ``` 48 | 49 | It requires a font handle, a pointer to some text, the number of characters to consider and a target width. It returns a split point, and an actual width (both are optional - pass `NULL` if not required). 50 | 51 | Units are in pixels. 52 | 53 | Drawing 54 | ------- 55 | Use `bmfont_draw()` to draw runs of text: 56 | 57 | ``` C 58 | result_t bmfont_draw(bmfont_t *bmfont, 59 | screen_t *scr, 60 | const char *text, 61 | int len, 62 | colour_t fg, 63 | colour_t bg, 64 | const point_t *pos, 65 | point_t *end_pos); 66 | ``` 67 | 68 | It requires a font handle, the screen to draw to, a pointer to some text, the number of characters to consider, foreground and background colours, and a start position. It returns an end position (optional - pass `NULL` if not required). 69 | 70 | The screen origin is at the top left. 71 | 72 | Limitations 73 | ----------- 74 | * There's no character mapping yet - characters are treated as bytes, not UTF-8. 75 | * There's no tracking or kerning. 76 | -------------------------------------------------------------------------------- /docs/composite.md: -------------------------------------------------------------------------------- 1 | [DPTLib](https://github.com/dpt/DPTLib) > framebuf > composite 2 | ============================================================== 3 | "composite" is a sub-library of DPTLib for performing [Porter-Duff bitmap compositing](https://keithp.com/~keithp/porterduff/p253-porter.pdf). 4 | 5 | The code is written to make use of degenerate cases where pixels are fully transparent or fully opaque. 6 | 7 | Compositing 8 | ----------- 9 | Given input source `src` and destination `dst` bitmaps every pixel is composited according to the chosen `rule` and written back to `dst`. 10 | 11 | The bitmaps given must have alpha channels: `pixelfmt_rgba8888` and `pixelfmt_bgra8888` formats are currently supported. 12 | 13 | ``` C 14 | result_t composite(composite_rule_t rule, 15 | const bitmap_t *src, 16 | bitmap_t *dst); 17 | ``` 18 | 19 | Rules 20 | ----- 21 | * `composite_RULE_CLEAR` 22 | * [0, 0] 23 | * `composite_RULE_SRC` 24 | * [Sa, Sc] 25 | * `composite_RULE_DST` 26 | * [Da, Dc] 27 | * `composite_RULE_SRC_OVER` 28 | * [Sa + Da·(1 – Sa), Sc + Dc·(1 – Sa)] 29 | * `composite_RULE_DST_OVER` 30 | * [Da + Sa·(1 – Da), Dc + Sc·(1 – Da)] 31 | * `composite_RULE_SRC_IN` 32 | * [Sa·Da, Sc·Da] 33 | * `composite_RULE_DST_IN` 34 | * [Da·Sa, Dc·Sa] 35 | * `composite_RULE_SRC_OUT` 36 | * [Sa·(1 – Da), Sc·(1 – Da)] 37 | * `composite_RULE_DST_OUT` 38 | * [Da·(1 – Sa), Dc·(1 – Sa)] 39 | * `composite_RULE_SRC_ATOP` 40 | * [Da, Sc·Da + Dc·(1 – Sa)] 41 | * `composite_RULE_DST_ATOP` 42 | * [Sa, Dc·Sa + Sc·(1 – Da)] 43 | * `composite_RULE_XOR` 44 | * [Sa + Da – 2·Sa·Da, Sc·(1 – Da) + Dc·(1 – Sa)] 45 | 46 | Limitations 47 | ----------- 48 | The 'destination out' rule can presently suffer with some distortions. 49 | 50 | -------------------------------------------------------------------------------- /docs/stream.md: -------------------------------------------------------------------------------- 1 | [DPTLib](https://github.com/dpt/DPTLib) > io > stream 2 | ===================================================== 3 | "stream" is a sub-library of DPTLib for creating data sources and transforms. 4 | 5 | The core type `stream_t` is an interface which can be used to wrap, or create, sources of bytes. The interface is primarily byte oriented but block operations are supported too. Byte access is efficiently implemented as a macro. 6 | 7 | If a stream implementor also accepts a stream as input you can chain together the streams to build pipelines, similar to Unix pipes. 8 | 9 | Implementations of TIFF-style PackBits RLE and "Move to Front" compression and decompression are provided but they're really only intended as examples. 10 | 11 | This is a reimplementation of a technique that I was introduced to by Robin Watts and Paul Gardiner. 12 | 13 | Creating a stream 14 | ----------------- 15 | See `stream_mem_create()` and its associated functions for a concrete example of how to construct a stream. 16 | 17 | Using a stream 18 | -------------- 19 | Fetch a **byte** by using `stream_getc(stream)`. If the returned value is EOF then the stream has ended. 20 | 21 | Fetch a **block** by first using `stream_remaining_and_fill(stream)`. This will attempt to fill the buffer `stream->buf` up. Note that we don't specify by how much the buffer will be filled to allow for flexibility. 22 | 23 | Chaining streams 24 | ---------------- 25 | You can link streams together to create data pipelines that transform data in sequence. The second stream needs to be written to accept a stream as input, e.g. the example `stream_mtfcomp_create()` works like this. 26 | 27 | Provided example streams 28 | ------------------------ 29 | * `stream-stdio` 30 | - Creates a stream from a stdio FILE (read only). 31 | * `stream-mem` 32 | - Creates a stream from a single block of memory (read only). 33 | * `stream-packbits` 34 | - Performs PackBits RLE (de)compression. 35 | * `stream-mtfcomp` 36 | - Provides "move to front" adaptive (de)compression. 37 | 38 | Taking it further 39 | ----------------- 40 | Streams can be written to "fork" data into two separate pipes, to "cat" two pipes together, to "zip" pipes, etc. 41 | 42 | Remember to never cross the streams. 43 | -------------------------------------------------------------------------------- /include/base/debug.h: -------------------------------------------------------------------------------- 1 | /* debug.h -- debugging and logging macros */ 2 | 3 | #ifndef BASE_DEBUG_H 4 | #define BASE_DEBUG_H 5 | 6 | #include 7 | 8 | /* Log a message - available in all builds. */ 9 | #define logf_info(fmt, ...) fprintf(stderr, "(info) " fmt "\n", ##__VA_ARGS__) 10 | #define logf_warning(fmt, ...) fprintf(stderr, "(warning) " fmt "\n", ##__VA_ARGS__) 11 | #define logf_error(fmt, ...) fprintf(stderr, "(ERROR) %s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #define logf_fatal(fmt, ...) fprintf(stderr, "(FATAL) %s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) 13 | #define logf_abort(fmt, ...) fprintf(stderr, "(ABORT) %s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) 14 | 15 | /* Log a debug message - available only in debug builds. */ 16 | #ifndef NDEBUG 17 | # define logf_debug(fmt, ...) fprintf(stderr, "(debug) " fmt "\n", ##__VA_ARGS__) 18 | # define check(err) do { if (err) { logf_error("err=%x", err); goto failure; } } while (0) 19 | # define sentinel do { logf_error("sentinel"); goto failure; } while (0) 20 | #else 21 | # define logf_debug(fmt, ...) 22 | # define check(err) 23 | # define sentinel 24 | #endif 25 | 26 | #define haltf(...) do { logf_abort(__VA_ARGS__); abort(); } while (0) 27 | 28 | #endif /* BASE_DEBUG_H */ 29 | -------------------------------------------------------------------------------- /include/base/result.h: -------------------------------------------------------------------------------- 1 | /* result.h -- generic function return values */ 2 | 3 | #ifndef BASE_RESULT_H 4 | #define BASE_RESULT_H 5 | 6 | typedef int result_t; 7 | 8 | /* ----------------------------------------------------------------------- */ 9 | 10 | /* DPTLib bases */ 11 | #define result_BASE_GENERIC 0x0000 12 | #define result_BASE_STREAM 0x0100 13 | #define result_BASE_ATOM 0x0200 14 | #define result_BASE_HASH 0x0300 15 | #define result_BASE_PICKLE 0x0400 16 | #define result_BASE_TAGDB 0x0500 17 | #define result_BASE_FILENAMEDB 0x0600 18 | #define result_BASE_TEST 0x0700 19 | #define result_BASE_PACKER 0x0800 20 | #define result_BASE_LAYOUT 0x0900 21 | #define result_BASE_BITFIFO 0x0A00 22 | 23 | /* Non-DPTLib bases */ 24 | #define result_BASE_MMPLAYER 0x4000 25 | #define result_BASE_CONTAINER 0x4100 26 | #define result_BASE_CONTAINER_HASH 0x4200 27 | #define result_BASE_CONTAINER_QUEUE 0x4300 28 | 29 | /* AppEngine uses 0x8000+ */ 30 | 31 | /* ----------------------------------------------------------------------- */ 32 | 33 | #define result_OK (result_BASE_GENERIC + 0) /* No error */ 34 | #define result_OOM (result_BASE_GENERIC + 1) /* Out of memory */ 35 | #define result_FILE_NOT_FOUND (result_BASE_GENERIC + 2) 36 | #define result_BAD_ARG (result_BASE_GENERIC + 3) /* An argument was unacceptable */ 37 | #define result_BUFFER_OVERFLOW (result_BASE_GENERIC + 4) 38 | #define result_STOP_WALK (result_BASE_GENERIC + 5) /* Used to cancel callbacks */ 39 | #define result_PARSE_ERROR (result_BASE_GENERIC + 6) 40 | #define result_TOO_BIG (result_BASE_GENERIC + 7) 41 | #define result_NOT_IMPLEMENTED (result_BASE_GENERIC + 8) /* Function not implemented */ 42 | #define result_NOT_FOUND (result_BASE_GENERIC + 9) /* Item not found */ 43 | #define result_EXISTS (result_BASE_GENERIC + 10) /* Item already exists */ 44 | #define result_CLASHES (result_BASE_GENERIC + 11) /* Key clashes with existing one */ 45 | #define result_NULL_ARG (result_BASE_GENERIC + 12) /* An argument was NULL */ 46 | #define result_NOT_SUPPORTED (result_BASE_GENERIC + 13) /* Not supported, e.g. no hardware */ 47 | #define result_INCOMPATIBLE (result_BASE_GENERIC + 14) /* An argument was incompatible */ 48 | #define result_FOPEN_FAILED (result_BASE_GENERIC + 15) 49 | 50 | /* Stream result codes are in io/stream.h */ 51 | 52 | /* Atom result codes are in datastruct/atom.h */ 53 | 54 | /* Hash result codes are in datastruct/hash.h */ 55 | 56 | /* Pickle result codes are in databases/pickle.h */ 57 | 58 | /* TagDB result codes are in databases/tag-db.h */ 59 | 60 | /* FilenameDB result codes are in databases/filename-db.h */ 61 | 62 | #define result_TEST_PASSED (result_BASE_TEST + 0) 63 | #define result_TEST_FAILED (result_BASE_TEST + 1) 64 | 65 | /* Packer result codes are in geom/packer.h */ 66 | 67 | /* Layout result codes are in geom/layout.h */ 68 | 69 | /* ----------------------------------------------------------------------- */ 70 | 71 | #endif /* BASE_RESULT_H */ 72 | -------------------------------------------------------------------------------- /include/base/types.h: -------------------------------------------------------------------------------- 1 | /* types.h -- fixed-width integer types */ 2 | 3 | #ifndef BASE_TYPES_H 4 | #define BASE_TYPES_H 5 | 6 | #if defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L 7 | 8 | #include 9 | 10 | #else 11 | 12 | typedef signed char int8_t; 13 | typedef signed short int16_t; 14 | typedef signed int int32_t; 15 | typedef signed long long int64_t; 16 | 17 | typedef unsigned char uint8_t; 18 | typedef unsigned short uint16_t; 19 | typedef unsigned int uint32_t; 20 | typedef unsigned long long uint64_t; 21 | 22 | #ifdef _MSC_VER 23 | #ifdef _WIN64 24 | typedef __int64 intptr_t; 25 | #else 26 | typedef int intptr_t; 27 | #endif 28 | #endif 29 | 30 | #endif 31 | 32 | #endif /* BASE_TYPES_H */ 33 | -------------------------------------------------------------------------------- /include/base/utils.h: -------------------------------------------------------------------------------- 1 | /* utils.h -- various utilities */ 2 | 3 | #ifndef BASE_UTILS_H 4 | #define BASE_UTILS_H 5 | 6 | /* When on RISC OS, bring OSLib's types in. */ 7 | #ifdef __riscos 8 | #include "oslib/types.h" 9 | #endif 10 | 11 | /** 12 | * Returns the number of elements in the specified array. 13 | */ 14 | #ifndef NELEMS 15 | #define NELEMS(a) ((int) (sizeof(a) / sizeof((a)[0]))) 16 | #endif 17 | 18 | /** 19 | * Divide while rounding upwards. 20 | */ 21 | #define DIVIDE_ROUNDING_UP(n, m) (((n) + (m) - 1) / (m)) 22 | 23 | /** 24 | * Return the minimum of (a,b). 25 | */ 26 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) 27 | 28 | /** 29 | * Return the maximum of (a,b). 30 | */ 31 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) 32 | 33 | /** 34 | * Return 'a' clamped to the range [b..c]. 35 | */ 36 | #define CLAMP(a,b,c) MIN(MAX(a,b),c) 37 | 38 | /** 39 | * Suppress warnings about unused variables. 40 | */ 41 | #ifndef NOT_USED 42 | #define NOT_USED(x) ((x) = (x)) 43 | #endif 44 | 45 | /** 46 | * Inlining. 47 | */ 48 | #ifdef _WIN32 49 | #define INLINE __inline 50 | #else 51 | #define INLINE __inline__ 52 | #endif 53 | 54 | /** 55 | * Hints to compiler of probable execution path. 56 | */ 57 | #ifdef __GNUC__ 58 | #define likely(expr) __builtin_expect(!!(expr), 1) 59 | #define unlikely(expr) __builtin_expect(!!(expr), 0) 60 | #else 61 | #define likely(expr) (expr) 62 | #define unlikely(expr) (expr) 63 | #endif 64 | 65 | #endif /* BASE_UTILS_H */ 66 | -------------------------------------------------------------------------------- /include/databases/digest-db.h: -------------------------------------------------------------------------------- 1 | /* digest-db.h -- digest database */ 2 | 3 | /** 4 | * \file digest-db.h 5 | * 6 | * Digest database. 7 | * 8 | * digestdb is a wrapper around an atom set specifically for holding 9 | * (128-bit) digests. It is used by tagdb and filenamedb to share the cost of 10 | * storing digest values by replacing 128-bit digests with smaller indices. 11 | */ 12 | 13 | #ifndef DATABASES_DIGEST_DB_H 14 | #define DATABASES_DIGEST_DB_H 15 | 16 | #ifdef __cplusplus 17 | extern "C" 18 | { 19 | #endif 20 | 21 | #include 22 | 23 | #include "base/result.h" 24 | 25 | /* ----------------------------------------------------------------------- */ 26 | 27 | #define digestdb_DIGESTSZ 16 28 | 29 | /* ----------------------------------------------------------------------- */ 30 | 31 | result_t digestdb_init(void); 32 | void digestdb_fin(void); 33 | 34 | /* ----------------------------------------------------------------------- */ 35 | 36 | result_t digestdb_add(const unsigned char *digest, int *index); 37 | const unsigned char *digestdb_get(int index); 38 | 39 | /* ----------------------------------------------------------------------- */ 40 | 41 | unsigned int digestdb_hash(const void *a); 42 | int digestdb_compare(const void *a, const void *b); 43 | 44 | /* ----------------------------------------------------------------------- */ 45 | 46 | /* Utilities */ 47 | 48 | /** 49 | * Decode 32 characters of ASCII hex to 16 bytes. 50 | * 51 | * \return result_BAD_ARG if nonhex data is encountered. 52 | */ 53 | result_t digestdb_decode(unsigned char *digest, const char *text); 54 | 55 | /** 56 | * Encode 16 bytes to 32 characters of ASCII hex. 57 | */ 58 | void digestdb_encode(char *text, const unsigned char *digest); 59 | 60 | /* ----------------------------------------------------------------------- */ 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #endif /* DATABASES_DIGEST_DB_H */ 67 | -------------------------------------------------------------------------------- /include/databases/filename-db.h: -------------------------------------------------------------------------------- 1 | /* filename-db.h -- filename database */ 2 | 3 | /** 4 | * \file filename-db.h 5 | * 6 | * Filename database. 7 | * 8 | * The filenamedb is an associative array which maps keys (such as digests) 9 | * to filenames. The data is stored on disc. 10 | * 11 | * PrivateEye uses this to find out where an image lives given its digest. 12 | */ 13 | 14 | #ifndef DATABASES_FILENAME_DB_H 15 | #define DATABASES_FILENAME_DB_H 16 | 17 | #ifdef __cplusplus 18 | extern "C" 19 | { 20 | #endif 21 | 22 | #include 23 | 24 | #include "base/result.h" 25 | #include "databases/pickle.h" 26 | 27 | /* ----------------------------------------------------------------------- */ 28 | 29 | #define result_FILENAMEDB_INCOMPATIBLE (result_BASE_FILENAMEDB + 0) 30 | #define result_FILENAMEDB_COULDNT_OPEN_FILE (result_BASE_FILENAMEDB + 1) 31 | #define result_FILENAMEDB_SYNTAX_ERROR (result_BASE_FILENAMEDB + 2) 32 | #define result_FILENAMEDB_BUFF_OVERFLOW (result_BASE_FILENAMEDB + 3) 33 | 34 | /* ----------------------------------------------------------------------- */ 35 | 36 | #define T filenamedb_t 37 | 38 | /* ----------------------------------------------------------------------- */ 39 | 40 | result_t filenamedb_init(void); 41 | void filenamedb_fin(void); 42 | 43 | /* ----------------------------------------------------------------------- */ 44 | 45 | #define filenamedb_delete pickle_delete 46 | 47 | /* ----------------------------------------------------------------------- */ 48 | 49 | typedef struct filenamedb T; 50 | 51 | result_t filenamedb_open(const char *filename, T **db); 52 | void filenamedb_close(T *db); 53 | 54 | /** 55 | * Force any pending changes to disc. 56 | */ 57 | result_t filenamedb_commit(T *db); 58 | 59 | /* ----------------------------------------------------------------------- */ 60 | 61 | result_t filenamedb_add(T *db, 62 | const char *id, 63 | const char *filename); 64 | 65 | const char *filenamedb_get(T *db, 66 | const char *id); 67 | 68 | /* ----------------------------------------------------------------------- */ 69 | 70 | /** 71 | * Delete knowledge of filenames which don't exist on disc. 72 | */ 73 | result_t filenamedb_prune(T *db); 74 | 75 | /* ----------------------------------------------------------------------- */ 76 | 77 | #undef T 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif /* DATABASES_FILENAME_DB_H */ 84 | -------------------------------------------------------------------------------- /include/databases/pickle-reader-hash.h: -------------------------------------------------------------------------------- 1 | /* pickle-reader-hash.h -- glue methods to let pickle read from hashes */ 2 | 3 | #ifndef DATABASES_PICKLE_READER_HASH_H 4 | #define DATABASES_PICKLE_READER_HASH_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include "databases/pickle.h" 12 | 13 | /* Methods exposed for clients' re-use. */ 14 | 15 | pickle_reader_start_t pickle_reader_hash_start; 16 | pickle_reader_stop_t pickle_reader_hash_stop; 17 | pickle_reader_next_t pickle_reader_hash_next; 18 | 19 | extern const pickle_reader_methods_t pickle_reader_hash; 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif /* DATABASES_PICKLE_READER_HASH_H */ 26 | -------------------------------------------------------------------------------- /include/databases/pickle-writer-hash.h: -------------------------------------------------------------------------------- 1 | /* pickle-writer-hash.h -- glue methods to let pickle write to hashes */ 2 | 3 | #ifndef DATABASES_PICKLE_WRITER_HASH_H 4 | #define DATABASES_PICKLE_WRITER_HASH_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include "databases/pickle.h" 12 | 13 | /* Methods exposed for clients' re-use. */ 14 | 15 | pickle_writer_start_t pickle_writer_hash_start; 16 | pickle_writer_stop_t pickle_writer_hash_stop; 17 | pickle_writer_next_t pickle_writer_hash_next; 18 | 19 | extern const pickle_writer_methods_t pickle_writer_hash; 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif /* DATABASES_PICKLE_WRITER_HASH_H */ 26 | -------------------------------------------------------------------------------- /include/datastruct/bitfifo.h: -------------------------------------------------------------------------------- 1 | /* bitfifo.h -- fifo which stores bits */ 2 | 3 | /** 4 | * \file bitfifo.h 5 | * 6 | * A fifo which stores bits. 7 | */ 8 | 9 | #ifndef DATASTRUCT_BITFIFO_H 10 | #define DATASTRUCT_BITFIFO_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" 14 | { 15 | #endif 16 | 17 | #include 18 | 19 | #include "base/result.h" 20 | 21 | /* ----------------------------------------------------------------------- */ 22 | 23 | #define result_BITFIFO_EMPTY (result_BASE_BITFIFO + 0) 24 | #define result_BITFIFO_FULL (result_BASE_BITFIFO + 1) 25 | #define result_BITFIFO_INSUFFICIENT (result_BASE_BITFIFO + 2) 26 | 27 | /* ----------------------------------------------------------------------- */ 28 | 29 | #define T bitfifo_t 30 | 31 | /** 32 | * A bit fifo's type. 33 | */ 34 | typedef struct bitfifo T; 35 | 36 | /* ----------------------------------------------------------------------- */ 37 | 38 | /** 39 | * Create a bitfifo. 40 | * 41 | * \param nbits Minimum number of bits that the bitfifo should store. 42 | * 43 | * \return New bitfifo or NULL if OOM. 44 | */ 45 | bitfifo_t *bitfifo_create(int nbits); 46 | 47 | /** 48 | * Destroy a bitfifo. 49 | * 50 | * \param doomed bitfifo to destroy. 51 | */ 52 | void bitfifo_destroy(T *doomed); 53 | 54 | /* ----------------------------------------------------------------------- */ 55 | 56 | /* writes bits to 'head' onwards, wrapping around if required */ 57 | /* fifo will reject attempts to store more bits than there is space for */ 58 | result_t bitfifo_enqueue(T *fifo, 59 | const unsigned int *newbits, 60 | unsigned int newbitsoffset, 61 | size_t nnewbits); 62 | 63 | /* reads bits from 'tail' onwards, wrapping around if required */ 64 | result_t bitfifo_dequeue(T *fifo, 65 | unsigned int *outbits, 66 | size_t noutbits); 67 | 68 | /* ----------------------------------------------------------------------- */ 69 | 70 | /* empty the specified fifo */ 71 | void bitfifo_clear(T *fifo); 72 | 73 | /* returns number of used bits in the fifo */ 74 | size_t bitfifo_used(const T *fifo); 75 | 76 | /* returns non-zero if the fifo is full */ 77 | int bitfifo_full(const T *fifo); 78 | 79 | /* returns non-zero if the fifo is empty */ 80 | int bitfifo_empty(const T *fifo); 81 | 82 | /* ----------------------------------------------------------------------- */ 83 | 84 | #undef T 85 | 86 | /* ----------------------------------------------------------------------- */ 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #endif /* DATASTRUCT_BITFIFO_H */ 93 | -------------------------------------------------------------------------------- /include/datastruct/bitvec.h: -------------------------------------------------------------------------------- 1 | /* bitvec.h -- flexible arrays of bits */ 2 | 3 | /** 4 | * \file bitvec.h 5 | * 6 | * Vectors of bits. 7 | * 8 | * Bit vectors are an array of bits. They are of variable length and are 9 | * allocated dynamically. 10 | * 11 | * Unallocated bits are notionally always present and read as zero. 12 | * 13 | * \see Bit Array for manipulating a pre-allocated bit array. 14 | */ 15 | 16 | #ifndef DATASTRUCT_BITVEC_H 17 | #define DATASTRUCT_BITVEC_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" 21 | { 22 | #endif 23 | 24 | #include "base/result.h" 25 | 26 | #define T bitvec_t 27 | 28 | typedef struct bitvec T; 29 | 30 | typedef unsigned int bitvec_index_t; 31 | 32 | /* Creates a bit vector big enough to hold 'length' bits. 33 | * All bits are zero after creation. */ 34 | T *bitvec_create(unsigned int length); 35 | void bitvec_destroy(T *v); 36 | 37 | result_t bitvec_set(T *v, bitvec_index_t bit); 38 | void bitvec_clear(T *v, bitvec_index_t bit); 39 | result_t bitvec_toggle(T *v, bitvec_index_t bit); 40 | 41 | int bitvec_get(const T *v, bitvec_index_t bit); 42 | 43 | /* Returns the length of the vector in bits. */ 44 | unsigned int bitvec_length(const T *v); 45 | 46 | /* Returns the number of set bits in the vector. */ 47 | unsigned int bitvec_count(const T *v); 48 | 49 | /* Returns the number of the next set bit after 'n'. */ 50 | /* -1 should be the initial value (bits are numbered 0..) */ 51 | int bitvec_next(const T *v, int n); 52 | 53 | int bitvec_eq(const T *a, const T *b); 54 | 55 | result_t bitvec_and(const T *a, const T *b, T **c); 56 | result_t bitvec_or(const T *a, const T *b, T **c); 57 | 58 | void bitvec_set_all(T *v); 59 | void bitvec_clear_all(T *v); 60 | 61 | #undef T 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | #endif /* DATASTRUCT_BITVEC_H */ 68 | -------------------------------------------------------------------------------- /include/datastruct/hlist.h: -------------------------------------------------------------------------------- 1 | /* hlist.h -- "Hanson" linked list library */ 2 | 3 | /* See chapter 5 of C Interfaces and Implementations. */ 4 | 5 | #ifndef DATASTRUCT_HLIST_H 6 | #define DATASTRUCT_HLIST_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" 10 | { 11 | #endif 12 | 13 | #define T hlist_t 14 | 15 | typedef struct hlist *T; 16 | 17 | struct hlist 18 | { 19 | T rest; 20 | void *first; /* the payload */ 21 | }; 22 | 23 | T hlist_append(T list, T tail); 24 | T hlist_copy(T list); 25 | T hlist_list(void *x, ...); 26 | T hlist_pop(T list, void **x); 27 | T hlist_push(T list, void *x); 28 | T hlist_reverse(T list); 29 | int hlist_length(T list); 30 | void hlist_free(T *list); 31 | void hlist_map(T list, void apply(void **x, void *cl), void *cl); 32 | void **hlist_to_array(T list, void *end); 33 | 34 | #undef T 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | 40 | #endif /* DATASTRUCT_HLIST_H */ 41 | -------------------------------------------------------------------------------- /include/datastruct/list.h: -------------------------------------------------------------------------------- 1 | /* list.h -- linked lists */ 2 | 3 | /** 4 | * \file list.h 5 | * 6 | * A linked list. 7 | */ 8 | 9 | #ifndef DATASTRUCT_LIST_H 10 | #define DATASTRUCT_LIST_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" 14 | { 15 | #endif 16 | 17 | #include 18 | 19 | #define T list_t 20 | 21 | typedef struct list 22 | { 23 | struct list *next; 24 | } 25 | T; 26 | 27 | void list_init(T *anchor); 28 | 29 | /* Anchor is assumed to be a static element whose only job is to point to 30 | * the first element in the list. */ 31 | 32 | void list_add_to_head(T *anchor, T *item); 33 | 34 | void list_remove(T *anchor, T *doomed); 35 | 36 | typedef int (list_walk_callback_t)(T *, void *); 37 | 38 | int list_walk(T *anchor, list_walk_callback_t *cb, void *opaque); 39 | 40 | /* Searches the linked list looking for a key. The key is specified as an 41 | * offset from the start of the linked list element. It is an int-sized unit. 42 | */ 43 | T *list_find(T *anchor, size_t keyloc, int key); 44 | 45 | #undef T 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif /* DATASTRUCT_LIST_H */ 52 | -------------------------------------------------------------------------------- /include/datastruct/ntree.h: -------------------------------------------------------------------------------- 1 | /* ntree.h -- n-ary trees */ 2 | 3 | /** 4 | * \file ntree.h 5 | * 6 | * NTree is an N-ary tree. 7 | */ 8 | 9 | #ifndef DATASTRUCT_NTREE_H 10 | #define DATASTRUCT_NTREE_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" 14 | { 15 | #endif 16 | 17 | #include "base/result.h" 18 | 19 | #define T ntree_t 20 | 21 | typedef struct ntree T; 22 | 23 | /* ----------------------------------------------------------------------- */ 24 | 25 | result_t ntree_new(T **t); 26 | 27 | /* Unlinks the specified node from the tree. */ 28 | void ntree_unlink(T *t); 29 | 30 | /* Deletes the specified node and all children. */ 31 | void ntree_free(T *t); 32 | 33 | /* Unlinks the specified node from the tree, deletes it and all children. */ 34 | void ntree_delete(T *t); 35 | 36 | /* ----------------------------------------------------------------------- */ 37 | 38 | T *ntree_nth_child(T *t, int n); 39 | 40 | /* ----------------------------------------------------------------------- */ 41 | 42 | #define ntree_INSERT_AT_END -1 43 | 44 | result_t ntree_prepend(T *parent, T *node); 45 | result_t ntree_append(T *parent, T *node); 46 | result_t ntree_insert_before(T *parent, T *sibling, T *node); 47 | result_t ntree_insert_after(T *parent, T *sibling, T *node); 48 | 49 | result_t ntree_insert(T *t, int where, T *node); 50 | 51 | void ntree_set_data(T *t, void *data); 52 | void *ntree_get_data(T *t); 53 | 54 | int ntree_depth(T *t); 55 | int ntree_max_height(T *t); 56 | int ntree_n_nodes(T *t); 57 | 58 | T *ntree_next_sibling(T *t); 59 | T *ntree_prev_sibling(T *t); 60 | T *ntree_parent(T *t); 61 | T *ntree_first_child(T *t); 62 | T *ntree_last_child(T *t); 63 | 64 | /* ----------------------------------------------------------------------- */ 65 | 66 | typedef unsigned int ntree_walk_flags_t; 67 | 68 | #define ntree_WALK_ORDER_MASK (3u << 0) 69 | #define ntree_WALK_IN_ORDER (0u << 0) 70 | #define ntree_WALK_PRE_ORDER (1u << 0) 71 | #define ntree_WALK_POST_ORDER (2u << 0) 72 | 73 | #define ntree_WALK_LEAVES (1u << 2) 74 | #define ntree_WALK_BRANCHES (1u << 3) 75 | #define ntree_WALK_ALL (ntree_WALK_LEAVES | ntree_WALK_BRANCHES) 76 | 77 | typedef result_t (ntree_walk_fn_t)(T *t, void *opaque); 78 | 79 | /* max_depth of 0 means 'walk all', 1..N just walk level 1..N */ 80 | result_t ntree_walk(T *t, 81 | ntree_walk_flags_t flags, 82 | int max_depth, 83 | ntree_walk_fn_t *fn, 84 | void *opaque); 85 | 86 | /* ----------------------------------------------------------------------- */ 87 | 88 | typedef result_t (ntree_copy_fn_t)(void *data, void *opaque, void **newdata); 89 | 90 | result_t ntree_copy(T *t, ntree_copy_fn_t *fn, void *opaque, T **new_t); 91 | 92 | #undef T 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | #endif /* DATASTRUCT_NTREE_H */ 99 | -------------------------------------------------------------------------------- /include/fortify/ufortify.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FILE: 3 | * ufortify.h 4 | * 5 | * DESCRIPTION: 6 | * User options for fortify. Changes to this file require fortify.c to be 7 | * recompiled, but nothing else. 8 | */ 9 | 10 | #define FORTIFY_STORAGE /* storage for public functions */ 11 | 12 | #define FORTIFY_ALIGNMENT sizeof(double) /* Byte alignment of all memory blocks */ 13 | 14 | #define FORTIFY_BEFORE_SIZE 32 /* Bytes to allocate before block */ 15 | #define FORTIFY_BEFORE_VALUE 0xA3 /* Fill value before block */ 16 | 17 | #define FORTIFY_AFTER_SIZE 32 /* Bytes to allocate after block */ 18 | #define FORTIFY_AFTER_VALUE 0xA5 /* Fill value after block */ 19 | 20 | #define FORTIFY_FILL_ON_ALLOCATE /* Nuke out malloc'd memory */ 21 | #define FORTIFY_FILL_ON_ALLOCATE_VALUE 0xA7 /* Value to initialize with */ 22 | 23 | #define FORTIFY_FILL_ON_DEALLOCATE /* free'd memory is cleared */ 24 | #define FORTIFY_FILL_ON_DEALLOCATE_VALUE 0xA9 /* Value to de-initialize with */ 25 | 26 | #define FORTIFY_FILL_ON_CORRUPTION /* Nuke out corrupted memory */ 27 | 28 | /* #define FORTIFY_CHECK_ALL_MEMORY_ON_ALLOCATE */ 29 | #define FORTIFY_CHECK_ALL_MEMORY_ON_DEALLOCATE 30 | #define FORTIFY_PARANOID_DEALLOCATE 31 | 32 | /* #define FORTIFY_WARN_ON_ZERO_MALLOC */ /* A debug is issued on a malloc(0) */ 33 | /* #define FORTIFY_FAIL_ON_ZERO_MALLOC */ /* A malloc(0) will fail */ 34 | 35 | #define FORTIFY_WARN_ON_ALLOCATE_FAIL /* A debug is issued on a failed alloc */ 36 | #define FORTIFY_WARN_ON_FALSE_FAIL /* See Fortify_SetAllocateFailRate */ 37 | #define FORTIFY_WARN_ON_SIZE_T_OVERFLOW /* Watch for breaking the 64K limit in */ 38 | /* some braindead architectures... */ 39 | 40 | #define FORTIFY_TRACK_DEALLOCATED_MEMORY 41 | #define FORTIFY_DEALLOCATED_MEMORY_LIMIT 1048576 /* Maximum amount of deallocated bytes to keep */ 42 | /* #define FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */ 43 | /* #define FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */ 44 | 45 | /* #define FORTIFY_NO_PERCENT_P */ /* sprintf() doesn't support %p */ 46 | /* #define FORTIFY_STRDUP */ /* if you use non-ANSI strdup() */ 47 | 48 | #define FORTIFY_LOCK() 49 | #define FORTIFY_UNLOCK() 50 | 51 | #define FORTIFY_DELETE_STACK_SIZE 256 52 | 53 | #ifdef __cplusplus /* C++ only options go here */ 54 | 55 | /* #define FORTIFY_PROVIDE_ARRAY_NEW */ 56 | /* #define FORTIFY_PROVIDE_ARRAY_DELETE */ 57 | 58 | /* #define FORTIFY_AUTOMATIC_LOG_FILE */ 59 | #define FORTIFY_LOG_FILENAME "fortify.log" 60 | #include 61 | #define FORTIFY_FIRST_ERROR_FUNCTION cout << "\a\a\aFortify Hit Generated!\n" 62 | 63 | #endif /* __cplusplus */ 64 | -------------------------------------------------------------------------------- /include/framebuf/bitmap-set.h: -------------------------------------------------------------------------------- 1 | /* bitmap-set.h -- a set of bitmap images */ 2 | 3 | #ifndef FRAMEBUF_BITMAP_SET_H 4 | #define FRAMEBUF_BITMAP_SET_H 5 | 6 | #include "framebuf/bitmap.h" 7 | 8 | /** A set of identical bitmaps. */ 9 | typedef struct bitmap_set bitmap_set_t; 10 | 11 | struct bitmap_set 12 | { 13 | bitmap_format_MEMBERS; 14 | void **bases; /* an array of bitmap base pointers */ 15 | int nbases; 16 | }; 17 | 18 | #endif /* FRAMEBUF_BITMAP_SET_H */ 19 | -------------------------------------------------------------------------------- /include/framebuf/bitmap.h: -------------------------------------------------------------------------------- 1 | /* bitmap.h -- bitmap image type */ 2 | 3 | #ifndef FRAMEBUF_BITMAP_H 4 | #define FRAMEBUF_BITMAP_H 5 | 6 | #include "base/result.h" 7 | #include "framebuf/colour.h" 8 | #include "framebuf/pixelfmt.h" 9 | 10 | /** Common bitmap members. */ 11 | #define bitmap_format_MEMBERS \ 12 | int width, height; \ 13 | pixelfmt_t format; \ 14 | int rowbytes; \ 15 | colour_t *palette 16 | 17 | /** Common bitmap members. */ 18 | #define bitmap_all_MEMBERS \ 19 | int width, height; \ 20 | pixelfmt_t format; \ 21 | int rowbytes; \ 22 | colour_t *palette; \ 23 | void *base 24 | 25 | /** A bitmap. */ 26 | typedef struct bitmap bitmap_t; 27 | 28 | struct bitmap 29 | { 30 | bitmap_all_MEMBERS; 31 | }; 32 | 33 | result_t bitmap_init(bitmap_t *bm, 34 | int width, 35 | int height, 36 | pixelfmt_t fmt, 37 | int rowbytes, 38 | const colour_t *palette, 39 | void *base); 40 | 41 | void bitmap_clear(bitmap_t *bm, colour_t c); 42 | 43 | // it ought to be possible to provide instant flip_y by adjusting the base pointer and negating the rowbytes (which is why rowbytes is signed). 44 | //void bitmap_flip_y(bitmap_t *bm) 45 | //{ 46 | // uint8_t *base; 47 | // 48 | // base = bm->base; 49 | // base += bm->height * bm->rowbytes; 50 | // 51 | // bm->rowbytes = -bm->rowbytes; 52 | // 53 | // bm->base = base; 54 | //} 55 | 56 | result_t bitmap_load_png(bitmap_t *bm, const char *filename); 57 | result_t bitmap_save_png(const bitmap_t *bm, const char *filename); 58 | 59 | result_t bitmap_convert(const bitmap_t *bm, pixelfmt_t newfmt, bitmap_t **newbm); 60 | 61 | #endif /* FRAMEBUF_BITMAP_H */ 62 | -------------------------------------------------------------------------------- /include/framebuf/bmfont.h: -------------------------------------------------------------------------------- 1 | /* bmfont.h -- proportional bitmap font engine */ 2 | 3 | #ifndef DPTLIB_BMFONT_H 4 | #define DPTLIB_BMFONT_H 5 | 6 | #include "base/result.h" 7 | #include "geom/point.h" 8 | #include "framebuf/screen.h" 9 | 10 | typedef struct bmfont bmfont_t; 11 | typedef int bmfont_width_t; /* in pixels */ 12 | 13 | result_t bmfont_create(const char *png, bmfont_t **bmfont); 14 | void bmfont_destroy(bmfont_t *bmfont); 15 | 16 | void bmfont_get_info(bmfont_t *bmfont, int *width, int *height); 17 | 18 | result_t bmfont_measure(bmfont_t *bmfont, 19 | const char *text, 20 | int len, 21 | bmfont_width_t target_width, 22 | int *split_point, 23 | bmfont_width_t *actual_width); 24 | 25 | result_t bmfont_draw(bmfont_t *bmfont, 26 | screen_t *scr, 27 | const char *text, 28 | int len, 29 | colour_t fg, 30 | colour_t bg, 31 | const point_t *pos, 32 | point_t *end_pos); 33 | 34 | #endif /* DPTLIB_BMFONT_H */ 35 | -------------------------------------------------------------------------------- /include/framebuf/colour.h: -------------------------------------------------------------------------------- 1 | /* colour.h -- colour type */ 2 | 3 | #ifndef FRAMEBUF_COLOUR_H 4 | #define FRAMEBUF_COLOUR_H 5 | 6 | #include "framebuf/pixelfmt.h" 7 | 8 | typedef struct colour colour_t; 9 | 10 | struct colour 11 | { 12 | pixelfmt_rgba8888_t primary; 13 | }; 14 | 15 | /** Create a colour from (R,G,B). */ 16 | colour_t colour_rgb(int r, int g, int b); 17 | 18 | /** Create a colour from (R,G,B,A). */ 19 | colour_t colour_rgba(int r, int g, int b, int a); 20 | 21 | /** Return colour `c` as a pixel of format `fmt`. */ 22 | pixelfmt_any_t colour_to_pixel(const colour_t *palette, 23 | int nentries, 24 | colour_t required, 25 | pixelfmt_t fmt); 26 | 27 | /** Return the alpha component of the specified colour. */ 28 | unsigned int colour_get_alpha(const colour_t *c); 29 | 30 | #endif /* FRAMEBUF_COLOUR_H */ 31 | -------------------------------------------------------------------------------- /include/framebuf/composite.h: -------------------------------------------------------------------------------- 1 | /* composite.h -- Porter-Duff image compositing */ 2 | 3 | #ifndef COMPOSITE_H 4 | #define COMPOSITE_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include "base/result.h" 12 | 13 | #include "framebuf/bitmap.h" 14 | #include "framebuf/pixelfmt.h" 15 | 16 | typedef enum composite_rule 17 | { 18 | composite_RULE_CLEAR, 19 | composite_RULE_SRC, 20 | composite_RULE_DST, 21 | composite_RULE_SRC_OVER, 22 | composite_RULE_DST_OVER, 23 | composite_RULE_SRC_IN, 24 | composite_RULE_DST_IN, 25 | composite_RULE_SRC_OUT, 26 | composite_RULE_DST_OUT, 27 | composite_RULE_SRC_ATOP, 28 | composite_RULE_DST_ATOP, 29 | composite_RULE_XOR, 30 | composite_RULE__LIMIT 31 | } 32 | composite_rule_t; 33 | 34 | /** 35 | * Composites bitmap 'src' over 'dst' (or other rule). 36 | * 37 | * \param[in] rule Compositing rule to use. 38 | * \param[in] src First source bitmap. 39 | * \param[in] dst Second source and destination bitmap. 40 | * 41 | * \return Result. 42 | * 43 | * The given bitmaps must have alpha channels. 44 | */ 45 | result_t composite(composite_rule_t rule, 46 | const bitmap_t *src, 47 | bitmap_t *dst); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* COMPOSITE_H */ 54 | -------------------------------------------------------------------------------- /include/framebuf/screen.h: -------------------------------------------------------------------------------- 1 | /* screen.h -- screen type */ 2 | 3 | #ifndef FRAMEBUF_SCREEN_H 4 | #define FRAMEBUF_SCREEN_H 5 | 6 | #include "framebuf/bitmap.h" 7 | #include "geom/box.h" 8 | 9 | typedef struct screen screen_t; 10 | 11 | // define screen origin etc. 12 | 13 | struct screen 14 | { 15 | bitmap_all_MEMBERS; 16 | box_t clip; /* rectangular clip region, specified in pixels */ 17 | }; 18 | 19 | void screen_init(screen_t *scr, 20 | int width, 21 | int height, 22 | pixelfmt_t fmt, 23 | int rowbytes, 24 | colour_t *palette, 25 | box_t clip, 26 | void *base); 27 | 28 | void screen_for_bitmap(screen_t *scr, const bitmap_t *bm); 29 | 30 | box_t screen_get_clip(const screen_t *scr); 31 | 32 | #endif /* FRAMEBUF_SCREEN_H */ 33 | -------------------------------------------------------------------------------- /include/geom/box.h: -------------------------------------------------------------------------------- 1 | /* box.h -- box type */ 2 | 3 | #ifndef GEOM_BOX_H 4 | #define GEOM_BOX_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #ifndef __riscos 12 | /** A box inclusive of (x0,y0) and exclusive of (x1,y1). */ 13 | typedef struct box 14 | { 15 | int x0, y0, x1, y1; 16 | } 17 | box_t; 18 | #else 19 | #include "oslib/os.h" 20 | /* When on RISC OS, use OSLib's box type in preference. */ 21 | typedef os_box box_t; 22 | #endif 23 | 24 | /** 25 | * Reset the box to an invalid state. 26 | * 27 | * This sets x0,y0 to INT_MAX and the x1,y1 to INT_MIN. This is an invalid 28 | * box but will still produce a valid result when intersected with. 29 | * 30 | * \param[in] b The box to reset. 31 | */ 32 | void box_reset(box_t *b); 33 | 34 | /** 35 | * Affirms if box "outer" entirely contains box "inner". 36 | * 37 | * \param[in] inner The inner box. 38 | * \param[in] outer The outer box. 39 | * 40 | * \return Non-zero if the box is contained. 41 | */ 42 | int box_contains_box(const box_t *inner, const box_t *outer); 43 | 44 | /** 45 | * Affirms if the box "b" entirely contains the point (x,y). 46 | * 47 | * \param[in] b The box to test. 48 | * \param[in] x The x coordinate of the point to test. 49 | * \param[in] y The y coordinate of the point to test. 50 | * 51 | * \return Non-zero if the point is contained. 52 | */ 53 | int box_contains_point(const box_t *b, int x, int y); 54 | 55 | /** 56 | * Affirms if the box "a" intersects with box "b". 57 | * 58 | * \param[in] a The first box. 59 | * \param[in] b The second box. 60 | * 61 | * \return Non-zero if the boxes intersect. 62 | */ 63 | int box_intersects(const box_t *a, const box_t *b); 64 | 65 | /** 66 | * Populates the box "c" with the intersection of boxes "a" and "b". 67 | * 68 | * \param[in] a The first box. 69 | * \param[in] b The second box. 70 | * \param[out] c The output intersected box. 71 | * 72 | * \return Non-zero if the result is invalid. 73 | */ 74 | int box_intersection(const box_t *a, const box_t *b, box_t *c); 75 | 76 | /** 77 | * Populates the box "clipped" with the sizes of the edges discarded when clipping box "b" against "a". 78 | * 79 | * \param[in] a The first box. 80 | * \param[in] b The second box. 81 | * \param[out] clipped Not really a box, but one scalar per edge. Values are positive where "b" extends outside of "a", zero otherwise. 82 | */ 83 | void box_clipped(const box_t *a, const box_t *b, box_t *clipped); 84 | 85 | /** 86 | * Populates the box "c" with the union of boxes "a" and "b". 87 | * 88 | * \param[in] a The first box. 89 | * \param[in] b The second box. 90 | * \param[out] c The output unioned box. 91 | */ 92 | void box_union(const box_t *a, const box_t *b, box_t *c); 93 | 94 | /** 95 | * Affirms if the specified box is empty. 96 | * 97 | * \param[in] b The box to test. 98 | * 99 | * \return Non-zero if the box is empty. 100 | */ 101 | int box_is_empty(const box_t *b); 102 | 103 | /** 104 | * Grows the box outwards by "change". 105 | * 106 | * \param[in] b The box to grow. 107 | */ 108 | void box_grow(box_t *b, int change); 109 | 110 | /** 111 | * Rounds a box's coordinates so that they're a multiple of log2 x,y. 112 | * 113 | * x0 and y0 are rounded down. x1 and y1 are rounded up. 114 | * 115 | * \param[in] b The box to round. 116 | */ 117 | void box_round(box_t *b, int log2x, int log2y); 118 | 119 | /** 120 | * Rounds a box's coordinates so that they're a multiple of 4. 121 | * 122 | * x0 and y0 are rounded down. x1 and y1 are rounded up. 123 | * 124 | * \param[in] b The box to round. 125 | */ 126 | void box_round4(box_t *b); 127 | 128 | /** 129 | * Affirms if the box "b" is at least (w,h) in size. 130 | * 131 | * \param[in] b The box to test. 132 | * \param[in] w The width to test. 133 | * \param[in] h The height to test. 134 | * 135 | * \return Non-zero if the point is contained. 136 | */ 137 | int box_could_hold(const box_t *b, int w, int h); 138 | 139 | /** 140 | * Translates box "b" by (x,y) producing new box "t". 141 | * 142 | * \param[in] b The box to translate. 143 | * \param[in] x The amount to translate by horizontally. 144 | * \param[in] y The amount to translate by vertically. 145 | * \param[in] t The new box. 146 | */ 147 | void box_translated(const box_t *b, int x, int y, box_t *t); 148 | 149 | #ifdef __cplusplus 150 | } 151 | #endif 152 | 153 | #endif /* GEOM_BOX_H */ 154 | -------------------------------------------------------------------------------- /include/geom/layout.h: -------------------------------------------------------------------------------- 1 | /* layout.h -- laying out elements using the packer */ 2 | 3 | #ifndef GEOM_LAYOUT_H 4 | #define GEOM_LAYOUT_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include "base/result.h" 12 | #include "geom/box.h" 13 | #include "geom/packer.h" 14 | 15 | /* ----------------------------------------------------------------------- */ 16 | 17 | #define result_LAYOUT_BUFFER_FULL (result_BASE_LAYOUT + 0) 18 | 19 | /* ----------------------------------------------------------------------- */ 20 | 21 | 22 | typedef struct layout_element 23 | { 24 | enum 25 | { 26 | layout_BOX, 27 | layout_NEWLINE, 28 | } 29 | type; 30 | 31 | union 32 | { 33 | struct 34 | { 35 | int min_width, max_width; 36 | int height; 37 | } 38 | box; 39 | } 40 | data; 41 | } 42 | layout_element_t; 43 | 44 | typedef struct layout_spec 45 | { 46 | packer_t *packer; 47 | packer_loc_t loc; 48 | packer_cleardir_t clear; 49 | int spacing; 50 | int leading; 51 | } 52 | layout_spec_t; 53 | 54 | result_t layout_place(const layout_spec_t *spec, 55 | const layout_element_t *elements, 56 | int nelements, 57 | box_t *boxes, 58 | int nboxes); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif /* GEOM_LAYOUT_H */ 65 | -------------------------------------------------------------------------------- /include/geom/packer.h: -------------------------------------------------------------------------------- 1 | /* packer.h -- box packing for layout */ 2 | 3 | #ifndef GEOM_PACKER_H 4 | #define GEOM_PACKER_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include "base/result.h" 12 | #include "geom/box.h" 13 | 14 | /* ----------------------------------------------------------------------- */ 15 | 16 | #define result_PACKER_DIDNT_FIT (result_BASE_PACKER + 0) 17 | #define result_PACKER_EMPTY (result_BASE_PACKER + 1) 18 | 19 | /* ----------------------------------------------------------------------- */ 20 | 21 | #define T packer_t 22 | 23 | typedef struct packer T; 24 | 25 | T *packer_create(const box_t *dims); 26 | void packer_destroy(T *doomed); 27 | 28 | void packer_set_margins(T *packer, const box_t *margins); 29 | 30 | typedef enum packer_loc 31 | { 32 | packer_LOC_TOP_LEFT, 33 | packer_LOC_TOP_RIGHT, 34 | packer_LOC_BOTTOM_LEFT, 35 | packer_LOC_BOTTOM_RIGHT, 36 | packer_LOC__LIMIT, 37 | } 38 | packer_loc_t; 39 | 40 | /* returns the width of the next available area. */ 41 | int packer_next_width(T *packer, packer_loc_t loc); 42 | 43 | /* places an absolutely positioned box 'area'. ignores any margins. */ 44 | result_t packer_place_at(T *packer, 45 | const box_t *area); 46 | 47 | /* places a box of dimensions (w,h) in the next free area determined by 48 | * location 'loc'. */ 49 | result_t packer_place_by(T *packer, 50 | packer_loc_t loc, 51 | int w, 52 | int h, 53 | const box_t **pos); 54 | 55 | typedef enum packer_cleardir 56 | { 57 | packer_CLEAR_LEFT, 58 | packer_CLEAR_RIGHT, 59 | packer_CLEAR_BOTH, 60 | packer_CLEAR__LIMIT, 61 | } 62 | packer_cleardir_t; 63 | 64 | /* clears up to the next specified boundary. */ 65 | result_t packer_clear(T *packer, packer_cleardir_t clear); 66 | 67 | typedef result_t (packer_map_fn_t)(const box_t *area, void *opaque); 68 | /* calls 'fn' for every area known about. */ 69 | result_t packer_map(T *packer, packer_map_fn_t *fn, void *opaque); 70 | 71 | /* returns the union of all areas used. ignores margins. */ 72 | const box_t *packer_get_consumed_area(const T *packer); 73 | 74 | #undef T 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif /* GEOM_PACKER_H */ 81 | -------------------------------------------------------------------------------- /include/geom/point.h: -------------------------------------------------------------------------------- 1 | /* point.h -- point type */ 2 | 3 | #ifndef GEOM_POINT_H 4 | #define GEOM_POINT_H 5 | 6 | typedef struct point 7 | { 8 | int x, y; 9 | } 10 | point_t; 11 | 12 | #endif /* GEOM_POINT_H */ 13 | -------------------------------------------------------------------------------- /include/io/path.h: -------------------------------------------------------------------------------- 1 | /* path.h -- filename path handling */ 2 | 3 | #ifndef DPTLIB_PATH 4 | #define DPTLIB_PATH 5 | 6 | #define DPTLIB_MAXPATH 256 /* not ideal */ 7 | 8 | /** 9 | * Join 'leaf' with extension 'ext' according to the host convention. 10 | * 11 | * Note: Returns a pointer to an internal static buffer of length `DPTLIB_MAXPATH`. 12 | */ 13 | const char *path_join_leafname(const char *leaf, const char *ext); 14 | 15 | /** 16 | * Join 'root' with `nbranches` directory names according to the host convention. 17 | * 18 | * Note: Returns a pointer to an internal static buffer of length `DPTLIB_MAXPATH`. 19 | */ 20 | const char *path_join_filename(const char *root, int nbranches, ...); 21 | 22 | #endif /* DPTLIB_PATH */ 23 | -------------------------------------------------------------------------------- /include/io/stream-mem.h: -------------------------------------------------------------------------------- 1 | /* stream-mem.c -- memory block IO stream implementation */ 2 | 3 | #ifndef STREAM_MEM_H 4 | #define STREAM_MEM_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include 12 | 13 | #include "base/result.h" 14 | 15 | #include "io/stream.h" 16 | 17 | result_t stream_mem_create(const unsigned char *block, 18 | size_t length, 19 | stream_t **s); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif /* STREAM_MEM_H */ 26 | -------------------------------------------------------------------------------- /include/io/stream-mtfcomp.h: -------------------------------------------------------------------------------- 1 | /* stream-mtfcomp.h -- "move to front" adaptive compression stream */ 2 | 3 | #ifndef STREAM_MTFCOMP_H 4 | #define STREAM_MTFCOMP_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include "base/result.h" 12 | #include "io/stream.h" 13 | 14 | result_t stream_mtfcomp_create(stream_t *input, int bufsz, stream_t **s); 15 | result_t stream_mtfdecomp_create(stream_t *input, int bufsz, stream_t **s); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif /* STREAM_MTFCOMP_H */ 22 | -------------------------------------------------------------------------------- /include/io/stream-packbits.h: -------------------------------------------------------------------------------- 1 | /* stream-packbits.h -- PackBits compression */ 2 | 3 | #ifndef STREAM_PACKBITS_H 4 | #define STREAM_PACKBITS_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include "base/result.h" 12 | #include "io/stream.h" 13 | 14 | /* use 0 for a sensible default buffer size */ 15 | 16 | result_t stream_packbitscomp_create(stream_t *input, int bufsz, stream_t **s); 17 | result_t stream_packbitsdecomp_create(stream_t *input, int bufsz, stream_t **s); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif /* STREAM_PACKBITS_H */ 24 | -------------------------------------------------------------------------------- /include/io/stream-stdio.h: -------------------------------------------------------------------------------- 1 | /* stream-stdio.c -- C standard IO stream implementation */ 2 | 3 | #ifndef STREAM_STDIO_H 4 | #define STREAM_STDIO_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include 12 | 13 | #include "base/result.h" 14 | 15 | #include "io/stream.h" 16 | 17 | /* use 0 for a sensible default buffer size */ 18 | 19 | result_t stream_stdio_create(FILE *f, int bufsz, stream_t **s); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif /* STREAM_STDIO_H */ 26 | -------------------------------------------------------------------------------- /include/io/stream.h: -------------------------------------------------------------------------------- 1 | /* stream.h -- stream system */ 2 | 3 | /** 4 | * \file Stream (interface). 5 | * 6 | * A stream is a generic interface which can be used to wrap sources of 7 | * bytes. 8 | * 9 | * Single byte and block operations are supported. Byte access is efficient: 10 | * implemented as a macro. 11 | * 12 | * Some streams take other streams as input, allowing chains. 13 | * 14 | */ 15 | 16 | #ifndef STREAM_H 17 | #define STREAM_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" 21 | { 22 | #endif 23 | 24 | #include "base/result.h" 25 | 26 | /* ----------------------------------------------------------------------- */ 27 | 28 | #define result_STREAM_BAD_SEEK (result_BASE_STREAM + 0) 29 | #define result_STREAM_CANT_SEEK (result_BASE_STREAM + 1) 30 | #define result_STREAM_UNKNOWN_OP (result_BASE_STREAM + 2) 31 | 32 | /* ----------------------------------------------------------------------- */ 33 | 34 | typedef enum stream_opcode 35 | { 36 | stream_IN_MEMORY /**< Query whether stream is contained in memory. 37 | * Returns an int. */ 38 | } 39 | stream_opcode_t; 40 | 41 | /** 42 | * A type which holds a size or offset within a stream. 43 | */ 44 | typedef size_t stream_size_t; // TODO: Make this 64-bit where supported. 45 | 46 | /* stream_get returns an int, so can return EOF. */ 47 | /* stream_fill returns a stream_size_t, so can return stream_EOF. */ 48 | #define stream_EOF ((stream_size_t) -1) 49 | 50 | typedef struct stream stream_t; 51 | 52 | /* 53 | * Interfaces 54 | */ 55 | 56 | typedef result_t stream_op_t(stream_t *s, 57 | stream_opcode_t opcode, 58 | void *opaque); 59 | typedef result_t stream_seek_t(stream_t *s, stream_size_t pos); 60 | typedef int stream_get_t(stream_t *s); 61 | typedef stream_size_t stream_fill_t(stream_t *s); 62 | typedef stream_size_t stream_length_t(stream_t *s); 63 | typedef void stream_destroy_t(stream_t *doomed); 64 | 65 | /* This is exposed for efficiency - don't use these directly! */ 66 | struct stream 67 | { 68 | const unsigned char *buf; /**< Current buffer pointer. */ 69 | const unsigned char *end; /**< End of buffer pointer (exclusive - points to the char after buffer end). */ 70 | 71 | result_t last; /**< Last error. Set whenever we return `stream_EOF`? */ 72 | 73 | stream_op_t *op; 74 | stream_seek_t *seek; 75 | stream_get_t *get; 76 | stream_fill_t *fill; 77 | stream_length_t *length; 78 | stream_destroy_t *destroy; 79 | }; 80 | 81 | /* 82 | * User entry points 83 | */ 84 | 85 | stream_op_t stream_op; 86 | stream_seek_t stream_seek; 87 | stream_get_t stream_get; /**< `stream_getc()` is the inline alternative */ 88 | stream_fill_t stream_fill; 89 | stream_length_t stream_length; 90 | stream_destroy_t stream_destroy; 91 | 92 | /** Get a byte from a stream. Returns `EOF` (not `stream_EOF`) at EOF. */ 93 | #define stream_getc(s) (((s)->buf != (s)->end) ? *(s)->buf++ : (s)->get(s)) 94 | 95 | /** Put back the last byte gotten. */ 96 | #define stream_ungetc(s) --(s)->buf 97 | 98 | /** Returns the number of bytes remaining in the current buffer. */ 99 | #define stream_remaining(s) ((stream_size_t) ((s)->end - (s)->buf)) 100 | 101 | /** Returns the number of bytes remaining in the current buffer. 102 | * Will attempt to fill the buffer if it's found to be empty. */ 103 | #define stream_remaining_and_fill(s) \ 104 | (stream_remaining(s) != 0 ? stream_remaining(s) : (s)->fill(s)) 105 | 106 | #ifdef __cplusplus 107 | } 108 | #endif 109 | 110 | #endif /* STREAM_H */ 111 | -------------------------------------------------------------------------------- /include/test/all-tests.h: -------------------------------------------------------------------------------- 1 | /* all-tests.h */ 2 | 3 | #ifndef TESTS_ALL_TESTS_H 4 | #define TESTS_ALL_TESTS_H 5 | 6 | #include "base/result.h" 7 | 8 | typedef result_t (testfn_t)(const char *resources); 9 | 10 | /* datastruct */ 11 | extern testfn_t atom_test, 12 | bitarr_test, 13 | bitfifo_test, 14 | bitvec_test, 15 | cache_test, 16 | hash_test, 17 | list_test, 18 | ntree_test, 19 | vector_test; 20 | 21 | /* database */ 22 | extern testfn_t pickle_test, 23 | tagdb_test; 24 | 25 | /* framebuf */ 26 | extern testfn_t bmfont_test, 27 | composite_test; 28 | 29 | /* geom */ 30 | extern testfn_t box_test, 31 | layout_test, 32 | packer_test; 33 | 34 | /* io */ 35 | extern testfn_t stream_test; 36 | 37 | /* utils */ 38 | extern testfn_t array_test, 39 | bsearch_test; 40 | 41 | #endif /* TESTS_ALL_TESTS_H */ 42 | -------------------------------------------------------------------------------- /include/test/txtscr.h: -------------------------------------------------------------------------------- 1 | /* txtscr.h -- text format 'screen' */ 2 | 3 | #ifndef TEST_TXTSCR_H 4 | #define TEST_TXTSCR_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include "geom/box.h" 12 | 13 | #define T txtscr_t 14 | 15 | typedef struct txtscr T; 16 | 17 | T *txtscr_create(int width, int height); 18 | void txtscr_destroy(T *doomed); 19 | 20 | void txtscr_clear(T *scr); 21 | 22 | /* adds to the pixels, rather than overwriting */ 23 | void txtscr_addbox(T *scr, const box_t *box); 24 | 25 | void txtscr_print(T *scr); 26 | 27 | #undef T 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif /* TEST_TXTSCR_H */ 34 | -------------------------------------------------------------------------------- /include/utils/array.h: -------------------------------------------------------------------------------- 1 | /* array.h -- array utilities */ 2 | 3 | /** 4 | * \file array.h 5 | * 6 | * Utilities for operating on arrays. 7 | */ 8 | 9 | #ifndef UTILS_ARRAY_H 10 | #define UTILS_ARRAY_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" 14 | { 15 | #endif 16 | 17 | #include 18 | 19 | /* ----------------------------------------------------------------------- */ 20 | 21 | /** 22 | * Signifies an array of unknown length, e.g. when used as the size of an 23 | * array which is the final member of a struct. 24 | */ 25 | #define UNKNOWN 1 26 | 27 | /* ----------------------------------------------------------------------- */ 28 | 29 | /* Delete the specified element. */ 30 | void array_delete_element(void *array, 31 | size_t elemsize, 32 | int nelems, 33 | int doomed); 34 | 35 | /* Delete the specified elements. */ 36 | /* last_doomed is inclusive. */ 37 | void array_delete_elements(void *array, 38 | size_t elemsize, 39 | int nelems, 40 | int first_doomed, 41 | int last_doomed); 42 | 43 | /* ----------------------------------------------------------------------- */ 44 | 45 | /* Take the contents of an array which used to have elements 'oldwidth' bytes 46 | * wide and adjust them so they are 'newwidth' bytes wide. Set new bytes to 47 | * 'wipe_value'. */ 48 | void array_stretch1(unsigned char *base, 49 | int nelems, 50 | size_t oldwidth, 51 | size_t newwidth, 52 | int wipe_value); 53 | 54 | void array_stretch2(unsigned char *base, 55 | int nelems, 56 | size_t oldwidth, 57 | size_t newwidth, 58 | int wipe_value); 59 | 60 | /* Take the contents of an array which used to have elements 'oldwidth' bytes 61 | * wide and adjust them so they are 'newwidth' bytes wide. */ 62 | void array_squeeze1(unsigned char *base, 63 | int nelems, 64 | size_t oldwidth, 65 | size_t newwidth); 66 | 67 | void array_squeeze2(unsigned char *base, 68 | int nelems, 69 | size_t oldwidth, 70 | size_t newwidth); 71 | 72 | /* Temporary defines until the above functions are renamed. */ 73 | #define array_stretch array_stretch2 74 | #define array_squeeze array_squeeze2 75 | 76 | /* ----------------------------------------------------------------------- */ 77 | 78 | /** 79 | * Grow a dynamically allocated array as required. 80 | * 81 | * Presently the growth strategy is doubling. 82 | * 83 | * 'block' can be NULL to perform an initial alloc. 84 | * Start with used == allocated == 0. 85 | * 86 | * \param block Pointer to pointer to block. Updated on success. 87 | * \param elemsize Element size in bytes. 88 | * \param used Number of currently occupied elements. 89 | * \param allocated Pointer to number of allocated elements. Updated on exit. 90 | * \param need Number of unoccupied elements we need. 91 | * \param minimum Minimum number of elements to allocate. 92 | * 93 | * \return 0 - ok, 1 - out of memory 94 | */ 95 | int array_grow(void **block, 96 | size_t elemsize, 97 | int used, 98 | int *allocated, 99 | int need, 100 | int minimum); 101 | 102 | /** 103 | * Shrink a dynamically allocated array to have no free entries. 104 | * 105 | * \param block Pointer to pointer to block. Updated on exit. 106 | * \param elemsize Element size. 107 | * \param used Number of currently occupied elements. 108 | * \param allocated Pointer to number of allocated elements. Updated on exit. 109 | * 110 | * \return 0 - ok, 1 - out of memory 111 | */ 112 | int array_shrink(void **block, 113 | size_t elemsize, 114 | int used, 115 | int *allocated); 116 | 117 | /* ----------------------------------------------------------------------- */ 118 | 119 | #ifdef __cplusplus 120 | } 121 | #endif 122 | 123 | #endif /* UTILS_ARRAY_H */ 124 | -------------------------------------------------------------------------------- /include/utils/bsearch.h: -------------------------------------------------------------------------------- 1 | /* bsearch.h -- binary searching arrays */ 2 | 3 | #ifndef UTILS_BSEARCH_H 4 | #define UTILS_BSEARCH_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include 12 | 13 | /* Binary search an array 'nelems' long for 'want'. 14 | * Each array element is 'stride' bytes wide. */ 15 | 16 | /* Example: 17 | * 18 | * To search an array, ordered by key, composed of the following structures: 19 | * 20 | * struct foo 21 | * { 22 | * int key; 23 | * int value; 24 | * } 25 | * foo_t; 26 | * 27 | * foo_t foos[100]; 28 | * 29 | * index = bsearch_int(&foos[0].key, 100, sizeof(foo_t), 42); 30 | * 31 | * 'index' is the index of the element, or < 0 if not found. 32 | */ 33 | 34 | int bsearch_short(const short *array, 35 | unsigned int nelems, 36 | size_t stride, 37 | short want); 38 | 39 | int bsearch_ushort(const unsigned short *array, 40 | unsigned int nelems, 41 | size_t stride, 42 | unsigned short want); 43 | 44 | int bsearch_int(const int *array, 45 | unsigned int nelems, 46 | size_t stride, 47 | int want); 48 | 49 | int bsearch_uint(const unsigned int *array, 50 | unsigned int nelems, 51 | size_t stride, 52 | unsigned int want); 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | 58 | #endif /* UTILS_BSEARCH_H */ 59 | -------------------------------------------------------------------------------- /include/utils/bytesex.h: -------------------------------------------------------------------------------- 1 | /* bytesex.h -- reversing bytesex */ 2 | 3 | #ifndef UTILS_BYTESEX_H 4 | #define UTILS_BYTESEX_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | #include 12 | 13 | /* Reverse bytesex. 14 | * 15 | * 's'hort or 'l'ong 16 | * 17 | * _m -> from memory (takes a pointer, reads as chars) 18 | * _pair -> two packed arguments 19 | * _block -> array of things to swap 20 | */ 21 | 22 | unsigned short int rev_s(unsigned short int); 23 | unsigned short int rev_s_m(const unsigned char *); 24 | 25 | unsigned int rev_s_pair(unsigned int); 26 | unsigned int rev_s_pair_m(const unsigned char *); 27 | 28 | unsigned int rev_l(unsigned int); 29 | unsigned int rev_l_m(const unsigned char *); 30 | 31 | void rev_s_block(unsigned short int *array, size_t nelems); 32 | void rev_l_block(unsigned int *array, size_t nelems); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* UTILS_BYTESEX_H */ 39 | -------------------------------------------------------------------------------- /include/utils/fxp.h: -------------------------------------------------------------------------------- 1 | /* fxp.h -- fixed point helpers */ 2 | 3 | #ifndef UTILS_FXP_H 4 | #define UTILS_FXP_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | /* Signed multiply of two 16.16 fixed-point numbers. */ 12 | int smull_fxp16(int x, int y); 13 | 14 | /* Unsigned multiply of two 16.16 fixed-point numbers. */ 15 | unsigned int umull_fxp16(unsigned int x, unsigned int y); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif /* UTILS_FXP_H */ 22 | -------------------------------------------------------------------------------- /include/utils/maths.h: -------------------------------------------------------------------------------- 1 | /* maths.h -- maths utils */ 2 | 3 | #ifndef UTILS_MATHS_H 4 | #define UTILS_MATHS_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | /* Greatest common divisor of m,n */ 12 | int gcd(int m, int n); 13 | 14 | /* Degrees to radians */ 15 | double degs_to_rads(double degs); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif /* UTILS_MATHS_H */ 22 | -------------------------------------------------------------------------------- /include/utils/pack.h: -------------------------------------------------------------------------------- 1 | /* pack.h -- structure packing and unpacking helpers */ 2 | 3 | /** 4 | * \file Pack (interface). 5 | * 6 | * Structure packing and unpacking routines. 7 | * 8 | * Inspired by printf, scanf and the Python 'struct' module these allow a 9 | * string composed of formatting character to specify how data should be 10 | * marshalled into memory. 11 | */ 12 | 13 | #ifndef UTILS_PACK_H 14 | #define UTILS_PACK_H 15 | 16 | #ifdef __cplusplus 17 | extern "C" 18 | { 19 | #endif 20 | 21 | #include 22 | #include 23 | 24 | /** 25 | * Structure packing. 26 | * 27 | * The arguments are packed into 'buf' according to the format string 'fmt' 28 | * using little-endian byte order. 29 | * 30 | * The format string argument accepts the following format characters: 31 | * 32 | * - 'c' to pack into 8 bits (notional char) 33 | * - 's' to pack into 16 bits (notional short) 34 | * - 'i' to pack into 32 bits (notional int) 35 | * - 'q' to pack into 64 bits (notional long long 'quad') 36 | * 37 | * Each format character may be preceded by a count. 38 | * 39 | * 40 | * Examples: 41 | * 42 | * n = pack(outbuf, "ccc", 1, 2, 3); ("ccc" can also be written "3c") 43 | * n = pack(outbuf, "2si", 0x2000, 12345, 1 << 31); 44 | * 45 | * 46 | * Using '*' instead of a count invokes array mode: the next argument is 47 | * used as an array length and the next after that as an array base pointer. 48 | * 49 | * Example: 50 | * 51 | * n = pack(outbuf, "*s", 5, shortarray); 52 | * 53 | * Writes out five shorts from shortarray to outbuf. 54 | * 55 | * 56 | * \param outbuf Output buffer to receive packed values. 57 | * \param fmt Format string specifying what to pack. 58 | * 59 | * \return Number of bytes used in output buffer, or zero if error. 60 | */ 61 | size_t pack(unsigned char *outbuf, const char *fmt, ...); 62 | 63 | /** 64 | * Structure unpacking. 65 | * 66 | * The arguments are unpacked from 'buf' according to the format string 67 | * 'fmt' using little-endian byte order. 68 | * 69 | * \see pack for a description of the format string. 70 | * 71 | * Example: 72 | * 73 | * n = unpack(inbuf, "c3i", &byte1, &byte2, &byte3, &flags); 74 | * 75 | * Retrieves three characters and an int from 'inbuf'. 76 | * 77 | * 78 | * Using '*' instead of a count invokes array mode: the next argument is 79 | * used as an array length and the next after that as an array base pointer. 80 | * 81 | * Example: 82 | * 83 | * n = unpack(inbuf, "*s", 5, shortarray); 84 | * 85 | * Reads in five shorts from inbuf into shortarray. 86 | * 87 | * 88 | * Additionally, unpack can specify different source and destination sizes by 89 | * prefixing a formatting character with a source size qualifier: 90 | * 91 | * - 'b' - byte 92 | * - 'h' - half-word 93 | * - 'w' - word 94 | * - 'd' - double word 95 | * 96 | * (Note that these specifiers are all different than the formatting characters). 97 | * 98 | * With these qualifers, sign becomes important. You can write CSIQ for unsigned 99 | * arguments, or csiq for signed arguments. 100 | * 101 | * Example: 102 | * 103 | * n = unpack(inbuf, "hQ", &quad); 104 | * 105 | * Unpacks a two-byte quantity into an unsigned long long. 106 | * 107 | * Of course, this works in array mode too. 108 | * 109 | * 110 | * unpack copes with different endian formats. Prefix the string with: 111 | * 112 | * - '<' to unpack little endian data 113 | * - '>' to unpack big endian data 114 | * 115 | * The default is [ought to be] platform dependent. 116 | * 117 | * 118 | * \param inbuf Input buffer of packed values. 119 | * \param fmt Format string specifying what to unpack. 120 | * 121 | * \return Number of bytes used from input buffer, or zero if error. 122 | */ 123 | size_t unpack(const unsigned char *inbuf, const char *fmt, ...); 124 | 125 | /** 126 | * Variant of unpack() which accepts a va_list. 127 | */ 128 | size_t vunpack(const unsigned char *buf, const char *fmt, va_list args); 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | 134 | #endif /* UTILS_PACK_H */ 135 | -------------------------------------------------------------------------------- /include/utils/primes.h: -------------------------------------------------------------------------------- 1 | /* primes.h -- cache of prime numbers */ 2 | 3 | #ifndef UTILS_PRIMES_H 4 | #define UTILS_PRIMES_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | /* Returns the nearest prime number to 'x' from a greatly reduced range. 12 | * Intended as a cache of values for use when sizing data structures. */ 13 | int prime_nearest(int x); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* UTILS_PRIMES_H */ 20 | -------------------------------------------------------------------------------- /libraries/databases/pickle/delete.c: -------------------------------------------------------------------------------- 1 | /* delete.c -- delete a pickle file */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef __riscos 8 | #include "oslib/osfile.h" 9 | #endif 10 | 11 | #include "databases/pickle.h" 12 | 13 | void pickle_delete(const char *filename) 14 | { 15 | assert(filename); 16 | 17 | #ifdef __riscos 18 | xosfile_delete(filename, NULL, NULL, NULL, NULL, NULL); 19 | #else 20 | remove(filename); 21 | #endif 22 | } 23 | -------------------------------------------------------------------------------- /libraries/databases/pickle/hash-reader.c: -------------------------------------------------------------------------------- 1 | /* hash-reader.c -- glue methods to let pickle operate on hashes */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef FORTIFY 9 | #include "fortify/fortify.h" 10 | #endif 11 | 12 | #include "base/utils.h" 13 | 14 | #include "datastruct/hash.h" 15 | 16 | #include "databases/pickle.h" 17 | #include "databases/pickle-reader-hash.h" 18 | 19 | typedef struct pickle_reader_hash_state 20 | { 21 | hash_t *hash; 22 | int cont; 23 | } 24 | pickle_reader_hash_state_t; 25 | 26 | result_t pickle_reader_hash_start(const void *assocarr, 27 | void *opaque, 28 | void **pstate) 29 | { 30 | pickle_reader_hash_state_t *state; 31 | 32 | NOT_USED(opaque); 33 | 34 | state = malloc(sizeof(*state)); 35 | if (state == NULL) 36 | return result_OOM; 37 | 38 | state->hash = (hash_t *) assocarr; 39 | state->cont = 0; 40 | 41 | *pstate = state; 42 | 43 | return result_OK; 44 | } 45 | 46 | void pickle_reader_hash_stop(void *state, void *opaque) 47 | { 48 | NOT_USED(opaque); 49 | 50 | free(state); 51 | } 52 | 53 | result_t pickle_reader_hash_next(void *vstate, 54 | const void **key, 55 | const void **value, 56 | void *opaque) 57 | { 58 | result_t err; 59 | pickle_reader_hash_state_t *state = vstate; 60 | 61 | NOT_USED(opaque); 62 | 63 | err = hash_walk_continuation(state->hash, 64 | state->cont, 65 | &state->cont, 66 | key, 67 | value); 68 | 69 | return (err == result_HASH_END) ? result_PICKLE_END : err; 70 | } 71 | 72 | const pickle_reader_methods_t pickle_reader_hash = 73 | { 74 | pickle_reader_hash_start, 75 | pickle_reader_hash_stop, 76 | pickle_reader_hash_next 77 | }; 78 | -------------------------------------------------------------------------------- /libraries/databases/pickle/hash-writer.c: -------------------------------------------------------------------------------- 1 | /* hash-writer.c -- glue methods to let pickle operate on hashes */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef FORTIFY 9 | #include "fortify/fortify.h" 10 | #endif 11 | 12 | #include "base/utils.h" 13 | 14 | #include "datastruct/hash.h" 15 | 16 | #include "databases/pickle.h" 17 | #include "databases/pickle-writer-hash.h" 18 | 19 | result_t pickle_writer_hash_start(void *assocarr, 20 | void **pstate, 21 | void *opaque) 22 | { 23 | NOT_USED(opaque); 24 | 25 | *pstate = (void *) assocarr; 26 | 27 | return result_OK; 28 | } 29 | 30 | result_t pickle_writer_hash_next(void *state, 31 | void *key, 32 | void *value, 33 | void *opaque) 34 | { 35 | NOT_USED(opaque); 36 | 37 | return hash_insert((hash_t *) state, key, value); 38 | } 39 | 40 | const pickle_writer_methods_t pickle_writer_hash = 41 | { 42 | pickle_writer_hash_start, 43 | NULL, 44 | pickle_writer_hash_next 45 | }; 46 | -------------------------------------------------------------------------------- /libraries/databases/pickle/pickle.c: -------------------------------------------------------------------------------- 1 | /* pickle.c -- serialise an associative array to file */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef FORTIFY 10 | #include "fortify/fortify.h" 11 | #endif 12 | 13 | #include "base/result.h" 14 | #include "base/utils.h" 15 | 16 | #include "databases/pickle.h" 17 | 18 | /* ----------------------------------------------------------------------- */ 19 | 20 | static const char signature[] = PICKLE_SIGNATURE; 21 | 22 | /* ----------------------------------------------------------------------- */ 23 | 24 | /* write out a version numbered header */ 25 | static result_t pickle__write_header(FILE *f, 26 | const char *comments, 27 | size_t commentslen) 28 | { 29 | static const char commentchar[] = "# "; 30 | int rc; 31 | 32 | rc = fprintf(f, "%s%.*s\n%s\n", 33 | commentchar, 34 | (int) commentslen, 35 | comments, 36 | signature); 37 | if (rc < 0) 38 | return result_BUFFER_OVERFLOW; // FIXME hard coded error number (could use errno?) 39 | 40 | return result_OK; 41 | } 42 | 43 | static result_t pickle__write_body(FILE *f, 44 | void *assocarr, 45 | const pickle_reader_methods_t *reader, 46 | const pickle_format_methods_t *format, 47 | void *opaque) 48 | { 49 | result_t err; 50 | void *state = NULL; 51 | const void *key; 52 | const void *value; 53 | 54 | if (reader->start) 55 | { 56 | err = reader->start(assocarr, opaque, &state); 57 | if (err) 58 | return err; 59 | } 60 | 61 | while ((err = reader->next(state, &key, &value, opaque)) == result_OK) 62 | { 63 | char buffer1[256]; 64 | char buffer2[768]; 65 | int rc; 66 | 67 | // FIXME: get the format methods to pass back how much they used then we 68 | // can pack the entire lot into the output buffer as we go 69 | 70 | err = format->key(key, buffer1, NELEMS(buffer1), opaque); 71 | if (err == result_PICKLE_SKIP) 72 | continue; 73 | else if (err) 74 | goto exit; 75 | 76 | err = format->value(value, buffer2, NELEMS(buffer2), opaque); 77 | if (err == result_PICKLE_SKIP) 78 | continue; 79 | else if (err) 80 | goto exit; 81 | 82 | rc = fprintf(f, "%s%.*s%s\n", 83 | buffer1, 84 | (int) format->splitlen, format->split, 85 | buffer2); 86 | if (rc < 0) 87 | { 88 | err = result_BUFFER_OVERFLOW; // FIXME hard coded error number (could use errno?) 89 | goto exit; 90 | } 91 | } 92 | 93 | if (err == result_PICKLE_END) 94 | err = result_OK; 95 | 96 | exit: 97 | 98 | if (reader->stop) 99 | reader->stop(state, opaque); 100 | 101 | return err; 102 | } 103 | 104 | /* ----------------------------------------------------------------------- */ 105 | 106 | result_t pickle_pickle(const char *filename, 107 | void *assocarr, 108 | const pickle_reader_methods_t *reader, 109 | const pickle_format_methods_t *format, 110 | void *opaque) 111 | { 112 | result_t err; 113 | FILE *f; 114 | 115 | assert(filename); 116 | assert(assocarr); 117 | assert(reader); 118 | assert(format); 119 | 120 | assert(reader->next); /* start and stop can be NULL, but we need next */ 121 | 122 | f = fopen(filename, "wb"); 123 | if (f == NULL) 124 | return result_PICKLE_COULDNT_OPEN_FILE; 125 | 126 | err = pickle__write_header(f, format->comments, format->commentslen); 127 | if (err) 128 | goto failure; 129 | 130 | err = pickle__write_body(f, assocarr, reader, format, opaque); 131 | if (err) 132 | goto failure; 133 | 134 | fclose(f); 135 | 136 | return result_OK; 137 | 138 | 139 | failure: 140 | 141 | fclose(f); 142 | 143 | return err; 144 | } 145 | -------------------------------------------------------------------------------- /libraries/datastruct/atom/create.c: -------------------------------------------------------------------------------- 1 | /* create.c -- atoms */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "utils/barith.h" 10 | 11 | #include "datastruct/atom.h" 12 | 13 | #include "impl.h" 14 | 15 | atom_set_t *atom_create(void) 16 | { 17 | return atom_create_tuned(0, 0); /* use default values */ 18 | } 19 | 20 | atom_set_t *atom_create_tuned(size_t locpoolsz, size_t blkpoolsz) 21 | { 22 | atom_set_t *s; 23 | 24 | s = calloc(1, sizeof(*s)); 25 | if (s == NULL) 26 | return NULL; 27 | 28 | s->log2locpoolsz = locpoolsz ? ceillog2_size_t(locpoolsz) : LOG2LOCPOOLSZ; 29 | s->log2blkpoolsz = blkpoolsz ? ceillog2_size_t(blkpoolsz) : LOG2BLKPOOLSZ; 30 | 31 | return s; 32 | } 33 | -------------------------------------------------------------------------------- /libraries/datastruct/atom/delete-block.c: -------------------------------------------------------------------------------- 1 | /* delete-block.c -- atoms */ 2 | 3 | #include 4 | 5 | #include "datastruct/atom.h" 6 | 7 | void atom_delete_block(atom_set_t *set, 8 | const unsigned char *block, 9 | size_t length) 10 | { 11 | atom_delete(set, atom_for_block(set, block, length)); 12 | } 13 | -------------------------------------------------------------------------------- /libraries/datastruct/atom/delete.c: -------------------------------------------------------------------------------- 1 | /* delete.c -- atoms */ 2 | 3 | #include 4 | #include 5 | 6 | #include "datastruct/atom.h" 7 | 8 | #include "impl.h" 9 | 10 | /* Delete the specified atom by flipping the sign of the length field. This 11 | * leaves the data in place but inaccessible. */ 12 | void atom_delete(atom_set_t *s, atom_t a) 13 | { 14 | int *plength; 15 | int length; 16 | 17 | assert(s); 18 | 19 | if (a == atom_NOT_FOUND) 20 | return; 21 | 22 | if (!s->locpools) 23 | return; /* empty set */ 24 | 25 | assert(s->l_used >= 1); 26 | 27 | if (!ATOMVALID(a)) 28 | return; /* out of range */ 29 | 30 | plength = &ATOMLENGTH(a); 31 | length = *plength; 32 | if (length < 0) 33 | return; /* already deleted */ 34 | 35 | #ifndef NDEBUG 36 | /* scribble over the deleted copy */ 37 | memset(ATOMPTR(a), 0xAA, length); 38 | #endif 39 | 40 | *plength = -length; 41 | } 42 | -------------------------------------------------------------------------------- /libraries/datastruct/atom/destroy.c: -------------------------------------------------------------------------------- 1 | /* destroy.c -- atoms */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/atom.h" 10 | 11 | #include "impl.h" 12 | 13 | void atom_destroy(atom_set_t *s) 14 | { 15 | unsigned int i; 16 | 17 | if (s == NULL) 18 | return; 19 | 20 | /* delete all location pools */ 21 | 22 | for (i = 0; i < s->l_used; i++) 23 | free(s->locpools[i].locs); 24 | 25 | /* delete the location pool pointers */ 26 | 27 | free(s->locpools); 28 | 29 | /* delete all block pools */ 30 | 31 | for (i = 0; i < s->b_used; i++) 32 | free(s->blkpools[i].blks); 33 | 34 | /* delete the block pool pointers */ 35 | 36 | free(s->blkpools); 37 | 38 | free(s); 39 | } 40 | -------------------------------------------------------------------------------- /libraries/datastruct/atom/for-block.c: -------------------------------------------------------------------------------- 1 | /* for-block.c -- atoms */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "datastruct/atom.h" 9 | 10 | #include "impl.h" 11 | 12 | atom_t atom_for_block(atom_set_t *s, 13 | const unsigned char *block, 14 | size_t sizet_length) 15 | { 16 | int length; 17 | const locpool_t *pend; 18 | const locpool_t *p; 19 | 20 | assert(s); 21 | assert(block); 22 | assert(sizet_length > 0); 23 | 24 | /* The current implementation uses an int for the length of a block, and 25 | * negative numbers indicate unused blocks, so we cannot cope with lengths 26 | * greater than INT_MAX even though the interface allows size_t. */ 27 | if (sizet_length > INT_MAX) 28 | return result_TOO_BIG; 29 | 30 | length = (int) sizet_length; 31 | 32 | /* linear search every locpool */ 33 | 34 | pend = s->locpools + s->l_used; 35 | for (p = s->locpools; p < pend; p++) 36 | { 37 | const loc_t *lend; 38 | const loc_t *l; 39 | 40 | /* linear search every loc */ 41 | 42 | lend = p->locs + p->used; 43 | for (l = p->locs; l < lend; l++) 44 | if (l->length == length && memcmp(l->ptr, block, length) == 0) 45 | return (atom_t)(((p - s->locpools) << s->log2locpoolsz) + (l - p->locs)); 46 | } 47 | 48 | return atom_NOT_FOUND; 49 | } 50 | -------------------------------------------------------------------------------- /libraries/datastruct/atom/get.c: -------------------------------------------------------------------------------- 1 | /* get.c -- atoms */ 2 | 3 | #include 4 | #include 5 | 6 | #include "datastruct/atom.h" 7 | 8 | #include "impl.h" 9 | 10 | const unsigned char *atom_get(atom_set_t *s, atom_t a, size_t *plength) 11 | { 12 | int length; 13 | 14 | assert(s); 15 | assert(a != atom_NOT_FOUND); 16 | 17 | if (!s->locpools) 18 | return NULL; /* empty set */ 19 | 20 | assert(s->l_used >= 1); 21 | 22 | if (!ATOMVALID(a)) 23 | return NULL; /* out of range */ 24 | 25 | length = ATOMLENGTH(a); 26 | if (length < 0) 27 | return NULL; /* deleted */ 28 | 29 | if (plength) 30 | *plength = length; 31 | 32 | return ATOMPTR(a); 33 | } 34 | -------------------------------------------------------------------------------- /libraries/datastruct/atom/impl.h: -------------------------------------------------------------------------------- 1 | /* impl.h -- atoms */ 2 | 3 | /* An atom_set consists of a series of block pools and location pools. 4 | * 5 | * Block pools are allocated up front and filled with atoms (chunks of data) 6 | * until they're full, or run out of room, at which point a new block is 7 | * allocated. 8 | * 9 | * Location pools hold pointers to allocated blocks within the block pools. 10 | */ 11 | 12 | #ifndef IMPL_H 13 | #define IMPL_H 14 | 15 | #include 16 | 17 | /* ----------------------------------------------------------------------- */ 18 | 19 | #define LOG2LOCPOOLSZ 5 /* default: 32 locs per pool */ 20 | #define LOG2BLKPOOLSZ 9 /* default: 512 bytes per pool */ 21 | 22 | #define LOCPTRMINSZ 4 /* minimum number of locpool_t's to allocate */ 23 | #define BLKPTRMINSZ 4 /* minimum number of blkpool_t's to allocate */ 24 | 25 | /* ----------------------------------------------------------------------- */ 26 | 27 | /** 28 | * Convert an atom into a loc. 29 | */ 30 | #define ATOMLOC(i) \ 31 | s->locpools[(i) >> s->log2locpoolsz].locs[(i) & ((1 << s->log2locpoolsz) - 1)] 32 | 33 | /** 34 | * Retrieve an atom's pointer. 35 | */ 36 | #define ATOMPTR(i) \ 37 | (ATOMLOC(i).ptr) 38 | 39 | /** 40 | * Retrieve an atom's length. 41 | */ 42 | #define ATOMLENGTH(i) \ 43 | (ATOMLOC(i).length) 44 | 45 | /** 46 | * Returns true if the specified atom corresponds to an allocated (but not 47 | * necessarily used) index. 48 | */ 49 | #define ATOMVALID(i) \ 50 | ((unsigned int) i < ((s->l_used - 1U) << s->log2locpoolsz) + s->locpools[s->l_used - 1].used) 51 | 52 | /* ----------------------------------------------------------------------- */ 53 | 54 | /* Stores the location and length of a block. */ 55 | typedef struct loc 56 | { 57 | unsigned char *ptr; /* pointer into block */ 58 | int length; /* length of block (-ve if deallocated) */ 59 | } 60 | loc_t; 61 | 62 | /* Stores the location and used count of a location pool. */ 63 | typedef struct locpool 64 | { 65 | struct loc *locs; 66 | int used; 67 | } 68 | locpool_t; 69 | 70 | /* Stores the location and used count of a block pool. */ 71 | typedef struct blkpool 72 | { 73 | unsigned char *blks; 74 | int used; // gets compared with size_t ... 75 | } 76 | blkpool_t; 77 | 78 | struct atom_set 79 | { 80 | size_t log2locpoolsz; /* log2 number of locations per locpool */ 81 | size_t log2blkpoolsz; /* log2 number of bytes per blkpool */ 82 | 83 | locpool_t *locpools; /* growable array of location pools */ 84 | unsigned int l_used; 85 | unsigned int l_allocated; 86 | 87 | blkpool_t *blkpools; /* growable array of block pools */ 88 | unsigned int b_used; 89 | unsigned int b_allocated; 90 | }; 91 | 92 | /* ----------------------------------------------------------------------- */ 93 | 94 | result_t atom_ensure_loc_space(atom_set_t *s); 95 | result_t atom_ensure_blk_space(atom_set_t *s, size_t length); 96 | 97 | #endif /* IMPL_H */ 98 | -------------------------------------------------------------------------------- /libraries/datastruct/atom/set.c: -------------------------------------------------------------------------------- 1 | /* set.c -- atoms */ 2 | 3 | #include 4 | #include 5 | 6 | #include "datastruct/atom.h" 7 | 8 | #include "impl.h" 9 | 10 | result_t atom_set(atom_set_t *s, 11 | atom_t a, 12 | const unsigned char *block, 13 | size_t length) 14 | { 15 | result_t err; 16 | atom_t newa; 17 | loc_t *p, *q; 18 | loc_t t; 19 | 20 | assert(s); 21 | assert(a != atom_NOT_FOUND); 22 | assert(block); 23 | assert(length > 0); 24 | 25 | if (!s->locpools) 26 | return result_ATOM_SET_EMPTY; 27 | 28 | assert(s->l_used >= 1); 29 | 30 | if (!ATOMVALID(a)) 31 | return result_ATOM_OUT_OF_RANGE; 32 | 33 | err = atom_new(s, block, length, &newa); 34 | if (err == result_ATOM_NAME_EXISTS && newa == a) 35 | /* setting an atom to its existing data is ignored */ 36 | return result_OK; 37 | else if (err) 38 | return err; 39 | 40 | atom_delete(s, a); 41 | 42 | /* now transpose old and new atoms */ 43 | 44 | p = &ATOMLOC(a); 45 | q = &ATOMLOC(newa); 46 | 47 | t = *p; 48 | *p = *q; 49 | *q = t; 50 | 51 | return result_OK; 52 | } 53 | -------------------------------------------------------------------------------- /libraries/datastruct/bitarr/count.c: -------------------------------------------------------------------------------- 1 | /* count.c -- arrays of bits */ 2 | 3 | #include 4 | 5 | #include "utils/barith.h" 6 | #include "datastruct/bitarr.h" 7 | 8 | int bitarr_count(const bitarr_t *arr, size_t bytelen) 9 | { 10 | const bitarr_elem_t *base; 11 | const bitarr_elem_t *end; 12 | int c; 13 | 14 | base = arr->entries; 15 | end = base + (bytelen >> (BITARR_SHIFT - 3)); // FIXME: This will round off any sub-word units... 16 | 17 | c = 0; 18 | while (base != end) 19 | c += countbits(*base++); 20 | 21 | return c; 22 | } 23 | -------------------------------------------------------------------------------- /libraries/datastruct/bitarr/test/bitarr-test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "base/result.h" 11 | #include "base/utils.h" 12 | #include "datastruct/bitarr.h" 13 | 14 | #include "test/all-tests.h" 15 | 16 | #define NBITS 97 17 | 18 | typedef bitarr_ARRAY(NBITS) testbits_t; 19 | 20 | static void dumpbits(const testbits_t *arr, int nbits) 21 | { 22 | int i; 23 | int c; 24 | 25 | c = 0; 26 | for (i = nbits - 1; i >= 0; i--) 27 | { 28 | int b; 29 | 30 | b = bitarr_get(arr, i); 31 | c += b; 32 | printf("%d", b); 33 | } 34 | 35 | printf("\n%d bits set\n", c); 36 | } 37 | 38 | result_t bitarr_test(const char *resources) 39 | { 40 | testbits_t arr; 41 | int i; 42 | 43 | NOT_USED(resources); 44 | 45 | printf("test: create\n"); 46 | 47 | bitarr_wipe(arr, sizeof(arr)); 48 | 49 | 50 | printf("test: set\n"); 51 | 52 | for (i = 0; i < NBITS; i++) 53 | bitarr_set(&arr, i); 54 | 55 | dumpbits(&arr, NBITS); 56 | 57 | 58 | printf("test: clear\n"); 59 | 60 | for (i = 0; i < NBITS; i++) 61 | bitarr_clear(&arr, i); 62 | 63 | dumpbits(&arr, NBITS); 64 | 65 | 66 | printf("test: toggle\n"); 67 | 68 | for (i = 0; i < NBITS; i++) 69 | bitarr_toggle(&arr, i); 70 | 71 | dumpbits(&arr, NBITS); 72 | 73 | 74 | printf("test: count\n"); 75 | 76 | /* a cast is required :-| */ 77 | printf("%d bits set\n", bitarr_count((bitarr_t *) &arr, sizeof(arr))); 78 | 79 | 80 | return result_TEST_PASSED; 81 | } 82 | -------------------------------------------------------------------------------- /libraries/datastruct/bitfifo/test/bitfifo-test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef FORTIFY 8 | #include "fortify/fortify.h" 9 | #endif 10 | 11 | #include "base/result.h" 12 | #include "base/utils.h" 13 | #include "datastruct/bitfifo.h" 14 | 15 | #include "test/all-tests.h" 16 | 17 | #define MAXSIZE 32 18 | 19 | static const struct 20 | { 21 | int length; /* in bits */ 22 | unsigned int after_dequeue; 23 | } 24 | expected[] = 25 | { 26 | { 1, 0x00000001 }, 27 | { 2, 0x00000003 }, 28 | { 3, 0x00000007 }, 29 | { 4, 0x0000000F }, 30 | { 31, 0x7FFFFFFF }, 31 | { 32, 0xFFFFFFFF }, 32 | }; 33 | 34 | /* shows changes from previous stats */ 35 | static void dump(const bitfifo_t *fifo) 36 | { 37 | static size_t previous_used = (size_t) -1; /* aka SIZE_MAX */ 38 | static int previous_full = INT_MAX; 39 | static int previous_empty = INT_MAX; 40 | 41 | size_t used; 42 | int full; 43 | int empty; 44 | 45 | used = bitfifo_used(fifo); 46 | full = bitfifo_full(fifo); 47 | empty = bitfifo_empty(fifo); 48 | 49 | printf("{"); 50 | if (used != previous_used) 51 | printf("used=%zu ", used); 52 | if (full != previous_full) 53 | printf("full=%d ", full); 54 | if (empty != previous_empty) 55 | printf("empty=%d ", empty); 56 | printf("}\n"); 57 | 58 | previous_used = used; 59 | previous_full = full; 60 | previous_empty = empty; 61 | } 62 | 63 | result_t bitfifo_test(const char *resources) 64 | { 65 | const unsigned int all_ones = ~0; 66 | 67 | result_t err; 68 | bitfifo_t *fifo; 69 | int i; 70 | unsigned int outbits; 71 | 72 | NOT_USED(resources); 73 | 74 | fifo = bitfifo_create(MAXSIZE); 75 | if (fifo == NULL) 76 | return result_OOM; 77 | dump(fifo); 78 | 79 | printf("test: enqueue/dequeue...\n"); 80 | 81 | for (i = 0; i < NELEMS(expected); i++) 82 | { 83 | int length; 84 | 85 | length = expected[i].length; 86 | 87 | printf("%d bits\n", length); 88 | 89 | /* put 'size_to_try' 1 bits into the queue */ 90 | err = bitfifo_enqueue(fifo, &all_ones, 0, length); 91 | if (err) 92 | goto Failure; 93 | dump(fifo); 94 | 95 | /* pull the bits back out */ 96 | outbits = 0; 97 | err = bitfifo_dequeue(fifo, &outbits, length); 98 | if (err) 99 | goto Failure; 100 | dump(fifo); 101 | 102 | if (outbits != expected[i].after_dequeue) 103 | printf("*** difference: %.8x <> %.8x\n", 104 | outbits, 105 | expected[i].after_dequeue); 106 | } 107 | 108 | printf("...done\n"); 109 | 110 | printf("test: completely fill up the fifo\n"); 111 | err = bitfifo_enqueue(fifo, &all_ones, 0, MAXSIZE); 112 | if (err) 113 | goto Failure; 114 | dump(fifo); 115 | 116 | printf("test: enqueue another bit (should error)\n"); 117 | err = bitfifo_enqueue(fifo, &all_ones, 0, 1); 118 | if (err != result_BITFIFO_FULL) 119 | goto Failure; 120 | dump(fifo); 121 | 122 | printf("test: do 32 dequeue-enqueue ops...\n"); 123 | for (i = 0; i < MAXSIZE; i++) 124 | { 125 | printf("dequeue a single bit\n"); 126 | err = bitfifo_dequeue(fifo, &outbits, 1); 127 | if (err) 128 | goto Failure; 129 | dump(fifo); 130 | 131 | printf("enqueue a single bit\n"); 132 | err = bitfifo_enqueue(fifo, &all_ones, 0, 1); 133 | if (err) 134 | goto Failure; 135 | dump(fifo); 136 | } 137 | 138 | printf("...done\n"); 139 | 140 | bitfifo_destroy(fifo); 141 | 142 | return result_TEST_PASSED; 143 | 144 | 145 | Failure: 146 | 147 | return result_TEST_FAILED; 148 | } 149 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/and.c: -------------------------------------------------------------------------------- 1 | /* and.c -- bit vectors */ 2 | 3 | #include 4 | 5 | #include "base/utils.h" 6 | 7 | #include "datastruct/bitvec.h" 8 | 9 | #include "impl.h" 10 | 11 | result_t bitvec_and(const bitvec_t *a, const bitvec_t *b, bitvec_t **c) 12 | { 13 | int l; 14 | bitvec_t *v; 15 | int i; 16 | 17 | *c = NULL; 18 | 19 | /* all set bits will be contained in the minimum span of both arrays */ 20 | l = MIN(a->length, b->length); 21 | 22 | /* create vec, ensuring that enough space is allocated to perform the op */ 23 | v = bitvec_create(l << LOG2BITSPERWORD); 24 | if (v == NULL) 25 | return result_OOM; 26 | 27 | for (i = 0; i < l; i++) 28 | v->vec[i] = a->vec[i] & b->vec[i]; 29 | 30 | *c = v; 31 | 32 | return result_OK; 33 | } 34 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/clear-all.c: -------------------------------------------------------------------------------- 1 | /* clear-all.c -- bit vectors */ 2 | 3 | #include 4 | 5 | #include "datastruct/bitvec.h" 6 | 7 | #include "impl.h" 8 | 9 | void bitvec_clear_all(bitvec_t *v) 10 | { 11 | /* Note: This may clear more bits than strictly required. */ 12 | 13 | memset(v->vec, 0x00, v->length * sizeof(*v->vec)); 14 | } 15 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/clear.c: -------------------------------------------------------------------------------- 1 | /* clear.c -- bit vectors */ 2 | 3 | #include "datastruct/bitvec.h" 4 | 5 | #include "impl.h" 6 | 7 | void bitvec_clear(bitvec_t *v, bitvec_index_t bit) 8 | { 9 | unsigned int word; 10 | 11 | word = bit >> LOG2BITSPERWORD; 12 | 13 | if (word >= v->length) 14 | return; 15 | 16 | v->vec[word] &= ~(bitvec_1 << (bit & WORDMASK)); 17 | } 18 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/count.c: -------------------------------------------------------------------------------- 1 | /* count.c -- bit vectors */ 2 | 3 | #include "utils/barith.h" 4 | #include "datastruct/bitvec.h" 5 | 6 | #include "impl.h" 7 | 8 | unsigned int bitvec_count(const bitvec_t *v) 9 | { 10 | unsigned int c; 11 | unsigned int i; 12 | 13 | c = 0; 14 | for (i = 0; i < v->length; i++) 15 | c += bitvec_countbits(v->vec[i]); 16 | 17 | return c; 18 | } 19 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/create.c: -------------------------------------------------------------------------------- 1 | /* create.c -- bit vectors */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "base/result.h" 11 | 12 | #include "datastruct/bitvec.h" 13 | 14 | #include "impl.h" 15 | 16 | bitvec_t *bitvec_create(unsigned int length) 17 | { 18 | result_t err; 19 | bitvec_t *v; 20 | 21 | v = malloc(sizeof(*v)); 22 | if (v == NULL) 23 | return NULL; 24 | 25 | v->length = 0; 26 | v->vec = NULL; 27 | 28 | err = bitvec_ensure(v, length >> LOG2BITSPERWORD); 29 | if (err) 30 | { 31 | assert(err == result_OOM); 32 | return NULL; 33 | } 34 | 35 | return v; 36 | } 37 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/destroy.c: -------------------------------------------------------------------------------- 1 | /* destroy.c -- bit vectors */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/bitvec.h" 10 | 11 | #include "impl.h" 12 | 13 | void bitvec_destroy(bitvec_t *v) 14 | { 15 | if (v == NULL) 16 | return; 17 | 18 | free(v->vec); 19 | free(v); 20 | } 21 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/ensure.c: -------------------------------------------------------------------------------- 1 | /* ensure.c -- bit vectors */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "base/result.h" 11 | 12 | #include "datastruct/bitvec.h" 13 | 14 | #include "impl.h" 15 | 16 | result_t bitvec_ensure(bitvec_t *v, unsigned int need) 17 | { 18 | if (need > v->length) 19 | { 20 | unsigned int length; 21 | bitvec_T *vec; 22 | 23 | length = need; 24 | 25 | vec = realloc(v->vec, length * sizeof(*v->vec)); 26 | if (vec == NULL) 27 | return result_OOM; 28 | 29 | /* wipe the new segment */ 30 | memset(vec + v->length, 0, (length - v->length) * sizeof(*v->vec)); 31 | 32 | v->length = length; 33 | v->vec = vec; 34 | } 35 | 36 | return result_OK; 37 | } 38 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/eq.c: -------------------------------------------------------------------------------- 1 | /* eq.c -- bit vectors */ 2 | 3 | #include 4 | 5 | #include "base/utils.h" 6 | 7 | #include "datastruct/bitvec.h" 8 | 9 | #include "impl.h" 10 | 11 | /* If a bitvec had previously had a high bit set, then cleared it, then the 12 | * high allocated words may all be zero. 13 | * 14 | * e.g. using nibbles for words it's like this: 15 | * 16 | * 0100 1000 0000 0111 17 | * 18 | * Then it has its MSB unset: 19 | * 20 | * 0000 1000 0000 0111 21 | * 22 | * So the top words are zero. Now we want to compare against some other word 23 | * with possibly the same situation: 24 | * 25 | * 1000 0000 0111 26 | * 27 | * So they're not the same length, but do have the same bits set. 28 | */ 29 | 30 | int bitvec_eq(const bitvec_t *a, const bitvec_t *b) 31 | { 32 | unsigned int al; 33 | unsigned int bl; 34 | unsigned int l; 35 | const bitvec_t *p; /* the longer one */ 36 | 37 | al = a->length; 38 | bl = b->length; 39 | 40 | l = MIN(al, bl); 41 | 42 | if (l > 0) /* space for bits allocated */ 43 | { 44 | int r; 45 | 46 | r = memcmp(a->vec, b->vec, l * BYTESPERWORD); 47 | if (r != 0) 48 | return 0; /* not equal */ 49 | } 50 | 51 | if (al == bl) 52 | return 1; /* equal */ 53 | 54 | p = (al == l) ? b : a; /* pick the longer one */ 55 | 56 | for (; l < p->length; l++) 57 | if (p->vec[l]) 58 | return 0; /* nonzero bits found - not equal */ 59 | 60 | return 1; /* all remaining words were zero - equal */ 61 | } 62 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/get.c: -------------------------------------------------------------------------------- 1 | /* get.c -- bit vectors */ 2 | 3 | #include "datastruct/bitvec.h" 4 | 5 | #include "impl.h" 6 | 7 | int bitvec_get(const bitvec_t *v, bitvec_index_t bit) 8 | { 9 | unsigned int word; 10 | 11 | word = bit >> LOG2BITSPERWORD; 12 | 13 | if (word >= v->length) 14 | return 0; 15 | 16 | return (v->vec[word] & (bitvec_1 << (bit & WORDMASK))) != 0; 17 | } 18 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/impl.h: -------------------------------------------------------------------------------- 1 | /* impl.h -- bit vectors */ 2 | 3 | #ifndef DATASTRUCT_BITVEC_IMPL_H 4 | #define DATASTRUCT_BITVEC_IMPL_H 5 | 6 | #ifdef BITVEC_64 7 | #define bitvec_T unsigned long long 8 | #define bitvec_1 1ull 9 | #define bitvec_ctz ctz_64 10 | #define bitvec_countbits countbits_64 11 | #define LOG2BITSPERWORD 6 12 | #else 13 | #define bitvec_T unsigned int 14 | #define bitvec_1 1u 15 | #define bitvec_ctz ctz 16 | #define bitvec_countbits countbits 17 | #define LOG2BITSPERWORD 5 18 | #endif 19 | 20 | #define BYTESPERWORD (1 << (LOG2BITSPERWORD - 3)) 21 | #define WORDMASK ((1 << LOG2BITSPERWORD) - 1) 22 | 23 | struct bitvec 24 | { 25 | unsigned int length; /* length in words */ 26 | bitvec_T *vec; 27 | }; 28 | 29 | result_t bitvec_ensure(bitvec_t *v, unsigned int need); 30 | 31 | #endif /* DATASTRUCT_BITVEC_IMPL_H */ 32 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/length.c: -------------------------------------------------------------------------------- 1 | /* length.c -- bit vectors */ 2 | 3 | #include 4 | 5 | #include "datastruct/bitvec.h" 6 | 7 | #include "impl.h" 8 | 9 | unsigned int bitvec_length(const bitvec_t *v) 10 | { 11 | return v->length << LOG2BITSPERWORD; 12 | } 13 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/next.c: -------------------------------------------------------------------------------- 1 | /* next.c -- bit vectors */ 2 | 3 | #include "utils/barith.h" 4 | #include "datastruct/bitvec.h" 5 | 6 | #include "impl.h" 7 | 8 | int bitvec_next(const bitvec_t *v, int n) 9 | { 10 | unsigned int hi; 11 | int lo; 12 | 13 | if (!v->vec) 14 | return -1; /* no vec allocated */ 15 | 16 | if (n >= 0) 17 | { 18 | hi = n >> LOG2BITSPERWORD; 19 | lo = n & WORDMASK; 20 | 21 | if (lo == WORDMASK) /* at word boundary: skip first step */ 22 | { 23 | hi++; 24 | lo = -1; /* -1 => no mask */ 25 | } 26 | } 27 | else 28 | { 29 | hi = 0; 30 | lo = -1; 31 | } 32 | 33 | for (; hi < v->length; hi++) 34 | { 35 | bitvec_T word; 36 | bitvec_T bits; 37 | 38 | word = v->vec[hi]; 39 | if (word == 0) 40 | continue; /* no bits set */ 41 | 42 | if (lo >= 0) 43 | word &= ~((bitvec_1 << (lo + 1)) - 1); /* mask off considered bits */ 44 | 45 | bits = LSB(word); 46 | if (bits) 47 | return (hi << LOG2BITSPERWORD) + bitvec_ctz(bits); 48 | 49 | lo = -1; /* don't mask the next words */ 50 | } 51 | 52 | return -1; /* ran out of words */ 53 | } 54 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/or.c: -------------------------------------------------------------------------------- 1 | /* or.c -- bit vectors */ 2 | 3 | #include 4 | 5 | #include "base/utils.h" 6 | 7 | #include "datastruct/bitvec.h" 8 | 9 | #include "impl.h" 10 | 11 | result_t bitvec_or(const bitvec_t *a, const bitvec_t *b, bitvec_t **c) 12 | { 13 | int min, max; 14 | bitvec_t *v; 15 | int i; 16 | const bitvec_t *longest; 17 | 18 | *c = NULL; 19 | 20 | min = MIN(a->length, b->length); 21 | max = MAX(a->length, b->length); 22 | 23 | /* create vec, ensuring that enough space is allocated to perform the op */ 24 | v = bitvec_create(max << LOG2BITSPERWORD); 25 | if (v == NULL) 26 | return result_OOM; 27 | 28 | for (i = 0; i < min; i++) 29 | v->vec[i] = a->vec[i] | b->vec[i]; 30 | 31 | longest = (a->length > b->length) ? a : b; 32 | 33 | for (i = min; i < max; i++) 34 | v->vec[i] = longest->vec[i]; 35 | 36 | *c = v; 37 | 38 | return result_OK; 39 | } 40 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/set-all.c: -------------------------------------------------------------------------------- 1 | /* set-all.c -- bit vectors */ 2 | 3 | #include 4 | 5 | #include "datastruct/bitvec.h" 6 | 7 | #include "impl.h" 8 | 9 | void bitvec_set_all(bitvec_t *v) 10 | { 11 | // this is probably doing the wrong thing by setting all 'known' bits. 12 | // what you'd expect is that every single bit (including those unallocated) 13 | // would now be returned as one, so we'd need a flag to say what to read 14 | // unallocated bits as 15 | 16 | /* Note: This may set more bits than strictly required. */ 17 | 18 | memset(v->vec, 0xFF, v->length * BYTESPERWORD); 19 | } 20 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/set.c: -------------------------------------------------------------------------------- 1 | /* set.c -- bit vectors */ 2 | 3 | #include "base/result.h" 4 | 5 | #include "datastruct/bitvec.h" 6 | 7 | #include "impl.h" 8 | 9 | result_t bitvec_set(bitvec_t *v, bitvec_index_t bit) 10 | { 11 | result_t err; 12 | unsigned int word; 13 | 14 | word = bit >> LOG2BITSPERWORD; 15 | 16 | err = bitvec_ensure(v, word + 1); 17 | if (err) 18 | return err; 19 | 20 | v->vec[word] |= bitvec_1 << (bit & WORDMASK); 21 | 22 | return result_OK; 23 | } 24 | -------------------------------------------------------------------------------- /libraries/datastruct/bitvec/toggle.c: -------------------------------------------------------------------------------- 1 | /* toggle.c -- bit vectors */ 2 | 3 | #include "base/result.h" 4 | 5 | #include "datastruct/bitvec.h" 6 | 7 | #include "impl.h" 8 | 9 | result_t bitvec_toggle(bitvec_t *v, bitvec_index_t bit) 10 | { 11 | result_t err; 12 | unsigned int word; 13 | 14 | word = bit >> LOG2BITSPERWORD; 15 | 16 | err = bitvec_ensure(v, word + 1); 17 | if (err) 18 | return err; 19 | 20 | v->vec[word] ^= bitvec_1 << (bit & WORDMASK); 21 | 22 | return result_OK; 23 | } 24 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/count.c: -------------------------------------------------------------------------------- 1 | /* count.c -- hash */ 2 | 3 | #include "datastruct/hash.h" 4 | 5 | #include "impl.h" 6 | 7 | int hash_count(hash_t *hash) 8 | { 9 | return hash->count; 10 | } 11 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/create.c: -------------------------------------------------------------------------------- 1 | /* create.c -- hash */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "base/utils.h" 11 | 12 | #include "base/result.h" 13 | #include "utils/primes.h" 14 | 15 | #include "datastruct/hash.h" 16 | 17 | #include "impl.h" 18 | 19 | /* ----------------------------------------------------------------------- */ 20 | 21 | /* Basic string hash. Retained for reference. */ 22 | /*static unsigned int string_hash(const void *a) 23 | { 24 | const char *s = a; 25 | unsigned int h; 26 | 27 | h = 0; 28 | while (*s) 29 | h = h * 37 + *s++; 30 | 31 | return h; 32 | }*/ 33 | 34 | /* Fowler/Noll/Vo FNV-1 hash */ 35 | static unsigned int string_hash(const void *a) 36 | { 37 | const char *s = a; 38 | unsigned int h; 39 | 40 | h = 0x811c9dc5; 41 | while (*s) 42 | { 43 | h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24); 44 | h ^= *s++; 45 | } 46 | 47 | return h; 48 | } 49 | 50 | static int string_compare(const void *a, const void *b) 51 | { 52 | const char *sa = a; 53 | const char *sb = b; 54 | 55 | return strcmp(sa, sb); 56 | } 57 | 58 | static void string_destroy(void *string) 59 | { 60 | free(string); 61 | } 62 | 63 | /* ----------------------------------------------------------------------- */ 64 | 65 | void hash_no_destroy_key(void *string) 66 | { 67 | NOT_USED(string); 68 | } 69 | 70 | void hash_no_destroy_value(void *string) 71 | { 72 | NOT_USED(string); 73 | } 74 | 75 | /* ----------------------------------------------------------------------- */ 76 | 77 | result_t hash_create(const void *default_value, 78 | int nbins, 79 | hash_fn_t *fn, 80 | hash_compare_t *compare, 81 | hash_destroy_key_t *destroy_key, 82 | hash_destroy_value_t *destroy_value, 83 | hash_t **ph) 84 | { 85 | hash_t *h; 86 | hash_node_t **bins; 87 | 88 | h = malloc(sizeof(*h)); 89 | if (h == NULL) 90 | return result_OOM; 91 | 92 | nbins = prime_nearest(nbins); 93 | 94 | bins = calloc(nbins, sizeof(*h->bins)); 95 | if (bins == NULL) 96 | { 97 | free(h); 98 | return result_OOM; 99 | } 100 | 101 | /* the default routines handle strings */ 102 | 103 | h->nbins = nbins; 104 | h->bins = bins; 105 | 106 | h->count = 0; 107 | 108 | h->default_value = default_value; 109 | 110 | h->hash_fn = fn ? fn : string_hash; 111 | h->compare = compare ? compare : string_compare; 112 | h->destroy_key = destroy_key ? destroy_key : string_destroy; 113 | h->destroy_value = destroy_value ? destroy_value : string_destroy; 114 | 115 | *ph = h; 116 | 117 | return result_OK; 118 | } 119 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/destroy.c: -------------------------------------------------------------------------------- 1 | /* destroy.c -- hash */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/hash.h" 10 | 11 | #include "impl.h" 12 | 13 | void hash_destroy(hash_t *h) 14 | { 15 | unsigned int i; 16 | 17 | for (i = 0; i < h->nbins; i++) 18 | while (h->bins[i]) 19 | hash_remove_node(h, &h->bins[i]); 20 | 21 | free(h->bins); 22 | 23 | free(h); 24 | } 25 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/impl.h: -------------------------------------------------------------------------------- 1 | /* impl.h -- hash */ 2 | 3 | #ifndef DATASTRUCT_HASH_IMPL_H 4 | #define DATASTRUCT_HASH_IMPL_H 5 | 6 | #include "datastruct/hash.h" 7 | 8 | /* ----------------------------------------------------------------------- */ 9 | 10 | typedef struct hash_node 11 | { 12 | struct hash_node *next; 13 | 14 | const void *key; 15 | const void *value; 16 | } 17 | hash_node_t; 18 | 19 | struct hash 20 | { 21 | hash_node_t **bins; 22 | unsigned int nbins; 23 | 24 | int count; 25 | 26 | const void *default_value; 27 | 28 | hash_fn_t *hash_fn; 29 | hash_compare_t *compare; 30 | hash_destroy_key_t *destroy_key; 31 | hash_destroy_value_t *destroy_value; 32 | }; 33 | 34 | /* ----------------------------------------------------------------------- */ 35 | 36 | hash_node_t **hash_lookup_node(hash_t *h, const void *key); 37 | void hash_remove_node(hash_t *h, hash_node_t **n); 38 | 39 | /* ----------------------------------------------------------------------- */ 40 | 41 | #endif /* DATASTRUCT_HASH_IMPL_H */ 42 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/insert.c: -------------------------------------------------------------------------------- 1 | /* insert.c -- hash */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "base/result.h" 10 | 11 | #include "datastruct/hash.h" 12 | 13 | #include "impl.h" 14 | 15 | result_t hash_insert(hash_t *h, const void *key, const void *value) 16 | { 17 | hash_node_t **n; 18 | 19 | n = hash_lookup_node(h, key); 20 | if (*n) 21 | { 22 | /* already exists: update the value */ 23 | 24 | h->destroy_value((void *)(*n)->value); /* must cast away const */ 25 | 26 | (*n)->value = value; 27 | 28 | h->destroy_key((void *) key); /* must cast away const */ 29 | } 30 | else 31 | { 32 | hash_node_t *m; 33 | 34 | /* not found: create new node */ 35 | 36 | m = malloc(sizeof(*m)); 37 | if (m == NULL) 38 | return result_OOM; 39 | 40 | m->next = NULL; 41 | m->key = key; 42 | m->value = value; 43 | 44 | h->count++; 45 | 46 | *n = m; 47 | } 48 | 49 | return result_OK; 50 | } 51 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/lookup-node.c: -------------------------------------------------------------------------------- 1 | /* lookup-node.c -- hash */ 2 | 3 | #include 4 | 5 | #include "datastruct/hash.h" 6 | 7 | #include "impl.h" 8 | 9 | hash_node_t **hash_lookup_node(hash_t *h, const void *key) 10 | { 11 | unsigned int hash; 12 | hash_node_t **n; 13 | 14 | hash = h->hash_fn(key) % h->nbins; 15 | for (n = &h->bins[hash]; *n != NULL; n = &(*n)->next) 16 | if (h->compare(key, (*n)->key) == 0) 17 | break; 18 | 19 | return n; 20 | } 21 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/lookup.c: -------------------------------------------------------------------------------- 1 | /* lookup.c -- hash */ 2 | 3 | #include 4 | 5 | #include "datastruct/hash.h" 6 | 7 | #include "impl.h" 8 | 9 | const void *hash_lookup(hash_t *h, const void *key) 10 | { 11 | hash_node_t **n; 12 | 13 | n = hash_lookup_node(h, key); 14 | 15 | return (*n != NULL) ? (*n)->value : h->default_value; 16 | } 17 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/remove.c: -------------------------------------------------------------------------------- 1 | /* remove.c -- hash */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/hash.h" 10 | 11 | #include "impl.h" 12 | 13 | void hash_remove_node(hash_t *h, hash_node_t **n) 14 | { 15 | hash_node_t *doomed; 16 | 17 | doomed = *n; 18 | 19 | *n = doomed->next; 20 | 21 | h->destroy_key((void *) doomed->key); 22 | h->destroy_value((void *) doomed->value); 23 | 24 | free(doomed); 25 | 26 | h->count--; 27 | } 28 | 29 | void hash_remove(hash_t *h, const void *key) 30 | { 31 | hash_node_t **n; 32 | 33 | n = hash_lookup_node(h, key); 34 | hash_remove_node(h, n); 35 | } 36 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/test/hash-test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "base/result.h" 10 | #include "base/utils.h" 11 | #include "utils/array.h" 12 | 13 | #include "datastruct/hash.h" 14 | 15 | #include "test/all-tests.h" 16 | 17 | static char *my_strdup(const char *s) 18 | { 19 | size_t l; 20 | char *d; 21 | 22 | l = strlen(s); 23 | 24 | d = malloc(l + 1); 25 | if (d == NULL) 26 | return NULL; 27 | 28 | memcpy(d, s, l + 1); 29 | 30 | return d; 31 | } 32 | 33 | static int my_walk_fn(const void *key, const void *value, void *opaque) 34 | { 35 | const char *sk = key; 36 | const char *sv = value; 37 | 38 | NOT_USED(opaque); 39 | 40 | printf("walk '%s':'%s'...\n", (const char *) sk, (const char *) sv); 41 | 42 | return 0; 43 | } 44 | 45 | result_t hash_test(const char *resources) 46 | { 47 | static const struct 48 | { 49 | const char *name; 50 | const char *value; 51 | } 52 | data[] = 53 | { 54 | { "deckard", "rick" }, 55 | { "batty", "roy" }, 56 | { "tyrell", "rachael" }, 57 | { "gaff", "n/a" }, 58 | { "bryant", "n/a" }, 59 | { "pris", "n/a" }, 60 | { "sebastian", "jf" }, 61 | }; 62 | 63 | result_t err; 64 | hash_t *d; 65 | int i; 66 | 67 | NOT_USED(resources); 68 | 69 | printf("test: create\n"); 70 | 71 | /* use default string handling */ 72 | err = hash_create(NULL, 20, NULL, NULL, NULL, NULL, &d); 73 | if (err) 74 | goto Failure; 75 | 76 | printf("test: insert\n"); 77 | 78 | for (i = 0; i < NELEMS(data); i++) 79 | { 80 | char *s; 81 | char *v; 82 | 83 | printf("adding '%s':'%s'...\n", data[i].name, data[i].value); 84 | 85 | s = my_strdup(data[i].name); 86 | v = my_strdup(data[i].value); 87 | 88 | if (!s || !v) 89 | { 90 | free(s); 91 | free(v); 92 | goto Failure; 93 | } 94 | 95 | err = hash_insert(d, s, v); 96 | if (err) 97 | { 98 | free(s); 99 | free(v); 100 | goto Failure; 101 | } 102 | } 103 | 104 | printf("count = %d\n", hash_count(d)); 105 | 106 | printf("test: iterate\n"); 107 | 108 | hash_walk(d, my_walk_fn, NULL); 109 | 110 | printf("test: iterate by continuation\n"); 111 | 112 | { 113 | int cont = 0; 114 | 115 | for (;;) 116 | { 117 | const void *key; 118 | const void *value; 119 | 120 | printf("cont = %x\n", cont); 121 | 122 | err = hash_walk_continuation(d, cont, &cont, &key, &value); 123 | if (err == result_HASH_END) 124 | break; 125 | 126 | printf("walk '%s':'%s'...\n", (const char *) key, (const char *) value); 127 | } 128 | } 129 | 130 | printf("test: remove\n"); 131 | 132 | for (i = 0; i < NELEMS(data); i++) 133 | hash_remove(d, data[i].name); 134 | 135 | printf("count = %d\n", hash_count(d)); 136 | 137 | printf("test: destroy\n"); 138 | 139 | hash_destroy(d); 140 | 141 | return result_TEST_PASSED; 142 | 143 | 144 | Failure: 145 | 146 | printf("\n\n*** Error %x\n", err); 147 | 148 | return result_TEST_FAILED; 149 | } 150 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/walk-cont.c: -------------------------------------------------------------------------------- 1 | /* walk-cont.c -- hash */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "base/result.h" 11 | 12 | #include "datastruct/hash.h" 13 | 14 | #include "impl.h" 15 | 16 | result_t hash_walk_continuation(hash_t *h, 17 | int continuation, 18 | int *nextcontinuation, 19 | const void **key, 20 | const void **value) 21 | { 22 | unsigned int bin; 23 | unsigned int item; 24 | unsigned int i; 25 | hash_node_t *n; 26 | hash_node_t *next = NULL; 27 | 28 | if (continuation == -1) /* previous iteration was the last element */ 29 | return result_HASH_END; 30 | 31 | /* The continuation value is treated as a pair of 16-bit fields, the top 32 | * half being the bin and the bottom half being the node within the bin. */ 33 | 34 | bin = ((unsigned int) continuation ) >> 16; 35 | item = ((unsigned int) continuation & 0x0000ffff) >> 0; 36 | 37 | if (bin >= h->nbins) 38 | return result_HASH_BAD_CONT; /* invalid continuation value */ 39 | 40 | /* if we're starting off, scan forward to the first occupied bin */ 41 | 42 | if (continuation == 0) 43 | { 44 | for (; bin < h->nbins; bin++) 45 | if (h->bins[bin]) 46 | break; 47 | 48 | if (bin == h->nbins) 49 | return result_HASH_END; /* all bins were empty */ 50 | } 51 | 52 | i = 0; /* node counter */ 53 | 54 | for (n = h->bins[bin]; n; n = next) 55 | { 56 | next = n->next; 57 | 58 | if (i == item) 59 | break; 60 | 61 | i++; 62 | } 63 | 64 | if (n == NULL) /* invalid continuation value */ 65 | return result_HASH_BAD_CONT; 66 | 67 | *key = n->key; 68 | *value = n->value; 69 | 70 | /* form the continuation value and return it */ 71 | 72 | /* a chain this long would be very odd, but ... */ 73 | assert(i + 1 <= 0xffff); 74 | 75 | if (next) 76 | { 77 | *nextcontinuation = (bin << 16) | (i + 1); /* current bin, next node */ 78 | return result_OK; 79 | } 80 | 81 | /* scan forward to the next occupied bin */ 82 | 83 | while (++bin < h->nbins) 84 | if (h->bins[bin]) 85 | { 86 | *nextcontinuation = bin << 16; /* next occupied bin, first node */ 87 | return result_OK; 88 | } 89 | 90 | *nextcontinuation = -1; /* ran out of bins - remember for next iter */ 91 | 92 | return result_OK; 93 | } 94 | -------------------------------------------------------------------------------- /libraries/datastruct/hash/walk.c: -------------------------------------------------------------------------------- 1 | /* walk.c -- hash */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "base/result.h" 10 | 11 | #include "datastruct/hash.h" 12 | 13 | #include "impl.h" 14 | 15 | result_t hash_walk(const hash_t *h, hash_walk_callback_t *cb, void *cbarg) 16 | { 17 | unsigned int i; 18 | 19 | for (i = 0; i < h->nbins; i++) 20 | { 21 | hash_node_t *n; 22 | hash_node_t *next; 23 | 24 | for (n = h->bins[i]; n != NULL; n = next) 25 | { 26 | result_t r; 27 | 28 | next = n->next; 29 | 30 | r = cb(n->key, n->value, cbarg); 31 | if (r) 32 | return r; 33 | } 34 | } 35 | 36 | return result_OK; 37 | } 38 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/append.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/hlist.h" 11 | 12 | #include "impl.h" 13 | 14 | T hlist_append(T list, T tail) 15 | { 16 | T *p = &list; 17 | 18 | while (*p) 19 | p = &(*p)->rest; 20 | 21 | *p = tail; 22 | 23 | return list; 24 | } 25 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/copy.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/hlist.h" 11 | 12 | #include "impl.h" 13 | 14 | T hlist_copy(T list) 15 | { 16 | T head; 17 | T *p; 18 | 19 | p = &head; 20 | 21 | for (; list; list = list->rest) 22 | { 23 | *p = malloc(sizeof(**p)); 24 | if (*p == NULL) 25 | return NULL; /* FIXME: This won't unwind the mallocs in the failure case. */ 26 | 27 | (*p)->first = list->first; 28 | p = &(*p)->rest; 29 | } 30 | 31 | *p = NULL; 32 | 33 | return head; 34 | } 35 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/free.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef FORTIFY 8 | #include "fortify/fortify.h" 9 | #endif 10 | 11 | #include "datastruct/hlist.h" 12 | 13 | #include "impl.h" 14 | 15 | void hlist_free(T *list) 16 | { 17 | T next; 18 | 19 | assert(list != NULL); 20 | 21 | for (; *list; *list = next) 22 | { 23 | next = (*list)->rest; 24 | free(*list); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/impl.h: -------------------------------------------------------------------------------- 1 | /* impl.h -- hlist */ 2 | 3 | #define T hlist_t 4 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/length.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/hlist.h" 11 | 12 | #include "impl.h" 13 | 14 | int hlist_length(T list) 15 | { 16 | int n; 17 | 18 | for (n = 0; list; list = list->rest) 19 | n++; 20 | 21 | return n; 22 | } 23 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/list.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/hlist.h" 11 | 12 | #include "impl.h" 13 | 14 | T hlist_list(void *x, ...) 15 | { 16 | va_list ap; 17 | T list; 18 | T *p; 19 | 20 | p = &list; 21 | 22 | va_start(ap, x); 23 | 24 | for (; x; x = va_arg(ap, void *)) 25 | { 26 | *p = malloc(sizeof(**p)); 27 | if (*p == NULL) 28 | return NULL; /* FIXME: This won't unwind the mallocs in the failure case. */ 29 | 30 | (*p)->first = x; 31 | p = &(*p)->rest; 32 | } 33 | 34 | *p = NULL; 35 | 36 | va_end(ap); 37 | 38 | return list; 39 | } 40 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/map.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef FORTIFY 8 | #include "fortify/fortify.h" 9 | #endif 10 | 11 | #include "datastruct/hlist.h" 12 | 13 | #include "impl.h" 14 | 15 | void hlist_map(T list, void apply(void **x, void *cl), void *cl) 16 | { 17 | T next; 18 | 19 | assert(apply != NULL); 20 | 21 | /* Difference from CII: a next pointer is maintained for some robustness. 22 | */ 23 | 24 | for (; list; list = next) 25 | { 26 | next = list->rest; 27 | apply(&list->first, cl); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/pop.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/hlist.h" 11 | 12 | #include "impl.h" 13 | 14 | T hlist_pop(T list, void **x) 15 | { 16 | if (list) 17 | { 18 | T head = list->rest; 19 | if (x) 20 | *x = list->first; 21 | free(list); 22 | return head; 23 | } 24 | else 25 | { 26 | return list; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/push.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/hlist.h" 11 | 12 | #include "impl.h" 13 | 14 | T hlist_push(T list, void *x) 15 | { 16 | T p; 17 | 18 | p = malloc(sizeof(*p)); 19 | 20 | p->first = x; 21 | p->rest = list; 22 | 23 | return p; 24 | } 25 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/reverse.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/hlist.h" 11 | 12 | #include "impl.h" 13 | 14 | T hlist_reverse(T list) 15 | { 16 | T head; 17 | T next; 18 | 19 | head = NULL; 20 | 21 | for (; list; list = next) 22 | { 23 | next = list->rest; 24 | list->rest = head; 25 | head = list; 26 | } 27 | 28 | return head; 29 | } 30 | -------------------------------------------------------------------------------- /libraries/datastruct/hlist/to-array.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/hlist.h" 11 | 12 | #include "impl.h" 13 | 14 | void **hlist_to_array(T list, void *end) 15 | { 16 | int n; 17 | void **array; 18 | int i; 19 | 20 | n = hlist_length(list); 21 | 22 | array = malloc((n + 1) * sizeof(*array)); 23 | if (array == NULL) 24 | return NULL; 25 | 26 | for (i = 0; i < n; i++) 27 | { 28 | array[i] = list->first; 29 | list = list->rest; 30 | } 31 | 32 | array[i] = end; 33 | return array; 34 | } 35 | -------------------------------------------------------------------------------- /libraries/datastruct/list/add-head.c: -------------------------------------------------------------------------------- 1 | 2 | #include "datastruct/list.h" 3 | 4 | void list_add_to_head(list_t *anchor, list_t *item) 5 | { 6 | item->next = anchor->next; 7 | anchor->next = item; 8 | } 9 | -------------------------------------------------------------------------------- /libraries/datastruct/list/find.c: -------------------------------------------------------------------------------- 1 | 2 | #include "datastruct/list.h" 3 | 4 | list_t *list_find(list_t *anchor, size_t keyloc, int key) 5 | { 6 | list_t *e; 7 | 8 | #define GET_KEY(element, offset) (*((int *) ((char *) element + offset))) 9 | 10 | for (e = anchor; e != NULL; e = e->next) 11 | if (GET_KEY(e, keyloc) == key) 12 | return e; 13 | 14 | return NULL; 15 | } 16 | -------------------------------------------------------------------------------- /libraries/datastruct/list/init.c: -------------------------------------------------------------------------------- 1 | 2 | #include "datastruct/list.h" 3 | 4 | void list_init(list_t *anchor) 5 | { 6 | anchor->next = NULL; 7 | } 8 | -------------------------------------------------------------------------------- /libraries/datastruct/list/remove.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "datastruct/list.h" 5 | 6 | void list_remove(list_t *anchor, list_t *doomed) 7 | { 8 | list_t *e; 9 | 10 | for (e = anchor; e->next != doomed; e = e->next) 11 | assert(e != NULL); /* if we hit NULL then throw a wobbly */ 12 | 13 | /* 'e' is the element preceding the one to remove */ 14 | 15 | e->next = doomed->next; /* == e->next->next; */ 16 | } 17 | -------------------------------------------------------------------------------- /libraries/datastruct/list/test/list-test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #ifdef FORTIFY 5 | #include "fortify/fortify.h" 6 | #endif 7 | 8 | #include "base/result.h" 9 | #include "base/utils.h" 10 | #include "utils/array.h" 11 | 12 | #include "datastruct/list.h" 13 | 14 | #include "test/all-tests.h" 15 | 16 | typedef struct node 17 | { 18 | list_t ll; 19 | char string[32]; 20 | } 21 | node_t; 22 | 23 | static int printelement(list_t *e, void *opaque) 24 | { 25 | node_t *n; 26 | 27 | NOT_USED(opaque); 28 | 29 | n = (node_t *) e; 30 | 31 | printf("%p: %s\n", (void *) e, n->string); 32 | 33 | return 0; 34 | } 35 | 36 | result_t list_test(const char *resources) 37 | { 38 | node_t data[] = 39 | { 40 | { { NULL }, "deckard" }, 41 | { { NULL }, "batty" }, 42 | { { NULL }, "rachael" }, 43 | { { NULL }, "gaff" }, 44 | { { NULL }, "bryant" }, 45 | { { NULL }, "pris" }, 46 | { { NULL }, "sebastian" }, 47 | }; 48 | 49 | list_t anchor = { NULL }; 50 | 51 | int i; 52 | 53 | NOT_USED(resources); 54 | 55 | printf("test: add to head\n"); 56 | 57 | for (i = 0; i < NELEMS(data); i++) 58 | { 59 | printf("adding '%s'...\n", data[i].string); 60 | list_add_to_head(&anchor, &data[i].ll); 61 | } 62 | 63 | printf("test: iterate\n"); 64 | 65 | list_walk(&anchor, printelement, NULL); 66 | 67 | return result_TEST_PASSED; 68 | } 69 | -------------------------------------------------------------------------------- /libraries/datastruct/list/walk.c: -------------------------------------------------------------------------------- 1 | 2 | #include "datastruct/list.h" 3 | 4 | int list_walk(list_t *anchor, list_walk_callback_t cb, void *opaque) 5 | { 6 | list_t *e; 7 | list_t *next; 8 | int rc; 9 | 10 | /* Be careful walking the list. The callback may be destroying the objects 11 | * we're handling to it. 12 | */ 13 | 14 | for (e = anchor->next; e != NULL; e = next) 15 | { 16 | next = e->next; 17 | if ((rc = cb(e, opaque)) < 0) 18 | return rc; 19 | } 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/copy.c: -------------------------------------------------------------------------------- 1 | /* copy.c -- n-ary tree */ 2 | 3 | #include 4 | 5 | #include "base/result.h" 6 | #include "datastruct/ntree.h" 7 | 8 | #include "impl.h" 9 | 10 | result_t ntree_copy(ntree_t *t, 11 | ntree_copy_fn_t *fn, 12 | void *opaque, 13 | ntree_t **new_t) 14 | { 15 | result_t err; 16 | void *data; 17 | ntree_t *new_node; 18 | ntree_t *child; 19 | 20 | if (!t) 21 | return result_BAD_ARG; 22 | 23 | err = fn(t->data, opaque, &data); 24 | if (err) 25 | return err; 26 | 27 | err = ntree_new(&new_node); 28 | if (err) 29 | return err; 30 | 31 | ntree_set_data(new_node, data); 32 | 33 | /* we walk the list of children backwards 34 | * so we can prepend, which takes constant time */ 35 | 36 | for (child = ntree_last_child(t); child; child = child->prev) 37 | { 38 | ntree_t *new_child; 39 | 40 | err = ntree_copy(child, fn, opaque, &new_child); 41 | if (err) 42 | return err; 43 | 44 | err = ntree_prepend(new_node, new_child); 45 | if (err) 46 | return err; 47 | } 48 | 49 | *new_t = new_node; 50 | 51 | return err; 52 | } 53 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/delete.c: -------------------------------------------------------------------------------- 1 | /* delete.c -- n-ary tree */ 2 | 3 | #include 4 | 5 | #include "datastruct/ntree.h" 6 | 7 | #include "impl.h" 8 | 9 | void ntree_delete(ntree_t *t) 10 | { 11 | assert(t); 12 | 13 | if (!IS_ROOT(t)) 14 | ntree_unlink(t); 15 | 16 | ntree_free(t); 17 | } 18 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/depth.c: -------------------------------------------------------------------------------- 1 | /* depth.c -- n-ary tree */ 2 | 3 | #include "datastruct/ntree.h" 4 | 5 | #include "impl.h" 6 | 7 | int ntree_depth(ntree_t *t) 8 | { 9 | int d; 10 | 11 | d = 0; 12 | 13 | while (t) 14 | { 15 | d++; 16 | t = t->parent; 17 | } 18 | 19 | return d; 20 | } 21 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/first-child.c: -------------------------------------------------------------------------------- 1 | /* first-child.c -- n-ary tree */ 2 | 3 | #include 4 | 5 | #include "datastruct/ntree.h" 6 | 7 | #include "impl.h" 8 | 9 | ntree_t *ntree_first_child(ntree_t *t) 10 | { 11 | return t ? t->children : NULL; 12 | } 13 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/free.c: -------------------------------------------------------------------------------- 1 | /* free.c -- n-ary tree */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/ntree.h" 11 | 12 | #include "impl.h" 13 | 14 | void ntree_free(ntree_t *t) 15 | { 16 | ntree_t *next; 17 | 18 | assert(t); 19 | 20 | for (; t; t = next) 21 | { 22 | next = t->next; 23 | 24 | if (t->children) 25 | ntree_free(t->children); 26 | 27 | free(t); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/get-data.c: -------------------------------------------------------------------------------- 1 | /* get-data.c -- n-ary tree */ 2 | 3 | #include "datastruct/ntree.h" 4 | 5 | #include "impl.h" 6 | 7 | void *ntree_get_data(ntree_t *t) 8 | { 9 | return t->data; 10 | } 11 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/impl.h: -------------------------------------------------------------------------------- 1 | /* impl.h -- n-ary tree */ 2 | 3 | #ifndef NTREE_IMPL_H 4 | #define NTREE_IMPL_H 5 | 6 | #include 7 | 8 | #include "datastruct/ntree.h" 9 | 10 | struct ntree 11 | { 12 | ntree_t *next; 13 | ntree_t *prev; 14 | ntree_t *parent; 15 | ntree_t *children; 16 | void *data; 17 | }; 18 | 19 | #define IS_ROOT(t) ((t)->parent == NULL && \ 20 | (t)->prev == NULL && \ 21 | (t)->next == NULL) 22 | 23 | #endif /* NTREE_IMPL_H */ 24 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/insert-after.c: -------------------------------------------------------------------------------- 1 | /* insert-after.c -- n-ary tree */ 2 | 3 | #include 4 | #include 5 | 6 | #include "base/utils.h" 7 | 8 | #include "base/result.h" 9 | #include "datastruct/ntree.h" 10 | 11 | #include "impl.h" 12 | 13 | result_t ntree_insert_after(ntree_t *parent, ntree_t *sibling, ntree_t *node) 14 | { 15 | NOT_USED(parent); 16 | NOT_USED(sibling); 17 | NOT_USED(node); 18 | 19 | assert("NYI" == NULL); 20 | 21 | return result_OK; 22 | } 23 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/insert-before.c: -------------------------------------------------------------------------------- 1 | /* insert-before.c -- n-ary tree */ 2 | 3 | #include 4 | #include 5 | 6 | #include "datastruct/ntree.h" 7 | 8 | #include "impl.h" 9 | 10 | result_t ntree_insert_before(ntree_t *parent, ntree_t *sibling, ntree_t *node) 11 | { 12 | assert(node->parent == NULL); 13 | 14 | node->parent = parent; 15 | 16 | if (sibling) 17 | { 18 | if (sibling->prev) 19 | { 20 | node->prev = sibling->prev; 21 | node->prev->next = node; 22 | node->next = sibling; 23 | sibling->prev = node; 24 | } 25 | else 26 | { 27 | parent->children = node; // or node->parent->children = node; 28 | node->next = sibling; 29 | sibling->prev = node; 30 | } 31 | } 32 | else 33 | { 34 | /* not given a sibling */ 35 | 36 | if (parent->children) 37 | { 38 | /* insert at end */ 39 | sibling = parent->children; 40 | while (sibling->next) 41 | sibling = sibling->next; 42 | node->prev = sibling; 43 | sibling->next = node; 44 | } 45 | else 46 | { 47 | parent->children = node; 48 | } 49 | } 50 | 51 | return result_OK; 52 | } 53 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/insert.c: -------------------------------------------------------------------------------- 1 | /* insert.c -- n-ary tree */ 2 | 3 | #include 4 | 5 | #include "datastruct/ntree.h" 6 | 7 | #include "impl.h" 8 | 9 | result_t ntree_insert(ntree_t *parent, int where, ntree_t *node) 10 | { 11 | ntree_t *sibling; 12 | 13 | if (where > 0) 14 | sibling = ntree_nth_child(parent, where); 15 | else if (where == 0) /* prepend */ 16 | sibling = parent->children; 17 | else /* append */ 18 | sibling = NULL; 19 | 20 | return ntree_insert_before(parent, sibling, node); 21 | } 22 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/last-child.c: -------------------------------------------------------------------------------- 1 | /* last-child.c -- n-ary tree */ 2 | 3 | #include "datastruct/ntree.h" 4 | 5 | #include "impl.h" 6 | 7 | ntree_t *ntree_last_child(ntree_t *t) 8 | { 9 | t = t->children; 10 | if (t) 11 | while (t->next) 12 | t = t->next; 13 | 14 | return t; 15 | } 16 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/max-height.c: -------------------------------------------------------------------------------- 1 | /* max-height.c -- n-ary tree */ 2 | 3 | #include "datastruct/ntree.h" 4 | 5 | #include "impl.h" 6 | 7 | int ntree_max_height(ntree_t *t) 8 | { 9 | int max; 10 | ntree_t *child; 11 | 12 | max = 0; 13 | 14 | if (!t) 15 | return max; 16 | 17 | for (child = t->children; child; child = child->next) 18 | { 19 | int h; 20 | 21 | h = ntree_max_height(child); 22 | if (h > max) 23 | max = h; 24 | } 25 | 26 | return max + 1; 27 | } 28 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/n-nodes.c: -------------------------------------------------------------------------------- 1 | /* n-nodes.c -- n-ary tree */ 2 | 3 | #include "base/utils.h" 4 | 5 | #include "datastruct/ntree.h" 6 | 7 | #include "impl.h" 8 | 9 | static result_t ntree_count_func(ntree_t *t, void *opaque) 10 | { 11 | int *n; 12 | 13 | NOT_USED(t); 14 | 15 | n = opaque; 16 | 17 | (*n)++; 18 | 19 | return result_OK; 20 | } 21 | 22 | int ntree_n_nodes(ntree_t *t) 23 | { 24 | int n; 25 | 26 | n = 0; 27 | 28 | ntree_walk(t, 29 | ntree_WALK_IN_ORDER | ntree_WALK_ALL, 30 | 0, 31 | ntree_count_func, 32 | (void *) &n); 33 | 34 | return n; 35 | } 36 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/new.c: -------------------------------------------------------------------------------- 1 | /* new.c -- n-ary tree */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "base/result.h" 10 | 11 | #include "datastruct/ntree.h" 12 | 13 | #include "impl.h" 14 | 15 | result_t ntree_new(ntree_t **t) 16 | { 17 | ntree_t *n; 18 | 19 | n = calloc(1, sizeof(*n)); 20 | if (n == NULL) 21 | return result_OOM; 22 | 23 | *t = n; 24 | 25 | return result_OK; 26 | } 27 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/next-sibling.c: -------------------------------------------------------------------------------- 1 | /* next-sibling.c -- n-ary tree */ 2 | 3 | #include 4 | 5 | #include "datastruct/ntree.h" 6 | 7 | #include "impl.h" 8 | 9 | ntree_t *ntree_next_sibling(ntree_t *t) 10 | { 11 | return t ? t->next : NULL; 12 | } 13 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/nth-child.c: -------------------------------------------------------------------------------- 1 | /* nth-child.c -- n-ary tree */ 2 | 3 | #include "datastruct/ntree.h" 4 | 5 | #include "impl.h" 6 | 7 | ntree_t *ntree_nth_child(ntree_t *t, int n) 8 | { 9 | t = t->children; 10 | if (t) 11 | while (n-- > 0 && t) 12 | t = t->next; 13 | 14 | return t; 15 | } 16 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/parent.c: -------------------------------------------------------------------------------- 1 | /* parent.c -- n-ary tree */ 2 | 3 | #include 4 | 5 | #include "datastruct/ntree.h" 6 | 7 | #include "impl.h" 8 | 9 | ntree_t *ntree_parent(ntree_t *t) 10 | { 11 | return t ? t->parent : NULL; 12 | } 13 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/prepend.c: -------------------------------------------------------------------------------- 1 | /* prepend.c -- n-ary tree */ 2 | 3 | #include 4 | 5 | #include "datastruct/ntree.h" 6 | 7 | #include "impl.h" 8 | 9 | result_t ntree_prepend(ntree_t *parent, ntree_t *node) 10 | { 11 | return ntree_insert_before(parent, parent->children, node); 12 | } 13 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/prev-sibling.c: -------------------------------------------------------------------------------- 1 | /* prev-sibling.c -- n-ary tree */ 2 | 3 | #include 4 | 5 | #include "datastruct/ntree.h" 6 | 7 | #include "impl.h" 8 | 9 | ntree_t *ntree_prev_sibling(ntree_t *t) 10 | { 11 | return t ? t->prev : NULL; 12 | } 13 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/set-data.c: -------------------------------------------------------------------------------- 1 | /* set-data.c -- n-ary tree */ 2 | 3 | #include "datastruct/ntree.h" 4 | 5 | #include "impl.h" 6 | 7 | void ntree_set_data(ntree_t *t, void *data) 8 | { 9 | t->data = data; 10 | } 11 | -------------------------------------------------------------------------------- /libraries/datastruct/ntree/unlink.c: -------------------------------------------------------------------------------- 1 | /* unlink.c -- n-ary tree */ 2 | 3 | #include 4 | #include 5 | 6 | #include "datastruct/ntree.h" 7 | 8 | #include "impl.h" 9 | 10 | void ntree_unlink(ntree_t *t) 11 | { 12 | assert(t); 13 | 14 | if (t->prev) 15 | t->prev->next = t->next; 16 | else if (t->parent) 17 | t->parent->children = t->next; 18 | 19 | t->parent = NULL; 20 | 21 | if (t->next) 22 | { 23 | t->next->prev = t->prev; 24 | t->next = NULL; 25 | } 26 | 27 | t->prev = NULL; 28 | } 29 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/clear.c: -------------------------------------------------------------------------------- 1 | /* clear.c -- vector - flexible array */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/vector.h" 10 | 11 | #include "impl.h" 12 | 13 | void vector_clear(vector_t *v) 14 | { 15 | v->used = 0; 16 | } 17 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/create.c: -------------------------------------------------------------------------------- 1 | /* create.c -- vector - flexible array */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/vector.h" 10 | 11 | #include "impl.h" 12 | 13 | vector_t *vector_create(size_t width) 14 | { 15 | vector_t *v; 16 | 17 | v = calloc(1, sizeof(*v)); 18 | if (v == NULL) 19 | return NULL; 20 | 21 | v->width = width; 22 | 23 | return v; 24 | } 25 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/destroy.c: -------------------------------------------------------------------------------- 1 | /* destroy.c -- vector - flexible array */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/vector.h" 10 | 11 | #include "impl.h" 12 | 13 | void vector_destroy(vector_t *doomed) 14 | { 15 | if (doomed == NULL) 16 | return; 17 | 18 | free(doomed->base); 19 | free(doomed); 20 | } 21 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/ensure.c: -------------------------------------------------------------------------------- 1 | /* ensure.c -- vector - flexible array */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/vector.h" 10 | 11 | #include "impl.h" 12 | 13 | result_t vector_ensure(vector_t *v, unsigned int need) 14 | { 15 | if (need > v->allocated) 16 | { 17 | unsigned int required; 18 | void *newbase; 19 | 20 | required = need; 21 | 22 | newbase = realloc(v->base, required * v->width); 23 | if (newbase == NULL) 24 | return result_OOM; 25 | 26 | // Note: We're not wiping the new portion of the array. 27 | 28 | v->allocated = required; 29 | v->base = newbase; 30 | } 31 | 32 | return result_OK; 33 | } 34 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/get.c: -------------------------------------------------------------------------------- 1 | /* get.c -- vector - flexible array */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "datastruct/vector.h" 11 | 12 | #include "impl.h" 13 | 14 | void *vector_get(const vector_t *v, unsigned int index) 15 | { 16 | assert(index < v->allocated); 17 | 18 | return VECTOR_INDEX(v, index); 19 | } 20 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/impl.h: -------------------------------------------------------------------------------- 1 | /* impl.h -- vector - flexible array */ 2 | 3 | #ifndef IMPL_H 4 | #define IMPL_H 5 | 6 | #include 7 | 8 | struct vector 9 | { 10 | size_t width; /* width of an element */ 11 | unsigned int used; /* entries used */ 12 | unsigned int allocated; /* entries allocated */ 13 | void *base; /* vector itself */ 14 | }; 15 | 16 | /* Calculate address of element 'i'. */ 17 | #define VECTOR_INDEX(v, i) ((char *) v->base + (i) * v->width) 18 | 19 | #endif /* IMPL_H */ 20 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/insert.c: -------------------------------------------------------------------------------- 1 | /* insert.c -- vector - flexible array */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef FORTIFY 8 | #include "fortify/fortify.h" 9 | #endif 10 | 11 | #include "datastruct/vector.h" 12 | 13 | #include "impl.h" 14 | 15 | result_t vector_insert(vector_t *v, const void *value) 16 | { 17 | result_t err; 18 | unsigned int used; 19 | void *base; 20 | 21 | used = v->used; 22 | 23 | if ((err = vector_ensure(v, used + 1)) != result_OK) 24 | return err; 25 | 26 | base = vector_get(v, (int) used); 27 | assert(base != NULL); /* can't fail, so assert */ 28 | 29 | memcpy(base, value, v->width); 30 | v->used++; 31 | 32 | return result_OK; 33 | } 34 | 35 | result_t vector_insert_many(vector_t *v, const void *values, int nvalues) 36 | { 37 | result_t err; 38 | unsigned int used; 39 | void *base; 40 | 41 | used = v->used; 42 | 43 | if ((err = vector_ensure(v, used + nvalues)) != result_OK) 44 | return err; 45 | 46 | base = vector_get(v, (int) used); 47 | assert(base != NULL); /* can't fail, so assert */ 48 | 49 | memcpy(base, values, v->width * nvalues); 50 | v->used += nvalues; 51 | 52 | return result_OK; 53 | } 54 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/length.c: -------------------------------------------------------------------------------- 1 | /* length.c -- vector - flexible array */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/vector.h" 10 | 11 | #include "impl.h" 12 | 13 | size_t vector_length(const vector_t *v) 14 | { 15 | return v->used; 16 | } 17 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/set-length.c: -------------------------------------------------------------------------------- 1 | /* set-length.c -- vector - flexible array */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/vector.h" 10 | 11 | #include "impl.h" 12 | 13 | result_t vector_set_length(vector_t *v, unsigned int length) 14 | { 15 | void *newbase; 16 | 17 | newbase = realloc(v->base, length * v->width); 18 | if (newbase == NULL) 19 | return result_OOM; 20 | 21 | v->used = length; // FIXME: Looks wrong. 22 | v->allocated = length; 23 | v->base = newbase; 24 | 25 | return result_OK; 26 | } 27 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/set-width.c: -------------------------------------------------------------------------------- 1 | /* set-width.c -- vector - flexible array */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "utils/barith.h" 10 | #include "utils/array.h" 11 | 12 | #include "datastruct/vector.h" 13 | 14 | #include "impl.h" 15 | 16 | result_t vector_set_width(vector_t *v, size_t width) 17 | { 18 | void *newbase; 19 | size_t currsz; 20 | size_t newsz; 21 | 22 | if (width == 0) 23 | return result_BAD_ARG; 24 | 25 | if (width == v->width) 26 | return result_OK; 27 | 28 | currsz = v->allocated * v->width; 29 | newsz = v->used * width; 30 | 31 | /* Squeeze now, before shrinking the block. */ 32 | if (width < v->width) 33 | array_squeeze(v->base, v->used, v->width, width); // 64-bit 34 | 35 | /* Avoid calling realloc for the same size block. */ 36 | if (currsz != newsz) 37 | { 38 | newbase = realloc(v->base, newsz); 39 | if (newbase == NULL) 40 | return result_OOM; 41 | } 42 | else 43 | { 44 | newbase = v->base; 45 | } 46 | 47 | /* Stretch now that the block has been grown. */ 48 | if (width > v->width) 49 | array_stretch(newbase, v->used, v->width, width, 0); // 64-bit 50 | 51 | v->width = width; 52 | /* v->used remains the same */ 53 | v->allocated = v->used; 54 | v->base = newbase; 55 | 56 | return result_OK; 57 | } 58 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/set.c: -------------------------------------------------------------------------------- 1 | /* set.c -- vector - flexible array */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "base/utils.h" 11 | 12 | #include "datastruct/vector.h" 13 | 14 | #include "impl.h" 15 | 16 | void vector_set(vector_t *vector, unsigned int index, const void *value) 17 | { 18 | assert(index < vector->allocated); 19 | 20 | /* Silently ignore requests to assign to non-existent entries. */ 21 | if (index >= vector->allocated) 22 | return; 23 | 24 | memcpy(VECTOR_INDEX(vector, index), value, vector->width); 25 | 26 | /* Set 'used' to indicate the next available slot. */ 27 | vector->used = MAX(vector->used, index + 1); 28 | } 29 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/test/vector-test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #ifdef FORTIFY 5 | #include "fortify/fortify.h" 6 | #endif 7 | 8 | #include "base/result.h" 9 | #include "base/utils.h" 10 | #include "datastruct/vector.h" 11 | 12 | #include "test/all-tests.h" 13 | 14 | #define WIDTH 4 /* bytes */ 15 | 16 | static const unsigned int set_lengths[] = { 25, 50, 75, 100 }; 17 | 18 | static const size_t set_widths[] = { 3, 2, 1, 2, 3, 4 }; 19 | 20 | static const int primes[] = 21 | { 22 | 2, 3, 5, 7, 11, 13, 17, 19, 23 | 23, 29, 31, 37, 41, 43, 47, 53, 24 | 59, 61, 67, 71, 73, 79, 83, 89, 25 | 97, 101, 103, 107, 109, 113, 127 26 | }; 27 | 28 | result_t vector_test(const char *resources) 29 | { 30 | vector_t *v; 31 | int i; 32 | int *p; 33 | 34 | NOT_USED(resources); 35 | 36 | printf("test: create\n"); 37 | 38 | v = vector_create(WIDTH); 39 | if (v == NULL) 40 | goto Failure; 41 | 42 | 43 | printf("test: clear\n"); 44 | 45 | vector_clear(v); 46 | 47 | 48 | printf("test: length\n"); 49 | 50 | printf("length = %zu\n", vector_length(v)); 51 | 52 | 53 | printf("test: set length\n"); 54 | 55 | for (i = 0; i < NELEMS(set_lengths); i++) 56 | { 57 | size_t new_length; 58 | 59 | printf("test: set length to %u\n", set_lengths[i]); 60 | 61 | vector_set_length(v, set_lengths[i]); 62 | 63 | new_length = vector_length(v); 64 | 65 | printf("new length = %zu\n", new_length); 66 | 67 | if (new_length != set_lengths[i]) 68 | { 69 | printf("*** did not resize as expected!\n"); 70 | goto Failure; 71 | } 72 | } 73 | 74 | 75 | printf("test: get / populate with values\n"); 76 | 77 | p = vector_get(v, 0); 78 | for (i = 0; i < NELEMS(primes); i++) 79 | *p++ = primes[i]; 80 | 81 | printf("...populated\n"); 82 | 83 | 84 | printf("test: set width\n"); 85 | 86 | for (i = 0; i < NELEMS(set_widths); i++) 87 | { 88 | size_t new_width; 89 | 90 | printf("test: set width to %zu\n", set_widths[i]); 91 | 92 | vector_set_width(v, set_widths[i]); 93 | 94 | new_width = vector_width(v); 95 | 96 | printf("new width = %zu\n", new_width); 97 | 98 | if (new_width != set_widths[i]) 99 | { 100 | printf("*** did not resize as expected!\n"); 101 | goto Failure; 102 | } 103 | 104 | printf("...resized\n"); 105 | } 106 | 107 | 108 | printf("test: ensure values are intact\n"); 109 | 110 | p = vector_get(v, 0); 111 | for (i = 0; i < NELEMS(primes); i++) 112 | { 113 | if (*p != primes[i]) 114 | { 115 | printf("*** %d ought to be %d at index %d\n", *p, primes[i], i); 116 | goto Failure; 117 | } 118 | 119 | p++; 120 | } 121 | 122 | printf("...yes, they are\n"); 123 | 124 | 125 | 126 | printf("test: destroy\n"); 127 | 128 | vector_destroy(v); 129 | 130 | 131 | return result_TEST_PASSED; 132 | 133 | 134 | Failure: 135 | 136 | return result_TEST_FAILED; 137 | } 138 | -------------------------------------------------------------------------------- /libraries/datastruct/vector/width.c: -------------------------------------------------------------------------------- 1 | /* width.c -- vector - flexible array */ 2 | 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "datastruct/vector.h" 10 | 11 | #include "impl.h" 12 | 13 | size_t vector_width(const vector_t *v) 14 | { 15 | return v->width; 16 | } 17 | -------------------------------------------------------------------------------- /libraries/fortify/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeLists.txt 2 | # 3 | # DPTLib 4 | # 5 | # Copyright (c) David Thomas, 2020-2021 6 | # 7 | # vim: sw=4 ts=8 et 8 | 9 | add_library(Fortify fortify.c) 10 | target_compile_definitions(Fortify PRIVATE FORTIFY) 11 | target_include_directories(Fortify PUBLIC ../../include/) 12 | -------------------------------------------------------------------------------- /libraries/framebuf/bitmap/load.c: -------------------------------------------------------------------------------- 1 | /* load.c */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "base/result.h" 9 | #include "framebuf/bitmap.h" 10 | 11 | static int file_is_png(FILE *fp) 12 | { 13 | #define PNGSIGLEN (8) 14 | unsigned char buf[PNGSIGLEN]; 15 | 16 | if (fseek(fp, 0, SEEK_SET) < 0) 17 | return 0; 18 | 19 | if (fread(buf, 1, PNGSIGLEN, fp) != PNGSIGLEN) 20 | return 0; 21 | 22 | return png_sig_cmp(&buf[0], 0, PNGSIGLEN) == 0; 23 | } 24 | 25 | result_t bitmap_load_png(bitmap_t *bm, const char *filename) 26 | { 27 | result_t rc; 28 | FILE *fp; 29 | png_structp png_ptr = NULL; 30 | png_infop info_ptr; 31 | png_uint_32 pngwidth, pngheight; 32 | int pngbitdepth, pngcolourtype; 33 | unsigned char *pixels = NULL; 34 | png_bytep *row_pointers = NULL; 35 | pixelfmt_t bm_fmt; 36 | int bm_rowbytes; 37 | png_uint_32 h; 38 | 39 | fp = fopen(filename, "rb"); 40 | if (fp == NULL) 41 | { 42 | rc = result_FILE_NOT_FOUND; 43 | goto cleanup; 44 | } 45 | 46 | if (!file_is_png(fp)) 47 | { 48 | rc = result_BAD_ARG; 49 | goto cleanup; 50 | } 51 | 52 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 53 | if (png_ptr == NULL) 54 | { 55 | rc = result_OOM; 56 | goto cleanup; 57 | } 58 | 59 | info_ptr = png_create_info_struct(png_ptr); 60 | if (info_ptr == NULL) 61 | { 62 | rc = result_OOM; 63 | goto cleanup; 64 | } 65 | 66 | if (setjmp(png_jmpbuf(png_ptr))) 67 | { 68 | rc = result_BAD_ARG; 69 | goto cleanup; 70 | } 71 | 72 | png_init_io(png_ptr, fp); 73 | png_set_sig_bytes(png_ptr, PNGSIGLEN); 74 | png_read_info(png_ptr, info_ptr); 75 | png_get_IHDR(png_ptr, info_ptr, 76 | &pngwidth, &pngheight, &pngbitdepth, &pngcolourtype, 77 | NULL, NULL, NULL); 78 | 79 | if (pngbitdepth != 8) 80 | { 81 | rc = result_INCOMPATIBLE; 82 | goto cleanup; 83 | } 84 | 85 | switch (pngcolourtype) 86 | { 87 | case PNG_COLOR_TYPE_RGB: 88 | bm_fmt = pixelfmt_rgbx8888; 89 | png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); 90 | break; 91 | case PNG_COLOR_TYPE_RGBA: 92 | bm_fmt = pixelfmt_rgba8888; 93 | break; 94 | default: 95 | rc = result_INCOMPATIBLE; 96 | goto cleanup; 97 | } 98 | 99 | bm_rowbytes = (pngwidth << pixelfmt_log2bpp(bm_fmt)) >> 3; 100 | 101 | pixels = malloc(bm_rowbytes * pngheight); 102 | if (pixels == NULL) 103 | goto oom; 104 | 105 | row_pointers = malloc(pngheight * sizeof(*row_pointers)); 106 | if (row_pointers == NULL) 107 | goto oom; 108 | 109 | for (h = 0; h < pngheight; h++) 110 | row_pointers[h] = pixels + bm_rowbytes * h; 111 | 112 | png_read_image(png_ptr, row_pointers); 113 | 114 | bitmap_init(bm, 115 | pngwidth, pngheight, 116 | bm_fmt, 117 | bm_rowbytes, 118 | NULL, /* no palette */ 119 | pixels); 120 | 121 | pixels = NULL; /* belongs to bitmap now */ 122 | 123 | rc = result_OK; 124 | goto cleanup; 125 | 126 | oom: 127 | rc = result_OOM; 128 | goto cleanup; 129 | 130 | cleanup: 131 | free(row_pointers); 132 | free(pixels); 133 | if (png_ptr) 134 | png_destroy_read_struct(&png_ptr, NULL, NULL); 135 | fclose(fp); 136 | return rc; 137 | } 138 | 139 | /* vim: set ts=8 sts=2 sw=2 et: */ 140 | -------------------------------------------------------------------------------- /libraries/framebuf/bitmap/save.c: -------------------------------------------------------------------------------- 1 | /* save.c */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "base/result.h" 9 | #include "framebuf/bitmap.h" 10 | 11 | result_t bitmap_save_png(const bitmap_t *bm, const char *filename) 12 | { 13 | #ifdef DPTLIB_IMAGES_READ_ONLY 14 | return result_NOT_SUPPORTED; 15 | #else 16 | result_t rc; 17 | pixelfmt_t fmt; 18 | size_t bytespp; 19 | FILE *fp; 20 | png_structp png_ptr = NULL; 21 | png_infop info_ptr = NULL; 22 | png_bytep outrow = NULL; 23 | pixelfmt_xxxa8888_t *inrow; // more like xxxx8888 24 | int x,y; 25 | 26 | switch (bm->format) 27 | { 28 | case pixelfmt_bgrx8888: 29 | fmt = PNG_COLOR_TYPE_RGB; 30 | bytespp = 3; 31 | break; 32 | case pixelfmt_bgra8888: 33 | fmt = PNG_COLOR_TYPE_RGBA; 34 | bytespp = 4; 35 | break; 36 | default: 37 | return result_NOT_SUPPORTED; 38 | } 39 | 40 | fp = fopen(filename, "wb"); 41 | if (fp == NULL) 42 | { 43 | rc = result_FOPEN_FAILED; 44 | goto cleanup; 45 | } 46 | 47 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 48 | if (png_ptr == NULL) 49 | { 50 | rc = result_OOM; 51 | goto cleanup; 52 | } 53 | 54 | info_ptr = png_create_info_struct(png_ptr); 55 | if (info_ptr == NULL) 56 | { 57 | rc = result_OOM; 58 | goto cleanup; 59 | } 60 | 61 | if (setjmp(png_jmpbuf(png_ptr))) 62 | { 63 | rc = result_BAD_ARG; /* not ideal */ 64 | goto cleanup; 65 | } 66 | 67 | png_init_io(png_ptr, fp); 68 | 69 | png_set_IHDR(png_ptr, info_ptr, 70 | bm->width, bm->height, 71 | 8, 72 | fmt, 73 | PNG_INTERLACE_NONE, 74 | PNG_COMPRESSION_TYPE_DEFAULT, 75 | PNG_FILTER_TYPE_DEFAULT); 76 | 77 | png_write_info(png_ptr, info_ptr); 78 | 79 | // consider: 80 | // png_write_image(png_ptr, row_pointers); 81 | // png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); 82 | // png_set_packing for <8bpp images 83 | 84 | outrow = malloc(bytespp * bm->width * sizeof(png_byte)); 85 | if (outrow == NULL) 86 | { 87 | rc = result_OOM; 88 | goto cleanup; 89 | } 90 | 91 | inrow = bm->base; 92 | 93 | for (y = 0; y < bm->height; y++) 94 | { 95 | png_bytep pout = &outrow[0]; 96 | 97 | switch (bm->format) 98 | { 99 | case pixelfmt_bgrx8888: 100 | for (x = 0; x < bm->width; x++) 101 | { 102 | pixelfmt_xxxa8888_t in = *inrow++; 103 | *pout++ = PIXELFMT_xxRx8888(in); 104 | *pout++ = PIXELFMT_xGxx8888(in); 105 | *pout++ = PIXELFMT_Bxxx8888(in); 106 | } 107 | break; 108 | 109 | case pixelfmt_bgra8888: 110 | for (x = 0; x < bm->width; x++) 111 | { 112 | pixelfmt_xxxa8888_t in = *inrow++; 113 | *pout++ = PIXELFMT_xxRx8888(in); 114 | *pout++ = PIXELFMT_xGxx8888(in); 115 | *pout++ = PIXELFMT_Bxxx8888(in); 116 | *pout++ = PIXELFMT_xxxA8888(in); 117 | } 118 | break; 119 | 120 | default: 121 | assert(0); 122 | } 123 | 124 | png_write_row(png_ptr, outrow); 125 | //inrow += bm->rowbytes / 4; 126 | } 127 | 128 | png_write_end(png_ptr, NULL); 129 | 130 | rc = result_OK; 131 | 132 | cleanup: 133 | fclose(fp); 134 | png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); 135 | png_destroy_write_struct(&png_ptr, NULL); 136 | free(outrow); 137 | 138 | return rc; 139 | #endif /* DPTLIB_IMAGES_READ_ONLY */ 140 | } 141 | 142 | /* vim: set ts=8 sts=2 sw=2 et: */ 143 | -------------------------------------------------------------------------------- /libraries/framebuf/colour/colour.c: -------------------------------------------------------------------------------- 1 | /* colour.c */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "framebuf/pixelfmt.h" 8 | #include "framebuf/colour.h" 9 | 10 | colour_t colour_rgb(int r, int g, int b) 11 | { 12 | return colour_rgba(r, g, b, PIXELFMT_OPAQUE); 13 | } 14 | 15 | colour_t colour_rgba(int r, int g, int b, int a) 16 | { 17 | colour_t c; 18 | 19 | c.primary = PIXELFMT_MAKE_RGBA8888(r, g, b, a); 20 | return c; 21 | } 22 | 23 | static unsigned int closest_palette_entry(const colour_t *palette, 24 | int nentries, 25 | colour_t required) 26 | { 27 | #if 1 28 | /* libjpeg's weights */ 29 | const int red_weight = 19595; /* 0.29900 * 65536 (rounded down) */ 30 | const int green_weight = 38470; /* 0.58700 * 65536 (rounded up) */ 31 | const int blue_weight = 7471; /* 0.11400 * 65536 (rounded down) */ 32 | #else 33 | /* libpng's weights */ 34 | const int red_weight = 13938; /* 0.212671 * 65536 (rounded up) */ 35 | const int green_weight = 46869; /* 0.715160 * 65536 (rounded up) */ 36 | const int blue_weight = 4729; /* 0.072169 * 65536 (rounded down) */ 37 | #endif 38 | 39 | pixelfmt_rgba8888_t req; 40 | int closest; 41 | unsigned int dist; 42 | int req_r, req_g, req_b; 43 | int i; 44 | pixelfmt_rgba8888_t ent; 45 | int ent_r, ent_g, ent_b; 46 | int dr, dg, db; 47 | unsigned int curdist; 48 | 49 | req = required.primary; 50 | req_r = PIXELFMT_Rxxx8888(req); 51 | req_g = PIXELFMT_xGxx8888(req); 52 | req_b = PIXELFMT_xxBx8888(req); 53 | 54 | closest = -1; 55 | dist = INT_MAX; 56 | 57 | for (i = 0; i < nentries; i++) 58 | { 59 | ent = palette[i].primary; 60 | ent_r = PIXELFMT_Rxxx8888(ent); 61 | ent_g = PIXELFMT_xGxx8888(ent); 62 | ent_b = PIXELFMT_xxBx8888(ent); 63 | dr = ent_r - req_r; 64 | dg = ent_g - req_g; 65 | db = ent_b - req_b; 66 | curdist = ((dr * dr) * red_weight + 67 | (dg * dg) * green_weight + 68 | (db * db) * blue_weight) >> 16; 69 | if (curdist < dist) 70 | { 71 | dist = curdist; 72 | closest = i; 73 | } 74 | } 75 | 76 | return closest; 77 | } 78 | 79 | pixelfmt_any_t colour_to_pixel(const colour_t *palette, 80 | int nentries, 81 | colour_t required, 82 | pixelfmt_t fmt) 83 | { 84 | pixelfmt_any_t r,g,b,a; 85 | 86 | switch (fmt) 87 | { 88 | case pixelfmt_p1: 89 | case pixelfmt_p2: 90 | case pixelfmt_p4: 91 | case pixelfmt_p8: 92 | return closest_palette_entry(palette, nentries, required); 93 | 94 | case pixelfmt_rgbx8888: 95 | return (PIXELFMT_OPAQUE << PIXELFMT_xxxA8888_SHIFT) | required.primary; /* ensure opaque */ 96 | 97 | case pixelfmt_rgba8888: 98 | return required.primary; 99 | 100 | case pixelfmt_bgrx8888: 101 | case pixelfmt_bgra8888: 102 | r = PIXELFMT_Rxxx8888(required.primary); 103 | g = PIXELFMT_xGxx8888(required.primary); 104 | b = PIXELFMT_xxBx8888(required.primary); 105 | a = (fmt == pixelfmt_bgra8888) ? PIXELFMT_xxxA8888(required.primary) : PIXELFMT_OPAQUE; 106 | return PIXELFMT_MAKE_BGRA8888(r, g, b, a); 107 | 108 | default: 109 | assert("Unimplemented pixel format" == NULL); 110 | return 0xFFFFFFFF; 111 | } 112 | } 113 | 114 | unsigned int colour_get_alpha(const colour_t *c) 115 | { 116 | return PIXELFMT_xxxA8888(c->primary); 117 | } 118 | -------------------------------------------------------------------------------- /libraries/framebuf/pixelfmt/log2bpp.c: -------------------------------------------------------------------------------- 1 | /* log2bpp.c -- given a pixel format return its log2 bits-per-pixel size */ 2 | 3 | #include 4 | 5 | #include "framebuf/pixelfmt.h" 6 | 7 | int pixelfmt_log2bpp(pixelfmt_t fmt) 8 | { 9 | switch (fmt) 10 | { 11 | case pixelfmt_p1: 12 | return 0; 13 | case pixelfmt_p2: 14 | return 1; 15 | case pixelfmt_p4: 16 | return 2; 17 | case pixelfmt_p8: 18 | case pixelfmt_y8: 19 | return 3; 20 | 21 | case pixelfmt_bgrx4444: 22 | case pixelfmt_rgbx4444: 23 | case pixelfmt_xbgr4444: 24 | case pixelfmt_xrgb4444: 25 | case pixelfmt_bgrx5551: 26 | case pixelfmt_rgbx5551: 27 | case pixelfmt_xbgr1555: 28 | case pixelfmt_xrgb1555: 29 | case pixelfmt_bgr565: 30 | case pixelfmt_rgb565: 31 | return 4; 32 | 33 | case pixelfmt_bgrx8888: 34 | case pixelfmt_rgbx8888: 35 | case pixelfmt_xbgr8888: 36 | case pixelfmt_xrgb8888: 37 | case pixelfmt_bgra8888: 38 | case pixelfmt_rgba8888: 39 | case pixelfmt_abgr8888: 40 | case pixelfmt_argb8888: 41 | return 5; 42 | 43 | default: 44 | assert(0); 45 | return -1; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /libraries/framebuf/screen/screen.c: -------------------------------------------------------------------------------- 1 | /* screen.c */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "framebuf/screen.h" 8 | 9 | void screen_init(screen_t *scr, 10 | int width, 11 | int height, 12 | pixelfmt_t fmt, 13 | int rowbytes, 14 | colour_t *palette, 15 | box_t clip, 16 | void *base) 17 | { 18 | assert(scr); 19 | 20 | scr->width = width; 21 | scr->height = height; 22 | scr->format = fmt; 23 | scr->rowbytes = rowbytes; 24 | scr->palette = palette; 25 | scr->clip = clip; 26 | scr->base = base; 27 | } 28 | 29 | void screen_for_bitmap(screen_t *scr, const bitmap_t *bm) 30 | { 31 | assert(scr); 32 | assert(bm); 33 | 34 | memcpy(scr, bm, offsetof(screen_t, clip)); /* copy common members */ 35 | box_reset(&scr->clip); 36 | scr->base = bm->base; 37 | } 38 | 39 | box_t screen_get_clip(const screen_t *scr) 40 | { 41 | box_t cur; 42 | 43 | cur.x0 = 0; 44 | cur.y0 = 0; 45 | cur.x1 = scr->width; 46 | cur.y1 = scr->height; 47 | 48 | if (box_is_empty(&scr->clip)) 49 | return cur; 50 | 51 | (void) box_intersection(&cur, &scr->clip, &cur); 52 | return cur; 53 | } 54 | -------------------------------------------------------------------------------- /libraries/geom/box/clipped.c: -------------------------------------------------------------------------------- 1 | /* clipped.c -- calculate clipped away edge sizes */ 2 | 3 | #include "base/utils.h" 4 | 5 | #include "geom/box.h" 6 | 7 | void box_clipped(const box_t *a, const box_t *b, box_t *c) 8 | { 9 | c->x0 = MAX(a->x0 - b->x0, 0); 10 | c->y0 = MAX(a->y0 - b->y0, 0); 11 | c->x1 = MAX(b->x1 - a->x1, 0); 12 | c->y1 = MAX(b->y1 - a->y1, 0); 13 | } 14 | -------------------------------------------------------------------------------- /libraries/geom/box/contains-box.c: -------------------------------------------------------------------------------- 1 | /* contains-box.c -- return true if box "inside" is contained by box "outside" */ 2 | 3 | #include "geom/box.h" 4 | 5 | int box_contains_box(const box_t *inner, const box_t *outer) 6 | { 7 | return inner->x0 >= outer->x0 && 8 | inner->y0 >= outer->y0 && 9 | inner->x1 <= outer->x1 && 10 | inner->y1 <= outer->y1; 11 | } 12 | -------------------------------------------------------------------------------- /libraries/geom/box/contains-point.c: -------------------------------------------------------------------------------- 1 | /* contains-point.c -- return true if "box" contains the point (x,y) */ 2 | 3 | #include "base/utils.h" 4 | 5 | #include "geom/box.h" 6 | 7 | int box_contains_point(const box_t *box, int x, int y) 8 | { 9 | return x >= box->x0 && x < box->x1 && 10 | y >= box->y0 && y < box->y1; 11 | } 12 | -------------------------------------------------------------------------------- /libraries/geom/box/could-hold.c: -------------------------------------------------------------------------------- 1 | /* could-hold.c -- return true if "box" can hold a box of size (w,h) */ 2 | 3 | #include "geom/box.h" 4 | 5 | int box_could_hold(const box_t *box, int w, int h) 6 | { 7 | return (box->x1 - box->x0) >= w && 8 | (box->y1 - box->y0) >= h; 9 | } 10 | -------------------------------------------------------------------------------- /libraries/geom/box/grow.c: -------------------------------------------------------------------------------- 1 | /* grow.c -- increases the size of "box" by "change" */ 2 | 3 | #include "geom/box.h" 4 | 5 | void box_grow(box_t *box, int change) 6 | { 7 | box->x0 -= change; 8 | box->y0 -= change; 9 | box->x1 += change; 10 | box->y1 += change; 11 | } 12 | -------------------------------------------------------------------------------- /libraries/geom/box/intersection.c: -------------------------------------------------------------------------------- 1 | /* intersection.c -- compute "c" the result of intersecting boxes "a" and "b" */ 2 | 3 | #include "base/utils.h" 4 | 5 | #include "geom/box.h" 6 | 7 | int box_intersection(const box_t *a, const box_t *b, box_t *c) 8 | { 9 | c->x0 = MAX(a->x0, b->x0); 10 | c->y0 = MAX(a->y0, b->y0); 11 | c->x1 = MIN(a->x1, b->x1); 12 | c->y1 = MIN(a->y1, b->y1); 13 | 14 | return box_is_empty(c); 15 | } 16 | -------------------------------------------------------------------------------- /libraries/geom/box/intersects.c: -------------------------------------------------------------------------------- 1 | /* intersects.c -- return true if box "a" overlaps box "b" */ 2 | 3 | #include "geom/box.h" 4 | 5 | int box_intersects(const box_t *a, const box_t *b) 6 | { 7 | return a->x0 < b->x1 && a->x1 > b->x0 && 8 | a->y0 < b->y1 && a->y1 > b->y0; 9 | } 10 | -------------------------------------------------------------------------------- /libraries/geom/box/is-empty.c: -------------------------------------------------------------------------------- 1 | /* is-empty.c -- return whether the specified box is empty */ 2 | 3 | #include "geom/box.h" 4 | 5 | int box_is_empty(const box_t *box) 6 | { 7 | return (box->x0 >= box->x1) || 8 | (box->y0 >= box->y1); 9 | } 10 | -------------------------------------------------------------------------------- /libraries/geom/box/reset.c: -------------------------------------------------------------------------------- 1 | /* reset.c -- set box 'b' to be invalid */ 2 | 3 | #include 4 | 5 | #include "geom/box.h" 6 | 7 | void box_reset(box_t *b) 8 | { 9 | const box_t invalid = { INT_MAX, INT_MAX, INT_MIN, INT_MIN }; 10 | 11 | *b = invalid; 12 | } 13 | -------------------------------------------------------------------------------- /libraries/geom/box/round.c: -------------------------------------------------------------------------------- 1 | /* round.c -- round a box's coords so they're a multiple of log2 x,y */ 2 | 3 | #include "base/utils.h" 4 | 5 | #include "geom/box.h" 6 | 7 | void box_round(box_t *pb, int log2x, int log2y) 8 | { 9 | const int x = (1 << log2x) - 1; 10 | const int y = (1 << log2y) - 1; 11 | box_t b = *pb; 12 | 13 | b.x0 = (b.x0 ) & ~x; 14 | b.y0 = (b.y0 ) & ~y; 15 | b.x1 = (b.x1 + x) & ~x; 16 | b.y1 = (b.y1 + y) & ~y; 17 | 18 | *pb = b; 19 | } 20 | -------------------------------------------------------------------------------- /libraries/geom/box/round4.c: -------------------------------------------------------------------------------- 1 | /* round4.c -- round a box's coords so they're a multiple of 4 */ 2 | 3 | #include "geom/box.h" 4 | 5 | void box_round4(box_t *box) 6 | { 7 | box_t b = *box; 8 | 9 | b.x0 = (b.x0 ) & ~3; 10 | b.y0 = (b.y0 ) & ~3; 11 | b.x1 = (b.x1 + 3) & ~3; 12 | b.y1 = (b.y1 + 3) & ~3; 13 | 14 | *box = b; 15 | } 16 | -------------------------------------------------------------------------------- /libraries/geom/box/test/box-test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "base/types.h" 7 | #include "base/utils.h" 8 | #include "geom/box.h" 9 | 10 | #include "geom/box.h" 11 | 12 | #include "test/all-tests.h" 13 | 14 | static int boxeq(const box_t *a, const box_t *b) 15 | { 16 | return a->x0 == b->x0 && a->y0 == b->y0 && 17 | a->x1 == b->x1 && a->y1 == b->y1; 18 | } 19 | 20 | static result_t test_reset_empty(void) 21 | { 22 | box_t reset; 23 | 24 | box_reset(&reset); 25 | return box_is_empty(&reset) ? result_TEST_PASSED : result_TEST_FAILED; 26 | } 27 | 28 | static result_t test_contains_box(void) 29 | { 30 | static const box_t outer = { 10, 10, 12, 12 }; // 2x2 box 31 | static const box_t contained = { 10, 10, 11, 11 }; // 1x1 box 32 | static const box_t not_contained = { 10, 10, 11, 13 }; // 1x3 box 33 | 34 | if (!box_contains_box(&outer, &outer)) 35 | return result_TEST_FAILED; 36 | 37 | if (!box_contains_box(&contained, &outer)) 38 | return result_TEST_FAILED; 39 | 40 | if (box_contains_box(¬_contained, &outer)) 41 | return result_TEST_FAILED; 42 | 43 | return result_TEST_PASSED; 44 | } 45 | 46 | static result_t test_contains_point(void) 47 | { 48 | typedef struct { int x,y; } point_t; 49 | 50 | static const box_t b = { 10, 10, 12, 12 }; // 2x2 box 51 | static const point_t goodpoints[] = { {10,10}, {11,11} }; 52 | static const point_t badpoints[] = { {9,9}, {12,12} }; 53 | 54 | size_t i; 55 | 56 | for (i = 0; i < NELEMS(goodpoints); i++) 57 | if (!box_contains_point(&b, goodpoints[i].x, goodpoints[i].y)) 58 | { 59 | printf("box_contains_point() failed good point #%zu\n", i); 60 | return result_TEST_FAILED; 61 | } 62 | 63 | for (i = 0; i < NELEMS(badpoints); i++) 64 | if (box_contains_point(&b, badpoints[i].x, badpoints[i].y)) 65 | { 66 | printf("box_contains_point() failed bad point #%zu\n", i); 67 | return result_TEST_FAILED; 68 | } 69 | 70 | return result_TEST_PASSED; 71 | } 72 | 73 | static result_t test_translated(void) 74 | { 75 | static const box_t initial = { 10, 20, 30, 40 }; 76 | static const box_t expected = { 13, 25, 33, 45 }; 77 | 78 | box_t translated; 79 | 80 | box_translated(&initial, 0, 0, &translated); 81 | if (!boxeq(&translated, &initial)) 82 | return result_TEST_FAILED; 83 | 84 | box_translated(&initial, 3, 5, &translated); 85 | if (!boxeq(&translated, &expected)) 86 | return result_TEST_FAILED; 87 | 88 | return result_TEST_PASSED; 89 | } 90 | 91 | result_t box_test(const char *resources) 92 | { 93 | typedef result_t (*boxtestfn)(void); 94 | 95 | static const boxtestfn tests[] = 96 | { 97 | test_reset_empty, 98 | test_contains_box, 99 | test_contains_point, 100 | test_translated 101 | }; 102 | 103 | result_t rc; 104 | size_t i; 105 | int nfailures; 106 | 107 | NOT_USED(resources); 108 | 109 | nfailures = 0; 110 | for (i = 0; i < NELEMS(tests); i++) 111 | { 112 | rc = tests[i](); 113 | if (rc != result_TEST_PASSED) 114 | nfailures++; 115 | } 116 | 117 | return (nfailures == 0) ? result_TEST_PASSED : result_TEST_FAILED; 118 | } 119 | -------------------------------------------------------------------------------- /libraries/geom/box/translated.c: -------------------------------------------------------------------------------- 1 | /* translated.c -- translate box "b" by (x,y) producing new box "t" */ 2 | 3 | #include "base/utils.h" 4 | 5 | #include "geom/box.h" 6 | 7 | void box_translated(const box_t *b, int x, int y, box_t *t) 8 | { 9 | t->x0 = b->x0 + x; 10 | t->y0 = b->y0 + y; 11 | t->x1 = b->x1 + x; 12 | t->y1 = b->y1 + y; 13 | } 14 | -------------------------------------------------------------------------------- /libraries/geom/box/union.c: -------------------------------------------------------------------------------- 1 | /* union.c -- return a box "c" that contains both boxes "a" and "b" */ 2 | 3 | #include "base/utils.h" 4 | 5 | #include "geom/box.h" 6 | 7 | void box_union(const box_t *a, const box_t *b, box_t *c) 8 | { 9 | c->x0 = MIN(a->x0, b->x0); 10 | c->y0 = MIN(a->y0, b->y0); 11 | c->x1 = MAX(a->x1, b->x1); 12 | c->y1 = MAX(a->y1, b->y1); 13 | } 14 | -------------------------------------------------------------------------------- /libraries/geom/layout/test/layout-test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "base/utils.h" 7 | #include "geom/box.h" 8 | #include "test/txtscr.h" 9 | 10 | #include "geom/layout.h" 11 | 12 | #include "test/all-tests.h" 13 | 14 | result_t layout_test(const char *resources) 15 | { 16 | static const box_t dims = { 0, 0, 8, 8 }; 17 | static const layout_element_t elements[] = 18 | { 19 | { layout_BOX, { .box = { 2, 2, 2 } } }, 20 | { layout_BOX, { .box = { 2, 2, 2 } } }, 21 | { layout_BOX, { .box = { 1, INT_MAX, 2 } } }, 22 | }; 23 | 24 | result_t err; 25 | packer_t *packer; 26 | layout_spec_t spec; 27 | box_t boxes[3]; 28 | int i; 29 | box_t used; 30 | txtscr_t *scr; 31 | 32 | NOT_USED(resources); 33 | 34 | packer = packer_create(&dims); 35 | if (packer == NULL) 36 | goto failure; 37 | 38 | spec.packer = packer; 39 | spec.loc = packer_LOC_TOP_LEFT; 40 | spec.clear = packer_CLEAR_LEFT; 41 | spec.spacing = 2; 42 | spec.leading = 2; 43 | 44 | err = layout_place(&spec, 45 | elements, 46 | NELEMS(elements), 47 | boxes, 48 | NELEMS(boxes)); 49 | if (err) 50 | goto failure; 51 | 52 | used = *packer_get_consumed_area(packer); 53 | 54 | printf("layout_test: consumed: <%d,%d-%d,%d>\n", used.x0, used.y0, used.x1, used.y1); 55 | 56 | packer_destroy(packer); 57 | 58 | scr = txtscr_create(8, 8); 59 | if (scr == NULL) 60 | goto failure; 61 | 62 | txtscr_clear(scr); 63 | 64 | for (i = 0; i < NELEMS(boxes); i++) 65 | txtscr_addbox(scr, &boxes[i]); 66 | 67 | txtscr_print(scr); 68 | 69 | txtscr_destroy(scr); 70 | 71 | return result_TEST_PASSED; 72 | 73 | 74 | failure: 75 | 76 | return result_TEST_FAILED; 77 | } 78 | -------------------------------------------------------------------------------- /libraries/geom/packer/impl.h: -------------------------------------------------------------------------------- 1 | /* impl.h -- box packing for layout */ 2 | 3 | #ifndef IMPL_H 4 | #define IMPL_H 5 | 6 | #include "geom/packer.h" 7 | 8 | typedef enum packer_sortdir 9 | { 10 | packer_SORT_TOP_LEFT, 11 | packer_SORT_TOP_RIGHT, 12 | packer_SORT_BOTTOM_LEFT, 13 | packer_SORT_BOTTOM_RIGHT, 14 | packer_SORT__LIMIT, 15 | } 16 | packer_sortdir_t; 17 | 18 | struct packer 19 | { 20 | box_t *areas; 21 | int allocedareas; 22 | int usedareas; 23 | 24 | box_t dims; /* page size */ 25 | 26 | box_t margins; /* page size minus margins (but not the 27 | margins themselves) */ 28 | 29 | int nextindex; 30 | box_t nextarea; /* area returned by packer_next */ 31 | 32 | box_t placed_area; /* last packer_place_by result */ 33 | 34 | packer_sortdir_t order; /* order to which we have sorted */ 35 | int sorted; // bool 36 | 37 | box_t consumed_area; /* total consumed area */ 38 | }; 39 | 40 | #endif /* IMPL_H */ 41 | -------------------------------------------------------------------------------- /libraries/io/path/path.c: -------------------------------------------------------------------------------- 1 | /* path.c */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "io/path.h" 9 | 10 | const char *path_join_leafname(const char *leaf, const char *ext) 11 | { 12 | static char buf[DPTLIB_MAXPATH]; 13 | 14 | const char *fmt = 15 | #ifdef __riscos 16 | "%s/%s"; 17 | #else 18 | "%s.%s"; 19 | #endif 20 | 21 | assert(leaf); 22 | assert(ext); 23 | 24 | snprintf(buf, sizeof(buf), fmt, leaf, ext); 25 | 26 | return buf; 27 | } 28 | 29 | const char *path_join_filename(const char *root, int nbranches, ...) 30 | { 31 | static char buf[DPTLIB_MAXPATH]; 32 | 33 | const char *sep = 34 | #ifdef __riscos 35 | "."; 36 | #else 37 | "/"; 38 | #endif 39 | va_list args; 40 | 41 | assert(root); 42 | assert(nbranches < 1000); 43 | 44 | va_start(args, nbranches); 45 | strncpy(buf, root, sizeof(buf)); 46 | while (nbranches--) 47 | { 48 | strcat(buf, sep); 49 | strcat(buf, va_arg(args, const char *)); 50 | } 51 | va_end(args); 52 | 53 | return buf; 54 | } 55 | -------------------------------------------------------------------------------- /libraries/io/stream/stream-mem.c: -------------------------------------------------------------------------------- 1 | /* stream-mem.c -- memory block IO stream implementation */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "base/result.h" 9 | #include "base/utils.h" 10 | 11 | #include "io/stream.h" 12 | 13 | #include "io/stream-mem.h" 14 | 15 | typedef struct stream_mem 16 | { 17 | stream_t base; 18 | 19 | const unsigned char *block; 20 | stream_size_t length; 21 | } 22 | stream_mem_t; 23 | 24 | static result_t stream_mem_seek(stream_t *s, stream_size_t pos) 25 | { 26 | stream_mem_t *sm = (stream_mem_t *) s; 27 | 28 | if (pos > sm->length) /* allow seeks equal to file length (to EOF) */ 29 | return result_STREAM_BAD_SEEK; 30 | 31 | sm->base.buf = sm->block + pos; 32 | 33 | return result_OK; 34 | } 35 | 36 | static int stream_mem_get(stream_t *s) 37 | { 38 | stream_mem_t *sm = (stream_mem_t *) s; 39 | 40 | NOT_USED(sm); /* only used in debug builds */ 41 | 42 | /* are we only called when buffer empty? */ 43 | assert(sm->base.buf == sm->base.end); 44 | 45 | return EOF; 46 | } 47 | 48 | static stream_size_t stream_mem_fill(stream_t *s) 49 | { 50 | return stream_remaining(s); /* no refill */ 51 | } 52 | 53 | static stream_size_t stream_mem_length(stream_t *s) 54 | { 55 | stream_mem_t *sm = (stream_mem_t *) s; 56 | 57 | return sm->length; 58 | } 59 | 60 | result_t stream_mem_create(const unsigned char *block, 61 | stream_size_t length, 62 | stream_t **s) 63 | { 64 | stream_mem_t *sm; 65 | 66 | assert(block); 67 | 68 | sm = malloc(sizeof(*sm)); 69 | if (!sm) 70 | return result_OOM; 71 | 72 | sm->base.buf = block; 73 | sm->base.end = block + length; 74 | 75 | sm->base.last = result_OK; 76 | 77 | sm->base.op = NULL; 78 | sm->base.seek = stream_mem_seek; 79 | sm->base.get = stream_mem_get; 80 | sm->base.fill = stream_mem_fill; 81 | sm->base.length = stream_mem_length; 82 | sm->base.destroy = NULL; 83 | 84 | sm->block = block; 85 | sm->length = length; 86 | 87 | *s = &sm->base; 88 | 89 | return result_OK; 90 | } 91 | -------------------------------------------------------------------------------- /libraries/io/stream/stream-stdio.c: -------------------------------------------------------------------------------- 1 | /* stream-stdio.c -- C standard IO stream implementation */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "base/result.h" 10 | 11 | #include "io/stream.h" 12 | 13 | #include "io/stream-stdio.h" 14 | 15 | typedef struct stream_file 16 | { 17 | stream_t base; 18 | FILE *file; 19 | stream_size_t length; 20 | 21 | stream_size_t bufsz; 22 | unsigned char buffer[1]; /* flexible final member */ 23 | } 24 | stream_file_t; 25 | 26 | static result_t stream_stdio_seek(stream_t *s, stream_size_t pos) 27 | { 28 | stream_file_t *sf = (stream_file_t *) s; 29 | 30 | fseek(sf->file, pos, SEEK_SET); 31 | 32 | sf->base.buf = sf->base.end; /* force a re-fill */ 33 | 34 | return result_OK; 35 | } 36 | 37 | /* ensure we have at least one byte in the buffer. return it, or EOF. */ 38 | static int stream_stdio_get(stream_t *s) 39 | { 40 | stream_file_t *sf = (stream_file_t *) s; 41 | size_t remaining = stream_remaining(s); 42 | 43 | if (remaining == 0) 44 | { 45 | size_t read; 46 | 47 | read = fread(sf->buffer, 1, sf->bufsz, sf->file); 48 | if (read == 0 && feof(sf->file)) 49 | return EOF; 50 | 51 | sf->base.buf = sf->buffer; 52 | sf->base.end = sf->buffer + read; 53 | } 54 | 55 | return *sf->base.buf++; 56 | } 57 | 58 | static stream_size_t stream_stdio_fill(stream_t *s) 59 | { 60 | stream_file_t *sf = (stream_file_t *) s; 61 | size_t remaining = stream_remaining(s); 62 | size_t read; 63 | 64 | if (remaining >= sf->bufsz) 65 | return remaining; /* buffer already full */ 66 | 67 | /* shift any remaining bytes to the start of the buffer */ 68 | if (remaining) 69 | memmove(sf->buffer, sf->base.buf, remaining); 70 | 71 | /* try to fill the buffer */ 72 | read = fread(sf->buffer + remaining, 1, sf->bufsz - remaining, sf->file); 73 | if (read == 0 && feof(sf->file)) 74 | return stream_EOF; /* encountered EOF but bytes may remain! */ 75 | 76 | sf->base.buf = sf->buffer; 77 | sf->base.end = sf->buffer + remaining + read; 78 | 79 | return stream_remaining(s); /* success */ 80 | } 81 | 82 | static stream_size_t stream_stdio_length_quick(stream_t *s) 83 | { 84 | stream_file_t *sf = (stream_file_t *) s; 85 | 86 | return (int) sf->length; 87 | } 88 | 89 | static stream_size_t stream_stdio_length(stream_t *s) 90 | { 91 | stream_file_t *sf = (stream_file_t *) s; 92 | long int pos; 93 | 94 | /* cache the file's length */ 95 | 96 | pos = ftell(sf->file); 97 | fseek(sf->file, 0, SEEK_END); 98 | sf->length = ftell(sf->file); 99 | fseek(sf->file, pos, SEEK_SET); 100 | 101 | sf->base.length = stream_stdio_length_quick; 102 | 103 | return (int) sf->length; 104 | } 105 | 106 | static void stream_stdio_destroy(stream_t *doomed) 107 | { 108 | stream_file_t *sf = (stream_file_t *) doomed; 109 | 110 | fclose(sf->file); 111 | } 112 | 113 | result_t stream_stdio_create(FILE *f, int bufsz, stream_t **s) 114 | { 115 | stream_file_t *sf; 116 | 117 | if (bufsz <= 0) 118 | bufsz = 128; 119 | 120 | assert(f); 121 | 122 | sf = malloc(offsetof(stream_file_t, buffer) + bufsz); 123 | if (!sf) 124 | return result_OOM; 125 | 126 | sf->base.buf = 127 | sf->base.end = sf->buffer; /* force a fill on first use */ 128 | 129 | sf->base.last = result_OK; 130 | 131 | sf->base.op = NULL; 132 | sf->base.seek = stream_stdio_seek; 133 | sf->base.get = stream_stdio_get; 134 | sf->base.fill = stream_stdio_fill; 135 | sf->base.length = stream_stdio_length; 136 | sf->base.destroy = stream_stdio_destroy; 137 | 138 | sf->file = f; 139 | sf->length = 0; 140 | sf->bufsz = bufsz; 141 | 142 | *s = &sf->base; 143 | 144 | return result_OK; 145 | } 146 | -------------------------------------------------------------------------------- /libraries/io/stream/stream.c: -------------------------------------------------------------------------------- 1 | /* stream.c -- stream system support functions */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef FORTIFY 8 | #include "fortify/fortify.h" 9 | #endif 10 | 11 | #include "base/result.h" 12 | 13 | #include "io/stream.h" 14 | 15 | result_t stream_op(stream_t *s, stream_opcode_t opcode, void *opaque) 16 | { 17 | if (!s->op) 18 | return result_STREAM_UNKNOWN_OP; 19 | 20 | return s->op(s, opcode, opaque); 21 | } 22 | 23 | result_t stream_seek(stream_t *s, stream_size_t pos) 24 | { 25 | if (!s->seek) 26 | return result_STREAM_CANT_SEEK; 27 | 28 | return s->seek(s, pos); 29 | } 30 | 31 | int stream_get(stream_t *s) 32 | { 33 | if (stream_remaining(s) < 1) 34 | if (s->fill(s) == 0) 35 | return EOF; 36 | 37 | return *s->buf++; 38 | } 39 | 40 | stream_size_t stream_fill(stream_t *s) 41 | { 42 | if (!s->fill) 43 | return 0; 44 | 45 | return s->fill(s); 46 | } 47 | 48 | stream_size_t stream_length(stream_t *s) 49 | { 50 | if (!s->length) 51 | return 0; 52 | 53 | return s->length(s); 54 | } 55 | 56 | void stream_destroy(stream_t *doomed) 57 | { 58 | if (!doomed) 59 | return; 60 | 61 | if (doomed->destroy) 62 | doomed->destroy(doomed); 63 | 64 | free(doomed); 65 | } 66 | -------------------------------------------------------------------------------- /libraries/test/txtscr/txtscr.c: -------------------------------------------------------------------------------- 1 | /* txtscr.c -- text format 'screen' */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef FORTIFY 8 | #include "fortify/fortify.h" 9 | #endif 10 | 11 | #include "geom/box.h" 12 | 13 | #include "test/txtscr.h" 14 | 15 | struct txtscr 16 | { 17 | int width, height; 18 | unsigned char *screen; 19 | }; 20 | 21 | txtscr_t *txtscr_create(int width, int height) 22 | { 23 | txtscr_t *scr; 24 | 25 | scr = malloc(sizeof(*scr)); 26 | if (scr == NULL) 27 | return NULL; 28 | 29 | scr->screen = malloc(width * height * sizeof(*scr->screen)); 30 | if (scr->screen == NULL) 31 | { 32 | free(scr); 33 | return NULL; 34 | } 35 | 36 | scr->width = width; 37 | scr->height = height; 38 | 39 | return scr; 40 | } 41 | 42 | void txtscr_destroy(txtscr_t *doomed) 43 | { 44 | if (!doomed) 45 | return; 46 | 47 | free(doomed->screen); 48 | free(doomed); 49 | } 50 | 51 | void txtscr_clear(txtscr_t *scr) 52 | { 53 | memset(scr->screen, 0, scr->width * scr->height * sizeof(*scr->screen)); 54 | } 55 | 56 | /* adds to the pixels, rather than overwriting */ 57 | void txtscr_addbox(txtscr_t *scr, const box_t *box) 58 | { 59 | int x, y; 60 | 61 | for (y = box->y0; y < box->y1; y++) 62 | for (x = box->x0; x < box->x1; x++) 63 | scr->screen[y * scr->width + x]++; 64 | } 65 | 66 | void txtscr_print(txtscr_t *scr) 67 | { 68 | static const char map[] = ".123456789ABCDEF"; 69 | 70 | int x, y; 71 | 72 | for (y = scr->height - 1; y >= 0; y--) 73 | { 74 | for (x = 0; x < scr->width; x++) 75 | { 76 | unsigned int c; 77 | 78 | c = scr->screen[y * scr->width + x]; 79 | c = (c >= sizeof(map) - 1) ? '?' : map[c]; 80 | 81 | printf("%c", c); 82 | } 83 | printf("\n"); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /libraries/utils/array/delelem.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "utils/array.h" 6 | 7 | void array_delete_element(void *array, 8 | size_t elemsize, 9 | int nelems, 10 | int doomed) 11 | { 12 | /* alternative: 13 | array_delete_elements(array, elemsize, nelems, doomed, doomed); */ 14 | 15 | size_t n; 16 | char *to; 17 | char *from; 18 | 19 | n = nelems - (doomed + 1); 20 | if (n == 0) 21 | return; 22 | 23 | to = (char *) array + elemsize * doomed; 24 | from = (char *) array + elemsize * (doomed + 1); 25 | 26 | memmove(to, from, n * elemsize); 27 | } 28 | -------------------------------------------------------------------------------- /libraries/utils/array/delelems.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "utils/array.h" 6 | 7 | void array_delete_elements(void *array, 8 | size_t elemsize, 9 | int nelems, 10 | int first_doomed, 11 | int last_doomed) 12 | { 13 | size_t n; 14 | char *to; 15 | char *from; 16 | 17 | n = nelems - (last_doomed + 1); 18 | if (n == 0) 19 | return; 20 | 21 | to = (char *) array + elemsize * first_doomed; 22 | from = (char *) array + elemsize * (last_doomed + 1); 23 | 24 | memmove(to, from, n * elemsize); 25 | } 26 | -------------------------------------------------------------------------------- /libraries/utils/array/grow.c: -------------------------------------------------------------------------------- 1 | /* grow.c -- grow an array */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "utils/array.h" 11 | #include "utils/barith.h" 12 | 13 | /* used, need, minimum - specified as number of elements (not bytes) */ 14 | int array_grow(void **pblock, 15 | size_t elemsize, 16 | int used, 17 | int *pallocated, 18 | int need, 19 | int minimum) 20 | { 21 | int to_allocate; 22 | void *block; 23 | 24 | assert(pblock); 25 | assert(elemsize > 0); 26 | assert(used >= 0); 27 | assert(pallocated); 28 | assert(need > 0); 29 | assert(minimum > 0); 30 | 31 | need += used; 32 | 33 | if (need < minimum) 34 | need = minimum; 35 | 36 | if (need <= *pallocated) 37 | return 0; /* block has enough spare space */ 38 | 39 | /* Rounding up to the next largest power of two strategy. */ 40 | to_allocate = power2gt(need - 1); /* subtract 1 to make greater or equal */ 41 | 42 | block = realloc(*pblock, elemsize * to_allocate); 43 | if (block == NULL) 44 | return 1; /* out of memory */ 45 | 46 | *pblock = block; 47 | *pallocated = to_allocate; 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /libraries/utils/array/shrink.c: -------------------------------------------------------------------------------- 1 | /* shrink.c -- shrink wrap an array */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "utils/array.h" 11 | 12 | int array_shrink(void **pblock, 13 | size_t elemsize, 14 | int used, 15 | int *pallocated) 16 | { 17 | void *block; 18 | 19 | assert(pblock); 20 | assert(elemsize > 0); 21 | assert(used > 0); 22 | assert(pallocated); 23 | 24 | block = realloc(*pblock, elemsize * used); 25 | if (block == NULL) 26 | return 1; /* out of memory */ 27 | 28 | *pblock = block; 29 | *pallocated = used; 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /libraries/utils/array/squeeze.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "utils/array.h" 6 | 7 | /* walk forwards, skip first element */ 8 | void array_squeeze1(unsigned char *base, 9 | int nelems, 10 | size_t oldwidth, 11 | size_t newwidth) 12 | { 13 | int i; 14 | 15 | assert(oldwidth > newwidth); 16 | 17 | for (i = 1; i < nelems; i++) 18 | memmove(base + i * newwidth, base + i * oldwidth, newwidth); 19 | } 20 | 21 | void array_squeeze2(unsigned char *base, 22 | int nelems, 23 | size_t oldwidth, 24 | size_t newwidth) 25 | { 26 | unsigned char *end; 27 | unsigned char *p, *q; 28 | 29 | assert(oldwidth > newwidth); 30 | 31 | end = base + nelems * oldwidth; 32 | 33 | p = base + 1 * oldwidth; 34 | q = base + 1 * newwidth; 35 | 36 | while (p < end) 37 | { 38 | memmove(q, p, newwidth); 39 | 40 | p += oldwidth; 41 | q += newwidth; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /libraries/utils/array/stretch.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "utils/array.h" 6 | 7 | /* Periodically wipe regions within the specified block. */ 8 | static void array_memset_stride(unsigned char *base, 9 | int nelems, 10 | size_t width, 11 | size_t stride, 12 | int value) 13 | { 14 | /* for certain values the alignment of base is predictable so that would 15 | * could conceivably move out of memset if it proves to be an overhead */ 16 | 17 | /* e.g. if base is aligned to 4 and width is also 4 then we could just 18 | * rattle through memory stashing whole words */ 19 | 20 | while (nelems--) 21 | { 22 | memset(base, value, width); 23 | base += stride; 24 | } 25 | } 26 | 27 | /* 28 | * |A| -> |AB| -> |A | 29 | * |B| |CD| |B | 30 | * |C| | | |C | 31 | * |D| | | |D | 32 | */ 33 | 34 | /* walk backwards, skip last element */ 35 | void array_stretch1(unsigned char *base, 36 | int nelems, 37 | size_t oldwidth, 38 | size_t newwidth, 39 | int wipe_value) 40 | { 41 | int i; 42 | 43 | assert(oldwidth < newwidth); 44 | 45 | for (i = nelems - 1; i > 0; i--) 46 | memmove(base + i * newwidth, base + i * oldwidth, oldwidth); 47 | 48 | array_memset_stride(base + oldwidth, 49 | nelems, 50 | newwidth - oldwidth, 51 | newwidth, 52 | wipe_value); 53 | } 54 | 55 | void array_stretch2(unsigned char *base, 56 | int nelems, 57 | size_t oldwidth, 58 | size_t newwidth, 59 | int wipe_value) 60 | { 61 | unsigned char *p, *q; 62 | 63 | assert(oldwidth < newwidth); 64 | 65 | p = base + (nelems - 1) * oldwidth; 66 | q = base + (nelems - 1) * newwidth; 67 | 68 | while (p > base) 69 | { 70 | memmove(q, p, oldwidth); 71 | 72 | p -= oldwidth; 73 | q -= newwidth; 74 | } 75 | 76 | array_memset_stride(base + oldwidth, 77 | nelems, 78 | newwidth - oldwidth, 79 | newwidth, 80 | wipe_value); 81 | } 82 | -------------------------------------------------------------------------------- /libraries/utils/array/test/array-test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #ifdef FORTIFY 6 | #include "fortify/fortify.h" 7 | #endif 8 | 9 | #include "base/result.h" 10 | #include "base/utils.h" 11 | 12 | #include "utils/array.h" 13 | 14 | #include "test/all-tests.h" 15 | 16 | result_t array_test(const char *resources) 17 | { 18 | int delelem1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 19 | int delelem2[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 20 | 21 | union 22 | { 23 | int i[9]; 24 | char c[9 * sizeof(int)]; 25 | } 26 | sqz1 = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 } }; 27 | 28 | union 29 | { 30 | int i[9]; 31 | char c[9 * sizeof(int)]; 32 | } 33 | sqz2 = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 } }; 34 | 35 | union 36 | { 37 | char c[9 * sizeof(int)]; 38 | int i[9]; 39 | } 40 | str1 = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 } }; 41 | 42 | union 43 | { 44 | char c[9 * sizeof(int)]; 45 | int i[9]; 46 | } 47 | str2 = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 } }; 48 | 49 | int t; 50 | int i; 51 | 52 | NOT_USED(resources); 53 | 54 | 55 | printf("test: delete element\n"); 56 | 57 | array_delete_element(delelem1, 58 | sizeof(delelem1[0]), 59 | NELEMS(delelem1), 60 | 4); 61 | 62 | t = 0; 63 | for (i = 0; i < 9 - 1; i++) 64 | t += delelem1[i]; 65 | 66 | if (t != 1 + 2 + 3 + 4 + 6 + 7 + 8 + 9) 67 | { 68 | printf("unexpected checksum\n"); 69 | goto Failure; 70 | } 71 | 72 | 73 | printf("test: delete elements\n"); 74 | 75 | array_delete_elements(delelem2, 76 | sizeof(delelem2[0]), 77 | NELEMS(delelem2), 78 | 3, 5 /* inclusive */); 79 | 80 | t = 0; 81 | for (i = 0; i < 9 - 3; i++) 82 | t += delelem2[i]; 83 | 84 | if (t != 1 + 2 + 3 + 7 + 8 + 9) 85 | { 86 | printf("unexpected checksum\n"); 87 | goto Failure; 88 | } 89 | 90 | 91 | printf("test: squeeze elements\n"); 92 | 93 | array_squeeze1((unsigned char *) &sqz1.i, 9, sizeof(int), sizeof(char)); 94 | 95 | t = 0; 96 | for (i = 0; i < 9; i++) 97 | t += sqz1.c[i]; 98 | 99 | if (t != 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) 100 | { 101 | printf("unexpected checksum %d\n", t); 102 | goto Failure; 103 | } 104 | 105 | 106 | printf("test: squeeze elements variant 2\n"); 107 | 108 | array_squeeze2((unsigned char *) &sqz2.i, 9, sizeof(int), sizeof(char)); 109 | 110 | t = 0; 111 | for (i = 0; i < 9; i++) 112 | t += sqz2.c[i]; 113 | 114 | if (t != 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) 115 | { 116 | printf("unexpected checksum %d\n", t); 117 | goto Failure; 118 | } 119 | 120 | 121 | printf("test: stretch elements\n"); 122 | 123 | array_stretch1((unsigned char *) &str1.c, 9, sizeof(char), sizeof(int), 0); 124 | 125 | t = 0; 126 | for (i = 0; i < 9; i++) 127 | t += str1.i[i]; 128 | 129 | if (t != 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) 130 | { 131 | printf("unexpected checksum %d\n", t); 132 | goto Failure; 133 | } 134 | 135 | 136 | printf("test: stretch elements variant 2\n"); 137 | 138 | array_stretch2((unsigned char *) &str2.c, 9, sizeof(char), sizeof(int), 0); 139 | 140 | t = 0; 141 | for (i = 0; i < 9; i++) 142 | t += str2.i[i]; 143 | 144 | if (t != 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) 145 | { 146 | printf("unexpected checksum %d\n", t); 147 | goto Failure; 148 | } 149 | 150 | 151 | return result_TEST_PASSED; 152 | 153 | 154 | Failure: 155 | 156 | return result_TEST_FAILED; 157 | } 158 | -------------------------------------------------------------------------------- /libraries/utils/barith/barith.c: -------------------------------------------------------------------------------- 1 | /* barith.c -- define all of barith */ 2 | 3 | #define BARITH_INLINE 4 | 5 | #include "utils/barith.h" 6 | -------------------------------------------------------------------------------- /libraries/utils/bsearch/bsearch-impl.h: -------------------------------------------------------------------------------- 1 | /* bsearch-impl.h -- binary searching arrays */ 2 | 3 | #if !defined(TYPE) || !defined(NAME) 4 | #error TYPE and NAME must be defined. 5 | #endif 6 | 7 | #include 8 | #include 9 | 10 | #include "utils/barith.h" 11 | 12 | #include "utils/bsearch.h" 13 | 14 | int NAME(const TYPE *array, unsigned int nelems, size_t stride, TYPE want) 15 | { 16 | unsigned int searchRange; 17 | unsigned int i; 18 | TYPE c; 19 | 20 | assert(stride > 0); 21 | 22 | if (nelems == 0) 23 | return -1; 24 | 25 | assert(array != NULL); 26 | 27 | stride /= sizeof(*array); 28 | 29 | searchRange = power2le(nelems); 30 | 31 | i = searchRange - 1; 32 | if (want > array[i * stride]) 33 | i = nelems - searchRange; /* rangeShift */ 34 | 35 | do 36 | { 37 | searchRange >>= 1; 38 | 39 | c = array[i * stride]; 40 | 41 | if (want < c) 42 | i -= searchRange; 43 | else if (want > c) 44 | i += searchRange; 45 | else 46 | break; 47 | } 48 | while (searchRange != 0); 49 | 50 | if (want == c) 51 | { 52 | assert(i < nelems); 53 | return i; 54 | } 55 | 56 | return -1; 57 | } 58 | -------------------------------------------------------------------------------- /libraries/utils/bsearch/bsearch-int.c: -------------------------------------------------------------------------------- 1 | /* bsearch-int.c -- binary searching arrays */ 2 | 3 | #define TYPE int 4 | #define NAME bsearch_int 5 | 6 | #include "bsearch-impl.h" 7 | -------------------------------------------------------------------------------- /libraries/utils/bsearch/bsearch-short.c: -------------------------------------------------------------------------------- 1 | /* bsearch-short.c -- binary searching arrays */ 2 | 3 | #define TYPE short 4 | #define NAME bsearch_short 5 | 6 | #include "bsearch-impl.h" 7 | -------------------------------------------------------------------------------- /libraries/utils/bsearch/bsearch-uint.c: -------------------------------------------------------------------------------- 1 | /* bsearch-uint.c -- binary searching arrays */ 2 | 3 | #define TYPE unsigned int 4 | #define NAME bsearch_uint 5 | 6 | #include "bsearch-impl.h" 7 | -------------------------------------------------------------------------------- /libraries/utils/bsearch/bsearch-ushort.c: -------------------------------------------------------------------------------- 1 | /* bsearch-ushort.c -- binary searching arrays */ 2 | 3 | #define TYPE unsigned short 4 | #define NAME bsearch_ushort 5 | 6 | #include "bsearch-impl.h" 7 | -------------------------------------------------------------------------------- /libraries/utils/bsearch/test/bsearch-test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef FORTIFY 7 | #include "fortify/fortify.h" 8 | #endif 9 | 10 | #include "base/result.h" 11 | #include "base/utils.h" 12 | 13 | #include "utils/bsearch.h" 14 | 15 | #include "test/all-tests.h" 16 | 17 | result_t bsearch_test(const char *resources) 18 | { 19 | static const int ints[] = { INT_MIN, INT_MIN + 1, INT_MAX - 1, INT_MAX }; 20 | 21 | int i; 22 | int nfailures = 0; 23 | 24 | NOT_USED(resources); 25 | 26 | printf("test: int array\n"); 27 | 28 | for (i = 0; i < NELEMS(ints); i++) 29 | { 30 | printf("searching for %d...", ints[i]); 31 | 32 | if (bsearch_int(ints, NELEMS(ints), sizeof(ints[0]), ints[i]) == -1) 33 | { 34 | printf("failed!\n"); 35 | nfailures++; 36 | } 37 | else 38 | { 39 | printf("ok!\n"); 40 | } 41 | } 42 | 43 | printf("\n"); 44 | 45 | 46 | static const unsigned int uints[] = { 0, 1, UINT_MAX - 1, UINT_MAX }; 47 | 48 | printf("test: unsigned int array\n"); 49 | 50 | for (i = 0; i < NELEMS(uints); i++) 51 | { 52 | printf("searching for %u...", uints[i]); 53 | 54 | if (bsearch_uint(uints, NELEMS(uints), sizeof(uints[0]), uints[i]) == -1) 55 | { 56 | printf("failed!\n"); 57 | nfailures++; 58 | } 59 | else 60 | { 61 | printf("ok!\n"); 62 | } 63 | } 64 | 65 | printf("\n"); 66 | 67 | 68 | static const short shorts[] = { SHRT_MIN, SHRT_MIN + 1, SHRT_MAX - 1, SHRT_MAX }; 69 | 70 | printf("test: short array\n"); 71 | 72 | for (i = 0; i < NELEMS(shorts); i++) 73 | { 74 | printf("searching for %d...", shorts[i]); 75 | 76 | if (bsearch_short(shorts, NELEMS(shorts), sizeof(shorts[0]), shorts[i]) == -1) 77 | { 78 | printf("failed!\n"); 79 | nfailures++; 80 | } 81 | else 82 | { 83 | printf("ok!\n"); 84 | } 85 | } 86 | 87 | printf("\n"); 88 | 89 | 90 | static const unsigned short ushorts[] = { 0, 1, USHRT_MAX - 1, USHRT_MAX }; 91 | 92 | printf("test: unsigned short array\n"); 93 | 94 | for (i = 0; i < NELEMS(ushorts); i++) 95 | { 96 | printf("searching for %u...", ushorts[i]); 97 | 98 | if (bsearch_ushort(ushorts, NELEMS(ushorts), sizeof(ushorts[0]), ushorts[i]) == -1) 99 | { 100 | printf("failed!\n"); 101 | nfailures++; 102 | } 103 | else 104 | { 105 | printf("ok!\n"); 106 | } 107 | } 108 | 109 | printf("\n"); 110 | 111 | printf("bsearch: %d failure(s)\n", nfailures); 112 | 113 | return (nfailures > 0) ? result_TEST_FAILED : result_TEST_PASSED; 114 | } 115 | -------------------------------------------------------------------------------- /libraries/utils/bytesex/rev-l-block.c: -------------------------------------------------------------------------------- 1 | /* rev-l-block.c -- reversing bytesex */ 2 | 3 | #include 4 | 5 | #include "utils/bytesex.h" 6 | 7 | #include "util.h" 8 | 9 | void rev_l_block(unsigned int *array, size_t nelems) 10 | { 11 | unsigned int *p; 12 | unsigned int mask; 13 | 14 | assert(array != NULL); 15 | 16 | p = array; 17 | 18 | mask = 0xffff00ffU; 19 | 20 | while (nelems-- != 0) 21 | { 22 | unsigned int r0, r1; 23 | 24 | r0 = *p; 25 | 26 | r1 = r0 ^ ROR(int, r0, 16); 27 | r1 = mask & (r1 >> 8); 28 | r0 = r1 ^ ROR(int, r0, 8); 29 | 30 | *p++ = r0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /libraries/utils/bytesex/rev-l-m.c: -------------------------------------------------------------------------------- 1 | /* rev-l-m.c -- reversing bytesex */ 2 | 3 | #include "utils/bytesex.h" 4 | 5 | unsigned int rev_l_m(const unsigned char *p) 6 | { 7 | unsigned int a, b, c, d; 8 | 9 | a = p[0]; 10 | b = p[1]; 11 | c = p[2]; 12 | d = p[3]; 13 | 14 | return (a << 24) | (b << 16) | (c << 8) | (d << 0); 15 | } 16 | -------------------------------------------------------------------------------- /libraries/utils/bytesex/rev-l.c: -------------------------------------------------------------------------------- 1 | /* rev-l.c -- reversing bytesex */ 2 | 3 | #include "utils/bytesex.h" 4 | 5 | #include "util.h" 6 | 7 | unsigned int rev_l(unsigned int r0) 8 | { 9 | unsigned int mask; 10 | unsigned int r1; 11 | 12 | mask = 0xffff00ffU; 13 | 14 | r1 = r0 ^ ROR(int, r0, 16); 15 | r1 = mask & (r1 >> 8); 16 | r0 = r1 ^ ROR(int, r0, 8); 17 | 18 | return r0; 19 | } 20 | -------------------------------------------------------------------------------- /libraries/utils/bytesex/rev-s-block.c: -------------------------------------------------------------------------------- 1 | /* rev-s-block.c -- reversing bytesex */ 2 | 3 | #include 4 | 5 | #include "utils/bytesex.h" 6 | 7 | void rev_s_block(unsigned short int *array, size_t nelems) 8 | { 9 | unsigned short int *p; 10 | unsigned int *q; 11 | size_t n; 12 | unsigned int mask; 13 | 14 | assert(array != NULL); 15 | 16 | if (nelems == 0) 17 | return; 18 | 19 | p = array; 20 | 21 | /* align to a 4-byte boundary */ 22 | if (((int) p & 3) != 0) 23 | { 24 | unsigned short int r0; 25 | 26 | r0 = *p; 27 | 28 | *p++ = (unsigned short int)((r0 >> 8) | (r0 << 8)); 29 | 30 | nelems--; 31 | } 32 | 33 | q = (void *) p; /* work around increase in alignment */ 34 | 35 | n = (nelems >> 1) + 1; /* watch the birdie */ 36 | 37 | mask = 0xff00ffffU; /* prepare the convert-o-tron */ 38 | 39 | /* now do pairs at a time */ 40 | while (--n != 0) 41 | { 42 | unsigned int r0, r1; 43 | 44 | r0 = *q; 45 | 46 | r1 = mask & (r0 << 8); 47 | r0 &= ~(mask >> 8); 48 | r0 = r1 | (r0 >> 8); 49 | 50 | *q++ = r0; 51 | } 52 | 53 | p = (void *) q; 54 | 55 | /* deal with trailer, if any */ 56 | if ((nelems & 1) != 0) 57 | { 58 | unsigned short int r0; 59 | 60 | r0 = *p; 61 | 62 | *p = (unsigned short int)((r0 >> 8) | (r0 << 8)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /libraries/utils/bytesex/rev-s-m.c: -------------------------------------------------------------------------------- 1 | /* rev-s-m.c -- reversing bytesex */ 2 | 3 | #include "utils/bytesex.h" 4 | 5 | unsigned short int rev_s_m(const unsigned char *p) 6 | { 7 | unsigned short a, b; 8 | 9 | a = p[0]; 10 | b = p[1]; 11 | 12 | return (unsigned short int)((a << 8) | (b << 0)); 13 | } 14 | -------------------------------------------------------------------------------- /libraries/utils/bytesex/rev-s-pair-m.c: -------------------------------------------------------------------------------- 1 | /* rev-s-pair-m.c -- reversing bytesex */ 2 | 3 | 4 | #include "utils/bytesex.h" 5 | 6 | unsigned int rev_s_pair_m(const unsigned char *p) 7 | { 8 | unsigned int a, b, c, d; 9 | 10 | a = p[0]; 11 | b = p[1]; 12 | c = p[2]; 13 | d = p[3]; 14 | 15 | return (a << 8) | (b << 0) | (c << 24) | (d << 16); 16 | } 17 | -------------------------------------------------------------------------------- /libraries/utils/bytesex/rev-s-pair.c: -------------------------------------------------------------------------------- 1 | /* rev-s-pair.c -- reversing bytesex */ 2 | 3 | #include "utils/bytesex.h" 4 | 5 | unsigned int rev_s_pair(unsigned int r0) 6 | { 7 | unsigned int mask; 8 | unsigned int r1; 9 | 10 | mask = 0xff00ffffU; 11 | 12 | r1 = mask & (r0 << 8); 13 | r0 &= ~(mask >> 8); 14 | r0 = r1 | (r0 >> 8); 15 | 16 | return r0; 17 | } 18 | -------------------------------------------------------------------------------- /libraries/utils/bytesex/rev-s.c: -------------------------------------------------------------------------------- 1 | /* rev-s.c -- reversing bytesex */ 2 | 3 | #include "utils/bytesex.h" 4 | 5 | unsigned short int rev_s(unsigned short int r0) 6 | { 7 | return (unsigned short int)((r0 >> 8) | (r0 << 8)); 8 | } 9 | -------------------------------------------------------------------------------- /libraries/utils/bytesex/util.h: -------------------------------------------------------------------------------- 1 | /* util.h -- utils for reversing bytesex */ 2 | 3 | #include 4 | 5 | #ifndef BYTESEX_UTIL_H 6 | #define BYTESEX_UTIL_H 7 | 8 | /* Rotate 'x' right by 'n' bits. */ 9 | #define ROR(type, x, n) ( ((x) >> (n)) | ((x) << ((sizeof(type) * CHAR_BIT) - (n))) ) 10 | 11 | #endif /* BYTESEX_UTIL_H */ 12 | -------------------------------------------------------------------------------- /libraries/utils/fxp/smull-fxp16.c: -------------------------------------------------------------------------------- 1 | /* smull-fxp16.c -- fixed point helpers */ 2 | 3 | #include "utils/fxp.h" 4 | 5 | #define T int 6 | #define LL long long 7 | 8 | T smull_fxp16(T x, T y) 9 | { 10 | return (T)(((LL) x * (LL) y) >> 16); 11 | } 12 | -------------------------------------------------------------------------------- /libraries/utils/fxp/umull-fxp16.c: -------------------------------------------------------------------------------- 1 | /* umull-fxp16.c -- fixed point helpers */ 2 | 3 | #include "utils/fxp.h" 4 | 5 | #define T unsigned int 6 | #define LL unsigned long long 7 | 8 | T umull_fxp16(T x, T y) 9 | { 10 | return (T)(((LL) x * (LL) y) >> 16); 11 | } 12 | -------------------------------------------------------------------------------- /libraries/utils/maths/degs-to-rads.c: -------------------------------------------------------------------------------- 1 | /* degs-to-rads.c -- degrees to radians */ 2 | 3 | #include "utils/maths.h" 4 | 5 | #define TWICEPI 6.2831853071795864769252867665590 6 | 7 | double degs_to_rads(double degs) 8 | { 9 | return degs * TWICEPI / 360.0; 10 | } 11 | -------------------------------------------------------------------------------- /libraries/utils/maths/gcd.c: -------------------------------------------------------------------------------- 1 | /* gcd.c -- greatest common divisor */ 2 | 3 | #include "utils/maths.h" 4 | 5 | /* Knuth Volume 1 1.1E p2 */ 6 | 7 | int gcd(int m, int n) 8 | { 9 | int r; 10 | 11 | while (n > 0) 12 | { 13 | r = m % n; 14 | m = n; 15 | n = r; 16 | } 17 | 18 | return m; 19 | } 20 | -------------------------------------------------------------------------------- /libraries/utils/primes/primes.c: -------------------------------------------------------------------------------- 1 | /* primes.c -- cache of prime numbers */ 2 | 3 | #include "base/utils.h" 4 | 5 | #include "utils/primes.h" 6 | 7 | /* A selection of primes. */ 8 | static const int primes[] = 9 | { 10 | 17, 97, 173, 251, 337, 421, 503, 601, 683, 787, 881, 983, 11 | }; 12 | 13 | int prime_nearest(int x) 14 | { 15 | int i; 16 | 17 | for (i = 0; i < NELEMS(primes); i++) 18 | if (primes[i] >= x) 19 | return primes[i]; 20 | 21 | return primes[i - 1]; /* choose the final value */ 22 | } 23 | -------------------------------------------------------------------------------- /pngusr-ro.dfa: -------------------------------------------------------------------------------- 1 | # pngusr-ro.dfa 2 | 3 | everything = off 4 | 5 | option ERROR_TEXT on 6 | option READ_EXPAND on 7 | option READ_FILLER on 8 | option READ_STRIP_16_TO_8 on 9 | option SEQUENTIAL_READ on 10 | option SETJMP on 11 | option STDIO on 12 | -------------------------------------------------------------------------------- /pngusr-rw.dfa: -------------------------------------------------------------------------------- 1 | # pngusr-rw.dfa 2 | 3 | everything = on 4 | -------------------------------------------------------------------------------- /resources/bmfonts/digits-font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpt/DPTLib/98cbc142c0261b75df0e514cabef011c55e092c2/resources/bmfonts/digits-font.png -------------------------------------------------------------------------------- /resources/bmfonts/gliderrider-font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpt/DPTLib/98cbc142c0261b75df0e514cabef011c55e092c2/resources/bmfonts/gliderrider-font.png -------------------------------------------------------------------------------- /resources/bmfonts/henry-font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpt/DPTLib/98cbc142c0261b75df0e514cabef011c55e092c2/resources/bmfonts/henry-font.png -------------------------------------------------------------------------------- /resources/bmfonts/ms-sans-serif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpt/DPTLib/98cbc142c0261b75df0e514cabef011c55e092c2/resources/bmfonts/ms-sans-serif.png -------------------------------------------------------------------------------- /resources/bmfonts/tall-font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpt/DPTLib/98cbc142c0261b75df0e514cabef011c55e092c2/resources/bmfonts/tall-font.png -------------------------------------------------------------------------------- /resources/bmfonts/tiny-font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpt/DPTLib/98cbc142c0261b75df0e514cabef011c55e092c2/resources/bmfonts/tiny-font.png -------------------------------------------------------------------------------- /resources/composite/A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpt/DPTLib/98cbc142c0261b75df0e514cabef011c55e092c2/resources/composite/A.png -------------------------------------------------------------------------------- /resources/composite/B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpt/DPTLib/98cbc142c0261b75df0e514cabef011c55e092c2/resources/composite/B.png --------------------------------------------------------------------------------