diff options
153 files changed, 2817 insertions, 5791 deletions
diff --git a/.clang-tidy b/.clang-tidy index 9accc2c..5013b26 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,32 +1,23 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + Checks: > *, - -*-magic-numbers, - -*-uppercase-literal-suffix, - -android-cloexec-fopen, - -bugprone-branch-clone, + -*-vararg, + -altera-*, + -bugprone-assignment-in-if-condition, + -bugprone-easily-swappable-parameters, -bugprone-macro-parentheses, - -bugprone-narrowing-conversions, - -bugprone-not-null-terminated-result, - -bugprone-reserved-identifier, - -bugprone-suspicious-string-compare, - -cert-dcl37-c, - -cert-dcl51-cpp, - -cert-err34-c, - -clang-analyzer-alpha.*, - -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling, - -cppcoreguidelines-avoid-non-const-global-variables, - -cppcoreguidelines-macro-usage, - -cppcoreguidelines-narrowing-conversions, - -google-readability-todo, - -hicpp-multiway-paths-covered, - -hicpp-signed-bitwise, - -llvm-header-guard, + -clang-diagnostic-unused-function, + -clang-diagnostic-unused-macros, -llvmlibc-*, - -misc-no-recursion, - -misc-non-private-member-variables-in-classes, - -misc-unused-parameters, - -modernize-use-trailing-return-type, - -readability-implicit-bool-conversion, -WarningsAsErrors: '*' -HeaderFilterRegex: '.*' + -modernize-macro-to-enum, + -readability-identifier-length, +CheckOptions: + - key: hicpp-uppercase-literal-suffix.NewSuffixes + value: 'L;U;UL;ULL' + - key: readability-uppercase-literal-suffix.NewSuffixes + value: 'L;U;UL;ULL' FormatStyle: file +HeaderFilterRegex: '.*/lilv/[^/]+.h' +WarningsAsErrors: '*' @@ -1,4 +1,9 @@ -build/** -.waf-* -.lock-waf* +# Copyright 2018-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +.meson-subproject-wrap-hash.txt __pycache__ +build/** +subprojects/packagecache/ +subprojects/sphinxygen-1.0.0/ +subprojects/sphinxygen/ diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index cc8b569..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "waflib"] - path = waflib - url = ../../drobilla/autowaf.git diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 0000000..f9693c0 --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,18 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: lilv +Upstream-Contact: David Robillard <d@drobilla.net> +Source: https://gitlab.com/drobilla/lilv + +Files: AUTHORS NEWS lilv.ttl +Copyright: 2006-2022 David Robillard <d@drobilla.net> +Comment: Contributed to the Commons as a representation of simple facts +License: 0BSD OR ISC + +Files: .clant.json +Copyright: 2020 David Robillard <d@drobilla.net> +Comment: Contributed to the Commons as a tool configuration +License: 0BSD OR ISC + +Files: bindings/test/*.ttl.in test/*/*.ttl.in test/lv2/core.lv2/*.ttl +Copyright: 2015-2022 David Robillard <d@drobilla.net> +License: ISC @@ -1,13 +1,13 @@ -Copyright 2011-2021 David Robillard <d@drobilla.net> +Copyright 2011-2022 David Robillard <d@drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. -THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
\ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 9b54f51..0000000 --- a/INSTALL +++ /dev/null @@ -1,66 +0,0 @@ -Installation Instructions -========================= - -Basic Installation ------------------- - -Building this software requires only Python. To install with default options: - - ./waf configure - ./waf - ./waf install # or sudo ./waf install - -Configuration Options ---------------------- - -All supported options can be viewed using the command: - - ./waf --help - -Most options only need to be passed during the configure stage, for example: - - ./waf configure --prefix=/usr - ./waf - ./waf install - -Compiler Configuration ----------------------- - -Several standard environment variables can be used to control how compilers are -invoked: - - * CC: Path to C compiler - * CFLAGS: C compiler options - * CXX: Path to C++ compiler - * CXXFLAGS: C++ compiler options - * CPPFLAGS: C preprocessor options - * LINKFLAGS: Linker options - -Library Versioning ------------------- - -This library uses semantic versioning <http://semver.org/>. - -Several major versions can be installed in parallel. The shared library name, -include directory, and pkg-config file are suffixed with the major version -number. For example, a library named "foo" at version 1.x.y might install: - - /usr/include/foo-1/foo/foo.h - /usr/lib/foo-1.so.1.x.y - /usr/lib/pkgconfig/foo-1.pc - -Dependencies can check for the package "foo-1" with pkg-config. - -Packaging ---------- - -Everything can be installed to a specific root directory by passing a --destdir -option to the install stage (or setting the DESTDIR environment variable), -which adds a prefix to all install paths. For example: - - ./waf configure --prefix=/usr - ./waf - ./waf install --destdir=/tmp/package - -Packages should allow parallel installation of several major versions. For -example, the above would be packaged as "foo-1".
\ No newline at end of file diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..2adecf0 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,77 @@ +<!-- Copyright 2022 David Robillard <d@drobilla.net> --> +<!-- SPDX-License-Identifier: ISC --> + +Installation Instructions +========================= + +Prerequisites +------------- + +To build from source, you will need: + + * A relatively modern C compiler (GCC, Clang, and MSVC are known to work). + + * [Meson](http://mesonbuild.com/), which depends on + [Python](http://python.org/). + +This is a brief overview of building this project with meson. See the meson +documentation for more detailed information. + +Configuration +------------- + +The build is configured with the `setup` command, which creates a new build +directory with the given name: + + meson setup build + +Some environment variables are read during `setup` and stored with the +configuration: + + * `CC`: Path to C compiler. + * `CFLAGS`: C compiler options. + * `LDFLAGS`: Linker options. + +However, it is better to use meson options for configuration. All options can +be inspected with the `configure` command from within the build directory: + + cd build + meson configure + +Options can be set by passing C-style "define" options to `configure`: + + meson configure -Dc_args="-march=native" -Dprefix="/opt/mypackage/" + +Note that some options, such as `strict` and `werror` are for +developer/maintainer use only. Please don't file issues about anything that +happens when they are enabled. + +Building +-------- + +From within a configured build directory, everything can be built with the +`compile` command: + + meson compile + +Similarly, tests can be run with the `test` command: + + meson test + +Meson can also generate a project for several popular IDEs, see the `backend` +option for details. + +Installation +------------ + +A compiled project can be installed with the `install` command: + + meson install + +You may need to acquire root permissions to install to a system-wide prefix. +For packaging, the installation may be staged to a directory using the +`DESTDIR` environment variable or the `--destdir` option: + + DESTDIR=/tmp/mypackage/ meson install + + meson install --destdir=/tmp/mypackage/ diff --git a/LICENSES/0BSD.txt b/LICENSES/0BSD.txt new file mode 100644 index 0000000..b3e8cfd --- /dev/null +++ b/LICENSES/0BSD.txt @@ -0,0 +1,12 @@ +Copyright 2011-2022 David Robillard <d@drobilla.net> + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/LICENSES/ISC.txt b/LICENSES/ISC.txt new file mode 120000 index 0000000..012065c --- /dev/null +++ b/LICENSES/ISC.txt @@ -0,0 +1 @@ +../COPYING
\ No newline at end of file @@ -1,11 +1,48 @@ -lilv (0.24.13) unstable; +lilv (0.24.21) unstable; urgency=medium + * Allow LILV_API to be defined by the user + * Clean up code + * Clean up inconsistent tool command line interfaces + * Convert man pages to mdoc + * Fix dependencies in pkg-config file + * Fix potential crash when writing state files fails + * Override pkg-config dependency within meson + * Remove junk files from documentation install + * Replace duplicated dox_to_sphinx script with sphinxygen dependency + * Switch to external zix dependency + + -- David Robillard <d@drobilla.net> Mon, 15 May 2023 00:02:51 +0000 + +lilv (0.24.20) stable; urgency=medium + + * Adopt REUSE machine-readable licensing standard + * Update project metadata + + -- David Robillard <d@drobilla.net> Fri, 09 Sep 2022 17:28:30 +0000 + +lilv (0.24.18) stable; urgency=medium + + * Allow programs to be used from subproject + * Fix default LV2_PATH + + -- David Robillard <d@drobilla.net> Fri, 12 Aug 2022 22:15:29 +0000 + +lilv (0.24.16) stable; urgency=medium + + * Fix fallback flock() detection on MacOS + * Switch to meson build system + + -- David Robillard <d@drobilla.net> Tue, 19 Jul 2022 01:16:26 +0000 + +lilv (0.24.14) stable; urgency=medium + + * Fix build issues with newer toolchains * Fix unused parameter warnings * Update zix tree - -- David Robillard <d@drobilla.net> Mon, 11 Jan 2021 11:20:41 +0000 + -- David Robillard <d@drobilla.net> Fri, 27 May 2022 01:38:26 +0000 -lilv (0.24.12) stable; +lilv (0.24.12) stable; urgency=medium * Allow connecting ports to structures in Python * Fix potential memory error when joining filesystem paths @@ -16,7 +53,7 @@ lilv (0.24.12) stable; -- David Robillard <d@drobilla.net> Thu, 07 Jan 2021 21:46:06 +0000 -lilv (0.24.10) stable; +lilv (0.24.10) stable; urgency=medium * Fix memory leaks in lv2bench * Fix various minor warnings and other code quality issues @@ -25,7 +62,7 @@ lilv (0.24.10) stable; -- David Robillard <d@drobilla.net> Sun, 27 Sep 2020 12:17:02 +0000 -lilv (0.24.8) stable; +lilv (0.24.8) stable; urgency=medium * Allow passing strings for URIs in Python API when unambiguous * Fix cases where incorrect translation is used @@ -35,7 +72,7 @@ lilv (0.24.8) stable; -- David Robillard <d@drobilla.net> Sun, 26 Apr 2020 15:55:26 +0000 -lilv (0.24.6) stable; +lilv (0.24.6) stable; urgency=medium * Add more strict error detection when storing plugin state properties * Add option to override LV2_PATH in applications @@ -49,7 +86,7 @@ lilv (0.24.6) stable; -- David Robillard <d@drobilla.net> Sun, 10 Nov 2019 21:39:37 +0000 -lilv (0.24.4) stable; +lilv (0.24.4) stable; urgency=medium * Don't attempt to load remote or non-Turtle files * Fix saving state when broken links are encountered @@ -64,14 +101,14 @@ lilv (0.24.4) stable; -- David Robillard <d@drobilla.net> Sun, 22 Jul 2018 18:42:00 +0000 -lilv (0.24.2) stable; +lilv (0.24.2) stable; urgency=medium * Fix comparison of restored states with paths * Fix saving state to paths that contain URI delimiters (#, ?, etc) -- David Robillard <d@drobilla.net> Wed, 04 Jan 2017 16:48:08 +0000 -lilv (0.24.0) stable; +lilv (0.24.0) stable; urgency=medium * Add LILV_URI_ATOM_PORT and LILV_URI_CV_PORT defines * Add lilv_state_set_metadata() for adding state banks/comments/etc (based @@ -94,7 +131,7 @@ lilv (0.24.0) stable; -- David Robillard <d@drobilla.net> Tue, 20 Sep 2016 02:24:57 +0000 -lilv (0.22.0) stable; +lilv (0.22.0) stable; urgency=medium * Add lilv_file_uri_parse() for correct URI to path conversion * Add lilv_free() for systems picky about such things @@ -121,7 +158,7 @@ lilv (0.22.0) stable; -- David Robillard <d@drobilla.net> Thu, 08 Oct 2015 19:39:29 +0000 -lilv (0.20.0) stable; +lilv (0.20.0) stable; urgency=medium * Add convenient lilv_new_file_uri for creating file URIs * Add lilv_world_unload_bundle() and lilv_world_unload_resource() @@ -142,7 +179,7 @@ lilv (0.20.0) stable; -- David Robillard <d@drobilla.net> Fri, 08 Aug 2014 22:21:32 +0000 -lilv (0.18.0) stable; +lilv (0.18.0) stable; urgency=medium * Add lilv_port_get_node() for using world query functions with ports * Add support for running plugins from Python by Kaspar Emanuel @@ -159,7 +196,7 @@ lilv (0.18.0) stable; -- David Robillard <d@drobilla.net> Sat, 04 Jan 2014 21:06:42 +0000 -lilv (0.16.0) stable; +lilv (0.16.0) stable; urgency=medium * Add lilv_nodes_merge() * Add lilv_world_ask() for easily checking if a statement exists @@ -181,7 +218,7 @@ lilv (0.16.0) stable; -- David Robillard <d@drobilla.net> Mon, 18 Feb 2013 21:43:10 +0000 -lilv (0.14.4) stable; +lilv (0.14.4) stable; urgency=medium * Add lv2bench utility * Add option to build utilities as static binaries @@ -201,13 +238,13 @@ lilv (0.14.4) stable; -- David Robillard <d@drobilla.net> Thu, 23 Aug 2012 05:38:29 +0000 -lilv (0.14.2) stable; +lilv (0.14.2) stable; urgency=medium * Fix dynmanifest support -- David Robillard <d@drobilla.net> Thu, 19 Apr 2012 20:11:31 +0000 -lilv (0.14.0) stable; +lilv (0.14.0) stable; urgency=medium * Add LilvState API for handling plugin state. This makes it simple to save and restore plugin state both in memory and on disk, as well as save @@ -238,7 +275,7 @@ lilv (0.14.0) stable; -- David Robillard <d@drobilla.net> Thu, 19 Apr 2012 00:06:28 +0000 -lilv (0.5.0) stable; +lilv (0.5.0) stable; urgency=medium * Add ability to build static library * Add lv2core as a pkg-config dependency (for lv2.h header include) @@ -249,7 +286,7 @@ lilv (0.5.0) stable; -- David Robillard <d@drobilla.net> Thu, 29 Sep 2011 04:00:00 +0000 -lilv (0.4.4) stable; +lilv (0.4.4) stable; urgency=medium * Fix building python bindings * Fix lilv_ui_is_supported when Lilv is built independently @@ -259,14 +296,14 @@ lilv (0.4.4) stable; -- David Robillard <d@drobilla.net> Sat, 11 Jun 2011 15:20:11 +0000 -lilv (0.4.2) stable; +lilv (0.4.2) stable; urgency=medium * Fix build system Python 3 compatibility * Fix compilation issues on some systems -- David Robillard <d@drobilla.net> Wed, 25 May 2011 23:00:00 +0000 -lilv (0.4.0) stable; +lilv (0.4.0) stable; urgency=medium * Initial version (forked from SLV2) @@ -1,3 +1,6 @@ +<!-- Copyright 2006-2019 David Robillard <d@drobilla.net> --> +<!-- SPDX-License-Identifier: ISC --> + Lilv ==== diff --git a/bindings/python/Makefile b/bindings/python/Makefile index e63c124..32f199d 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -1,5 +1,7 @@ # Makefile for Sphinx documentation # +# Copyright 2016 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC # You can set these variables from the command line. SPHINXOPTS = diff --git a/bindings/python/conf.py b/bindings/python/conf.py index 005e03a..68c1145 100644 --- a/bindings/python/conf.py +++ b/bindings/python/conf.py @@ -1,4 +1,8 @@ # -*- coding: utf-8 -*- + +# Copyright 2016-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + # # Lilv documentation build configuration file, created by # sphinx-quickstart on Sun Sep 4 18:25:58 2016. @@ -56,9 +60,9 @@ copyright = u'2016, David Robillard' # built documents. # # The short X.Y version. -version = '0.24.12' +version = '0.24.21' # The full version, including alpha/beta/rc tags. -release = '0.24.12' +release = '0.24.21' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/bindings/python/index.rst b/bindings/python/index.rst index 4616054..b44fa08 100644 --- a/bindings/python/index.rst +++ b/bindings/python/index.rst @@ -1,3 +1,7 @@ +.. + Copyright 2016 David Robillard <d@drobilla.net> + SPDX-License-Identifier: ISC + Lilv Python Documentation ========================= diff --git a/bindings/python/lilv.py b/bindings/python/lilv.py index 98da72f..ab7a20b 100644 --- a/bindings/python/lilv.py +++ b/bindings/python/lilv.py @@ -1,9 +1,12 @@ """Lilv Python interface""" +# Copyright 2016-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: ISC + __author__ = "David Robillard" -__copyright__ = "Copyright 2016-2020 David Robillard" +__copyright__ = "Copyright 2016-2022 David Robillard" __license__ = "ISC" -__version__ = "0.24.12" +__version__ = "0.24.21" __maintainer__ = "David Robillard" __email__ = "d@drobilla.net" __status__ = "Production" diff --git a/bindings/python/lv2_apply.py b/bindings/python/lv2_apply.py index 4c7d9b4..bb95682 100755 --- a/bindings/python/lv2_apply.py +++ b/bindings/python/lv2_apply.py @@ -1,6 +1,9 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +# Copyright 2011-2016 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: ISC + import math import lilv import sys diff --git a/bindings/python/lv2_list.py b/bindings/python/lv2_list.py index babe1b4..1bb233c 100755 --- a/bindings/python/lv2_list.py +++ b/bindings/python/lv2_list.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Copyright 2007-2011 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: ISC + import lilv world = lilv.World() diff --git a/bindings/python/lv2_list_presets.py b/bindings/python/lv2_list_presets.py index 4e0c9b1..a6439d6 100755 --- a/bindings/python/lv2_list_presets.py +++ b/bindings/python/lv2_list_presets.py @@ -1,6 +1,9 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +# Copyright 2019-2020 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: ISC + import sys import lilv diff --git a/bindings/python/meson.build b/bindings/python/meson.build new file mode 100644 index 0000000..1cffd71 --- /dev/null +++ b/bindings/python/meson.build @@ -0,0 +1,9 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +pymod = import('python') +py = pymod.find_installation('python3', required: get_option('bindings_py')) + +if py.found() + py.install_sources(files('lilv.py')) +endif diff --git a/bindings/test/bindings_test_plugin.c b/bindings/test/bindings_test_plugin.c index 2df64ea..18907d5 100644 --- a/bindings/test/bindings_test_plugin.c +++ b/bindings/test/bindings_test_plugin.c @@ -1,19 +1,6 @@ -/* - Copyright 2006-2019 David Robillard <d@drobilla.net> - Copyright 2006 Steve Harris <steve@plugin.org.uk> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2006-2019 David Robillard <d@drobilla.net> +// Copyright 2006 Steve Harris <steve@plugin.org.uk> +// SPDX-License-Identifier: ISC /** LV2 headers are based on the URI of the specification they come from, so a @@ -197,10 +184,5 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor(uint32_t index) { - switch (index) { - case 0: - return &descriptor; - default: - return NULL; - } + return index ? NULL : &descriptor; } diff --git a/bindings/test/python/test_api.py b/bindings/test/python/test_api.py index 8d3a94a..d70dbe6 100644 --- a/bindings/test/python/test_api.py +++ b/bindings/test/python/test_api.py @@ -1,17 +1,6 @@ # Copyright 2016-2020 David Robillard <d@drobilla.net> # Copyright 2013 Kaspar Emanuel <kaspar.emanuel@gmail.com> -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# SPDX-License-Identifier: ISC import lilv import os diff --git a/doc/c/Doxyfile b/doc/Doxyfile.in index ce10524..2ca5694 100644 --- a/doc/c/Doxyfile +++ b/doc/Doxyfile.in @@ -1,3 +1,6 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + PROJECT_NAME = Lilv PROJECT_BRIEF = "A library for simple use of LV2 plugins" @@ -21,6 +24,8 @@ SHOW_FILES = NO MACRO_EXPANSION = YES PREDEFINED = LILV_API LILV_DEPRECATED -INPUT = ../../include/lilv/lilv.h +RECURSIVE = YES +STRIP_FROM_PATH = @LILV_SRCDIR@ +INPUT = @LILV_SRCDIR@/include/lilv/lilv.h -OUTPUT_DIRECTORY = . +OUTPUT_DIRECTORY = @DOX_OUTPUT@ diff --git a/doc/api/meson.build b/doc/api/meson.build new file mode 100644 index 0000000..8c8293b --- /dev/null +++ b/doc/api/meson.build @@ -0,0 +1,9 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +c_lilv_rst = custom_target( + 'lilv.rst', + command: [sphinxygen, '-f', '@INPUT0@', '@OUTDIR@'], + input: [c_index_xml] + c_rst_files, + output: 'lilv.rst', +) diff --git a/doc/c/index.rst b/doc/c/index.rst deleted file mode 100644 index 6968981..0000000 --- a/doc/c/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -#### -Lilv -#### - -.. include:: summary.rst - -.. toctree:: - - overview - api/lilv diff --git a/doc/c/wscript b/doc/c/wscript deleted file mode 100644 index d515ddf..0000000 --- a/doc/c/wscript +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python - -def build(bld): - dox_to_sphinx = bld.path.find_node("../../scripts/dox_to_sphinx.py") - index_xml = bld.path.get_bld().make_node("xml/index.xml") - - files = [ - ("../summary.rst", "sphinx/summary.rst"), - ("index.rst", "sphinx/index.rst"), - ("overview.rst", "sphinx/overview.rst"), - ("plugins.rst", "sphinx/plugins.rst"), - ("uis.rst", "sphinx/uis.rst"), - ("world.rst", "sphinx/world.rst"), - ] - - # Run Doxygen to generate XML documentation - bld(features="doxygen", doxyfile="Doxyfile") - - # Substitute variables to make Sphinx configuration file - bld(features="subst", - source="../conf.py.in", - target="sphinx/conf.py", - LILV_VERSION=bld.env.LILV_VERSION) - - # Copy static documentation files to Sphinx build directory - for f in files: - bld(features="subst", is_copy=True, source=f[0], target=f[1]) - - # Generate Sphinx markup from Doxygen XML - bld.add_group() - bld(rule="${PYTHON} " + dox_to_sphinx.abspath() + " -f ${SRC} ${TGT}", - source=index_xml, - target="sphinx/api/") - - doc_dir = bld.env.DOCDIR + "/lilv-%s/" % bld.env.LILV_MAJOR_VERSION - - # Run Sphinx to generate HTML documentation - for builder in ["html", "singlehtml"]: - bld(features="sphinx", - sphinx_source=bld.path.get_bld().make_node("sphinx"), - sphinx_output_format=builder, - sphinx_options=["-E", "-q", "-t", builder], - install_path=doc_dir + "c/%s/" % builder) diff --git a/doc/conf.py.in b/doc/conf.py.in index e62eaff..444b70a 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -1,9 +1,14 @@ +# Copyright 2020-2021 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: ISC + # Project information -project = "Lilv" -copyright = "2020, David Robillard" +project = "@LILV_TITLE@" +copyright = "2020-2023, David Robillard" author = "David Robillard" release = "@LILV_VERSION@" +version = "@LILV_VERSION@" +desc = "A library for loading LV2 plugins" # General configuration @@ -12,6 +17,13 @@ language = "en" nitpicky = True pygments_style = "friendly" +try: + import sphinx_lv2_theme + + have_lv2_theme = True +except ModuleNotFoundError: + have_lv2_theme = False + # Ignore everything opaque or external for nitpicky mode _opaque = [ "FILE", @@ -38,42 +50,78 @@ nitpick_ignore = list(map(lambda x: ("c:identifier", x), _opaque)) # HTML output -html_theme = "sphinx_lv2_theme" html_copy_source = False -html_short_title = "Lilv" - -if tags.has('singlehtml'): - html_sidebars = { - "**": [ - "globaltoc.html", - ] - } - - html_theme_options = { - "body_max_width": "65em", - "body_min_width": "50em", - "description": "A library for loading LV2 plugins", - "show_footer_version": True, - "show_logo_version": False, - "logo_name": True, - "nosidebar": False, - "page_width": "80em", - "sidebar_width": "11em", - "globaltoc_maxdepth": 3, - "globaltoc_collapse": False, - } +html_secnumber_suffix = " " +html_short_title = "@LILV_TITLE@" + +html_theme_options = { + "description": desc, + "logo_name": True, + "logo_width": "8em", +} + +if tags.has("singlehtml"): + html_sidebars = {"**": ["globaltoc.html"]} + html_theme_options.update( + { + "globaltoc_collapse": False, + "globaltoc_maxdepth": 3, + "nosidebar": False, + "page_width": "80em", + } + ) +else: + html_theme_options.update( + { + "globaltoc_collapse": True, + "globaltoc_maxdepth": 1, + "nosidebar": True, + "page_width": "60em", + } + ) + +if have_lv2_theme: + html_theme = "sphinx_lv2_theme" + + html_theme_options.update( + { + "show_footer_version": True, + "show_logo_version": True, + } + ) + + if tags.has("singlehtml"): + html_theme_options.update( + { + "body_max_width": "64em", + "body_min_width": "64em", + "nosidebar": False, + "sidebar_width": "12em", + } + ) + + else: + html_theme_options.update( + { + "body_max_width": "60em", + "body_min_width": "40em", + } + ) else: - html_theme_options = { - "body_max_width": "60em", - "body_min_width": "40em", - "description": "A library for loading LV2 plugins", - "show_footer_version": True, - "show_logo_version": False, - "logo_name": True, - "nosidebar": True, - "page_width": "60em", - "sidebar_width": "14em", - "globaltoc_maxdepth": 1, - "globaltoc_collapse": True, - } + html_theme = "alabaster" + + if tags.has("singlehtml"): + html_theme_options = { + "body_max_width": "58em", + "body_min_width": "40em", + "sidebar_width": "16em", + } + + else: + html_theme_options = { + "body_max_width": "60em", + "body_min_width": "40em", + "nosidebar": True, + "show_relbars": True, + } diff --git a/doc/html/meson.build b/doc/html/meson.build new file mode 100644 index 0000000..26d3a03 --- /dev/null +++ b/doc/html/meson.build @@ -0,0 +1,32 @@ +# Copyright 2021-2023 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +html_dir = docdir / versioned_name / 'html' + +# TODO: Add install_tag: 'doc' after requiring meson 0.60.0 + +custom_target( + 'html', + build_by_default: true, + command: [ + sphinx_build, '-M', 'html', '@OUTDIR@' / '..', '@OUTDIR@' / '..', + '-t', 'html', + ] + sphinx_flags, + input: [c_rst_files, c_lilv_rst, c_index_xml, conf_py], + install: true, + install_dir: html_dir, + output: [ + '_static', + 'api', + 'genindex.html', + 'index.html', + 'overview.html', + 'plugins.html', + 'uis.html', + 'world.html', + ], +) + +if not meson.is_subproject() + summary('Paginated HTML', get_option('prefix') / html_dir, section: 'Directories') +endif diff --git a/doc/summary.rst b/doc/index.rst index 313ffa8..46a9026 100644 --- a/doc/summary.rst +++ b/doc/index.rst @@ -1,3 +1,11 @@ +.. + Copyright 2020-2022 David Robillard <d@drobilla.net> + SPDX-License-Identifier: ISC + +#### +Lilv +#### + Lilv is a library for working with LV2_ plugins. It provides several types and functions that can be used to discover plugins, investigate their data, load and run them, and save and restore their state. @@ -6,4 +14,10 @@ Lilv is the standard implementation used by nearly all LV2 hosts. It implements the details of the LV2 specification on POSIX, MacOS, and Windows, and provides a simpler portable API for applications. +.. toctree:: + + overview + api/lilv + .. _LV2: http://lv2plug.in/ + diff --git a/doc/lv2apply.1 b/doc/lv2apply.1 index 4877aba..e963346 100644 --- a/doc/lv2apply.1 +++ b/doc/lv2apply.1 @@ -1,34 +1,66 @@ -.TH LV2APPLY 1 "05 Sep 2016" - -.SH NAME -.B lv2apply \- apply an LV2 plugin to an audio file -.SH SYNOPSIS -.B lv2apply [OPTION]... PLUGIN_URI - -.SH OPTIONS -.TP -\fB\-i IN_FILE\fR -Input file - -.TP -\fB\-o OUT_FILE\fR -Output file - -.TP -\fB\-c SYM VAL\fR -Set control port SYM to VAL - -.TP -\fB\-\-help\fR -Display help and exit - -.TP -\fB\-\-version\fR -Display version information and exit - -.SH "SEE ALSO" -.BR lv2ls(1) -.BR lv2info(1) - -.SH AUTHOR -lv2apply was written by David Robillard <d@drobilla.net> +.\" # Copyright 2010-2022 David Robillard <d@drobilla.net> +.\" # SPDX-License-Identifier: ISC +.Dd Nov 29, 2022 +.Dt LV2APPLY 1 +.Os Lilv 0.24.21 +.Sh NAME +.Nm lv2apply +.Nd apply an LV2 plugin to an audio file +.Sh SYNOPSIS +.Nm lv2apply +.Op Fl Vh +.Op Fl c Ar symbol value +.Op Fl i Ar in_file +.Op Fl o Ar out_file +.Op Fl Fl help +.Op Fl Fl version +.Ar plugin_uri +.Sh DESCRIPTION +.Nm +runs an LV2 plugin on an audio file and writes the processed output to another. +.Pp +The options are as follows: +.Pp +.Bl -tag -compact -width 3n +.It Fl V , Fl Fl version +Display version information and exit. +.Pp +.It Fl c Ar symbol value +Set control port +.Ar symbol +to +.Ar value. +.Pp +.It Fl h , Fl Fl help +Print the command line options. +.Pp +.It Fl i Ar in_file +Input file path. +.Pp +.It Fl o Ar out_file +Output file path. +.El +.Sh ENVIRONMENT +.Bl -tag -width LV2_PATH -compact +.It Ev LV2_PATH +List of directories to search for LV2 plugin bundles, +in the style of +.Ev PATH . +.El +.Sh EXIT STATUS +.Nm +exits with a status of 0, or non-zero if an error occurred. +.Sh SEE ALSO +.Bl -item -compact +.It +.Xr lv2bench 1 +.It +.Xr lv2info 1 +.It +.Xr lv2ls 1 +.El +.Sh AUTHORS +.Nm +is a part of lilv, by +.An David Robillard +.Mt d@drobilla.net . diff --git a/doc/lv2bench.1 b/doc/lv2bench.1 new file mode 100644 index 0000000..b1aeee5 --- /dev/null +++ b/doc/lv2bench.1 @@ -0,0 +1,55 @@ +.\" # Copyright 2022 David Robillard <d@drobilla.net> +.\" # SPDX-License-Identifier: ISC +.Dd Nov 29, 2022 +.Dt LV2BENCH 1 +.Os Lilv 0.24.21 +.Sh NAME +.Nm lv2bench +.Nd benchmark all installed and supported LV2 plugins +.Sh SYNOPSIS +.Nm lv2bench +.Op Fl fhV +.Op Fl b Ar block_size +.Op Fl n Ar frames +.Op Fl Fl full +.Op Fl Fl help +.Op Fl Fl version +.Sh DESCRIPTION +.Nm +is a simple utility for running basic benchmarks of installed LV2 plugins. +.Pp +The options are as follows: +.Pp +.Bl -tag -compact -width 3n +.It Fl V , Fl Fl version +Display version information and exit. +.Pp +.It Fl b Ar block_size +Block size, in audio frames. +.Pp +.It Fl f , Fl Fl full +Emit full plottable output with values for every block. +.Pp +.It Fl h , Fl Fl help +Print the command line options. +.Pp +.It Fl n Ar frames +Total number of audio frames to process. +.El +.Sh EXIT STATUS +.Nm +exits with a status of 0, or non-zero if an error occurred. +.Sh SEE ALSO +.Bl -item -compact +.It +.Xr lv2apply 1 +.It +.Xr lv2info 1 +.It +.Xr lv2ls 1 +.El +.Sh AUTHORS +.Nm +is a part of lilv, by +.An David Robillard +.Mt d@drobilla.net . diff --git a/doc/lv2info.1 b/doc/lv2info.1 index 32a3bec..4712ebd 100644 --- a/doc/lv2info.1 +++ b/doc/lv2info.1 @@ -1,33 +1,65 @@ -.TH LV2INFO 1 "05 Sep 2016" - -.SH NAME -.B lv2info \- print information about an installed LV2 plugin -.SH SYNOPSIS -.B lv2info PLUGIN_URI - -.SH OPTIONS -.TP -\fB\-p FILE\fR -Write Turtle description of plugin to FILE - -.TP -\fB\-m FILE\fR -Add record of plugin to manifest FILE - -.TP -\fB\-\-help\fR -Display help and exit - -.TP -\fB\-\-version\fR -Display version information and exit - -.SH "SEE ALSO" -.BR lilv(3), -.BR lv2ls(1) - -.SH AUTHOR -lv2info was written by David Robillard <d@drobilla.net> -.PP -This manual page was written by JaromÃr Mikes <mira.mikes@seznam.cz> -and David Robillard <d@drobilla.net> +.\" # Copyright 2009-2022 David Robillard <d@drobilla.net> +.\" # SPDX-License-Identifier: ISC +.Dd Nov 29, 2022 +.Dt LV2INFO 1 +.Os Lilv 0.24.21 +.Sh NAME +.Nm lv2info +.Nd print information about an installed LV2 plugin +.Sh SYNOPSIS +.Nm lv2info +.Op Fl hV +.Op Fl m Ar file +.Op Fl p Ar file +.Ar plugin_uri +.Sh DESCRIPTION +.Nm +prints a human-readable summary of information about an LV2 plugin. +.Pp +The plugin must be installed; +.Nm +will search for one with the given +.Ar plugin_uri +in the LV2 path. +.Pp +The options are as follows: +.Pp +.Bl -tag -compact -width 3n +.It Fl V , Fl Fl version +Display version information and exit. +.Pp +.It Fl h , Fl Fl help +Print the command line options. +.Pp +.It Fl m Ar file +Add record of plugin to Turtle manifest +.Ar file . +.Pp +.It Fl p Ar file +Write description of plugin to Turtle +.Ar file . +.El +.Sh ENVIRONMENT +.Bl -tag -width LV2_PATH -compact +.It Ev LV2_PATH +List of directories to search for LV2 plugin bundles, +in the style of +.Ev PATH . +.El +.Sh EXIT STATUS +.Nm +exits with a status of 0, or non-zero if an error occurred. +.Sh SEE ALSO +.Bl -item -compact +.It +.Xr lv2apply 1 +.It +.Xr lv2bench 1 +.It +.Xr lv2ls 1 +.El +.Sh AUTHORS +.Nm +is a part of lilv, by +.An David Robillard +.Mt d@drobilla.net . diff --git a/doc/lv2ls.1 b/doc/lv2ls.1 index 320b71c..fffe7c0 100644 --- a/doc/lv2ls.1 +++ b/doc/lv2ls.1 @@ -1,30 +1,59 @@ -.TH LV2LS 1 "26 Aug 2016" - -.SH NAME -.B lv2ls \- list all installed LV2 plugins - -.SH SYNOPSIS -.B lv2ls [OPTION]... - -.SH OPTIONS -.TP -\fB\-n\fR, \fB\-\-names\fR -Show names instead of URIs - -.TP -\fB\-\-help\fR -Display help and exit - -.TP -\fB\-\-version\fR -Display version information and exit - -.SH "SEE ALSO" -.BR lilv(3), -.BR lv2info(1) - -.SH AUTHOR -lv2ls was written by David Robillard <d@drobilla.net> -.PP -This manual page was written by JaromÃr Mikes <mira.mikes@seznam.cz> -and David Robillard <d@drobilla.net> +.\" # Copyright 2010-2022 David Robillard <d@drobilla.net> +.\" # SPDX-License-Identifier: ISC +.Dd Nov 29, 2022 +.Dt LV2LS 1 +.Os Lilv 0.24.21 +.Sh NAME +.Nm lv2ls +.Nd list all installed LV2 plugins +.Sh SYNOPSIS +.Nm lv2ls +.Op Fl Vhn +.Op Fl Fl help +.Op Fl Fl names +.Op Fl Fl version +.Sh DESCRIPTION +.Nm +prints the URI of every installed LV2 plugin to stdout. +.Pp +Plugins are discovered with the same mechanism used by most hosts. +The default path can be overridden by setting the +.Ev LV2_PATH +environment variable. +.Pp +The options are as follows: +.Pp +.Bl -tag -compact -width 3n +.It Fl V , Fl Fl version +Display version information and exit. +.Pp +.It Fl h , Fl Fl help +Print the command line options. +.Pp +.It Fl n , Fl Fl names +Show names instead of URIs. +.El +.Sh ENVIRONMENT +.Bl -tag -width LV2_PATH -compact +.It Ev LV2_PATH +List of directories to search for LV2 plugin bundles, +in the style of +.Ev PATH . +.El +.Sh EXIT STATUS +.Nm +exits with a status of 0, or non-zero if an error occurred. +.Sh SEE ALSO +.Bl -item -compact +.It +.Xr lv2apply 1 +.It +.Xr lv2bench 1 +.It +.Xr lv2info 1 +.El +.Sh AUTHORS +.Nm +is a part of lilv, by +.An David Robillard +.Mt d@drobilla.net . diff --git a/doc/meson.build b/doc/meson.build new file mode 100644 index 0000000..787ab4f --- /dev/null +++ b/doc/meson.build @@ -0,0 +1,66 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +docdir = get_option('datadir') / 'doc' + +# Find required programs +doxygen = find_program('doxygen', required: get_option('docs')) +sphinx_build = find_program('sphinx-build', required: get_option('docs')) + +# Find sphinxygen or fall back to subproject +sphinxygen = disabler() +if doxygen.found() and sphinx_build.found() + sphinxygen = find_program('sphinxygen', required: false) + if not sphinxygen.found() + subproject('sphinxygen') + sphinxygen = find_program('sphinxygen', required: get_option('docs')) + endif +endif + +# Build documentation if all required tools are found +build_docs = doxygen.found() and sphinxygen.found() and sphinx_build.found() +if build_docs + # Configure conf.py for Sphinx + conf_config = configuration_data() + conf_config.set('LILV_SRCDIR', lilv_src_root) + conf_config.set('LILV_TITLE', get_option('title')) + conf_config.set('LILV_VERSION', meson.project_version()) + conf_py = configure_file( + configuration: conf_config, + input: files('conf.py.in'), + output: 'conf.py', + ) + + # Copy hand-written documentation files + c_rst_files = files( + 'index.rst', + 'overview.rst', + 'plugins.rst', + 'uis.rst', + 'world.rst', + ) + foreach f : c_rst_files + configure_file(copy: true, input: f, output: '@PLAINNAME@') + endforeach + + # Generate reference documentation input with Doxygen and Sphinxygen + subdir('xml') + subdir('api') + + # Build strict Sphinx flags, with termination on warnings if werror=true + sphinx_flags = ['-E', '-a', '-q'] + if get_option('werror') + sphinx_flags += ['-W'] + endif + + # Run Sphinx to generate final documentation for each format + foreach format : ['html', 'singlehtml'] + if not get_option(format).disabled() + subdir(format) + endif + endforeach +endif + +if not meson.is_subproject() + summary('Documentation', build_docs, bool_yn: true, section: 'Components') +endif diff --git a/doc/c/overview.rst b/doc/overview.rst index 6abc123..17ebec9 100644 --- a/doc/c/overview.rst +++ b/doc/overview.rst @@ -1,3 +1,7 @@ +.. + Copyright 2020-2022 David Robillard <d@drobilla.net> + SPDX-License-Identifier: ISC + .. default-domain:: c .. highlight:: c diff --git a/doc/c/plugins.rst b/doc/plugins.rst index c86431e..c7ad547 100644 --- a/doc/c/plugins.rst +++ b/doc/plugins.rst @@ -1,3 +1,7 @@ +.. + Copyright 2020-2022 David Robillard <d@drobilla.net> + SPDX-License-Identifier: ISC + .. default-domain:: c .. highlight:: c diff --git a/doc/singlehtml/meson.build b/doc/singlehtml/meson.build new file mode 100644 index 0000000..4822d8c --- /dev/null +++ b/doc/singlehtml/meson.build @@ -0,0 +1,26 @@ +# Copyright 2021-2023 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +singlehtml_dir = docdir / versioned_name / 'singlehtml' + +# TODO: Add install_tag: 'doc' after requiring meson 0.60.0 + +custom_target( + 'singlehtml', + build_by_default: true, + command: [ + sphinx_build, '-M', 'singlehtml', '@OUTDIR@' / '..', '@OUTDIR@' / '..', + '-t', 'singlehtml', + ] + sphinx_flags, + input: [c_rst_files, c_lilv_rst, c_index_xml, conf_py], + install: true, + install_dir: singlehtml_dir, + output: [ + '_static', + 'index.html', + ], +) + +if not meson.is_subproject() + summary('Unified HTML', get_option('prefix') / singlehtml_dir, section: 'Directories') +endif diff --git a/doc/c/uis.rst b/doc/uis.rst index 5abaa2c..1169060 100644 --- a/doc/c/uis.rst +++ b/doc/uis.rst @@ -1,3 +1,7 @@ +.. + Copyright 2020-2022 David Robillard <d@drobilla.net> + SPDX-License-Identifier: ISC + .. default-domain:: c .. highlight:: c diff --git a/doc/c/world.rst b/doc/world.rst index 4128f77..8b71165 100644 --- a/doc/c/world.rst +++ b/doc/world.rst @@ -1,3 +1,7 @@ +.. + Copyright 2020-2022 David Robillard <d@drobilla.net> + SPDX-License-Identifier: ISC + .. default-domain:: c .. highlight:: c diff --git a/doc/xml/meson.build b/doc/xml/meson.build new file mode 100644 index 0000000..dc234f3 --- /dev/null +++ b/doc/xml/meson.build @@ -0,0 +1,21 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +doxygen = find_program('doxygen') + +config = configuration_data() +config.set('LILV_SRCDIR', lilv_src_root) +config.set('DOX_OUTPUT', meson.current_build_dir() / '..') + +c_doxyfile = configure_file( + configuration: config, + input: files('../Doxyfile.in'), + output: 'Doxyfile', +) + +c_index_xml = custom_target( + 'index.xml', + command: [doxygen, '@INPUT0@'], + input: [c_doxyfile] + c_headers, + output: 'index.xml', +) diff --git a/include/lilv/lilv.h b/include/lilv/lilv.h index 5fd7a9f..b863a14 100644 --- a/include/lilv/lilv.h +++ b/include/lilv/lilv.h @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC /// @file lilv.h API for Lilv, a lightweight LV2 host library. @@ -22,19 +9,22 @@ #include "lv2/core/lv2.h" #include "lv2/urid/urid.h" -#include <stdarg.h> +#include <stdarg.h> // IWYU pragma: keep #include <stdbool.h> #include <stdint.h> #include <stdio.h> -#if defined(_WIN32) && !defined(LILV_STATIC) && defined(LILV_INTERNAL) -# define LILV_API __declspec(dllexport) -#elif defined(_WIN32) && !defined(LILV_STATIC) -# define LILV_API __declspec(dllimport) -#elif defined(__GNUC__) -# define LILV_API __attribute__((visibility("default"))) -#else -# define LILV_API +// LILV_API must be used to decorate things in the public API +#ifndef LILV_API +# if defined(_WIN32) && !defined(LILV_STATIC) && defined(LILV_INTERNAL) +# define LILV_API __declspec(dllexport) +# elif defined(_WIN32) && !defined(LILV_STATIC) +# define LILV_API __declspec(dllimport) +# elif defined(__GNUC__) +# define LILV_API __attribute__((visibility("default"))) +# else +# define LILV_API +# endif #endif #if defined(__GNUC__) && \ diff --git a/include/lilv/lilvmm.hpp b/include/lilv/lilvmm.hpp index 0ac802d..6e270df 100644 --- a/include/lilv/lilvmm.hpp +++ b/include/lilv/lilvmm.hpp @@ -1,18 +1,5 @@ -/* - Copyright 2007-2017 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2017 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #ifndef LILV_LILVMM_HPP #define LILV_LILVMM_HPP @@ -60,20 +47,35 @@ uri_to_path(const char* uri) # pragma GCC diagnostic pop #endif -#define LILV_WRAP0(RT, prefix, name) \ - inline RT name() { return lilv_##prefix##_##name(me); } +#define LILV_WRAP0(RT, prefix, name) \ + inline RT name() \ + { \ + return lilv_##prefix##_##name(me); \ + } #define LILV_WRAP0_VOID(prefix, name) \ - inline void name() { lilv_##prefix##_##name(me); } + inline void name() \ + { \ + lilv_##prefix##_##name(me); \ + } #define LILV_WRAP1(RT, prefix, name, T1, a1) \ - inline RT name(T1 a1) { return lilv_##prefix##_##name(me, a1); } + inline RT name(T1 a1) \ + { \ + return lilv_##prefix##_##name(me, a1); \ + } #define LILV_WRAP1_VOID(prefix, name, T1, a1) \ - inline void name(T1 a1) { lilv_##prefix##_##name(me, a1); } + inline void name(T1 a1) \ + { \ + lilv_##prefix##_##name(me, a1); \ + } #define LILV_WRAP2(RT, prefix, name, T1, a1, T2, a2) \ - inline RT name(T1 a1, T2 a2) { return lilv_##prefix##_##name(me, a1, a2); } + inline RT name(T1 a1, T2 a2) \ + { \ + return lilv_##prefix##_##name(me, a1, a2); \ + } #define LILV_WRAP3(RT, prefix, name, T1, a1, T2, a2, T3, a3) \ inline RT name(T1 a1, T2 a2, T3 a3) \ @@ -82,11 +84,17 @@ uri_to_path(const char* uri) } #define LILV_WRAP2_VOID(prefix, name, T1, a1, T2, a2) \ - inline void name(T1 a1, T2 a2) { lilv_##prefix##_##name(me, a1, a2); } + inline void name(T1 a1, T2 a2) \ + { \ + lilv_##prefix##_##name(me, a1, a2); \ + } #ifndef SWIG # define LILV_WRAP_CONVERSION(CT) \ - inline operator CT*() const { return me; } + inline operator CT*() const \ + { \ + return me; \ + } #else # define LILV_WRAP_CONVERSION(CT) #endif @@ -133,22 +141,22 @@ struct Node { inline bool operator==(const Node& other) const { return equals(other); } - LILV_WRAP_CONVERSION(LilvNode); - - LILV_WRAP0(char*, node, get_turtle_token); - LILV_WRAP0(bool, node, is_uri); - LILV_WRAP0(const char*, node, as_uri); - LILV_WRAP0(bool, node, is_blank); - LILV_WRAP0(const char*, node, as_blank); - LILV_WRAP0(bool, node, is_literal); - LILV_WRAP0(bool, node, is_string); - LILV_WRAP0(const char*, node, as_string); - LILV_WRAP0(bool, node, is_float); - LILV_WRAP0(float, node, as_float); - LILV_WRAP0(bool, node, is_int); - LILV_WRAP0(int, node, as_int); - LILV_WRAP0(bool, node, is_bool); - LILV_WRAP0(bool, node, as_bool); + LILV_WRAP_CONVERSION(LilvNode) + + LILV_WRAP0(char*, node, get_turtle_token) + LILV_WRAP0(bool, node, is_uri) + LILV_WRAP0(const char*, node, as_uri) + LILV_WRAP0(bool, node, is_blank) + LILV_WRAP0(const char*, node, as_blank) + LILV_WRAP0(bool, node, is_literal) + LILV_WRAP0(bool, node, is_string) + LILV_WRAP0(const char*, node, as_string) + LILV_WRAP0(bool, node, is_float) + LILV_WRAP0(float, node, as_float) + LILV_WRAP0(bool, node, is_int) + LILV_WRAP0(int, node, as_int) + LILV_WRAP0(bool, node, is_bool) + LILV_WRAP0(bool, node, as_bool) LilvNode* me; }; @@ -158,10 +166,10 @@ struct ScalePoint { : me(c_obj) {} - LILV_WRAP_CONVERSION(const LilvScalePoint); + LILV_WRAP_CONVERSION(const LilvScalePoint) - LILV_WRAP0(const LilvNode*, scale_point, get_label); - LILV_WRAP0(const LilvNode*, scale_point, get_value); + LILV_WRAP0(const LilvNode*, scale_point, get_label) + LILV_WRAP0(const LilvNode*, scale_point, get_value) const LilvScalePoint* me; }; @@ -171,41 +179,41 @@ struct PluginClass { : me(c_obj) {} - LILV_WRAP_CONVERSION(const LilvPluginClass); + LILV_WRAP_CONVERSION(const LilvPluginClass) - LILV_WRAP0(Node, plugin_class, get_parent_uri); - LILV_WRAP0(Node, plugin_class, get_uri); - LILV_WRAP0(Node, plugin_class, get_label); - LILV_WRAP0(LilvPluginClasses*, plugin_class, get_children); + LILV_WRAP0(Node, plugin_class, get_parent_uri) + LILV_WRAP0(Node, plugin_class, get_uri) + LILV_WRAP0(Node, plugin_class, get_label) + LILV_WRAP0(LilvPluginClasses*, plugin_class, get_children) const LilvPluginClass* me; }; -#define LILV_WRAP_COLL(CT, ET, prefix) \ - inline CT(const Lilv##CT* c_obj) \ - : me(c_obj) \ - {} \ - LILV_WRAP_CONVERSION(const Lilv##CT); \ - LILV_WRAP0(unsigned, prefix, size); \ - LILV_WRAP1(ET, prefix, get, LilvIter*, i); \ - LILV_WRAP0(LilvIter*, prefix, begin); \ - LILV_WRAP1(LilvIter*, prefix, next, LilvIter*, i); \ - LILV_WRAP1(bool, prefix, is_end, LilvIter*, i); \ +#define LILV_WRAP_COLL(CT, ET, prefix) \ + inline CT(const Lilv##CT* c_obj) \ + : me(c_obj) \ + {} \ + LILV_WRAP_CONVERSION(const Lilv##CT) \ + LILV_WRAP0(unsigned, prefix, size) \ + LILV_WRAP1(ET, prefix, get, LilvIter*, i) \ + LILV_WRAP0(LilvIter*, prefix, begin) \ + LILV_WRAP1(LilvIter*, prefix, next, LilvIter*, i) \ + LILV_WRAP1(bool, prefix, is_end, LilvIter*, i) \ const Lilv##CT* me; struct PluginClasses { - LILV_WRAP_COLL(PluginClasses, PluginClass, plugin_classes); - LILV_WRAP1(PluginClass, plugin_classes, get_by_uri, const LilvNode*, uri); + LILV_WRAP_COLL(PluginClasses, PluginClass, plugin_classes) + LILV_WRAP1(PluginClass, plugin_classes, get_by_uri, const LilvNode*, uri) }; struct ScalePoints { - LILV_WRAP_COLL(ScalePoints, ScalePoint, scale_points); + LILV_WRAP_COLL(ScalePoints, ScalePoint, scale_points) }; struct Nodes { - LILV_WRAP_COLL(Nodes, Node, nodes); - LILV_WRAP1(bool, nodes, contains, const Node&, node); - LILV_WRAP0(Node, nodes, get_first); + LILV_WRAP_COLL(Nodes, Node, nodes) + LILV_WRAP1(bool, nodes, contains, const Node&, node) + LILV_WRAP0(Node, nodes, get_first) }; struct UI { @@ -213,23 +221,23 @@ struct UI { : me(c_obj) {} - LILV_WRAP_CONVERSION(const LilvUI); + LILV_WRAP_CONVERSION(const LilvUI) - LILV_WRAP0(const LilvNode*, ui, get_uri); - LILV_WRAP0(const LilvNode*, ui, get_bundle_uri); - LILV_WRAP0(const LilvNode*, ui, get_binary_uri); - LILV_WRAP0(const LilvNodes*, ui, get_classes); + LILV_WRAP0(const LilvNode*, ui, get_uri) + LILV_WRAP0(const LilvNode*, ui, get_bundle_uri) + LILV_WRAP0(const LilvNode*, ui, get_binary_uri) + LILV_WRAP0(const LilvNodes*, ui, get_classes) /*LILV_WRAP3(bool, ui, is_supported, LilvUISupportedFunc, supported_func, const LilvNode*, container_type, const LilvNode**, ui_type);*/ - LILV_WRAP1(bool, ui, is_a, const LilvNode*, class_uri); + LILV_WRAP1(bool, ui, is_a, const LilvNode*, class_uri) const LilvUI* me; }; struct UIs { - LILV_WRAP_COLL(UIs, UI, uis); + LILV_WRAP_COLL(UIs, UI, uis) }; struct Port { @@ -238,23 +246,29 @@ struct Port { , me(c_obj) {} - LILV_WRAP_CONVERSION(const LilvPort); + LILV_WRAP_CONVERSION(const LilvPort) -#define LILV_PORT_WRAP0(RT, name) \ - inline RT name() { return lilv_port_##name(parent, me); } +#define LILV_PORT_WRAP0(RT, name) \ + inline RT name() \ + { \ + return lilv_port_##name(parent, me); \ + } -#define LILV_PORT_WRAP1(RT, name, T1, a1) \ - inline RT name(T1 a1) { return lilv_port_##name(parent, me, a1); } +#define LILV_PORT_WRAP1(RT, name, T1, a1) \ + inline RT name(T1 a1) \ + { \ + return lilv_port_##name(parent, me, a1); \ + } - LILV_PORT_WRAP1(LilvNodes*, get_value, LilvNode*, predicate); + LILV_PORT_WRAP1(LilvNodes*, get_value, LilvNode*, predicate) LILV_PORT_WRAP0(LilvNodes*, get_properties) - LILV_PORT_WRAP1(bool, has_property, LilvNode*, property_uri); - LILV_PORT_WRAP1(bool, supports_event, LilvNode*, event_uri); - LILV_PORT_WRAP0(const LilvNode*, get_symbol); - LILV_PORT_WRAP0(LilvNode*, get_name); - LILV_PORT_WRAP0(const LilvNodes*, get_classes); - LILV_PORT_WRAP1(bool, is_a, LilvNode*, port_class); - LILV_PORT_WRAP0(LilvScalePoints*, get_scale_points); + LILV_PORT_WRAP1(bool, has_property, LilvNode*, property_uri) + LILV_PORT_WRAP1(bool, supports_event, LilvNode*, event_uri) + LILV_PORT_WRAP0(const LilvNode*, get_symbol) + LILV_PORT_WRAP0(LilvNode*, get_name) + LILV_PORT_WRAP0(const LilvNodes*, get_classes) + LILV_PORT_WRAP1(bool, is_a, LilvNode*, port_class) + LILV_PORT_WRAP0(LilvScalePoints*, get_scale_points) // TODO: get_range (output parameters) @@ -267,30 +281,30 @@ struct Plugin { : me(c_obj) {} - LILV_WRAP_CONVERSION(const LilvPlugin); - - LILV_WRAP0(bool, plugin, verify); - LILV_WRAP0(Node, plugin, get_uri); - LILV_WRAP0(Node, plugin, get_bundle_uri); - LILV_WRAP0(Nodes, plugin, get_data_uris); - LILV_WRAP0(Node, plugin, get_library_uri); - LILV_WRAP0(Node, plugin, get_name); - LILV_WRAP0(PluginClass, plugin, get_class); - LILV_WRAP1(Nodes, plugin, get_value, const Node&, pred); - LILV_WRAP1(bool, plugin, has_feature, const Node&, feature_uri); - LILV_WRAP0(Nodes, plugin, get_supported_features); - LILV_WRAP0(Nodes, plugin, get_required_features); - LILV_WRAP0(Nodes, plugin, get_optional_features); - LILV_WRAP0(unsigned, plugin, get_num_ports); - LILV_WRAP0(bool, plugin, has_latency); - LILV_WRAP0(unsigned, plugin, get_latency_port_index); - LILV_WRAP0(Node, plugin, get_author_name); - LILV_WRAP0(Node, plugin, get_author_email); - LILV_WRAP0(Node, plugin, get_author_homepage); - LILV_WRAP0(bool, plugin, is_replaced); - LILV_WRAP0(Nodes, plugin, get_extension_data); - LILV_WRAP0(UIs, plugin, get_uis); - LILV_WRAP1(Nodes, plugin, get_related, const Node&, type); + LILV_WRAP_CONVERSION(const LilvPlugin) + + LILV_WRAP0(bool, plugin, verify) + LILV_WRAP0(Node, plugin, get_uri) + LILV_WRAP0(Node, plugin, get_bundle_uri) + LILV_WRAP0(Nodes, plugin, get_data_uris) + LILV_WRAP0(Node, plugin, get_library_uri) + LILV_WRAP0(Node, plugin, get_name) + LILV_WRAP0(PluginClass, plugin, get_class) + LILV_WRAP1(Nodes, plugin, get_value, const Node&, pred) + LILV_WRAP1(bool, plugin, has_feature, const Node&, feature_uri) + LILV_WRAP0(Nodes, plugin, get_supported_features) + LILV_WRAP0(Nodes, plugin, get_required_features) + LILV_WRAP0(Nodes, plugin, get_optional_features) + LILV_WRAP0(unsigned, plugin, get_num_ports) + LILV_WRAP0(bool, plugin, has_latency) + LILV_WRAP0(unsigned, plugin, get_latency_port_index) + LILV_WRAP0(Node, plugin, get_author_name) + LILV_WRAP0(Node, plugin, get_author_email) + LILV_WRAP0(Node, plugin, get_author_homepage) + LILV_WRAP0(bool, plugin, is_replaced) + LILV_WRAP0(Nodes, plugin, get_extension_data) + LILV_WRAP0(UIs, plugin, get_uis) + LILV_WRAP1(Nodes, plugin, get_related, const Node&, type) inline Port get_port_by_index(unsigned index) const { @@ -312,7 +326,7 @@ struct Plugin { inline unsigned get_num_ports_of_class(LilvNode* class_1, ...) const { - va_list args; + va_list args; // NOLINT(cppcoreguidelines-init-variables) va_start(args, class_1); const uint32_t count = @@ -326,8 +340,8 @@ struct Plugin { }; struct Plugins { - LILV_WRAP_COLL(Plugins, Plugin, plugins); - LILV_WRAP1(Plugin, plugins, get_by_uri, const LilvNode*, uri); + LILV_WRAP_COLL(Plugins, Plugin, plugins) + LILV_WRAP1(Plugin, plugins, get_by_uri, const LilvNode*, uri) }; struct Instance { @@ -337,16 +351,15 @@ struct Instance { LILV_DEPRECATED inline Instance(Plugin plugin, double sample_rate) - { - me = lilv_plugin_instantiate(plugin, sample_rate, nullptr); - } + : me(lilv_plugin_instantiate(plugin, sample_rate, nullptr)) + {} - LILV_DEPRECATED inline Instance(Plugin plugin, - double sample_rate, - LV2_Feature* const* features) - { - me = lilv_plugin_instantiate(plugin, sample_rate, features); - } + LILV_DEPRECATED + inline Instance(Plugin plugin, + double sample_rate, + LV2_Feature* const* features) + : me(lilv_plugin_instantiate(plugin, sample_rate, features)) + {} static inline Instance* create(Plugin plugin, double sample_rate, @@ -357,18 +370,18 @@ struct Instance { return me ? new Instance(me) : nullptr; } - LILV_WRAP_CONVERSION(LilvInstance); + LILV_WRAP_CONVERSION(LilvInstance) LILV_WRAP2_VOID(instance, connect_port, unsigned, port_index, void*, - data_location); + data_location) - LILV_WRAP0_VOID(instance, activate); - LILV_WRAP1_VOID(instance, run, unsigned, sample_count); - LILV_WRAP0_VOID(instance, deactivate); + LILV_WRAP0_VOID(instance, activate) + LILV_WRAP1_VOID(instance, run, unsigned, sample_count) + LILV_WRAP0_VOID(instance, deactivate) inline const void* get_extension_data(const char* uri) const { @@ -392,10 +405,10 @@ struct World { inline ~World() { lilv_world_free(me); } - World(const World&) = delete; + World(const World&) = delete; World& operator=(const World&) = delete; - World(World&&) = delete; + World(World&&) = delete; World& operator=(World&&) = delete; inline LilvNode* new_uri(const char* uri) const @@ -424,13 +437,13 @@ struct World { return lilv_world_find_nodes(me, subject, predicate, object); } - LILV_WRAP2_VOID(world, set_option, const char*, uri, LilvNode*, value); - LILV_WRAP0_VOID(world, load_all); - LILV_WRAP1_VOID(world, load_bundle, LilvNode*, bundle_uri); - LILV_WRAP0(const LilvPluginClass*, world, get_plugin_class); - LILV_WRAP0(const LilvPluginClasses*, world, get_plugin_classes); - LILV_WRAP0(Plugins, world, get_all_plugins); - LILV_WRAP1(int, world, load_resource, const LilvNode*, resource); + LILV_WRAP2_VOID(world, set_option, const char*, uri, LilvNode*, value) + LILV_WRAP0_VOID(world, load_all) + LILV_WRAP1_VOID(world, load_bundle, LilvNode*, bundle_uri) + LILV_WRAP0(const LilvPluginClass*, world, get_plugin_class) + LILV_WRAP0(const LilvPluginClasses*, world, get_plugin_classes) + LILV_WRAP0(Plugins, world, get_all_plugins) + LILV_WRAP1(int, world, load_resource, const LilvNode*, resource) LilvWorld* me; }; diff --git a/lilv.pc.in b/lilv.pc.in deleted file mode 100644 index 97f4f8c..0000000 --- a/lilv.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@PREFIX@ -exec_prefix=@EXEC_PREFIX@ -libdir=@LIBDIR@ -includedir=@INCLUDEDIR@ - -Name: Lilv -Version: @LILV_VERSION@ -Description: Simple C library for hosting LV2 plugins -Requires: @LILV_PKG_DEPS@ -Libs: -L${libdir} -l@LIB_LILV@ @LILV_PKG_LIBS@ -Cflags: -I${includedir}/lilv-@LILV_MAJOR_VERSION@ @@ -1,29 +1,29 @@ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . -@prefix : <http://usefulinc.com/ns/doap#> . +@prefix doap: <http://usefulinc.com/ns/doap#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . -<http://drobilla.net/software/lilv> - a :Project ; - :bug-database <http://dev.drobilla.net/query?status=new&status=assigned&status=reopened&component=LILV&order=priority> ; - :developer [ - a foaf:Person ; - rdfs:seeAlso <http://drobilla.net/drobilla.rdf> ; - foaf:homepage <http://drobilla.net> ; - foaf:mbox_sha1sum "253b3c58086250260bac1232d744d150274ad308" ; - foaf:name "David Robillard" - ] ; - :download-page <http://download.drobilla.net> ; - :homepage <http://drobilla.net/software/lilv> ; - :license <http://usefulinc.com/doap/licenses/gpl> ; - :name "LILV" ; - :programming-language "C", "Turtle" ; - :repository [ - :browse <http://dev.drobilla.net/browser/trunk/lilv> ; - :location <http://svn.drobilla.net/lad/trunk/lilv> ; - a :SVNRepository - ] ; - :shortdesc "Library for simple use of LV2 plugins" ; - :shortname "LILV" . - +<http://drobilla.net/drobilla#me> + a foaf:Person ; + rdfs:seeAlso <http://drobilla.net/drobilla> ; + foaf:mbox <mailto:d@drobilla.net> ; + foaf:name "David Robillard" ; + foaf:nick "drobilla" . +<http://drobilla.net/software/lilv> + a doap:Project ; + doap:blog <https://drobilla.net/category/lilv/> ; + doap:bug-database <https://gitlab.com/lv2/lilv/issues> ; + doap:description "C library for hosting LV2 plugins" ; + doap:developer <http://drobilla.net/drobilla#me> ; + doap:download-page <http://download.drobilla.net/> ; + doap:homepage <http://drobilla.net/software/lilv> ; + doap:implements <http://lv2plug.in/ns/lv2core> ; + doap:license <http://opensource.org/licenses/isc> ; + doap:maintainer <http://drobilla.net/drobilla#me> ; + doap:name "Lilv" ; + doap:programming-language "C" ; + doap:repository [ + a doap:GitBranch ; + doap:location <https://gitlab.com/lv2/lilv.git> + ] . diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..5864f2e --- /dev/null +++ b/meson.build @@ -0,0 +1,261 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +project('lilv', ['c'], + version: '0.24.21', + license: 'ISC', + meson_version: '>= 0.56.0', + default_options: [ + 'b_ndebug=if-release', + 'buildtype=release', + 'c_std=c99', + ]) + +lilv_src_root = meson.current_source_dir() +major_version = meson.project_version().split('.')[0] +version_suffix = '-@0@'.format(major_version) +versioned_name = 'lilv' + version_suffix + +####################### +# Compilers and Flags # +####################### + +# Required tools +pkg = import('pkgconfig') +cc = meson.get_compiler('c') + +# Enable C++ support if bindings aren't disabled +if not get_option('bindings_cpp').disabled() + if add_languages(['cpp'], native: false, required: false) + cpp = meson.get_compiler('cpp') + endif +endif + +# Set global warning flags +subdir('meson/suppressions') + +########################## +# Platform Configuration # +########################## + +platform_defines = ['-DLILV_VERSION="@0@"'.format(meson.project_version())] +if host_machine.system() in ['gnu', 'linux'] + platform_defines += [ + '-D_POSIX_C_SOURCE=200809L', + ] +endif + +default_lv2_path = get_option('default_lv2_path') +if default_lv2_path == '' + if host_machine.system() == 'darwin' + lv2_dirs = [ + '~/.lv2', + '~/Library/Audio/Plug-Ins/LV2', + '/usr/local/lib/lv2', + '/usr/lib/lv2', + '/Library/Audio/Plug-Ins/LV2', + ] + + default_lv2_path = ':'.join(lv2_dirs) + + elif host_machine.system() == 'haiku' + default_lv2_path = ':'.join(['~/.lv2', '/boot/common/add-ons/lv2']) + + elif host_machine.system() == 'windows' + lv2_dirs = ['%%APPDATA%%\\\\LV2', '%%COMMONPROGRAMFILES%%\\\\LV2'] + default_lv2_path = ';'.join(lv2_dirs) + + else + lv2_dirs = [ + '~' / '.lv2', + '/usr/local' / get_option('libdir') / 'lv2', + '/usr' / get_option('libdir') / 'lv2', + ] + + default_lv2_path = ':'.join(lv2_dirs) + endif +endif + +platform_defines += [ + '-DLILV_DEFAULT_LV2_PATH="@0@"'.format(default_lv2_path) +] + +# Use versioned name everywhere to support parallel major version installations +if host_machine.system() == 'windows' + if get_option('default_library') == 'both' + error('default_library=both is not supported on Windows') + endif + soversion = '' +else + soversion = meson.project_version().split('.')[0] +endif + +add_project_arguments(platform_defines, language: ['c']) + +################ +# Dependencies # +################ + +m_dep = cc.find_library('m', required: false) +dl_dep = cc.find_library('dl', required: false) + +zix_dep = dependency('zix-0', fallback: 'zix', version: '>= 0.3.0') +serd_dep = dependency('serd-0', fallback: 'serd', version: '>= 0.30.10') +sord_dep = dependency('sord-0', fallback: 'sord', version: '>= 0.16.10') +lv2_dep = dependency('lv2', fallback: 'lv2', version: '>= 1.18.2') +sratom_dep = dependency('sratom-0', fallback: 'sratom', version: '>= 0.6.10') + +########### +# Library # +########### + +c_headers = files('include/lilv/lilv.h') +cpp_headers = files('include/lilv/lilvmm.hpp') + +sources = files( + 'src/collections.c', + 'src/instance.c', + 'src/lib.c', + 'src/node.c', + 'src/plugin.c', + 'src/pluginclass.c', + 'src/port.c', + 'src/query.c', + 'src/scalepoint.c', + 'src/state.c', + 'src/ui.c', + 'src/util.c', + 'src/world.c', +) + +common_dependencies = [ + dl_dep, + lv2_dep, + m_dep, + serd_dep, + sord_dep, + sratom_dep, + zix_dep, +] + +# Set appropriate arguments for building against the library type +extra_c_args = [] +if get_option('default_library') == 'static' + extra_c_args = ['-DLILV_STATIC'] +endif + +# Build main shared and/or static library +liblilv = library( + versioned_name, + sources, + c_args: c_suppressions + extra_c_args + ['-DLILV_INTERNAL'], + dependencies: common_dependencies, + gnu_symbol_visibility: 'hidden', + include_directories: include_directories('include', 'src'), + install: true, + soversion: soversion, + version: meson.project_version(), +) + +# Declare dependency for internal meson dependants +lilv_dep = declare_dependency( + compile_args: extra_c_args, + dependencies: common_dependencies, + include_directories: include_directories('include'), + link_with: liblilv, +) + +# Generage pkg-config file for external dependants +pkg.generate( + liblilv, + description: 'Library for hosting LV2 plugins', + extra_cflags: extra_c_args, + filebase: versioned_name, + name: 'Lilv', + requires: ['lv2'], + subdirs: [versioned_name], + version: meson.project_version(), +) + +# Override pkg-config dependency for internal meson dependants +meson.override_dependency(versioned_name, lilv_dep) + +# Install headers to a versioned include directory +install_headers(c_headers, subdir: versioned_name / 'lilv') +install_headers(cpp_headers, subdir: versioned_name / 'lilv') + +# Display top-level summary (before subdirectories to appear first) +if not meson.is_subproject() + summary( + { + 'Tests': not get_option('tests').disabled(), + 'Tools': not get_option('tools').disabled(), + }, + bool_yn: true, + section: 'Components', + ) + + summary('Default LV2_PATH', default_lv2_path, section: 'Configuration') + + summary( + { + 'Install prefix': get_option('prefix'), + 'Headers': get_option('prefix') / get_option('includedir'), + 'Libraries': get_option('prefix') / get_option('libdir'), + 'Executables': get_option('prefix') / get_option('bindir'), + 'Man pages': get_option('prefix') / get_option('mandir'), + }, + section: 'Directories', + ) +endif + +######### +# Tools # +######### + +if not get_option('tools').disabled() + subdir('tools') +endif + +############ +# Bindings # +############ + +if not get_option('bindings_py').disabled() + subdir('bindings/python') +endif + +########### +# Support # +########### + +if not get_option('docs').disabled() + subdir('doc') +endif + +if not get_option('tests').disabled() + # Get or build a static library for linking internal tests + if get_option('default_library') == 'both' + liblilv_static = liblilv.get_static_lib() + elif get_option('default_library') == 'shared' + liblilv_static = static_library( + versioned_name, + sources, + include_directories: include_directories('include', 'src'), + c_args: c_suppressions + ['-DLILV_INTERNAL', '-DLILV_STATIC'], + dependencies: common_dependencies, + gnu_symbol_visibility: 'default') + else + liblilv_static = liblilv + endif + + lilv_static_dep = declare_dependency( + compile_args: extra_c_args, + dependencies: common_dependencies, + include_directories: include_directories('include'), + link_with: liblilv_static, + ) + + # Build and run tests against static library + subdir('test') +endif diff --git a/meson/suppressions/meson.build b/meson/suppressions/meson.build new file mode 100644 index 0000000..14358bc --- /dev/null +++ b/meson/suppressions/meson.build @@ -0,0 +1,140 @@ +# Copyright 2020-2023 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +# Project-specific warning suppressions + +warning_level = get_option('warning_level') + +##### +# C # +##### + +c_suppressions = [] + +if cc.get_id() in ['clang', 'emscripten'] + if warning_level == 'everything' + c_suppressions += [ + '-Wno-cast-align', + '-Wno-cast-qual', + '-Wno-declaration-after-statement', + '-Wno-documentation-unknown-command', + '-Wno-double-promotion', + '-Wno-float-equal', + '-Wno-format-nonliteral', + '-Wno-implicit-float-conversion', + '-Wno-implicit-int-conversion', + '-Wno-nullable-to-nonnull-conversion', + '-Wno-padded', + '-Wno-reserved-id-macro', + '-Wno-shorten-64-to-32', + '-Wno-sign-conversion', + '-Wno-switch-enum', + '-Wno-vla', + ] + + if not meson.is_cross_build() + c_suppressions += [ + '-Wno-poison-system-directories', + ] + endif + endif + + if warning_level in ['everything', '3'] + c_suppressions += [ + '-Wno-nullability-extension', + ] + + if host_machine.system() == 'freebsd' + c_suppressions += [ + '-Wno-c11-extensions', + ] + elif host_machine.system() == 'darwin' + c_suppressions += [ + '-Wno-unused-macros', + ] + elif host_machine.system() == 'windows' + c_suppressions += [ + '-Wno-deprecated-declarations', + '-Wno-nonportable-system-include-path', + '-Wno-unused-macros', + ] + endif + endif + +elif cc.get_id() == 'gcc' + if warning_level == 'everything' + c_suppressions += [ + '-Wno-cast-align', + '-Wno-cast-qual', + '-Wno-conversion', + '-Wno-double-promotion', + '-Wno-float-equal', + '-Wno-format-nonliteral', + '-Wno-format-truncation', + '-Wno-inline', + '-Wno-padded', + '-Wno-stack-protector', + '-Wno-strict-overflow', + '-Wno-suggest-attribute=const', + '-Wno-suggest-attribute=pure', + '-Wno-switch-default', + '-Wno-switch-enum', + '-Wno-unsuffixed-float-constants', + '-Wno-unused-const-variable', + '-Wno-unused-parameter', + '-Wno-vla', + ] + endif + + if warning_level in ['everything', '3'] + c_suppressions += [ + '-Wno-pedantic', + ] + endif + + if host_machine.system() == 'windows' + c_suppressions += [ + '-Wno-bad-function-cast', + '-Wno-unused-macros', + ] + endif + +elif cc.get_id() == 'msvc' + c_suppressions += [ + '/experimental:external', + '/external:W0', + '/external:anglebrackets', + ] + + if warning_level == 'everything' + c_suppressions += [ + '/wd4061', # enumerator in switch is not explicitly handled + '/wd4191', # unsafe conversion from FARPROC + '/wd4365', # signed/unsigned mismatch + '/wd4514', # unreferenced inline function has been removed + '/wd4710', # function not inlined + '/wd4711', # function selected for automatic inline expansion + '/wd4774', # format string is not a string literal + '/wd4800', # implicit conversion to bool + '/wd4820', # padding added after construct + '/wd5045', # will insert Spectre mitigation for memory load + ] + endif + + if warning_level in ['everything', '3'] + c_suppressions += [ + '/wd4090', # different const qualifiers + '/wd4706', # assignment within conditional expression + ] + endif + + if warning_level in ['everything', '3', '2'] + c_suppressions += [ + '/wd4244', # conversion from floating point, possible loss of data + '/wd4267', # conversion from size_t, possible loss of data + '/wd4996', # POSIX name for this item is deprecated + ] + endif +endif + +c_suppressions = cc.get_supported_arguments(c_suppressions) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..4419e9d --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,29 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +option('bindings_py', type: 'feature', value: 'auto', yield: true, + description: 'Build Python bindings') + +option('bindings_cpp', type: 'feature', value: 'auto', yield: true, + description: 'Build C++ bindings') + +option('default_lv2_path', type: 'string', value: '', yield: true, + description: 'Default LV2_PATH to use if it is unset') + +option('docs', type: 'feature', value: 'auto', yield: true, + description: 'Build documentation') + +option('html', type: 'feature', value: 'auto', yield: true, + description: 'Build paginated HTML documentation') + +option('singlehtml', type: 'feature', value: 'auto', yield: true, + description: 'Build single-page HTML documentation') + +option('tests', type: 'feature', value: 'auto', yield: true, + description: 'Build tests') + +option('title', type: 'string', value: 'Lilv', + description: 'Project title') + +option('tools', type: 'feature', value: 'auto', yield: true, + description: 'Build command line utilities') diff --git a/scripts/dox_to_sphinx.py b/scripts/dox_to_sphinx.py deleted file mode 100755 index 024f125..0000000 --- a/scripts/dox_to_sphinx.py +++ /dev/null @@ -1,655 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2020 David Robillard <d@drobilla.net> -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -""" -Write Sphinx markup from Doxygen XML. - -Takes a path to a directory of XML generated by Doxygen, and emits a directory -with a reStructuredText file for every documented symbol. -""" - -import argparse -import os -import sys -import textwrap -import xml.etree.ElementTree - -__author__ = "David Robillard" -__date__ = "2020-11-18" -__email__ = "d@drobilla.net" -__license__ = "ISC" -__version__ = __date__.replace("-", ".") - - -def load_index(index_path): - """ - Load the index from XML. - - :returns: A dictionary from ID to skeleton records with basic information - for every documented entity. Some records have an ``xml_filename`` key - with the filename of a definition file. These files will be loaded later - to flesh out the records in the index. - """ - - root = xml.etree.ElementTree.parse(index_path).getroot() - index = {} - - for compound in root: - compound_id = compound.get("refid") - compound_kind = compound.get("kind") - compound_name = compound.find("name").text - if compound_kind in ["dir", "file", "page"]: - continue - - # Add record for compound (compounds appear only once in the index) - assert compound_id not in index - index[compound_id] = { - "kind": compound_kind, - "name": compound_name, - "xml_filename": compound_id + ".xml", - "children": [], - } - - name_prefix = ( - ("%s::" % compound_name) if compound_kind == "namespace" else "" - ) - - for child in compound.findall("member"): - if child.get("refid") in index: - assert compound_kind == "group" - continue - - # Everything has a kind and a name - child_record = { - "kind": child.get("kind"), - "name": name_prefix + child.find("name").text, - } - - if child.get("kind") == "enum": - # Enums are not compounds, but we want to resolve the parent of - # their values so they are not written as top level documents - child_record["children"] = [] - - if child.get("kind") == "enumvalue": - # Remove namespace prefix - child_record["name"] = child.find("name").text - - index[child.get("refid")] = child_record - - return index - - -def resolve_index(index, root): - """ - Walk a definition document and extend the index for linking. - - This does two things: sets the "parent" and "children" fields of all - applicable records, and sets the "strong" field of enums so that the - correct Sphinx role can be used when referring to them. - """ - - def add_child(index, parent_id, child_id): - parent = index[parent_id] - child = index[child_id] - - if child["kind"] == "enumvalue": - assert parent["kind"] == "enum" - assert "parent" not in child or child["parent"] == parent_id - child["parent"] = parent_id - - else: - if parent["kind"] in ["class", "struct", "union"]: - assert "parent" not in child or child["parent"] == parent_id - child["parent"] = parent_id - - if child_id not in parent["children"]: - parent["children"] += [child_id] - - compound = root.find("compounddef") - compound_kind = compound.get("kind") - - if compound_kind == "group": - for subgroup in compound.findall("innergroup"): - add_child(index, compound.get("id"), subgroup.get("refid")) - - for klass in compound.findall("innerclass"): - add_child(index, compound.get("id"), klass.get("refid")) - - for section in compound.findall("sectiondef"): - if section.get("kind").startswith("private"): - for member in section.findall("memberdef"): - if member.get("id") in index: - del index[member.get("id")] - else: - for member in section.findall("memberdef"): - member_id = member.get("id") - add_child(index, compound.get("id"), member_id) - - if member.get("kind") == "enum": - index[member_id]["strong"] = member.get("strong") == "yes" - for value in member.findall("enumvalue"): - add_child(index, member_id, value.get("id")) - - -def sphinx_role(record, lang): - """ - Return the Sphinx role used for a record. - - This is used for the description directive like ".. c:function::", and - links like ":c:func:`foo`. - """ - - kind = record["kind"] - - if kind in ["class", "function", "namespace", "struct", "union"]: - return lang + ":" + kind - - if kind == "define": - return "c:macro" - - if kind == "enum": - return lang + (":enum-class" if record["strong"] else ":enum") - - if kind == "typedef": - return lang + ":type" - - if kind == "enumvalue": - return lang + ":enumerator" - - if kind == "variable": - return lang + (":member" if "parent" in record else ":var") - - raise RuntimeError("No known role for kind '%s'" % kind) - - -def child_identifier(lang, parent_name, child_name): - """ - Return the identifier for an enum value or struct member. - - Sphinx, for some reason, uses a different syntax for this in C and C++. - """ - - separator = "::" if lang == "cpp" else "." - - return "%s%s%s" % (parent_name, separator, child_name) - - -def link_markup(index, lang, refid): - """Return a Sphinx link for a Doxygen reference.""" - - record = index[refid] - kind, name = record["kind"], record["name"] - role = sphinx_role(record, lang) - - if kind in ["class", "enum", "struct", "typedef", "union"]: - return ":%s:`%s`" % (role, name) - - if kind == "function": - return ":%s:func:`%s`" % (lang, name) - - if kind == "enumvalue": - parent_name = index[record["parent"]]["name"] - return ":%s:`%s`" % (role, child_identifier(lang, parent_name, name)) - - if kind == "variable": - if "parent" not in record: - return ":%s:var:`%s`" % (lang, name) - - parent_name = index[record["parent"]]["name"] - return ":%s:`%s`" % (role, child_identifier(lang, parent_name, name)) - - if kind == "define": - return ":%s:macro:`%s`" % (lang, name) - - raise RuntimeError("Unknown link target kind: %s" % kind) - - -def indent(markup, depth): - """ - Indent markup to a depth level. - - Like textwrap.indent() but takes an integer and works in reST indentation - levels for clarity." - """ - - return textwrap.indent(markup, " " * depth) - - -def heading(text, level): - """ - Return a ReST heading at a given level. - - Follows the style in the Python documentation guide, see - <https://devguide.python.org/documenting/#sections>. - """ - - assert 1 <= level <= 6 - - chars = ("#", "*", "=", "-", "^", '"') - line = chars[level] * len(text) - - return "%s%s\n%s\n\n" % (line + "\n" if level < 3 else "", text, line) - - -def dox_to_rst(index, lang, node): - """ - Convert documentation commands (docCmdGroup) to Sphinx markup. - - This is used to convert the content of descriptions in the documentation. - It recursively parses all children tags and raises a RuntimeError if any - unknown tag is encountered. - """ - - def field_value(markup): - """Return a value for a field as a single line or indented block.""" - if "\n" in markup.strip(): - return "\n" + indent(markup, 1) - - return " " + markup.strip() - - if node.tag == "lsquo": - return "‘" - - if node.tag == "rsquo": - return "’" - - if node.tag == "computeroutput": - assert len(node) == 0 - return "``%s``" % node.text - - if node.tag == "itemizedlist": - markup = "" - for item in node.findall("listitem"): - assert len(item) == 1 - markup += "\n- %s" % dox_to_rst(index, lang, item[0]) - - return markup - - if node.tag == "para": - markup = node.text if node.text is not None else "" - for child in node: - markup += dox_to_rst(index, lang, child) - markup += child.tail if child.tail is not None else "" - - return markup.strip() + "\n\n" - - if node.tag == "parameterlist": - markup = "" - for item in node.findall("parameteritem"): - name = item.find("parameternamelist/parametername") - description = item.find("parameterdescription") - assert len(description) == 1 - markup += "\n\n:param %s:%s" % ( - name.text, - field_value(dox_to_rst(index, lang, description[0])), - ) - - return markup + "\n" - - if node.tag == "programlisting": - return "\n.. code-block:: %s\n\n%s" % ( - lang, - indent(plain_text(node), 1), - ) - - if node.tag == "ref": - refid = node.get("refid") - if refid not in index: - sys.stderr.write("warning: Unresolved link: %s\n" % refid) - return node.text - - assert len(node) == 0 - assert len(link_markup(index, lang, refid)) > 0 - return link_markup(index, lang, refid) - - if node.tag == "simplesect": - assert len(node) == 1 - - if node.get("kind") == "return": - return "\n:returns:" + field_value( - dox_to_rst(index, lang, node[0]) - ) + "\n" - - if node.get("kind") == "see": - return dox_to_rst(index, lang, node[0]) - - raise RuntimeError("Unknown simplesect kind: %s" % node.get("kind")) - - if node.tag == "ulink": - return "`%s <%s>`_" % (node.text, node.get("url")) - - raise RuntimeError("Unknown documentation command: %s" % node.tag) - - -def description_markup(index, lang, node): - """Return the markup for a brief or detailed description.""" - - assert node.tag == "briefdescription" or node.tag == "detaileddescription" - assert not (node.tag == "briefdescription" and len(node) > 1) - assert len(node.text.strip()) == 0 - - return "".join([dox_to_rst(index, lang, child) for child in node]).strip() - - -def set_descriptions(index, lang, definition, record): - """Set a record's brief/detailed descriptions from the XML definition.""" - - for tag in ["briefdescription", "detaileddescription"]: - node = definition.find(tag) - if node is not None: - record[tag] = description_markup(index, lang, node) - - -def set_template_params(node, record): - """Set a record's template_params from the XML definition.""" - - template_param_list = node.find("templateparamlist") - if template_param_list is not None: - params = [] - for param in template_param_list.findall("param"): - if param.find("declname") is not None: - # Value parameter - type_text = plain_text(param.find("type")) - name_text = plain_text(param.find("declname")) - - params += ["%s %s" % (type_text, name_text)] - else: - # Type parameter - params += ["%s" % (plain_text(param.find("type")))] - - record["template_params"] = "%s" % ", ".join(params) - - -def plain_text(node): - """ - Return the plain text of a node with all tags ignored. - - This is needed where Doxygen may include refs but Sphinx needs plain text - because it parses things itself to generate links. - """ - - if node.tag == "sp": - markup = " " - elif node.text is not None: - markup = node.text - else: - markup = "" - - for child in node: - markup += plain_text(child) - markup += child.tail if child.tail is not None else "" - - return markup - - -def local_name(name): - """Return a name with all namespace prefixes stripped.""" - - return name[name.rindex("::") + 2 :] if "::" in name else name - - -def read_definition_doc(index, lang, root): - """Walk a definition document and update described records in the index.""" - - # Set descriptions for the compound itself - compound = root.find("compounddef") - compound_record = index[compound.get("id")] - set_descriptions(index, lang, compound, compound_record) - set_template_params(compound, compound_record) - - if compound.find("title") is not None: - compound_record["title"] = compound.find("title").text.strip() - - # Set documentation for all children - for section in compound.findall("sectiondef"): - if section.get("kind").startswith("private"): - continue - - for member in section.findall("memberdef"): - kind = member.get("kind") - record = index[member.get("id")] - set_descriptions(index, lang, member, record) - set_template_params(member, record) - - if compound.get("kind") in ["class", "struct", "union"]: - assert kind in ["function", "typedef", "variable"] - record["type"] = plain_text(member.find("type")) - - if kind == "enum": - for value in member.findall("enumvalue"): - set_descriptions( - index, lang, value, index[value.get("id")] - ) - - elif kind == "function": - record["prototype"] = "%s %s%s" % ( - plain_text(member.find("type")), - member.find("name").text, - member.find("argsstring").text, - ) - - elif kind == "typedef": - name = local_name(record["name"]) - args_text = member.find("argsstring").text - target_text = plain_text(member.find("type")) - if args_text is not None: # Function pointer - assert target_text[-2:] == "(*" and args_text[0] == ")" - record["type"] = target_text + args_text - record["definition"] = target_text + name + args_text - else: # Normal named typedef - assert target_text is not None - record["type"] = target_text - if member.find("definition").text.startswith("using"): - record["definition"] = "%s = %s" % ( - name, - target_text, - ) - else: - record["definition"] = "%s %s" % ( - target_text, - name, - ) - - elif kind == "variable": - record["definition"] = member.find("definition").text - - -def declaration_string(record): - """ - Return the string that describes a declaration. - - This is what follows the directive, and is in C/C++ syntax, except without - keywords like "typedef" and "using" as expected by Sphinx. For example, - "struct ThingImpl Thing" or "void run(int value)". - """ - - kind = record["kind"] - result = "" - - if "template_params" in record: - result = "template <%s> " % record["template_params"] - - if kind == "function": - result += record["prototype"] - elif kind == "typedef": - result += record["definition"] - elif kind == "variable": - if "parent" in record: - result += "%s %s" % (record["type"], local_name(record["name"])) - else: - result += record["definition"] - elif "type" in record: - result += "%s %s" % (record["type"], local_name(record["name"])) - else: - result += local_name(record["name"]) - - return result - - -def document_markup(index, lang, record): - """Return the complete document that describes some documented entity.""" - - kind = record["kind"] - role = sphinx_role(record, lang) - name = record["name"] - markup = "" - - if name != local_name(name): - markup += ".. cpp:namespace:: %s\n\n" % name[0 : name.rindex("::")] - - # Write top-level directive - markup += ".. %s:: %s\n" % (role, declaration_string(record)) - - # Write main description blurb - markup += "\n" + indent(record["briefdescription"] + "\n", 1) - if len(record["detaileddescription"]) > 0: - markup += "\n" + indent(record["detaileddescription"], 1) + "\n" - - assert ( - kind in ["class", "enum", "namespace", "struct", "union"] - or "children" not in record - ) - - # Sphinx C++ namespaces work by setting a scope, they have no content - child_indent = 0 if kind == "namespace" else 1 - - # Write inline children if applicable - markup += "\n" if "children" in record else "" - for child_id in record.get("children", []): - child_record = index[child_id] - child_role = sphinx_role(child_record, lang) - - child_header = ".. %s:: %s\n\n" % ( - child_role, - declaration_string(child_record), - ) - - markup += "\n" - markup += indent(child_header, child_indent) - markup += indent(child_record["briefdescription"], child_indent + 1) - markup += indent(child_record["detaileddescription"], child_indent + 1) - - return markup - - -def symbol_filename(name): - """Adapt the name of a symbol to be suitable for use as a filename.""" - - return name.replace("::", "__") - - -def emit_groups(index, lang, output_dir, force): - """Write a description file for every group documented in the index.""" - - for record in index.values(): - if record["kind"] != "group": - continue - - name = record["name"] - filename = os.path.join(output_dir, "%s.rst" % name) - if not force and os.path.exists(filename): - raise FileExistsError("File already exists: '%s'" % filename) - - with open(filename, "w") as rst: - rst.write(heading(record["title"], 1)) - - # Get all child group and symbol names - child_groups = {} - child_symbols = {} - for child_id in record["children"]: - child = index[child_id] - if child["kind"] == "group": - child_groups[child["name"]] = child - else: - child_symbols[child["name"]] = child - - # Emit description (document body) - if len(record["briefdescription"]) > 0: - rst.write(record["briefdescription"] + "\n\n") - if len(record["detaileddescription"]) > 0: - rst.write(record["detaileddescription"] + "\n\n") - - if len(child_groups) > 0: - # Emit TOC for child groups - rst.write(".. toctree::\n\n") - for name, group in child_groups.items(): - rst.write(indent(group["name"], 1) + "\n") - - # Emit symbols in sorted order - for name, symbol in child_symbols.items(): - rst.write("\n") - rst.write(document_markup(index, lang, symbol)) - rst.write("\n") - - -def run(index_xml_path, output_dir, language, force): - """Write a directory of Sphinx files from a Doxygen XML directory.""" - - # Build skeleton index from index.xml - xml_dir = os.path.dirname(index_xml_path) - index = load_index(index_xml_path) - - # Load all definition documents - definition_docs = [] - for record in index.values(): - if "xml_filename" in record: - xml_path = os.path.join(xml_dir, record["xml_filename"]) - definition_docs += [xml.etree.ElementTree.parse(xml_path)] - - # Do an initial pass of the definition documents to resolve the index - for root in definition_docs: - resolve_index(index, root) - - # Finally read the documentation from definition documents - for root in definition_docs: - read_definition_doc(index, language, root) - - # Create output directory - try: - os.makedirs(output_dir) - except OSError: - pass - - # Emit output files - emit_groups(index, language, output_dir, force) - - -if __name__ == "__main__": - ap = argparse.ArgumentParser( - usage="%(prog)s [OPTION]... XML_DIR OUTPUT_DIR", - description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter, - ) - - ap.add_argument( - "-f", - "--force", - action="store_true", - help="overwrite files", - ) - - ap.add_argument( - "-l", - "--language", - default="c", - choices=["c", "cpp"], - help="language domain for output", - ) - - ap.add_argument("index_xml_path", help="path index.xml from Doxygen") - ap.add_argument("output_dir", help="output directory") - - run(**vars(ap.parse_args(sys.argv[1:]))) diff --git a/src/.clang-tidy b/src/.clang-tidy new file mode 100644 index 0000000..0673649 --- /dev/null +++ b/src/.clang-tidy @@ -0,0 +1,21 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +Checks: > + -*-magic-numbers, + -android-cloexec-fopen, + -bugprone-narrowing-conversions, + -cert-err33-c, + -cert-err34-c, + -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling, + -clang-analyzer-valist.Uninitialized, + -concurrency-mt-unsafe, + -cppcoreguidelines-narrowing-conversions, + -google-readability-todo, + -hicpp-multiway-paths-covered, + -hicpp-signed-bitwise, + -llvm-header-guard, + -performance-no-int-to-ptr, + -readability-function-cognitive-complexity, + -readability-suspicious-call-argument, +InheritParentConfig: true diff --git a/src/collections.c b/src/collections.c index c2c752a..2ea812b 100644 --- a/src/collections.c +++ b/src/collections.c @@ -1,36 +1,23 @@ -/* - Copyright 2008-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2008-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_internal.h" #include "lilv/lilv.h" #include "sord/sord.h" -#include "zix/common.h" #include "zix/tree.h" #include <stdbool.h> #include <stddef.h> -#include <stdint.h> + +typedef void (*LilvFreeFunc)(void* ptr); int lilv_ptr_cmp(const void* a, const void* b, const void* user_data) { (void)user_data; - return (intptr_t)a - (intptr_t)b; + return a < b ? -1 : b < a ? 1 : 0; } int @@ -41,15 +28,23 @@ lilv_resource_node_cmp(const void* a, const void* b, const void* user_data) const SordNode* an = ((const LilvNode*)a)->node; const SordNode* bn = ((const LilvNode*)b)->node; - return (intptr_t)an - (intptr_t)bn; + return an < bn ? -1 : bn < an ? 1 : 0; } /* Generic collection functions */ +static void +destroy(void* const ptr, const void* const user_data) +{ + if (user_data) { + ((LilvFreeFunc)user_data)(ptr); + } +} + static inline LilvCollection* -lilv_collection_new(ZixComparator cmp, ZixDestroyFunc destructor) +lilv_collection_new(ZixTreeCompareFunc cmp, LilvFreeFunc free_func) { - return zix_tree_new(false, cmp, NULL, destructor); + return zix_tree_new(NULL, false, cmp, NULL, destroy, (const void*)free_func); } void @@ -85,28 +80,27 @@ lilv_collection_get(const LilvCollection* collection, const LilvIter* i) LilvScalePoints* lilv_scale_points_new(void) { - return lilv_collection_new(lilv_ptr_cmp, - (ZixDestroyFunc)lilv_scale_point_free); + return lilv_collection_new(lilv_ptr_cmp, (LilvFreeFunc)lilv_scale_point_free); } LilvNodes* lilv_nodes_new(void) { - return lilv_collection_new(lilv_ptr_cmp, (ZixDestroyFunc)lilv_node_free); + return lilv_collection_new(lilv_ptr_cmp, (LilvFreeFunc)lilv_node_free); } LilvUIs* lilv_uis_new(void) { return lilv_collection_new(lilv_header_compare_by_uri, - (ZixDestroyFunc)lilv_ui_free); + (LilvFreeFunc)lilv_ui_free); } LilvPluginClasses* lilv_plugin_classes_new(void) { return lilv_collection_new(lilv_header_compare_by_uri, - (ZixDestroyFunc)lilv_plugin_class_free); + (LilvFreeFunc)lilv_plugin_class_free); } /* URI based accessors (for collections of things with URIs) */ diff --git a/src/filesystem.c b/src/filesystem.c deleted file mode 100644 index 03614ce..0000000 --- a/src/filesystem.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - Copyright 2007-2021 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#define _POSIX_C_SOURCE 200809L /* for fileno */ -#define _BSD_SOURCE 1 /* for realpath, symlink */ -#define _DEFAULT_SOURCE 1 /* for realpath, symlink */ - -#ifdef __APPLE__ -# define _DARWIN_C_SOURCE 1 /* for flock */ -#endif - -#include "filesystem.h" -#include "lilv_config.h" -#include "lilv_internal.h" - -#ifdef _WIN32 -# include <direct.h> -# include <io.h> -# include <windows.h> -# define F_OK 0 -# define mkdir(path, flags) _mkdir(path) -# define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) -#else -# include <dirent.h> -# include <unistd.h> -#endif - -#if USE_FLOCK && USE_FILENO -# include <sys/file.h> -#endif - -#include <sys/stat.h> - -#include <errno.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifndef PAGE_SIZE -# define PAGE_SIZE 4096 -#endif - -static bool -lilv_is_dir_sep(const char c) -{ - return c == '/' || c == LILV_DIR_SEP[0]; -} - -#ifdef _WIN32 -static inline bool -is_windows_path(const char* path) -{ - return (isalpha(path[0]) && (path[1] == ':' || path[1] == '|') && - (path[2] == '/' || path[2] == '\\')); -} -#endif - -char* -lilv_temp_directory_path(void) -{ -#ifdef _WIN32 - DWORD len = GetTempPath(0, NULL); - char* buf = (char*)calloc(len, 1); - if (GetTempPath(len, buf) == 0) { - free(buf); - return NULL; - } - - return buf; -#else - const char* const tmpdir = getenv("TMPDIR"); - - return tmpdir ? lilv_strdup(tmpdir) : lilv_strdup("/tmp"); -#endif -} - -bool -lilv_path_is_absolute(const char* path) -{ - if (lilv_is_dir_sep(path[0])) { - return true; - } - -#ifdef _WIN32 - if (is_windows_path(path)) { - return true; - } -#endif - - return false; -} - -bool -lilv_path_is_child(const char* path, const char* dir) -{ - if (path && dir) { - const size_t path_len = strlen(path); - const size_t dir_len = strlen(dir); - return dir && path_len >= dir_len && !strncmp(path, dir, dir_len); - } - return false; -} - -char* -lilv_path_current(void) -{ - return getcwd(NULL, 0); -} - -char* -lilv_path_absolute(const char* path) -{ - if (lilv_path_is_absolute(path)) { - return lilv_strdup(path); - } - - char* cwd = getcwd(NULL, 0); - char* abs_path = lilv_path_join(cwd, path); - free(cwd); - return abs_path; -} - -char* -lilv_path_absolute_child(const char* path, const char* parent) -{ - if (lilv_path_is_absolute(path)) { - return lilv_strdup(path); - } - - return lilv_path_join(parent, path); -} - -char* -lilv_path_relative_to(const char* path, const char* base) -{ - const size_t path_len = strlen(path); - const size_t base_len = strlen(base); - const size_t min_len = (path_len < base_len) ? path_len : base_len; - - // Find the last separator common to both paths - size_t last_shared_sep = 0; - for (size_t i = 0; i < min_len && path[i] == base[i]; ++i) { - if (lilv_is_dir_sep(path[i])) { - last_shared_sep = i; - } - } - - if (last_shared_sep == 0) { - // No common components, return path - return lilv_strdup(path); - } - - // Find the number of up references ("..") required - size_t up = 0; - for (size_t i = last_shared_sep + 1; i < base_len; ++i) { - if (lilv_is_dir_sep(base[i])) { - ++up; - } - } - -#ifdef _WIN32 - const bool use_slash = strchr(path, '/'); -#else - static const bool use_slash = true; -#endif - - // Write up references - const size_t suffix_len = path_len - last_shared_sep; - char* rel = (char*)calloc(1, suffix_len + (up * 3) + 1); - for (size_t i = 0; i < up; ++i) { - if (use_slash) { - memcpy(rel + (i * 3), "../", 3); - } else { - memcpy(rel + (i * 3), "..\\", 3); - } - } - - // Write suffix - memcpy(rel + (up * 3), path + last_shared_sep + 1, suffix_len); - return rel; -} - -char* -lilv_path_parent(const char* path) -{ - const char* s = path + strlen(path) - 1; // Last character - - // Last non-slash - for (; s > path && lilv_is_dir_sep(*s); --s) { - } - - // Last internal slash - for (; s > path && !lilv_is_dir_sep(*s); --s) { - } - - // Skip duplicates - for (; s > path && lilv_is_dir_sep(*s); --s) { - } - - if (s == path) { // Hit beginning - return lilv_is_dir_sep(*s) ? lilv_strdup("/") : lilv_strdup("."); - } - - // Pointing to the last character of the result (inclusive) - char* dirname = (char*)malloc(s - path + 2); - memcpy(dirname, path, s - path + 1); - dirname[s - path + 1] = '\0'; - return dirname; -} - -char* -lilv_path_filename(const char* path) -{ - const size_t path_len = strlen(path); - size_t last_sep = path_len; - for (size_t i = 0; i < path_len; ++i) { - if (lilv_is_dir_sep(path[i])) { - last_sep = i; - } - } - - if (last_sep >= path_len) { - return lilv_strdup(path); - } - - const size_t ret_len = path_len - last_sep; - char* const ret = (char*)calloc(ret_len + 1, 1); - - strncpy(ret, path + last_sep + 1, ret_len); - return ret; -} - -char* -lilv_path_join(const char* a, const char* b) -{ - if (!a) { - return (b && b[0]) ? lilv_strdup(b) : NULL; - } - - const size_t a_len = strlen(a); - const size_t b_len = b ? strlen(b) : 0; - const bool a_end_is_sep = a_len > 0 && lilv_is_dir_sep(a[a_len - 1]); - const size_t pre_len = a_len - (a_end_is_sep ? 1 : 0); - char* path = (char*)calloc(1, a_len + b_len + 2); - memcpy(path, a, pre_len); - -#ifdef _WIN32 - // Use forward slash if it seems that the input paths do - const bool a_has_slash = strchr(a, '/'); - const bool b_has_slash = b && strchr(b, '/'); - if (a_has_slash || b_has_slash) { - path[pre_len] = '/'; - } else { - path[pre_len] = '\\'; - } -#else - path[pre_len] = '/'; -#endif - - if (b) { - memcpy(path + pre_len + 1, - b + (lilv_is_dir_sep(b[0]) ? 1 : 0), - lilv_is_dir_sep(b[0]) ? b_len - 1 : b_len); - } - return path; -} - -char* -lilv_path_canonical(const char* path) -{ - if (!path) { - return NULL; - } - -#if defined(_WIN32) - char* out = (char*)malloc(MAX_PATH); - GetFullPathName(path, MAX_PATH, out, NULL); - return out; -#else - char* real_path = realpath(path, NULL); - return real_path ? real_path : lilv_strdup(path); -#endif -} - -bool -lilv_path_exists(const char* path) -{ -#if USE_LSTAT - struct stat st; - return !lstat(path, &st); -#else - return !access(path, F_OK); -#endif -} - -bool -lilv_is_directory(const char* path) -{ - struct stat st; - return !stat(path, &st) && S_ISDIR(st.st_mode); -} - -int -lilv_copy_file(const char* src, const char* dst) -{ - FILE* in = fopen(src, "r"); - if (!in) { - return errno; - } - - FILE* out = fopen(dst, "w"); - if (!out) { - fclose(in); - return errno; - } - - char* page = (char*)malloc(PAGE_SIZE); - size_t n_read = 0; - int st = 0; - while ((n_read = fread(page, 1, PAGE_SIZE, in)) > 0) { - if (fwrite(page, 1, n_read, out) != n_read) { - st = errno; - break; - } - } - - if (!st && fflush(out)) { - st = errno; - } - - if (!st && (ferror(in) || ferror(out))) { - st = EBADF; - } - - free(page); - fclose(in); - fclose(out); - - return st; -} - -int -lilv_symlink(const char* oldpath, const char* newpath) -{ - int ret = 0; - if (strcmp(oldpath, newpath)) { -#ifdef _WIN32 - ret = !CreateHardLink(newpath, oldpath, 0); -#else - char* target = lilv_path_relative_to(oldpath, newpath); - - ret = symlink(target, newpath); - - free(target); -#endif - } - return ret; -} - -int -lilv_flock(FILE* file, bool lock, bool block) -{ -#ifdef _WIN32 - HANDLE handle = (HANDLE)_get_osfhandle(fileno(file)); - OVERLAPPED overlapped = {0}; - - if (lock) { - const DWORD flags = - (LOCKFILE_EXCLUSIVE_LOCK | (block ? 0 : LOCKFILE_FAIL_IMMEDIATELY)); - - return !LockFileEx(handle, flags, 0, UINT32_MAX, UINT32_MAX, &overlapped); - } else { - return !UnlockFileEx(handle, 0, UINT32_MAX, UINT32_MAX, &overlapped); - } -#elif USE_FLOCK && USE_FILENO - return flock(fileno(file), - (lock ? LOCK_EX : LOCK_UN) | (block ? 0 : LOCK_NB)); -#else - return 0; -#endif -} - -void -lilv_dir_for_each(const char* path, - void* data, - void (*f)(const char* path, const char* name, void* data)) -{ -#ifdef _WIN32 - char* pat = lilv_path_join(path, "*"); - WIN32_FIND_DATA fd; - HANDLE fh = FindFirstFile(pat, &fd); - if (fh != INVALID_HANDLE_VALUE) { - do { - if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..")) { - f(path, fd.cFileName, data); - } - } while (FindNextFile(fh, &fd)); - } - FindClose(fh); - free(pat); -#else - DIR* dir = opendir(path); - if (dir) { - for (struct dirent* entry = NULL; (entry = readdir(dir));) { - if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) { - f(path, entry->d_name, data); - } - } - closedir(dir); - } -#endif -} - -char* -lilv_create_temporary_directory_in(const char* pattern, const char* parent) -{ -#ifdef _WIN32 - static const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - static const int n_chars = sizeof(chars) - 1; - - const size_t pattern_len = strlen(pattern); - if (pattern_len < 7 || strcmp(pattern + pattern_len - 6, "XXXXXX")) { - errno = EINVAL; - return NULL; - } - - char* const path_pattern = lilv_path_join(parent, pattern); - const size_t path_pattern_len = strlen(path_pattern); - char* const suffix = path_pattern + path_pattern_len - 6; - - for (unsigned attempt = 0; attempt < 128; ++attempt) { - for (unsigned i = 0; i < 6; ++i) { - suffix[i] = chars[rand() % n_chars]; - } - - if (!mkdir(path_pattern, 0700)) { - return path_pattern; - } - } - - return NULL; -#else - char* const path_pattern = lilv_path_join(parent, pattern); - - return mkdtemp(path_pattern); // NOLINT (not a leak) -#endif -} - -char* -lilv_create_temporary_directory(const char* pattern) -{ - char* const tmpdir = lilv_temp_directory_path(); - char* const result = lilv_create_temporary_directory_in(pattern, tmpdir); - - free(tmpdir); - - return result; -} - -int -lilv_create_directories(const char* dir_path) -{ - char* path = lilv_strdup(dir_path); - const size_t path_len = strlen(path); - size_t i = 1; - -#ifdef _WIN32 - if (is_windows_path(dir_path)) { - i = 3; - } -#endif - - for (; i <= path_len; ++i) { - const char c = path[i]; - if (c == LILV_DIR_SEP[0] || c == '/' || c == '\0') { - path[i] = '\0'; - if (mkdir(path, 0755) && (errno != EEXIST || !lilv_is_directory(path))) { - free(path); - return errno; - } - path[i] = c; - } - } - - free(path); - return 0; -} - -static off_t -lilv_file_size(const char* path) -{ - struct stat buf; - if (stat(path, &buf)) { - return 0; - } - return buf.st_size; -} - -int -lilv_remove(const char* path) -{ -#ifdef _WIN32 - if (lilv_is_directory(path)) { - return !RemoveDirectory(path); - } -#endif - - return remove(path); -} - -bool -lilv_file_equals(const char* a_path, const char* b_path) -{ - if (!strcmp(a_path, b_path)) { - return true; // Paths match - } - - bool match = false; - FILE* a_file = NULL; - FILE* b_file = NULL; - char* const a_real = lilv_path_canonical(a_path); - char* const b_real = lilv_path_canonical(b_path); - if (!strcmp(a_real, b_real)) { - match = true; // Real paths match - } else if (lilv_file_size(a_path) != lilv_file_size(b_path)) { - match = false; // Sizes differ - } else if (!(a_file = fopen(a_real, "rb")) || - !(b_file = fopen(b_real, "rb"))) { - match = false; // Missing file matches nothing - } else { - // TODO: Improve performance by reading chunks - match = true; - while (!feof(a_file) && !feof(b_file)) { - if (fgetc(a_file) != fgetc(b_file)) { - match = false; - break; - } - } - } - - if (a_file) { - fclose(a_file); - } - if (b_file) { - fclose(b_file); - } - free(a_real); - free(b_real); - return match; -} diff --git a/src/filesystem.h b/src/filesystem.h deleted file mode 100644 index 1a8dc68..0000000 --- a/src/filesystem.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <stdbool.h> -#include <stdio.h> - -/// Return the path to a directory suitable for making temporary files -char* -lilv_temp_directory_path(void); - -/// Return true iff `path` is an absolute path -bool -lilv_path_is_absolute(const char* path); - -/// Return true iff `path` is a child of `dir` -bool -lilv_path_is_child(const char* path, const char* dir); - -/// Return the current working directory -char* -lilv_path_current(void); - -/** - Return `path` as an absolute path. - - If `path` is absolute, an identical copy of it is returned. Otherwise, the - returned path is relative to the current working directory. -*/ -char* -lilv_path_absolute(const char* path); - -/** - Return `path` as an absolute path relative to `parent`. - - If `path` is absolute, an identical copy of it is returned. Otherwise, the - returned path is relative to `parent`. -*/ -char* -lilv_path_absolute_child(const char* path, const char* parent); - -/** - Return `path` relative to `base` if possible. - - If `path` is not within `base`, a copy is returned. Otherwise, an - equivalent path relative to `base` is returned (which may contain - up-references). -*/ -char* -lilv_path_relative_to(const char* path, const char* base); - -/** - Return the path to the directory that contains `path`. - - Returns the root path if `path` is the root path. -*/ -char* -lilv_path_parent(const char* path); - -/** - Return the filename component of `path` without any directories. - - Returns the empty string if `path` is the root path. -*/ -char* -lilv_path_filename(const char* path); - -/// Join path `a` and path `b` with a single directory separator between them -char* -lilv_path_join(const char* a, const char* b); - -/** - Return `path` as a canonicalized absolute path. - - This expands all symbolic links, relative references, and removes extra - directory separators. -*/ -char* -lilv_path_canonical(const char* path); - -/// Return true iff `path` points to an existing file system entry -bool -lilv_path_exists(const char* path); - -/// Return true iff `path` points to an existing directory -bool -lilv_is_directory(const char* path); - -/** - Copy the file at path `src` to path `dst`. - - @return Zero on success, or a standard `errno` error code. -*/ -int -lilv_copy_file(const char* src, const char* dst); - -/** - Create a symlink at `newpath` that points to `oldpath`. - - @return Zero on success, otherwise non-zero and `errno` is set. -*/ -int -lilv_symlink(const char* oldpath, const char* newpath); - -/** - Set or remove an advisory exclusive lock on `file`. - - If the `lock` is true and the file is already locked by another process, or - by this process via a different file handle, then this will not succeed and - non-zero will be returned. - - @param file Handle for open file to lock. - @param lock True to set lock, false to release lock. - @param block If true, then this call will block until the lock is acquired. - @return Zero on success. -*/ -int -lilv_flock(FILE* file, bool lock, bool block); - -/** - Visit every file in the directory at `path`. - - @param path A path to a directory. - - @param data Opaque user data that is passed to `f`. - - @param f A function called on every entry in the directory. The `path` - parameter is always the directory path passed to this function, the `name` - parameter is the name of the directory entry (not its full path). -*/ -void -lilv_dir_for_each(const char* path, - void* data, - void (*f)(const char* path, const char* name, void* data)); - -/** - Create a unique temporary directory in a specific directory. - - The last six characters of `pattern` must be `XXXXXX` and will be replaced - with random characters. This works roughly like mkdtemp, except the pattern - should only be a directory name, not a full path. The created path will be - a child of the given parent directory. -*/ -char* -lilv_create_temporary_directory_in(const char* pattern, const char* parent); - -/** - Create a unique temporary directory. - - This is like lilv_create_temporary_directory_in(), except it creates the - directory in the system temporary directory. -*/ -char* -lilv_create_temporary_directory(const char* pattern); - -/** - Create the directory `dir_path` and any parent directories if necessary. - - @return Zero on success, or an `errno` error code. -*/ -int -lilv_create_directories(const char* dir_path); - -/// Remove the file or empty directory at `path` -int -lilv_remove(const char* path); - -/// Return true iff the given paths point to files with identical contents -bool -lilv_file_equals(const char* a_path, const char* b_path); diff --git a/src/instance.c b/src/instance.c index 6a2b856..379fe24 100644 --- a/src/instance.c +++ b/src/instance.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_internal.h" @@ -1,18 +1,5 @@ -/* - Copyright 2012-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2012-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_internal.h" diff --git a/src/lilv_config.h b/src/lilv_config.h index 10231c5..58d4429 100644 --- a/src/lilv_config.h +++ b/src/lilv_config.h @@ -1,102 +1,11 @@ -/* - Copyright 2021 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* - Configuration header that defines reasonable defaults at compile time. - - This allows compile-time configuration from the command line (typically via - the build system) while still allowing the source to be built without any - configuration. The build system can define LILV_NO_DEFAULT_CONFIG to disable - defaults, in which case it must define things like HAVE_FEATURE to enable - features. The design here ensures that compiler warnings or - include-what-you-use will catch any mistakes. -*/ +// Copyright 2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #ifndef LILV_CONFIG_H #define LILV_CONFIG_H // Define version unconditionally so a warning will catch a mismatch -#define LILV_VERSION "0.24.13" - -#if !defined(LILV_NO_DEFAULT_CONFIG) - -// We need unistd.h to check _POSIX_VERSION -# ifndef LILV_NO_POSIX -# ifdef __has_include -# if __has_include(<unistd.h>) -# include <unistd.h> -# endif -# elif defined(__unix__) -# include <unistd.h> -# endif -# endif - -// POSIX.1-2001: fileno() -# ifndef HAVE_FILENO -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L -# define HAVE_FILENO -# endif -# endif - -// Classic UNIX: flock() -# ifndef HAVE_FLOCK -# if defined(__unix__) -# define HAVE_FLOCK -# endif -# endif - -// POSIX.1-2001: lstat() -# ifndef HAVE_LSTAT -# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L -# define HAVE_LSTAT -# endif -# endif - -#endif // !defined(LILV_NO_DEFAULT_CONFIG) - -/* - Make corresponding USE_FEATURE defines based on the HAVE_FEATURE defines from - above or the command line. The code checks for these using #if (not #ifdef), - so there will be an undefined warning if it checks for an unknown feature, - and this header is always required by any code that checks for features, even - if the build system defines them all. -*/ - -#ifdef HAVE_FILENO -# define USE_FILENO 1 -#else -# define USE_FILENO 0 -#endif - -#ifdef HAVE_FLOCK -# define USE_FLOCK 1 -#else -# define USE_FLOCK 0 -#endif - -#ifdef HAVE_LSTAT -# define USE_LSTAT 1 -#else -# define USE_LSTAT 0 -#endif - -/* - Define required values. These are always used as a fallback, even with - LILV_NO_DEFAULT_CONFIG, since they must be defined for the build to work. -*/ +#define LILV_VERSION "0.24.21" // Separator between entries in variables like PATH #ifndef LILV_PATH_SEP @@ -121,7 +30,7 @@ # ifdef _WIN32 # define LILV_DEFAULT_LV2_PATH "%APPDATA%\\LV2;%COMMONPROGRAMFILES%\\LV2" # else -# define LILV_DEFAULT_LV2_PATH "~/.lv2:/usr/lib/lv2:/usr/local/lib/lv2" +# define LILV_DEFAULT_LV2_PATH "~/.lv2:/usr/local/lib/lv2:/usr/lib/lv2" # endif #endif diff --git a/src/lilv_internal.h b/src/lilv_internal.h index 12b56de..0a1f7d4 100644 --- a/src/lilv_internal.h +++ b/src/lilv_internal.h @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #ifndef LILV_INTERNAL_H #define LILV_INTERNAL_H @@ -35,22 +22,14 @@ extern "C" { #ifdef _WIN32 # include <direct.h> -# include <stdio.h> # include <windows.h> # define dlopen(path, flags) LoadLibrary(path) # define dlclose(lib) FreeLibrary((HMODULE)lib) # ifdef _MSC_VER -# define __func__ __FUNCTION__ # ifndef snprintf # define snprintf _snprintf # endif # endif -# ifndef INFINITY -# define INFINITY DBL_MAX + DBL_MAX -# endif -# ifndef NAN -# define NAN INFINITY - INFINITY -# endif static inline const char* dlerror(void) { @@ -1,25 +1,15 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "filesystem.h" +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + #include "lilv_internal.h" #include "lilv/lilv.h" #include "serd/serd.h" #include "sord/sord.h" +#include "zix/allocator.h" +#include "zix/filesystem.h" +#include "zix/path.h" +#include "zix/string_view.h" #include <math.h> #include <stdbool.h> @@ -160,13 +150,23 @@ lilv_new_uri(LilvWorld* world, const char* uri) LilvNode* lilv_new_file_uri(LilvWorld* world, const char* host, const char* path) { - char* abs_path = lilv_path_absolute(path); - SerdNode s = serd_node_new_file_uri( - (const uint8_t*)abs_path, (const uint8_t*)host, NULL, true); + SerdNode s = SERD_NODE_NULL; + if (zix_path_root_directory(path).length) { + s = serd_node_new_file_uri( + (const uint8_t*)path, (const uint8_t*)host, NULL, true); + } else { + char* const cwd = zix_current_path(NULL); + char* const abs_path = zix_path_join(NULL, cwd, path); + + s = serd_node_new_file_uri( + (const uint8_t*)abs_path, (const uint8_t*)host, NULL, true); + + zix_free(NULL, abs_path); + zix_free(NULL, cwd); + } LilvNode* ret = lilv_node_new(world, LILV_VALUE_URI, (const char*)s.buf); serd_node_free(&s); - free(abs_path); return ret; } diff --git a/src/plugin.c b/src/plugin.c index 9c7cbfd..f191eda 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_internal.h" @@ -580,9 +567,11 @@ lilv_plugin_get_port_ranges_float(const LilvPlugin* plugin, } uint32_t -lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* plugin, - const LilvNode* class_1, - va_list args) +lilv_plugin_get_num_ports_of_class_va( + const LilvPlugin* plugin, + const LilvNode* class_1, + va_list args // NOLINT(readability-non-const-parameter) +) { lilv_plugin_load_ports_if_necessary(plugin); @@ -624,7 +613,7 @@ lilv_plugin_get_num_ports_of_class(const LilvPlugin* plugin, const LilvNode* class_1, ...) { - va_list args; + va_list args; // NOLINT(cppcoreguidelines-init-variables) va_start(args, class_1); uint32_t count = lilv_plugin_get_num_ports_of_class_va(plugin, class_1, args); diff --git a/src/pluginclass.c b/src/pluginclass.c index 2f0afe7..f3da602 100644 --- a/src/pluginclass.c +++ b/src/pluginclass.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_internal.h" @@ -73,8 +60,9 @@ LilvPluginClasses* lilv_plugin_class_get_children(const LilvPluginClass* plugin_class) { // Returned list doesn't own categories - LilvPluginClasses* all = plugin_class->world->plugin_classes; - LilvPluginClasses* result = zix_tree_new(false, lilv_ptr_cmp, NULL, NULL); + LilvPluginClasses* all = plugin_class->world->plugin_classes; + LilvPluginClasses* result = + zix_tree_new(NULL, false, lilv_ptr_cmp, NULL, NULL, NULL); for (ZixTreeIter* i = zix_tree_begin((ZixTree*)all); i != zix_tree_end((ZixTree*)all); @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_internal.h" @@ -237,11 +224,12 @@ lilv_port_get_scale_points(const LilvPlugin* plugin, const LilvPort* port) sord_new_uri(plugin->world->world, (const uint8_t*)LV2_CORE__scalePoint), NULL); - LilvScalePoints* ret = NULL; - if (!sord_iter_end(points)) { - ret = lilv_scale_points_new(); + if (sord_iter_end(points)) { + return NULL; } + LilvScalePoints* ret = lilv_scale_points_new(); + FOREACH_MATCH (points) { const SordNode* point = sord_iter_get_node(points, SORD_OBJECT); @@ -257,7 +245,7 @@ lilv_port_get_scale_points(const LilvPlugin* plugin, const LilvPort* port) } sord_iter_free(points); - assert(!ret || lilv_nodes_size(ret) > 0); + assert(lilv_nodes_size(ret) > 0); return ret; } diff --git a/src/query.c b/src/query.c index eb179f2..3dd8eca 100644 --- a/src/query.c +++ b/src/query.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_internal.h" @@ -96,12 +83,7 @@ lilv_nodes_from_stream_objects_i18n(LilvWorld* world, } const SordNode* best = nolang; - if (syslang && partial) { - // Partial language match for system language - best = partial; - } else if (!best) { - // No languages matches at all, and no untranslated value - // Use any value, if possible + if ((syslang && partial) || !best) { best = partial; } diff --git a/src/scalepoint.c b/src/scalepoint.c index e2db948..60cc905 100644 --- a/src/scalepoint.c +++ b/src/scalepoint.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_internal.h" diff --git a/src/state.c b/src/state.c index a4a50a9..e67714d 100644 --- a/src/state.c +++ b/src/state.c @@ -1,26 +1,17 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "filesystem.h" +// Copyright 2007-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + #include "lilv_internal.h" #include "lilv/lilv.h" #include "serd/serd.h" #include "sord/sord.h" #include "sratom/sratom.h" +#include "zix/allocator.h" +#include "zix/filesystem.h" +#include "zix/path.h" +#include "zix/status.h" +#include "zix/string_view.h" #include "zix/tree.h" #include "lv2/atom/atom.h" @@ -120,8 +111,9 @@ value_cmp(const void* a, const void* b) } static void -path_rel_free(void* ptr) +map_free(void* ptr, const void* user_data) { + (void)user_data; free(((PathMap*)ptr)->abs); free(((PathMap*)ptr)->rel); free(ptr); @@ -247,7 +239,7 @@ path_exists(const char* path, const void* ignored) { (void)ignored; - return lilv_path_exists(path); + return zix_file_type(path) != ZIX_FILE_TYPE_NONE; } static bool @@ -260,19 +252,34 @@ static char* make_path(LV2_State_Make_Path_Handle handle, const char* path) { LilvState* state = (LilvState*)handle; - lilv_create_directories(state->dir); + zix_create_directories(NULL, state->dir); - return lilv_path_join(state->dir, path); + return zix_path_join(NULL, state->dir, path); +} + +static bool +path_is_child(const char* path, const char* dir) +{ + if (path && dir) { + const size_t path_len = strlen(path); + const size_t dir_len = strlen(dir); + return dir && path_len >= dir_len && !strncmp(path, dir, dir_len); + } + return false; } static char* abstract_path(LV2_State_Map_Path_Handle handle, const char* abs_path) { - LilvState* state = (LilvState*)handle; - char* path = NULL; - char* real_path = lilv_path_canonical(abs_path); - const PathMap key = {real_path, NULL}; - ZixTreeIter* iter = NULL; + LilvState* state = (LilvState*)handle; + char* path = NULL; + char* real_path = zix_canonical_path(NULL, abs_path); + if (!real_path) { + real_path = zix_path_lexically_normal(NULL, abs_path); + } + + const PathMap key = {real_path, NULL}; + ZixTreeIter* iter = NULL; if (abs_path[0] == '\0') { return lilv_strdup(abs_path); @@ -281,47 +288,47 @@ abstract_path(LV2_State_Map_Path_Handle handle, const char* abs_path) if (!zix_tree_find(state->abs2rel, &key, &iter)) { // Already mapped path in a previous call PathMap* pm = (PathMap*)zix_tree_get(iter); - free(real_path); + zix_free(NULL, real_path); return lilv_strdup(pm->rel); } - if (lilv_path_is_child(real_path, state->dir)) { + if (path_is_child(real_path, state->dir)) { // File in state directory (loaded, or created by plugin during save) - path = lilv_path_relative_to(real_path, state->dir); - } else if (lilv_path_is_child(real_path, state->scratch_dir)) { + path = zix_path_lexically_relative(NULL, real_path, state->dir); + } else if (path_is_child(real_path, state->scratch_dir)) { // File created by plugin earlier - path = lilv_path_relative_to(real_path, state->scratch_dir); + path = zix_path_lexically_relative(NULL, real_path, state->scratch_dir); if (state->copy_dir) { - int st = lilv_create_directories(state->copy_dir); + ZixStatus st = zix_create_directories(NULL, state->copy_dir); if (st) { - LILV_ERRORF( - "Error creating directory %s (%s)\n", state->copy_dir, strerror(st)); + LILV_ERRORF("Error creating directory %s (%s)\n", + state->copy_dir, + zix_strerror(st)); } - char* cpath = lilv_path_join(state->copy_dir, path); + char* cpath = zix_path_join(NULL, state->copy_dir, path); char* copy = lilv_get_latest_copy(real_path, cpath); - if (!copy || !lilv_file_equals(real_path, copy)) { + if (!copy || !zix_file_equals(NULL, real_path, copy)) { // No recent enough copy, make a new one free(copy); copy = lilv_find_free_path(cpath, path_exists, NULL); - if ((st = lilv_copy_file(real_path, copy))) { - LILV_ERRORF("Error copying state file %s (%s)\n", copy, strerror(st)); + if ((st = zix_copy_file(NULL, real_path, copy, 0U))) { + LILV_ERRORF( + "Error copying state file %s (%s)\n", copy, zix_strerror(st)); } } - free(real_path); - free(cpath); + zix_free(NULL, real_path); + zix_free(NULL, cpath); // Refer to the latest copy in plugin state real_path = copy; } } else if (state->link_dir) { // New path outside state directory, make a link - char* const name = lilv_path_filename(real_path); + const ZixStringView name = zix_path_filename(real_path); // Find a free name in the (virtual) state directory - path = lilv_find_free_path(name, lilv_state_has_path, state); - - free(name); + path = lilv_find_free_path(name.data, lilv_state_has_path, state); } else { // No link directory, preserve absolute path path = lilv_strdup(abs_path); @@ -342,12 +349,12 @@ absolute_path(LV2_State_Map_Path_Handle handle, const char* state_path) { LilvState* state = (LilvState*)handle; char* path = NULL; - if (lilv_path_is_absolute(state_path)) { + if (zix_path_is_absolute(state_path)) { // Absolute path, return identical path path = lilv_strdup(state_path); } else if (state->dir) { // Relative path inside state directory - path = lilv_path_join(state->dir, state_path); + path = zix_path_join(NULL, state->dir, state_path); } else { // State has not been saved, unmap path = lilv_strdup(lilv_state_rel2abs(state, state_path)); @@ -388,14 +395,15 @@ add_features(const LV2_Feature* const* features, return ret; } -/// Return the canonical path for a directory with a trailing separator +/// Return a normal path for a directory with a trailing separator static char* -real_dir(const char* path) +normal_dir(const char* path) { - char* abs_path = lilv_path_canonical(path); - char* base = lilv_path_join(abs_path, NULL); - free(abs_path); - return base; + char* const normal_path = zix_path_lexically_normal(NULL, path); + char* const base_path = zix_path_join(NULL, normal_path, NULL); + + zix_free(NULL, normal_path); + return base_path; } static const char* @@ -442,12 +450,12 @@ lilv_state_new_from_instance(const LilvPlugin* plugin, LilvWorld* const world = plugin->world; LilvState* const state = (LilvState*)calloc(1, sizeof(LilvState)); state->plugin_uri = lilv_node_duplicate(lilv_plugin_get_uri(plugin)); - state->abs2rel = zix_tree_new(false, abs_cmp, NULL, path_rel_free); - state->rel2abs = zix_tree_new(false, rel_cmp, NULL, NULL); - state->scratch_dir = scratch_dir ? real_dir(scratch_dir) : NULL; - state->copy_dir = copy_dir ? real_dir(copy_dir) : NULL; - state->link_dir = link_dir ? real_dir(link_dir) : NULL; - state->dir = save_dir ? real_dir(save_dir) : NULL; + state->abs2rel = zix_tree_new(NULL, false, abs_cmp, NULL, map_free, NULL); + state->rel2abs = zix_tree_new(NULL, false, rel_cmp, NULL, NULL, NULL); + state->scratch_dir = scratch_dir ? normal_dir(scratch_dir) : NULL; + state->copy_dir = copy_dir ? normal_dir(copy_dir) : NULL; + state->link_dir = link_dir ? normal_dir(link_dir) : NULL; + state->dir = save_dir ? normal_dir(save_dir) : NULL; state->atom_Path = map->map(map->handle, LV2_ATOM__Path); LV2_State_Map_Path pmap = {state, abstract_path, absolute_path}; @@ -571,10 +579,10 @@ set_state_dir_from_model(LilvState* state, const SordNode* graph) const char* uri = (const char*)sord_node_get_string(graph); char* path = lilv_file_uri_parse(uri, NULL); - state->dir = lilv_path_join(path, NULL); + state->dir = zix_path_join(NULL, path, NULL); free(path); } - assert(!state->dir || lilv_path_is_absolute(state->dir)); + assert(!state->dir || zix_path_is_absolute(state->dir)); } static LilvState* @@ -591,7 +599,7 @@ new_state_from_model(LilvWorld* world, // Allocate state LilvState* const state = (LilvState*)calloc(1, sizeof(LilvState)); - state->dir = lilv_path_join(dir, NULL); + state->dir = dir ? zix_path_join(NULL, dir, NULL) : NULL; state->atom_Path = map->map(map->handle, LV2_ATOM__Path); state->uri = lilv_node_new_from_node(world, node); @@ -742,7 +750,7 @@ lilv_state_new_from_file(LilvWorld* world, return NULL; } - uint8_t* abs_path = (uint8_t*)lilv_path_absolute(path); + uint8_t* abs_path = (uint8_t*)zix_canonical_path(NULL, path); SerdNode node = serd_node_new_file_uri(abs_path, NULL, NULL, true); SerdEnv* env = serd_env_new(&node); SordModel* model = sord_new(world->world, SORD_SPO, false); @@ -754,17 +762,18 @@ lilv_state_new_from_file(LilvWorld* world, (subject) ? subject->node : sord_node_from_serd_node(world->world, env, &node, NULL, NULL); - char* dirname = lilv_path_parent(path); - char* real_path = lilv_path_canonical(dirname); - char* dir_path = lilv_path_join(real_path, NULL); - LilvState* state = + const ZixStringView dirname = zix_path_parent_path(path); + char* const real_path = zix_canonical_path(NULL, dirname.data); + char* const dir_path = zix_path_join(NULL, real_path, NULL); + + LilvState* const state = new_state_from_model(world, map, model, subject_node, dir_path); - free(dir_path); - free(real_path); - free(dirname); + + zix_free(NULL, dir_path); + zix_free(NULL, real_path); serd_node_free(&node); - free(abs_path); + zix_free(NULL, abs_path); serd_reader_free(reader); sord_free(model); serd_env_free(env); @@ -925,7 +934,7 @@ add_state_to_manifest(LilvWorld* lworld, SerdEnv* env = serd_env_new(&manifest); SordModel* model = sord_new(world, SORD_SPO, false); - if (lilv_path_exists(manifest_path)) { + if (zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR) { // Read manifest into model SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); SerdStatus st = serd_reader_read_file(reader, manifest.buf); @@ -988,15 +997,15 @@ add_state_to_manifest(LilvWorld* lworld, LILV_ERRORF( "Failed to open %s for writing (%s)\n", manifest_path, strerror(errno)); r = 1; + } else { + SerdWriter* writer = ttl_file_writer(wfd, &manifest, &env); + zix_file_lock(wfd, ZIX_FILE_LOCK_BLOCK); + sord_write(model, writer, NULL); + zix_file_unlock(wfd, ZIX_FILE_LOCK_BLOCK); + serd_writer_free(writer); + fclose(wfd); } - SerdWriter* writer = ttl_file_writer(wfd, &manifest, &env); - lilv_flock(wfd, true, true); - sord_write(model, writer, NULL); - lilv_flock(wfd, false, true); - serd_writer_free(writer); - fclose(wfd); - sord_free(model); serd_node_free(&file); serd_node_free(&manifest); @@ -1009,31 +1018,44 @@ static bool link_exists(const char* path, const void* data) { const char* target = (const char*)data; - if (!lilv_path_exists(path)) { + if (zix_file_type(path) == ZIX_FILE_TYPE_NONE) { return false; } - char* real_path = lilv_path_canonical(path); + + char* real_path = zix_canonical_path(NULL, path); bool matches = !strcmp(real_path, target); - free(real_path); + zix_free(NULL, real_path); return !matches; } -static int -maybe_symlink(const char* oldpath, const char* newpath) +static ZixStatus +create_link(const char* oldpath, const char* newpath) { - if (link_exists(newpath, oldpath)) { - return 0; - } + const ZixStringView parent_path = zix_path_parent_path(newpath); + char* const parent = zix_string_view_copy(NULL, parent_path); - const int st = lilv_symlink(oldpath, newpath); - if (st) { - LILV_ERRORF( - "Failed to link %s => %s (%s)\n", newpath, oldpath, strerror(errno)); + char* const relpath = zix_path_lexically_relative(NULL, oldpath, parent); + + ZixStatus st = ZIX_STATUS_SUCCESS; + if ((st = zix_create_symlink(relpath, newpath))) { + if ((st = zix_create_hard_link(oldpath, newpath))) { + LILV_ERRORF( + "Failed to link %s => %s (%s)\n", newpath, oldpath, zix_strerror(st)); + } } + zix_free(NULL, relpath); + zix_free(NULL, parent); return st; } +static ZixStatus +maybe_symlink(const char* oldpath, const char* newpath) +{ + return link_exists(newpath, oldpath) ? ZIX_STATUS_SUCCESS + : create_link(oldpath, newpath); +} + static void write_property_array(const LilvState* state, const PropertyArray* array, @@ -1178,16 +1200,17 @@ lilv_state_make_links(const LilvState* state, const char* dir) for (ZixTreeIter* i = zix_tree_begin(state->abs2rel); i != zix_tree_end(state->abs2rel); i = zix_tree_iter_next(i)) { - const PathMap* pm = (const PathMap*)zix_tree_get(i); + const PathMap* const pm = (const PathMap*)zix_tree_get(i); + char* const path = zix_path_join(NULL, dir, pm->rel); - char* path = lilv_path_absolute_child(pm->rel, dir); - if (lilv_path_is_child(pm->abs, state->copy_dir) && - strcmp(state->copy_dir, dir)) { + if (path_is_child(pm->abs, state->copy_dir) && + !!strcmp(state->copy_dir, dir)) { // Link directly to snapshot in the copy directory maybe_symlink(pm->abs, path); - } else if (!lilv_path_is_child(pm->abs, dir)) { + } else if (!path_is_child(pm->abs, dir)) { const char* link_dir = state->link_dir ? state->link_dir : dir; - char* pat = lilv_path_absolute_child(pm->rel, link_dir); + char* pat = zix_path_join(NULL, link_dir, pm->rel); + if (!strcmp(dir, link_dir)) { // Link directory is save directory, make link at exact path remove(pat); @@ -1195,17 +1218,18 @@ lilv_state_make_links(const LilvState* state, const char* dir) } else { // Make a link in the link directory to external file char* lpath = lilv_find_free_path(pat, link_exists, pm->abs); - if (!lilv_path_exists(lpath)) { - if (lilv_symlink(pm->abs, lpath)) { + if (zix_file_type(lpath) == ZIX_FILE_TYPE_NONE) { + const ZixStatus st = create_link(pm->abs, lpath); + if (st) { LILV_ERRORF("Failed to link %s => %s (%s)\n", pm->abs, lpath, - strerror(errno)); + zix_strerror(st)); } } // Make a link in the save directory to the external link - char* target = lilv_path_relative_to(lpath, dir); + char* target = zix_path_lexically_relative(NULL, lpath, dir); maybe_symlink(lpath, path); free(target); free(lpath); @@ -1225,17 +1249,17 @@ lilv_state_save(LilvWorld* world, const char* dir, const char* filename) { - if (!filename || !dir || lilv_create_directories(dir)) { + if (!filename || !dir || zix_create_directories(NULL, dir)) { return 1; } - char* abs_dir = real_dir(dir); - char* const path = lilv_path_join(abs_dir, filename); + char* abs_dir = zix_canonical_path(NULL, dir); + char* const path = zix_path_join(NULL, abs_dir, filename); FILE* fd = fopen(path, "w"); if (!fd) { LILV_ERRORF("Failed to open %s (%s)\n", path, strerror(errno)); - free(abs_dir); - free(path); + zix_free(NULL, abs_dir); + zix_free(NULL, path); return 4; } @@ -1251,9 +1275,9 @@ lilv_state_save(LilvWorld* world, lilv_state_write(world, map, unmap, state, ttl, (const char*)node.buf, dir); // Set saved dir and uri (FIXME: const violation) - free(state->dir); + zix_free(NULL, state->dir); lilv_node_free(state->uri); - ((LilvState*)state)->dir = lilv_strdup(abs_dir); + ((LilvState*)state)->dir = zix_path_join(NULL, abs_dir, ""); ((LilvState*)state)->uri = lilv_new_uri(world, (const char*)node.buf); serd_node_free(&file); @@ -1263,15 +1287,15 @@ lilv_state_save(LilvWorld* world, // Add entry to manifest if (!ret) { - char* const manifest = lilv_path_join(abs_dir, "manifest.ttl"); + char* const manifest = zix_path_join(NULL, abs_dir, "manifest.ttl"); ret = add_state_to_manifest(world, state->plugin_uri, manifest, uri, path); - free(manifest); + zix_free(NULL, manifest); } - free(abs_dir); - free(path); + zix_free(NULL, abs_dir); + zix_free(NULL, path); return ret; } @@ -1307,7 +1331,7 @@ static void try_unlink(const char* state_dir, const char* path) { if (!strncmp(state_dir, path, strlen(state_dir))) { - if (lilv_path_exists(path) && lilv_remove(path)) { + if (zix_file_type(path) != ZIX_FILE_TYPE_NONE && zix_remove(path)) { LILV_ERRORF("Failed to remove %s (%s)\n", path, strerror(errno)); } } @@ -1317,7 +1341,7 @@ static char* get_canonical_path(const LilvNode* const node) { char* const path = lilv_node_get_path(node, NULL); - char* const real_path = lilv_path_canonical(path); + char* const real_path = zix_canonical_path(NULL, path); free(path); return real_path; @@ -1334,8 +1358,10 @@ lilv_state_delete(LilvWorld* world, const LilvState* state) LilvNode* bundle = lilv_new_file_uri(world, NULL, state->dir); LilvNode* manifest = lilv_world_get_manifest_uri(world, bundle); char* manifest_path = get_canonical_path(manifest); - const bool has_manifest = lilv_path_exists(manifest_path); - SordModel* model = sord_new(world->world, SORD_SPO, false); + const bool has_manifest = + manifest_path && zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR; + + SordModel* model = sord_new(world->world, SORD_SPO, false); if (has_manifest) { // Read manifest into temporary local model @@ -1353,11 +1379,11 @@ lilv_state_delete(LilvWorld* world, const LilvState* state) // Remove state file const uint8_t* uri = sord_node_get_string(file); char* path = (char*)serd_file_uri_parse(uri, NULL); - char* real_path = lilv_path_canonical(path); - if (path) { + char* real_path = zix_canonical_path(NULL, path); + if (real_path) { try_unlink(state->dir, real_path); } - serd_free(real_path); + zix_free(NULL, real_path); serd_free(path); } @@ -1383,9 +1409,9 @@ lilv_state_delete(LilvWorld* world, const LilvState* state) i != zix_tree_end(state->abs2rel); i = zix_tree_iter_next(i)) { const PathMap* pm = (const PathMap*)zix_tree_get(i); - char* path = lilv_path_join(state->dir, pm->rel); + char* path = zix_path_join(NULL, state->dir, pm->rel); try_unlink(state->dir, path); - free(path); + zix_free(NULL, path); } } else { // State loaded from model, get paths from loaded properties @@ -1397,7 +1423,7 @@ lilv_state_delete(LilvWorld* world, const LilvState* state) } } - if (lilv_remove(state->dir)) { + if (zix_remove(state->dir)) { LILV_ERRORF( "Failed to remove directory %s (%s)\n", state->dir, strerror(errno)); } @@ -1412,7 +1438,7 @@ lilv_state_delete(LilvWorld* world, const LilvState* state) } sord_free(model); - lilv_free(manifest_path); + zix_free(NULL, manifest_path); lilv_node_free(manifest); lilv_node_free(bundle); @@ -1460,7 +1486,7 @@ lilv_state_equals(const LilvState* a, const LilvState* b) { if (!lilv_node_equals(a->plugin_uri, b->plugin_uri) || (a->label && !b->label) || (b->label && !a->label) || - (a->label && b->label && strcmp(a->label, b->label)) || + (a->label && b->label && !!strcmp(a->label, b->label)) || a->props.n != b->props.n || a->n_values != b->n_values) { return false; } @@ -1469,8 +1495,8 @@ lilv_state_equals(const LilvState* a, const LilvState* b) PortValue* const av = &a->values[i]; PortValue* const bv = &b->values[i]; if (av->atom->size != bv->atom->size || av->atom->type != bv->atom->type || - strcmp(av->symbol, bv->symbol) || - memcmp(av->atom + 1, bv->atom + 1, av->atom->size)) { + !!strcmp(av->symbol, bv->symbol) || + !!memcmp(av->atom + 1, bv->atom + 1, av->atom->size)) { return false; } } @@ -1483,11 +1509,13 @@ lilv_state_equals(const LilvState* a, const LilvState* b) } if (ap->type == a->atom_Path) { - if (!lilv_file_equals(lilv_state_rel2abs(a, (char*)ap->value), - lilv_state_rel2abs(b, (char*)bp->value))) { + if (!zix_file_equals(NULL, + lilv_state_rel2abs(a, (char*)ap->value), + lilv_state_rel2abs(b, (char*)bp->value))) { return false; } - } else if (ap->size != bp->size || memcmp(ap->value, bp->value, ap->size)) { + } else if (ap->size != bp->size || + !!memcmp(ap->value, bp->value, ap->size)) { return false; } } @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_internal.h" @@ -1,37 +1,26 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "filesystem.h" +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + #include "lilv_internal.h" #include "lilv/lilv.h" #include "serd/serd.h" +#include "zix/allocator.h" +#include "zix/filesystem.h" +#include "zix/path.h" +#include "zix/string_view.h" #include <sys/stat.h> -#include <sys/types.h> #include <ctype.h> #include <errno.h> #include <stdarg.h> #include <stdbool.h> -#include <stddef.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> // IWYU pragma: keep void lilv_free(void* ptr) @@ -47,7 +36,7 @@ lilv_strjoin(const char* first, ...) memcpy(result, first, len); - va_list args; + va_list args; // NOLINT(cppcoreguidelines-init-variables) va_start(args, first); while (1) { const char* const s = va_arg(args, const char*); @@ -127,10 +116,9 @@ lilv_get_lang(void) lang[i] = '-'; // Convert _ to - } else if (env_lang[i] >= 'A' && env_lang[i] <= 'Z') { lang[i] = env_lang[i] + ('a' - 'A'); // Convert to lowercase - } else if (env_lang[i] >= 'a' && env_lang[i] <= 'z') { - lang[i] = env_lang[i]; // Lowercase letter, copy verbatim - } else if (env_lang[i] >= '0' && env_lang[i] <= '9') { - lang[i] = env_lang[i]; // Digit, copy verbatim + } else if ((env_lang[i] >= 'a' && env_lang[i] <= 'z') || + (env_lang[i] >= '0' && env_lang[i] <= '9')) { + lang[i] = env_lang[i]; // Lowercase letter or digit, copy verbatim } else if (env_lang[i] == '\0' || env_lang[i] == '.') { // End, or start of suffix (e.g. en_CA.utf-8), finished lang[i] = '\0'; @@ -231,7 +219,7 @@ lilv_find_free_path(const char* in_path, char* path = (char*)malloc(in_path_len + 7); memcpy(path, in_path, in_path_len + 1); - for (unsigned i = 2; i < 1000000u; ++i) { + for (unsigned i = 2U; i < 1000000U; ++i) { if (!exists(path, user_data)) { return path; } @@ -251,13 +239,13 @@ static void update_latest(const char* path, const char* name, void* data) { Latest* latest = (Latest*)data; - char* entry_path = lilv_path_join(path, name); + char* entry_path = zix_path_join(NULL, path, name); unsigned num = 0; if (sscanf(entry_path, latest->pattern, &num) == 1) { struct stat st; if (!stat(entry_path, &st)) { if (st.st_mtime >= latest->time) { - free(latest->latest); + zix_free(NULL, latest->latest); latest->latest = entry_path; } } else { @@ -265,7 +253,7 @@ update_latest(const char* path, const char* name, void* data) } } if (entry_path != latest->latest) { - free(entry_path); + zix_free(NULL, entry_path); } } @@ -273,8 +261,9 @@ update_latest(const char* path, const char* name, void* data) char* lilv_get_latest_copy(const char* path, const char* copy_path) { - char* copy_dir = lilv_path_parent(copy_path); - Latest latest = {lilv_strjoin(copy_path, ".%u", NULL), 0, NULL}; + char* copy_dir = zix_string_view_copy(NULL, zix_path_parent_path(copy_path)); + + Latest latest = {lilv_strjoin(copy_path, ".%u", NULL), 0, NULL}; struct stat st; if (!stat(path, &st)) { @@ -283,9 +272,9 @@ lilv_get_latest_copy(const char* path, const char* copy_path) LILV_ERRORF("stat(%s) (%s)\n", path, strerror(errno)); } - lilv_dir_for_each(copy_dir, &latest, update_latest); + zix_dir_for_each(copy_dir, &latest, update_latest); free(latest.pattern); - free(copy_dir); + zix_free(NULL, copy_dir); return latest.latest; } diff --git a/src/world.c b/src/world.c index 47dc147..695cc29 100644 --- a/src/world.c +++ b/src/world.c @@ -1,27 +1,13 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "filesystem.h" +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + #include "lilv_config.h" // IWYU pragma: keep #include "lilv_internal.h" #include "lilv/lilv.h" #include "serd/serd.h" #include "sord/sord.h" -#include "zix/common.h" +#include "zix/filesystem.h" #include "zix/tree.h" #include "lv2/core/lv2.h" @@ -29,7 +15,6 @@ #ifdef LILV_DYN_MANIFEST # include "lv2/dynmanifest/dynmanifest.h" -# include <dlfcn.h> #endif #include <assert.h> @@ -42,6 +27,13 @@ static int lilv_world_drop_graph(LilvWorld* world, const SordNode* graph); +static void +destroy_node(void* const ptr, const void* const user_data) +{ + (void)user_data; + lilv_node_free((LilvNode*)ptr); +} + LilvWorld* lilv_world_new(void) { @@ -61,10 +53,11 @@ lilv_world_new(void) world->plugin_classes = lilv_plugin_classes_new(); world->plugins = lilv_plugins_new(); world->zombies = lilv_plugins_new(); - world->loaded_files = zix_tree_new( - false, lilv_resource_node_cmp, NULL, (ZixDestroyFunc)lilv_node_free); - world->libs = zix_tree_new(false, lilv_lib_compare, NULL, NULL); + world->loaded_files = + zix_tree_new(NULL, false, lilv_resource_node_cmp, NULL, destroy_node, NULL); + + world->libs = zix_tree_new(NULL, false, lilv_lib_compare, NULL, NULL, NULL); #define NS_DCTERMS "http://purl.org/dc/terms/" #define NS_DYNMAN "http://lv2plug.in/ns/ext/dynmanifest#" @@ -928,7 +921,7 @@ lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri) still be used. */ ZixTreeIter* i = zix_tree_begin((ZixTree*)world->plugins); - while (i != zix_tree_end((ZixTree*)world->plugins)) { + while (i && i != zix_tree_end((ZixTree*)world->plugins)) { LilvPlugin* p = (LilvPlugin*)zix_tree_get(i); ZixTreeIter* next = zix_tree_iter_next(i); @@ -964,7 +957,7 @@ lilv_world_load_directory(LilvWorld* world, const char* dir_path) { char* path = lilv_expand(dir_path); if (path) { - lilv_dir_for_each(path, world, load_dir_entry); + zix_dir_for_each(path, world, load_dir_entry); free(path); } } @@ -1100,11 +1093,11 @@ lilv_world_load_file(LilvWorld* world, SerdReader* reader, const LilvNode* uri) size_t uri_len = 0; const uint8_t* const uri_str = sord_node_get_string_counted(uri->node, &uri_len); - if (strncmp((const char*)uri_str, "file:", 5)) { + if (!!strncmp((const char*)uri_str, "file:", 5)) { return SERD_FAILURE; // Not a local file } - if (strcmp((const char*)uri_str + uri_len - 4, ".ttl")) { + if (!!strcmp((const char*)uri_str + uri_len - 4, ".ttl")) { return SERD_FAILURE; // Not a Turtle file } diff --git a/src/zix/common.h b/src/zix/common.h deleted file mode 100644 index d47586c..0000000 --- a/src/zix/common.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - Copyright 2016-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#ifndef ZIX_COMMON_H -#define ZIX_COMMON_H - -#include <stdbool.h> - -/** - @addtogroup zix - @{ -*/ - -/** @cond */ -#if defined(_WIN32) && !defined(ZIX_STATIC) && defined(ZIX_INTERNAL) -# define ZIX_API __declspec(dllexport) -#elif defined(_WIN32) && !defined(ZIX_STATIC) -# define ZIX_API __declspec(dllimport) -#elif defined(__GNUC__) -# define ZIX_API __attribute__((visibility("default"))) -#else -# define ZIX_API -#endif - -#ifdef __GNUC__ -# define ZIX_PURE_FUNC __attribute__((pure)) -# define ZIX_CONST_FUNC __attribute__((const)) -# define ZIX_MALLOC_FUNC __attribute__((malloc)) -#else -# define ZIX_PURE_FUNC -# define ZIX_CONST_FUNC -# define ZIX_MALLOC_FUNC -#endif - -#define ZIX_PURE_API \ - ZIX_API \ - ZIX_PURE_FUNC - -#define ZIX_CONST_API \ - ZIX_API \ - ZIX_CONST_FUNC - -#define ZIX_MALLOC_API \ - ZIX_API \ - ZIX_MALLOC_FUNC - -/** @endcond */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __GNUC__ -# define ZIX_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1))) -#else -# define ZIX_LOG_FUNC(fmt, arg1) -#endif - -// Unused parameter macro to suppresses warnings and make it impossible to use -#if defined(__cplusplus) -# define ZIX_UNUSED(name) -#elif defined(__GNUC__) -# define ZIX_UNUSED(name) name##_unused __attribute__((__unused__)) -#else -# define ZIX_UNUSED(name) name -#endif - -typedef enum { - ZIX_STATUS_SUCCESS, - ZIX_STATUS_ERROR, - ZIX_STATUS_NO_MEM, - ZIX_STATUS_NOT_FOUND, - ZIX_STATUS_EXISTS, - ZIX_STATUS_BAD_ARG, - ZIX_STATUS_BAD_PERMS -} ZixStatus; - -static inline const char* -zix_strerror(const ZixStatus status) -{ - switch (status) { - case ZIX_STATUS_SUCCESS: - return "Success"; - case ZIX_STATUS_ERROR: - return "Unknown error"; - case ZIX_STATUS_NO_MEM: - return "Out of memory"; - case ZIX_STATUS_NOT_FOUND: - return "Not found"; - case ZIX_STATUS_EXISTS: - return "Exists"; - case ZIX_STATUS_BAD_ARG: - return "Bad argument"; - case ZIX_STATUS_BAD_PERMS: - return "Bad permissions"; - } - return "Unknown error"; -} - -/** - Function for comparing two elements. -*/ -typedef int (*ZixComparator)(const void* a, - const void* b, - const void* user_data); - -/** - Function for testing equality of two elements. -*/ -typedef bool (*ZixEqualFunc)(const void* a, const void* b); - -/** - Function to destroy an element. -*/ -typedef void (*ZixDestroyFunc)(void* ptr); - -/** - @} -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* ZIX_COMMON_H */ diff --git a/src/zix/tree.c b/src/zix/tree.c deleted file mode 100644 index 9faf13c..0000000 --- a/src/zix/tree.c +++ /dev/null @@ -1,727 +0,0 @@ -/* - Copyright 2011-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "zix/tree.h" - -#include "zix/common.h" - -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -typedef struct ZixTreeNodeImpl ZixTreeNode; - -struct ZixTreeImpl { - ZixTreeNode* root; - ZixDestroyFunc destroy; - ZixComparator cmp; - void* cmp_data; - size_t size; - bool allow_duplicates; -}; - -struct ZixTreeNodeImpl { - void* data; - struct ZixTreeNodeImpl* left; - struct ZixTreeNodeImpl* right; - struct ZixTreeNodeImpl* parent; - int balance; -}; - -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) - -// Uncomment these for debugging features -// #define ZIX_TREE_DUMP 1 -// #define ZIX_TREE_VERIFY 1 -// #define ZIX_TREE_HYPER_VERIFY 1 - -#if defined(ZIX_TREE_VERIFY) || defined(ZIX_TREE_HYPER_VERIFY) -# include "tree_debug.h" -# define ASSERT_BALANCE(n) assert(verify_balance(n)) -#else -# define ASSERT_BALANCE(n) -#endif - -#ifdef ZIX_TREE_DUMP -# include "tree_debug.h" -# define DUMP(t) zix_tree_print(t->root, 0) -# define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__) -#else -# define DUMP(t) -# define DEBUG_PRINTF(fmt, ...) -#endif - -ZixTree* -zix_tree_new(bool allow_duplicates, - ZixComparator cmp, - void* cmp_data, - ZixDestroyFunc destroy) -{ - ZixTree* t = (ZixTree*)malloc(sizeof(ZixTree)); - t->root = NULL; - t->destroy = destroy; - t->cmp = cmp; - t->cmp_data = cmp_data; - t->size = 0; - t->allow_duplicates = allow_duplicates; - return t; -} - -static void -zix_tree_free_rec(ZixTree* t, ZixTreeNode* n) -{ - if (n) { - zix_tree_free_rec(t, n->left); - zix_tree_free_rec(t, n->right); - if (t->destroy) { - t->destroy(n->data); - } - free(n); - } -} - -void -zix_tree_free(ZixTree* t) -{ - if (t) { - zix_tree_free_rec(t, t->root); - free(t); - } -} - -size_t -zix_tree_size(const ZixTree* t) -{ - return t->size; -} - -static void -rotate(ZixTreeNode* p, ZixTreeNode* q) -{ - assert(q->parent == p); - assert(p->left == q || p->right == q); - - q->parent = p->parent; - if (q->parent) { - if (q->parent->left == p) { - q->parent->left = q; - } else { - q->parent->right = q; - } - } - - if (p->right == q) { - // Rotate left - p->right = q->left; - q->left = p; - if (p->right) { - p->right->parent = p; - } - } else { - // Rotate right - assert(p->left == q); - p->left = q->right; - q->right = p; - if (p->left) { - p->left->parent = p; - } - } - - p->parent = q; -} - -/** - * Rotate left about `p`. - * - * p q - * / \ / \ - * A q => p C - * / \ / \ - * B C A B - */ -static ZixTreeNode* -rotate_left(ZixTreeNode* p, int* height_change) -{ - ZixTreeNode* const q = p->right; - *height_change = (q->balance == 0) ? 0 : -1; - - DEBUG_PRINTF("LL %ld\n", (intptr_t)p->data); - - assert(p->balance == 2); - assert(q->balance == 0 || q->balance == 1); - - rotate(p, q); - - // p->balance -= 1 + MAX(0, q->balance); - // q->balance -= 1 - MIN(0, p->balance); - --q->balance; - p->balance = -(q->balance); - - ASSERT_BALANCE(p); - ASSERT_BALANCE(q); - return q; -} - -/** - * Rotate right about `p`. - * - * p q - * / \ / \ - * q C => A p - * / \ / \ - * A B B C - * - */ -static ZixTreeNode* -rotate_right(ZixTreeNode* p, int* height_change) -{ - ZixTreeNode* const q = p->left; - *height_change = (q->balance == 0) ? 0 : -1; - - DEBUG_PRINTF("RR %ld\n", (intptr_t)p->data); - - assert(p->balance == -2); - assert(q->balance == 0 || q->balance == -1); - - rotate(p, q); - - // p->balance += 1 - MIN(0, q->balance); - // q->balance += 1 + MAX(0, p->balance); - ++q->balance; - p->balance = -(q->balance); - - ASSERT_BALANCE(p); - ASSERT_BALANCE(q); - return q; -} - -/** - * Rotate left about `p->left` then right about `p`. - * - * p r - * / \ / \ - * q D => q p - * / \ / \ / \ - * A r A B C D - * / \ - * B C - * - */ -static ZixTreeNode* -rotate_left_right(ZixTreeNode* p, int* height_change) -{ - ZixTreeNode* const q = p->left; - ZixTreeNode* const r = q->right; - - assert(p->balance == -2); - assert(q->balance == 1); - assert(r->balance == -1 || r->balance == 0 || r->balance == 1); - - DEBUG_PRINTF("LR %ld P: %2d Q: %2d R: %2d\n", - (intptr_t)p->data, - p->balance, - q->balance, - r->balance); - - rotate(q, r); - rotate(p, r); - - q->balance -= 1 + MAX(0, r->balance); - p->balance += 1 - MIN(MIN(0, r->balance) - 1, r->balance + q->balance); - // r->balance += MAX(0, p->balance) + MIN(0, q->balance); - - // p->balance = (p->left && p->right) ? -MIN(r->balance, 0) : 0; - // q->balance = - MAX(r->balance, 0); - r->balance = 0; - - *height_change = -1; - - ASSERT_BALANCE(p); - ASSERT_BALANCE(q); - ASSERT_BALANCE(r); - return r; -} - -/** - * Rotate right about `p->right` then right about `p`. - * - * p r - * / \ / \ - * A q => p q - * / \ / \ / \ - * r D A B C D - * / \ - * B C - * - */ -static ZixTreeNode* -rotate_right_left(ZixTreeNode* p, int* height_change) -{ - ZixTreeNode* const q = p->right; - ZixTreeNode* const r = q->left; - - assert(p->balance == 2); - assert(q->balance == -1); - assert(r->balance == -1 || r->balance == 0 || r->balance == 1); - - DEBUG_PRINTF("RL %ld P: %2d Q: %2d R: %2d\n", - (intptr_t)p->data, - p->balance, - q->balance, - r->balance); - - rotate(q, r); - rotate(p, r); - - q->balance += 1 - MIN(0, r->balance); - p->balance -= 1 + MAX(MAX(0, r->balance) + 1, r->balance + q->balance); - // r->balance += MAX(0, q->balance) + MIN(0, p->balance); - - // p->balance = (p->left && p->right) ? -MAX(r->balance, 0) : 0; - // q->balance = - MIN(r->balance, 0); - r->balance = 0; - // assert(r->balance == 0); - - *height_change = -1; - - ASSERT_BALANCE(p); - ASSERT_BALANCE(q); - ASSERT_BALANCE(r); - return r; -} - -static ZixTreeNode* -zix_tree_rebalance(ZixTree* t, ZixTreeNode* node, int* height_change) -{ -#ifdef ZIX_TREE_HYPER_VERIFY - const size_t old_height = height(node); -#endif - DEBUG_PRINTF("REBALANCE %ld (%d)\n", (intptr_t)node->data, node->balance); - *height_change = 0; - const bool is_root = !node->parent; - assert((is_root && t->root == node) || (!is_root && t->root != node)); - ZixTreeNode* replacement = node; - if (node->balance == -2) { - assert(node->left); - if (node->left->balance == 1) { - replacement = rotate_left_right(node, height_change); - } else { - replacement = rotate_right(node, height_change); - } - } else if (node->balance == 2) { - assert(node->right); - if (node->right->balance == -1) { - replacement = rotate_right_left(node, height_change); - } else { - replacement = rotate_left(node, height_change); - } - } - if (is_root) { - assert(!replacement->parent); - t->root = replacement; - } - DUMP(t); -#ifdef ZIX_TREE_HYPER_VERIFY - assert(old_height + *height_change == height(replacement)); -#endif - return replacement; -} - -ZixStatus -zix_tree_insert(ZixTree* t, void* e, ZixTreeIter** ti) -{ - DEBUG_PRINTF("**** INSERT %ld\n", (intptr_t)e); - int cmp = 0; - ZixTreeNode* n = t->root; - ZixTreeNode* p = NULL; - - // Find the parent p of e - while (n) { - p = n; - cmp = t->cmp(e, n->data, t->cmp_data); - if (cmp < 0) { - n = n->left; - } else if (cmp > 0 || t->allow_duplicates) { - n = n->right; - } else { - if (ti) { - *ti = n; - } - DEBUG_PRINTF("%ld EXISTS!\n", (intptr_t)e); - return ZIX_STATUS_EXISTS; - } - } - - // Allocate a new node n - if (!(n = (ZixTreeNode*)malloc(sizeof(ZixTreeNode)))) { - return ZIX_STATUS_NO_MEM; - } - memset(n, '\0', sizeof(ZixTreeNode)); - n->data = e; - n->balance = 0; - if (ti) { - *ti = n; - } - - bool p_height_increased = false; - - // Make p the parent of n - n->parent = p; - if (!p) { - t->root = n; - } else { - if (cmp < 0) { - assert(!p->left); - assert(p->balance == 0 || p->balance == 1); - p->left = n; - --p->balance; - p_height_increased = !p->right; - } else { - assert(!p->right); - assert(p->balance == 0 || p->balance == -1); - p->right = n; - ++p->balance; - p_height_increased = !p->left; - } - } - - DUMP(t); - - // Rebalance if necessary (at most 1 rotation) - assert(!p || p->balance == -1 || p->balance == 0 || p->balance == 1); - if (p && p_height_increased) { - int height_change = 0; - for (ZixTreeNode* i = p; i && i->parent; i = i->parent) { - if (i == i->parent->left) { - if (--i->parent->balance == -2) { - zix_tree_rebalance(t, i->parent, &height_change); - break; - } - } else { - assert(i == i->parent->right); - if (++i->parent->balance == 2) { - zix_tree_rebalance(t, i->parent, &height_change); - break; - } - } - - if (i->parent->balance == 0) { - break; - } - } - } - - DUMP(t); - - ++t->size; - -#ifdef ZIX_TREE_VERIFY - if (!verify(t, t->root)) { - return ZIX_STATUS_ERROR; - } -#endif - - return ZIX_STATUS_SUCCESS; -} - -ZixStatus -zix_tree_remove(ZixTree* t, ZixTreeIter* ti) -{ - ZixTreeNode* const n = ti; - ZixTreeNode** pp = NULL; // parent pointer - ZixTreeNode* to_balance = n->parent; // lowest node to balance - int d_balance = 0; // delta(balance) for n->parent - - DEBUG_PRINTF("*** REMOVE %ld\n", (intptr_t)n->data); - - if ((n == t->root) && !n->left && !n->right) { - t->root = NULL; - if (t->destroy) { - t->destroy(n->data); - } - free(n); - --t->size; - assert(t->size == 0); - return ZIX_STATUS_SUCCESS; - } - - // Set pp to the parent pointer to n, if applicable - if (n->parent) { - assert(n->parent->left == n || n->parent->right == n); - if (n->parent->left == n) { // n is left child - pp = &n->parent->left; - d_balance = 1; - } else { // n is right child - assert(n->parent->right == n); - pp = &n->parent->right; - d_balance = -1; - } - } - - assert(!pp || *pp == n); - - int height_change = 0; - if (!n->left && !n->right) { - // n is a leaf, just remove it - if (pp) { - *pp = NULL; - to_balance = n->parent; - height_change = (!n->parent->left && !n->parent->right) ? -1 : 0; - } - - } else if (!n->left) { - // Replace n with right (only) child - if (pp) { - *pp = n->right; - to_balance = n->parent; - } else { - t->root = n->right; - } - n->right->parent = n->parent; - height_change = -1; - - } else if (!n->right) { - // Replace n with left (only) child - if (pp) { - *pp = n->left; - to_balance = n->parent; - } else { - t->root = n->left; - } - n->left->parent = n->parent; - height_change = -1; - - } else { - // Replace n with in-order successor (leftmost child of right subtree) - ZixTreeNode* replace = n->right; - while (replace->left) { - assert(replace->left->parent == replace); - replace = replace->left; - } - - // Remove replace from parent (replace_p) - if (replace->parent->left == replace) { - height_change = replace->parent->right ? 0 : -1; - d_balance = 1; - to_balance = replace->parent; - replace->parent->left = replace->right; - } else { - assert(replace->parent == n); - height_change = replace->parent->left ? 0 : -1; - d_balance = -1; - to_balance = replace->parent; - replace->parent->right = replace->right; - } - - if (to_balance == n) { - to_balance = replace; - } - - if (replace->right) { - replace->right->parent = replace->parent; - } - - replace->balance = n->balance; - - // Swap node to delete with replace - if (pp) { - *pp = replace; - } else { - assert(t->root == n); - t->root = replace; - } - - replace->parent = n->parent; - replace->left = n->left; - n->left->parent = replace; - replace->right = n->right; - if (n->right) { - n->right->parent = replace; - } - - assert(!replace->parent || replace->parent->left == replace || - replace->parent->right == replace); - } - - // Rebalance starting at to_balance upwards. - for (ZixTreeNode* i = to_balance; i; i = i->parent) { - i->balance += d_balance; - if (d_balance == 0 || i->balance == -1 || i->balance == 1) { - break; - } - - assert(i != n); - i = zix_tree_rebalance(t, i, &height_change); - if (i->balance == 0) { - height_change = -1; - } - - if (i->parent) { - if (i == i->parent->left) { - d_balance = height_change * -1; - } else { - assert(i == i->parent->right); - d_balance = height_change; - } - } - } - - DUMP(t); - - if (t->destroy) { - t->destroy(n->data); - } - free(n); - - --t->size; - -#ifdef ZIX_TREE_VERIFY - if (!verify(t, t->root)) { - return ZIX_STATUS_ERROR; - } -#endif - - return ZIX_STATUS_SUCCESS; -} - -ZixStatus -zix_tree_find(const ZixTree* t, const void* e, ZixTreeIter** ti) -{ - ZixTreeNode* n = t->root; - while (n) { - const int cmp = t->cmp(e, n->data, t->cmp_data); - if (cmp == 0) { - break; - } - - if (cmp < 0) { - n = n->left; - } else { - n = n->right; - } - } - - *ti = n; - return (n) ? ZIX_STATUS_SUCCESS : ZIX_STATUS_NOT_FOUND; -} - -void* -zix_tree_get(const ZixTreeIter* ti) -{ - return ti ? ti->data : NULL; -} - -ZixTreeIter* -zix_tree_begin(ZixTree* t) -{ - if (!t->root) { - return NULL; - } - - ZixTreeNode* n = t->root; - while (n->left) { - n = n->left; - } - - return n; -} - -ZixTreeIter* -zix_tree_end(ZixTree* ZIX_UNUSED(t)) -{ - return NULL; -} - -ZixTreeIter* -zix_tree_rbegin(ZixTree* t) -{ - if (!t->root) { - return NULL; - } - - ZixTreeNode* n = t->root; - while (n->right) { - n = n->right; - } - - return n; -} - -ZixTreeIter* -zix_tree_rend(ZixTree* ZIX_UNUSED(t)) -{ - return NULL; -} - -bool -zix_tree_iter_is_end(const ZixTreeIter* i) -{ - return !i; -} - -bool -zix_tree_iter_is_rend(const ZixTreeIter* i) -{ - return !i; -} - -ZixTreeIter* -zix_tree_iter_next(ZixTreeIter* i) -{ - if (!i) { - return NULL; - } - - if (i->right) { - i = i->right; - while (i->left) { - i = i->left; - } - } else { - while (i->parent && i->parent->right == i) { // i is a right child - i = i->parent; - } - - i = i->parent; - } - - return i; -} - -ZixTreeIter* -zix_tree_iter_prev(ZixTreeIter* i) -{ - if (!i) { - return NULL; - } - - if (i->left) { - i = i->left; - while (i->right) { - i = i->right; - } - - } else { - while (i->parent && i->parent->left == i) { // i is a left child - i = i->parent; - } - - i = i->parent; - } - - return i; -} diff --git a/src/zix/tree.h b/src/zix/tree.h deleted file mode 100644 index a2d5fe7..0000000 --- a/src/zix/tree.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - Copyright 2011-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#ifndef ZIX_TREE_H -#define ZIX_TREE_H - -#include "zix/common.h" - -#include <stdbool.h> -#include <stddef.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - @addtogroup zix - @{ - @name Tree - @{ -*/ - -/** - A balanced binary search tree. -*/ -typedef struct ZixTreeImpl ZixTree; - -/** - An iterator over a @ref ZixTree. -*/ -typedef struct ZixTreeNodeImpl ZixTreeIter; - -/** - Create a new (empty) tree. -*/ -ZIX_API -ZixTree* -zix_tree_new(bool allow_duplicates, - ZixComparator cmp, - void* cmp_data, - ZixDestroyFunc destroy); - -/** - Free `t`. -*/ -ZIX_API -void -zix_tree_free(ZixTree* t); - -/** - Return the number of elements in `t`. -*/ -ZIX_PURE_API -size_t -zix_tree_size(const ZixTree* t); - -/** - Insert the element `e` into `t` and point `ti` at the new element. -*/ -ZIX_API -ZixStatus -zix_tree_insert(ZixTree* t, void* e, ZixTreeIter** ti); - -/** - Remove the item pointed at by `ti` from `t`. -*/ -ZIX_API -ZixStatus -zix_tree_remove(ZixTree* t, ZixTreeIter* ti); - -/** - Set `ti` to an element equal to `e` in `t`. - If no such item exists, `ti` is set to NULL. -*/ -ZIX_API -ZixStatus -zix_tree_find(const ZixTree* t, const void* e, ZixTreeIter** ti); - -/** - Return the data associated with the given tree item. -*/ -ZIX_PURE_API -void* -zix_tree_get(const ZixTreeIter* ti); - -/** - Return an iterator to the first (smallest) element in `t`. -*/ -ZIX_PURE_API -ZixTreeIter* -zix_tree_begin(ZixTree* t); - -/** - Return an iterator the the element one past the last element in `t`. -*/ -ZIX_CONST_API -ZixTreeIter* -zix_tree_end(ZixTree* t); - -/** - Return true iff `i` is an iterator to the end of its tree. -*/ -ZIX_CONST_API -bool -zix_tree_iter_is_end(const ZixTreeIter* i); - -/** - Return an iterator to the last (largest) element in `t`. -*/ -ZIX_PURE_API -ZixTreeIter* -zix_tree_rbegin(ZixTree* t); - -/** - Return an iterator the the element one before the first element in `t`. -*/ -ZIX_CONST_API -ZixTreeIter* -zix_tree_rend(ZixTree* t); - -/** - Return true iff `i` is an iterator to the reverse end of its tree. -*/ -ZIX_CONST_API -bool -zix_tree_iter_is_rend(const ZixTreeIter* i); - -/** - Return an iterator that points to the element one past `i`. -*/ -ZIX_PURE_API -ZixTreeIter* -zix_tree_iter_next(ZixTreeIter* i); - -/** - Return an iterator that points to the element one before `i`. -*/ -ZIX_PURE_API -ZixTreeIter* -zix_tree_iter_prev(ZixTreeIter* i); - -/** - @} - @} -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* ZIX_TREE_H */ diff --git a/subprojects/sphinxygen.wrap b/subprojects/sphinxygen.wrap new file mode 100644 index 0000000..013de9c --- /dev/null +++ b/subprojects/sphinxygen.wrap @@ -0,0 +1,14 @@ +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +[wrap-file] +directory = sphinxygen-1.0.0 +source_url = https://download.drobilla.net/sphinxygen-1.0.0.tar.gz +source_filename = sphinxygen-1.0.0.tar.gz +source_hash = 96b19e3b37d4886dcf3e89d4ccf0b66c0deb9f2e34ac151a7a6659a421f0282d + +# [wrap-git] +# url = https://gitlab.com/drobilla/sphinxygen.git +# push-url = ssh://git@gitlab.com:drobilla/sphinxygen.git +# revision = main +# depth = 1 diff --git a/test/.clang-tidy b/test/.clang-tidy index a6f6844..f6f74ab 100644 --- a/test/.clang-tidy +++ b/test/.clang-tidy @@ -1,42 +1,19 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + Checks: > - *, - -*-else-after-return, -*-magic-numbers, - -*-uppercase-literal-suffix, - -*-vararg, -android-cloexec-fopen, - -bugprone-assert-side-effect, -bugprone-branch-clone, - -bugprone-macro-parentheses, -bugprone-narrowing-conversions, - -bugprone-not-null-terminated-result, - -bugprone-reserved-identifier, - -bugprone-suspicious-string-compare, - -cert-dcl37-c, - -cert-dcl50-cpp, - -cert-dcl51-cpp, - -cert-err34-c, - -clang-analyzer-alpha.*, + -cert-err33-c, -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling, + -concurrency-mt-unsafe, -cppcoreguidelines-avoid-non-const-global-variables, - -cppcoreguidelines-macro-usage, -cppcoreguidelines-narrowing-conversions, - -cppcoreguidelines-pro-bounds-array-to-pointer-decay, - -fuchsia-overloaded-operator, - -google-explicit-constructor, - -google-readability-todo, - -hicpp-explicit-conversions, -hicpp-multiway-paths-covered, - -hicpp-no-array-decay, -hicpp-signed-bitwise, -llvm-header-guard, - -llvmlibc-*, - -misc-no-recursion, - -misc-non-private-member-variables-in-classes, - -misc-unused-parameters, - -modernize-return-braced-init-list, - -modernize-use-trailing-return-type, - -readability-implicit-bool-conversion, -WarningsAsErrors: '*' -HeaderFilterRegex: '.*' -FormatStyle: file + -readability-function-cognitive-complexity, + -readability-suspicious-call-argument, +InheritParentConfig: true diff --git a/test/bad_syntax.lv2/bad_syntax.c b/test/bad_syntax.lv2/bad_syntax.c index da9c041..b1b52e7 100644 --- a/test/bad_syntax.lv2/bad_syntax.c +++ b/test/bad_syntax.lv2/bad_syntax.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Bad syntax in plugin data file - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/bad_syntax.lv2/meson.build b/test/bad_syntax.lv2/meson.build new file mode 100644 index 0000000..dbda502 --- /dev/null +++ b/test/bad_syntax.lv2/meson.build @@ -0,0 +1,36 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'bad_syntax', + files('bad_syntax.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'bad_syntax.ttl'] + +foreach f : ttl_files + configure_file( + configuration: config, + input: files(f + '.in'), + output: f, + ) +endforeach + +test( + 'bad_syntax', + executable( + 'test_bad_syntax', + files('test_bad_syntax.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep], + ), + args: [meson.current_build_dir() / ''], + suite: 'plugin', +) + diff --git a/test/bad_syntax.lv2/test_bad_syntax.c b/test/bad_syntax.lv2/test_bad_syntax.c index 5f10828..39729d4 100644 --- a/test/bad_syntax.lv2/test_bad_syntax.c +++ b/test/bad_syntax.lv2/test_bad_syntax.c @@ -1,15 +1,12 @@ -#undef NDEBUG +// Copyright 2015-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC -#include "../src/filesystem.h" +#undef NDEBUG #include "lilv/lilv.h" -#include "serd/serd.h" #include <assert.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #define PLUGIN_URI "http://example.org/bad-syntax" @@ -25,12 +22,8 @@ main(int argc, char** argv) LilvWorld* world = lilv_world_new(); // Load test plugin bundle - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path); lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); diff --git a/test/cpp/.clang-tidy b/test/cpp/.clang-tidy new file mode 100644 index 0000000..5d20fa0 --- /dev/null +++ b/test/cpp/.clang-tidy @@ -0,0 +1,19 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +Checks: > + -cert-dcl50-cpp, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -fuchsia-overloaded-operator, + -google-explicit-constructor, + -google-readability-todo, + -hicpp-explicit-conversions, + -hicpp-no-array-decay, + -misc-non-private-member-variables-in-classes, + -modernize-return-braced-init-list, + -modernize-use-nodiscard, + -modernize-use-trailing-return-type, + -readability-implicit-bool-conversion, +HeaderFilterRegex: '.*/lilvmm\.hpp' +InheritParentConfig: true diff --git a/test/cpp/meson.build b/test/cpp/meson.build new file mode 100644 index 0000000..5b8169c --- /dev/null +++ b/test/cpp/meson.build @@ -0,0 +1,37 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +cpp_suppressions = [] +if cpp.get_id() == 'gcc' + cpp_suppressions += [ + '-Wno-cast-align', + '-Wno-padded', + ] +elif cpp.get_id() == 'clang' + cpp_suppressions += [ + '-Wno-c++98-compat', + '-Wno-cast-align', + '-Wno-cast-qual', + '-Wno-documentation-unknown-command', + '-Wno-padded', + '-Wno-poison-system-directories', + '-Wno-reserved-id-macro', + ] +elif cpp.get_id() == 'msvc' + cpp_suppressions += [ + '/wd4514', # unreferenced inline function has been removed + '/wd4820', # padding added after construct + ] +endif + +test( + 'lilv_hpp', + executable( + 'test_lilv_hpp', + files('test_lilv_hpp.cpp'), + cpp_args: test_args + cpp_suppressions, + dependencies: [lv2_dep, lilv_static_dep], + include_directories: include_directories('../../src'), + ), + suite: 'unit', +) diff --git a/test/cpp/test_lilv_hpp.cpp b/test/cpp/test_lilv_hpp.cpp new file mode 100644 index 0000000..7e6de72 --- /dev/null +++ b/test/cpp/test_lilv_hpp.cpp @@ -0,0 +1,12 @@ +// Copyright 2017-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#include "lilv/lilvmm.hpp" + +int +main() +{ + const Lilv::World world{}; + + return 0; +} diff --git a/test/failed_instantiation.lv2/failed_instantiation.c b/test/failed_instantiation.lv2/failed_instantiation.c index ecab647..2d75c1a 100644 --- a/test/failed_instantiation.lv2/failed_instantiation.c +++ b/test/failed_instantiation.lv2/failed_instantiation.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Failed instantiation - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/failed_instantiation.lv2/meson.build b/test/failed_instantiation.lv2/meson.build new file mode 100644 index 0000000..966eed0 --- /dev/null +++ b/test/failed_instantiation.lv2/meson.build @@ -0,0 +1,36 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'failed_instantiation', + files('failed_instantiation.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'failed_instantiation.ttl'] + +foreach f : ttl_files + configure_file( + configuration: config, + input: files(f + '.in'), + output: f, + ) +endforeach + +test( + 'failed_instantiation', + executable( + 'test_failed_instantiation', + files('test_failed_instantiation.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep], + ), + args: [meson.current_build_dir() / ''], + suite: 'plugin', +) + diff --git a/test/failed_instantiation.lv2/test_failed_instantiation.c b/test/failed_instantiation.lv2/test_failed_instantiation.c index 8dbefc3..ed46d5a 100644 --- a/test/failed_instantiation.lv2/test_failed_instantiation.c +++ b/test/failed_instantiation.lv2/test_failed_instantiation.c @@ -1,15 +1,12 @@ -#undef NDEBUG +// Copyright 2015-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC -#include "../src/filesystem.h" +#undef NDEBUG #include "lilv/lilv.h" -#include "serd/serd.h" #include <assert.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #define PLUGIN_URI "http://example.org/failed-instantiation" @@ -25,12 +22,8 @@ main(int argc, char** argv) LilvWorld* world = lilv_world_new(); // Load test plugin bundle - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path); lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); diff --git a/test/failed_lib_descriptor.lv2/failed_lib_descriptor.c b/test/failed_lib_descriptor.lv2/failed_lib_descriptor.c index c7c08cf..2d0baee 100644 --- a/test/failed_lib_descriptor.lv2/failed_lib_descriptor.c +++ b/test/failed_lib_descriptor.lv2/failed_lib_descriptor.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Failed lib descriptor - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/failed_lib_descriptor.lv2/meson.build b/test/failed_lib_descriptor.lv2/meson.build new file mode 100644 index 0000000..61de196 --- /dev/null +++ b/test/failed_lib_descriptor.lv2/meson.build @@ -0,0 +1,36 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'failed_lib_descriptor', + files('failed_lib_descriptor.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'failed_lib_descriptor.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + +test( + 'failed_lib_descriptor', + executable( + 'test_failed_lib_descriptor', + files('test_failed_lib_descriptor.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep], + ), + args: [meson.current_build_dir() / ''], + suite: 'plugin', +) + diff --git a/test/failed_lib_descriptor.lv2/test_failed_lib_descriptor.c b/test/failed_lib_descriptor.lv2/test_failed_lib_descriptor.c index 71a3b96..9a9641b 100644 --- a/test/failed_lib_descriptor.lv2/test_failed_lib_descriptor.c +++ b/test/failed_lib_descriptor.lv2/test_failed_lib_descriptor.c @@ -1,15 +1,12 @@ -#undef NDEBUG +// Copyright 2015-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC -#include "../src/filesystem.h" +#undef NDEBUG #include "lilv/lilv.h" -#include "serd/serd.h" #include <assert.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #define PLUGIN_URI "http://example.org/failed-lib-descriptor" @@ -25,12 +22,8 @@ main(int argc, char** argv) LilvWorld* world = lilv_world_new(); // Load test plugin bundle - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path); lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); diff --git a/test/lib_descriptor.lv2/lib_descriptor.c b/test/lib_descriptor.lv2/lib_descriptor.c index ab27c2b..bae1659 100644 --- a/test/lib_descriptor.lv2/lib_descriptor.c +++ b/test/lib_descriptor.lv2/lib_descriptor.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Missing descriptor - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" @@ -96,12 +82,7 @@ get_plugin(LV2_Lib_Handle handle, uint32_t index) { (void)handle; - switch (index) { - case 0: - return &descriptor; - default: - return NULL; - } + return index ? NULL : &descriptor; } static const LV2_Lib_Descriptor lib = {NULL, diff --git a/test/lib_descriptor.lv2/meson.build b/test/lib_descriptor.lv2/meson.build new file mode 100644 index 0000000..ea29b6a --- /dev/null +++ b/test/lib_descriptor.lv2/meson.build @@ -0,0 +1,36 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'lib_descriptor', + files('lib_descriptor.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'lib_descriptor.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + +test( + 'lib_descriptor', + executable( + 'test_lib_descriptor', + files('test_lib_descriptor.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep], + ), + args: [meson.current_build_dir() / ''], + suite: 'plugin', +) + diff --git a/test/lib_descriptor.lv2/test_lib_descriptor.c b/test/lib_descriptor.lv2/test_lib_descriptor.c index bf79be8..e971662 100644 --- a/test/lib_descriptor.lv2/test_lib_descriptor.c +++ b/test/lib_descriptor.lv2/test_lib_descriptor.c @@ -1,15 +1,12 @@ -#undef NDEBUG +// Copyright 2015-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC -#include "../src/filesystem.h" +#undef NDEBUG #include "lilv/lilv.h" -#include "serd/serd.h" #include <assert.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #define PLUGIN_URI "http://example.org/lib-descriptor" @@ -25,12 +22,8 @@ main(int argc, char** argv) LilvWorld* world = lilv_world_new(); // Load test plugin bundle - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path); lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); diff --git a/test/lilv_cxx_test.cpp b/test/lilv_cxx_test.cpp deleted file mode 100644 index 31d5e4e..0000000 --- a/test/lilv_cxx_test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright 2017-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "lilv/lilvmm.hpp" - -int -main() -{ - Lilv::World world; - - return 0; -} diff --git a/test/lilv_test_uri_map.h b/test/lilv_test_uri_map.h index 5f85c86..b4fba0f 100644 --- a/test/lilv_test_uri_map.h +++ b/test/lilv_test_uri_map.h @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #ifndef LILV_TEST_URI_MAP_H #define LILV_TEST_URI_MAP_H @@ -23,14 +10,13 @@ #include "serd/serd.h" #include <assert.h> -#include <stddef.h> #include <stdint.h> #include <stdlib.h> #include <string.h> typedef struct { - char** uris; - size_t n_uris; + char** uris; + uint32_t n_uris; } LilvTestUriMap; static inline void @@ -43,7 +29,7 @@ lilv_test_uri_map_init(LilvTestUriMap* const map) static inline void lilv_test_uri_map_clear(LilvTestUriMap* const map) { - for (size_t i = 0; i < map->n_uris; ++i) { + for (uint32_t i = 0; i < map->n_uris; ++i) { free(map->uris[i]); } @@ -57,7 +43,7 @@ map_uri(LV2_URID_Map_Handle handle, const char* uri) { LilvTestUriMap* map = (LilvTestUriMap*)handle; - for (size_t i = 0; i < map->n_uris; ++i) { + for (uint32_t i = 0; i < map->n_uris; ++i) { if (!strcmp(map->uris[i], uri)) { return i + 1; } diff --git a/test/lilv_test_utils.c b/test/lilv_test_utils.c index f658f1b..c3c47f0 100644 --- a/test/lilv_test_utils.c +++ b/test/lilv_test_utils.c @@ -1,28 +1,13 @@ -/* - Copyright 2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#define _POSIX_C_SOURCE 200809L /* for setenv */ +// Copyright 2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_test_utils.h" -#include "../src/filesystem.h" -#include "../src/lilv_internal.h" - #include "lilv/lilv.h" #include "serd/serd.h" +#include "zix/allocator.h" +#include "zix/filesystem.h" +#include "zix/path.h" #include <errno.h> #include <stdbool.h> @@ -46,13 +31,13 @@ lilv_test_env_new(void) env->plugin2_uri = lilv_new_uri(world, "http://example.org/foobar"); // Set custom LV2_PATH in build directory to only use test data - char* test_path = lilv_path_canonical(LILV_TEST_DIR); - char* lv2_path = lilv_strjoin(test_path, "/test_lv2_path", NULL); + char* test_path = zix_canonical_path(NULL, LILV_TEST_DIR); + char* lv2_path = zix_path_join(NULL, test_path, "lv2"); LilvNode* path = lilv_new_string(world, lv2_path); lilv_world_set_option(world, LILV_OPTION_LV2_PATH, path); - free(lv2_path); - free(test_path); lilv_node_free(path); + zix_free(NULL, lv2_path); + zix_free(NULL, test_path); return env; } @@ -60,10 +45,10 @@ lilv_test_env_new(void) void lilv_test_env_free(LilvTestEnv* env) { - free(env->test_content_path); - free(env->test_manifest_path); - free(env->test_bundle_uri); - free(env->test_bundle_path); + zix_free(NULL, env->test_content_path); + zix_free(NULL, env->test_manifest_path); + lilv_node_free(env->test_bundle_uri); + zix_free(NULL, env->test_bundle_path); lilv_node_free(env->plugin2_uri); lilv_node_free(env->plugin1_uri); lilv_world_free(env->world); @@ -77,16 +62,16 @@ create_bundle(LilvTestEnv* env, const char* plugin) { { - char* const test_dir = lilv_path_canonical(LILV_TEST_DIR); - char* const bundle_dir = lilv_path_join(test_dir, name); + char* const test_dir = zix_canonical_path(NULL, LILV_TEST_DIR); + char* const bundle_dir = zix_path_join(NULL, test_dir, name); - env->test_bundle_path = lilv_path_join(bundle_dir, ""); + env->test_bundle_path = zix_path_join(NULL, bundle_dir, ""); - lilv_free(bundle_dir); - lilv_free(test_dir); + zix_free(NULL, bundle_dir); + zix_free(NULL, test_dir); } - if (lilv_create_directories(env->test_bundle_path)) { + if (zix_create_directories(NULL, env->test_bundle_path)) { fprintf(stderr, "Failed to create directory '%s' (%s)\n", env->test_bundle_path, @@ -98,9 +83,12 @@ create_bundle(LilvTestEnv* env, (const uint8_t*)env->test_bundle_path, NULL, NULL, true); env->test_bundle_uri = lilv_new_uri(env->world, (const char*)s.buf); + env->test_manifest_path = - lilv_path_join(env->test_bundle_path, "manifest.ttl"); - env->test_content_path = lilv_path_join(env->test_bundle_path, "plugin.ttl"); + zix_path_join(NULL, env->test_bundle_path, "manifest.ttl"); + + env->test_content_path = + zix_path_join(NULL, env->test_bundle_path, "plugin.ttl"); serd_node_free(&s); @@ -152,21 +140,21 @@ void delete_bundle(LilvTestEnv* env) { if (env->test_content_path) { - lilv_remove(env->test_content_path); + zix_remove(env->test_content_path); } if (env->test_manifest_path) { - lilv_remove(env->test_manifest_path); + zix_remove(env->test_manifest_path); } if (env->test_bundle_path) { remove(env->test_bundle_path); } - free(env->test_content_path); - free(env->test_manifest_path); - free(env->test_bundle_uri); - free(env->test_bundle_path); + zix_free(NULL, env->test_content_path); + zix_free(NULL, env->test_manifest_path); + lilv_node_free(env->test_bundle_uri); + zix_free(NULL, env->test_bundle_path); env->test_content_path = NULL; env->test_manifest_path = NULL; @@ -188,3 +176,16 @@ set_env(const char* name, const char* value) setenv(name, value, 1); #endif } + +char* +lilv_create_temporary_directory(const char* pattern) +{ + char* const tmpdir = zix_temp_directory_path(NULL); + char* const path_pattern = zix_path_join(NULL, tmpdir, pattern); + char* const result = zix_create_temporary_directory(NULL, path_pattern); + + zix_free(NULL, path_pattern); + zix_free(NULL, tmpdir); + + return result; +} diff --git a/test/lilv_test_utils.h b/test/lilv_test_utils.h index 76d9bc1..f01b5b4 100644 --- a/test/lilv_test_utils.h +++ b/test/lilv_test_utils.h @@ -1,18 +1,5 @@ -/* - Copyright 2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #ifndef LILV_TEST_UTILS_H #define LILV_TEST_UTILS_H @@ -92,4 +79,8 @@ delete_bundle(LilvTestEnv* env); void set_env(const char* name, const char* value); +// Create a unique temporary directory +char* +lilv_create_temporary_directory(const char* pattern); + #endif // LILV_TEST_UTILS_H diff --git a/test/core.lv2/lv2core.ttl b/test/lv2/core.lv2/lv2core.ttl index 5659487..5659487 100644 --- a/test/core.lv2/lv2core.ttl +++ b/test/lv2/core.lv2/lv2core.ttl diff --git a/test/core.lv2/manifest.ttl b/test/lv2/core.lv2/manifest.ttl index a77ad71..a77ad71 100644 --- a/test/core.lv2/manifest.ttl +++ b/test/lv2/core.lv2/manifest.ttl diff --git a/test/lv2/core.lv2/meson.build b/test/lv2/core.lv2/meson.build new file mode 100644 index 0000000..0d02ae1 --- /dev/null +++ b/test/lv2/core.lv2/meson.build @@ -0,0 +1,11 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +ttl_files = files( + 'lv2core.ttl', + 'manifest.ttl', +) + +foreach file : ttl_files + configure_file(copy: true, input: file, output: '@PLAINNAME@') +endforeach diff --git a/test/meson.build b/test/meson.build new file mode 100644 index 0000000..06075b2 --- /dev/null +++ b/test/meson.build @@ -0,0 +1,112 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +#################### +# Project Metadata # +#################### + +if get_option('warning_level') == 'everything' + # Check release metadata + if not meson.is_subproject() + autoship = find_program('autoship', required: false) + if autoship.found() + test('autoship', autoship, args: ['test', lilv_src_root], suite: 'data') + endif + endif + + # Check licensing metadata + reuse = find_program('reuse', required: false) + if reuse.found() + test( + 'REUSE', reuse, + args: ['--root', lilv_src_root, 'lint'], + suite: 'data', + ) + endif +endif + +############## +# Test Setup # +############## + +test_args = ['-DLILV_STATIC'] +if cc.get_id() == 'msvc' + test_args += [ + '/wd4464', # relative include path contains '..' + ] +endif + +subdir('lv2/core.lv2') + +################ +# Bundle Tests # +################ + +subdir('bad_syntax.lv2') +subdir('failed_instantiation.lv2') +subdir('failed_lib_descriptor.lv2') +subdir('lib_descriptor.lv2') +subdir('missing_descriptor.lv2') +subdir('missing_name.lv2') +subdir('missing_plugin.lv2') +subdir('missing_port.lv2') +subdir('missing_port_name.lv2') +subdir('new_version.lv2') +subdir('old_version.lv2') +subdir('test_plugin.lv2') + +################ +# C++ Bindings # +################ + +if not get_option('bindings_cpp').disabled() + subdir('cpp') +endif + +############## +# Unit Tests # +############## + +unit_tests = [ + 'bad_port_index', + 'bad_port_symbol', + 'classes', + 'discovery', + 'get_symbol', + 'no_author', + 'no_verify', + 'plugin', + 'port', + 'preset', + 'project', + 'project_no_author', + 'prototype', + 'reload_bundle', + 'replace_version', + 'state', + 'string', + 'ui', + 'util', + 'value', + 'verify', + 'world', +] + +define_args = [ + '-DLILV_TEST_BUNDLE="@0@/"'.format(meson.current_build_dir() / 'test_plugin.lv2'), + '-DLILV_TEST_DIR="@0@/"'.format(meson.current_build_dir()), +] + +foreach unit : unit_tests + test( + unit, + executable( + 'test_@0@'.format(unit), + files('lilv_test_utils.c', 'test_@0@.c'.format(unit)), + c_args: define_args + test_args + c_suppressions, + include_directories: include_directories('../src'), + dependencies: [lv2_dep, lilv_static_dep], + ), + suite: 'unit', + ) +endforeach diff --git a/test/missing_descriptor.lv2/meson.build b/test/missing_descriptor.lv2/meson.build new file mode 100644 index 0000000..b4ad32f --- /dev/null +++ b/test/missing_descriptor.lv2/meson.build @@ -0,0 +1,36 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'missing_descriptor', + files('missing_descriptor.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_descriptor.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + +test( + 'missing_descriptor', + executable( + 'test_missing_descriptor', + files('test_missing_descriptor.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep], + ), + args: [meson.current_build_dir() / ''], + suite: 'plugin', +) + diff --git a/test/missing_descriptor.lv2/missing_descriptor.c b/test/missing_descriptor.lv2/missing_descriptor.c index ec1b473..ffcf7d6 100644 --- a/test/missing_descriptor.lv2/missing_descriptor.c +++ b/test/missing_descriptor.lv2/missing_descriptor.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Missing descriptor - Copyright 2011-2018 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2018 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/missing_descriptor.lv2/test_missing_descriptor.c b/test/missing_descriptor.lv2/test_missing_descriptor.c index 330e534..b737048 100644 --- a/test/missing_descriptor.lv2/test_missing_descriptor.c +++ b/test/missing_descriptor.lv2/test_missing_descriptor.c @@ -1,15 +1,12 @@ -#undef NDEBUG +// Copyright 2015-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC -#include "../src/filesystem.h" +#undef NDEBUG #include "lilv/lilv.h" -#include "serd/serd.h" #include <assert.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #define PLUGIN_URI "http://example.org/missing-descriptor" @@ -25,12 +22,8 @@ main(int argc, char** argv) LilvWorld* world = lilv_world_new(); // Load test plugin bundle - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path); lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); diff --git a/test/missing_name.lv2/meson.build b/test/missing_name.lv2/meson.build new file mode 100644 index 0000000..c32cbb5 --- /dev/null +++ b/test/missing_name.lv2/meson.build @@ -0,0 +1,36 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'missing_name', + files('missing_name.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_name.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + +test( + 'missing_name', + executable( + 'test_missing_name', + files('test_missing_name.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep], + ), + args: [meson.current_build_dir() / ''], + suite: 'plugin', +) + diff --git a/test/missing_name.lv2/missing_name.c b/test/missing_name.lv2/missing_name.c index 8c6e6fe..8538e73 100644 --- a/test/missing_name.lv2/missing_name.c +++ b/test/missing_name.lv2/missing_name.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Missing name - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/missing_name.lv2/test_missing_name.c b/test/missing_name.lv2/test_missing_name.c index 5cb069a..a8df1ab 100644 --- a/test/missing_name.lv2/test_missing_name.c +++ b/test/missing_name.lv2/test_missing_name.c @@ -1,15 +1,12 @@ -#undef NDEBUG +// Copyright 2015-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC -#include "../src/filesystem.h" +#undef NDEBUG #include "lilv/lilv.h" -#include "serd/serd.h" #include <assert.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #define PLUGIN_URI "http://example.org/missing-name" @@ -25,12 +22,8 @@ main(int argc, char** argv) LilvWorld* world = lilv_world_new(); // Load test plugin bundle - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path); lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); diff --git a/test/missing_plugin.lv2/meson.build b/test/missing_plugin.lv2/meson.build new file mode 100644 index 0000000..b5819ff --- /dev/null +++ b/test/missing_plugin.lv2/meson.build @@ -0,0 +1,36 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'missing_plugin', + files('missing_plugin.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_plugin.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + +test( + 'missing_plugin', + executable( + 'test_missing_plugin', + files('test_missing_plugin.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep], + ), + args: [meson.current_build_dir() / ''], + suite: 'plugin', +) + diff --git a/test/missing_plugin.lv2/missing_plugin.c b/test/missing_plugin.lv2/missing_plugin.c index 8ca146c..f496c6d 100644 --- a/test/missing_plugin.lv2/missing_plugin.c +++ b/test/missing_plugin.lv2/missing_plugin.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Missing plugin - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/missing_plugin.lv2/test_missing_plugin.c b/test/missing_plugin.lv2/test_missing_plugin.c index 861fcba..6eb1705 100644 --- a/test/missing_plugin.lv2/test_missing_plugin.c +++ b/test/missing_plugin.lv2/test_missing_plugin.c @@ -1,15 +1,12 @@ -#undef NDEBUG +// Copyright 2015-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC -#include "../src/filesystem.h" +#undef NDEBUG #include "lilv/lilv.h" -#include "serd/serd.h" #include <assert.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #define PLUGIN_URI "http://example.org/missing-plugin" @@ -25,12 +22,8 @@ main(int argc, char** argv) LilvWorld* world = lilv_world_new(); // Load test plugin bundle - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path); lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); diff --git a/test/missing_port.lv2/meson.build b/test/missing_port.lv2/meson.build new file mode 100644 index 0000000..f6138d8 --- /dev/null +++ b/test/missing_port.lv2/meson.build @@ -0,0 +1,36 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'missing_port', + files('missing_port.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_port.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + +test( + 'missing_port', + executable( + 'test_missing_port', + files('test_missing_port.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep], + ), + args: [meson.current_build_dir() / ''], + suite: 'plugin', +) + diff --git a/test/missing_port.lv2/missing_port.c b/test/missing_port.lv2/missing_port.c index c567d55..ce98c30 100644 --- a/test/missing_port.lv2/missing_port.c +++ b/test/missing_port.lv2/missing_port.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Missing port - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/missing_port.lv2/test_missing_port.c b/test/missing_port.lv2/test_missing_port.c index ec6713c..463fd63 100644 --- a/test/missing_port.lv2/test_missing_port.c +++ b/test/missing_port.lv2/test_missing_port.c @@ -1,15 +1,12 @@ -#undef NDEBUG +// Copyright 2015-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC -#include "../src/filesystem.h" +#undef NDEBUG #include "lilv/lilv.h" -#include "serd/serd.h" #include <assert.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #define PLUGIN_URI "http://example.org/missing-port" @@ -25,12 +22,8 @@ main(int argc, char** argv) LilvWorld* world = lilv_world_new(); // Load test plugin bundle - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path); lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); diff --git a/test/missing_port_name.lv2/meson.build b/test/missing_port_name.lv2/meson.build new file mode 100644 index 0000000..3bddcee --- /dev/null +++ b/test/missing_port_name.lv2/meson.build @@ -0,0 +1,36 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'missing_port_name', + files('missing_port_name.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_port_name.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + +test( + 'missing_port_name', + executable( + 'test_missing_port_name', + files('test_missing_port_name.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep], + ), + args: [meson.current_build_dir() / ''], + suite: 'plugin', +) + diff --git a/test/missing_port_name.lv2/missing_port_name.c b/test/missing_port_name.lv2/missing_port_name.c index 7a00945..d10498f 100644 --- a/test/missing_port_name.lv2/missing_port_name.c +++ b/test/missing_port_name.lv2/missing_port_name.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Missing port name - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/missing_port_name.lv2/test_missing_port_name.c b/test/missing_port_name.lv2/test_missing_port_name.c index 4d017d9..58e8120 100644 --- a/test/missing_port_name.lv2/test_missing_port_name.c +++ b/test/missing_port_name.lv2/test_missing_port_name.c @@ -1,15 +1,12 @@ -#undef NDEBUG +// Copyright 2015-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC -#include "../src/filesystem.h" +#undef NDEBUG #include "lilv/lilv.h" -#include "serd/serd.h" #include <assert.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #define PLUGIN_URI "http://example.org/missing-port-name" @@ -25,12 +22,8 @@ main(int argc, char** argv) LilvWorld* world = lilv_world_new(); // Load test plugin bundle - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, bundle_path); lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); diff --git a/test/new_version.lv2/meson.build b/test/new_version.lv2/meson.build new file mode 100644 index 0000000..bd90443 --- /dev/null +++ b/test/new_version.lv2/meson.build @@ -0,0 +1,24 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'new_version', + files('new_version.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'new_version.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + diff --git a/test/new_version.lv2/new_version.c b/test/new_version.lv2/new_version.c index 4de48e7..64be4f5 100644 --- a/test/new_version.lv2/new_version.c +++ b/test/new_version.lv2/new_version.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - New version - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/old_version.lv2/meson.build b/test/old_version.lv2/meson.build new file mode 100644 index 0000000..09434b1 --- /dev/null +++ b/test/old_version.lv2/meson.build @@ -0,0 +1,24 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'old_version', + files('old_version.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'old_version.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + diff --git a/test/old_version.lv2/old_version.c b/test/old_version.lv2/old_version.c index 7f97dad..64be4f5 100644 --- a/test/old_version.lv2/old_version.c +++ b/test/old_version.lv2/old_version.c @@ -1,19 +1,5 @@ -/* - Lilv Test Plugin - Old version - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/core/lv2.h" diff --git a/test/test_bad_port_index.c b/test/test_bad_port_index.c index 985d74e..99bdfc6 100644 --- a/test/test_bad_port_index.c +++ b/test/test_bad_port_index.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_bad_port_symbol.c b/test/test_bad_port_symbol.c index ae34ad0..2422e15 100644 --- a/test/test_bad_port_symbol.c +++ b/test/test_bad_port_symbol.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_classes.c b/test/test_classes.c index 332d847..2d33a57 100644 --- a/test/test_classes.c +++ b/test/test_classes.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_discovery.c b/test/test_discovery.c index f7f30ea..7d38207 100644 --- a/test/test_discovery.c +++ b/test/test_discovery.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_filesystem.c b/test/test_filesystem.c deleted file mode 100644 index 0a4aa4d..0000000 --- a/test/test_filesystem.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - Copyright 2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#undef NDEBUG - -#include "lilv_internal.h" - -#include "../src/filesystem.h" - -#include <assert.h> -#include <errno.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static bool -equals(char* string, const char* expected) -{ - const bool result = !strcmp(string, expected); - free(string); - return result; -} - -static void -test_temp_directory_path(void) -{ - char* tmpdir = lilv_temp_directory_path(); - - assert(lilv_is_directory(tmpdir)); - - free(tmpdir); -} - -static void -test_path_is_absolute(void) -{ - assert(lilv_path_is_absolute("/a/b")); - assert(lilv_path_is_absolute("/a")); - assert(lilv_path_is_absolute("/")); - - assert(!lilv_path_is_absolute("a/b")); - assert(!lilv_path_is_absolute("a")); - assert(!lilv_path_is_absolute(".")); - -#ifdef _WIN32 - assert(lilv_path_is_absolute("C:/a/b")); - assert(lilv_path_is_absolute("C:\\a\\b")); - assert(lilv_path_is_absolute("D:/a/b")); - assert(lilv_path_is_absolute("D:\\a\\b")); -#endif -} - -static void -test_path_is_child(void) -{ - assert(lilv_path_is_child("/a/b", "/a")); - assert(lilv_path_is_child("/a/b", "/a/")); - assert(lilv_path_is_child("/a/b/", "/a")); - assert(lilv_path_is_child("/a/b/", "/a/")); - - assert(!lilv_path_is_child("/a/b", "/a/c")); - assert(!lilv_path_is_child("/a/b", "/a/c/")); - assert(!lilv_path_is_child("/a/b/", "/a/c")); - assert(!lilv_path_is_child("/a/b/", "/a/c/")); - - assert(!lilv_path_is_child("/a/b", "/c")); - assert(!lilv_path_is_child("/a/b", "/c/")); - assert(!lilv_path_is_child("/a/b/", "/c")); - assert(!lilv_path_is_child("/a/b/", "/c/")); -} - -static void -test_path_current(void) -{ - char* cwd = lilv_path_current(); - - assert(lilv_is_directory(cwd)); - - free(cwd); -} - -static void -test_path_absolute(void) -{ - const char* const short_path = "a"; - const char* const long_path = "a/b/c"; - - char* const cwd = lilv_path_current(); - char* const expected_short = lilv_path_join(cwd, short_path); - char* const expected_long = lilv_path_join(cwd, long_path); - - assert(equals(lilv_path_absolute(short_path), expected_short)); - assert(equals(lilv_path_absolute(long_path), expected_long)); - - free(expected_long); - free(expected_short); - free(cwd); -} - -static void -test_path_absolute_child(void) -{ - const char* const parent = "/parent"; - const char* const short_path = "a"; - const char* const long_path = "a/b/c"; - - char* const expected_short = lilv_path_join(parent, short_path); - char* const expected_long = lilv_path_join(parent, long_path); - - assert(equals(lilv_path_absolute_child(short_path, parent), expected_short)); - - assert(equals(lilv_path_absolute_child(long_path, parent), expected_long)); - - free(expected_long); - free(expected_short); -} - -static void -test_path_relative_to(void) -{ - assert(equals(lilv_path_relative_to("/a/b", "/a/"), "b")); - assert(equals(lilv_path_relative_to("/a", "/b/c/"), "/a")); - assert(equals(lilv_path_relative_to("/a/b/c", "/a/b/d/"), "../c")); - assert(equals(lilv_path_relative_to("/a/b/c", "/a/b/d/e/"), "../../c")); - -#ifdef _WIN32 - assert(equals(lilv_path_relative_to("C:/a/b", "C:/a/"), "b")); - assert(equals(lilv_path_relative_to("C:/a", "C:/b/c/"), "../../a")); - assert(equals(lilv_path_relative_to("C:/a/b/c", "C:/a/b/d/"), "../c")); - assert(equals(lilv_path_relative_to("C:/a/b/c", "C:/a/b/d/e/"), "../../c")); - - assert(equals(lilv_path_relative_to("C:\\a\\b", "C:\\a\\"), "b")); - assert(equals(lilv_path_relative_to("C:\\a", "C:\\b\\c\\"), "..\\..\\a")); - assert( - equals(lilv_path_relative_to("C:\\a\\b\\c", "C:\\a\\b\\d\\"), "..\\c")); - assert(equals(lilv_path_relative_to("C:\\a\\b\\c", "C:\\a\\b\\d\\e\\"), - "..\\..\\c")); -#endif -} - -static void -test_path_parent(void) -{ - assert(equals(lilv_path_parent("/"), "/")); - assert(equals(lilv_path_parent("//"), "/")); - assert(equals(lilv_path_parent("/a"), "/")); - assert(equals(lilv_path_parent("/a/"), "/")); - assert(equals(lilv_path_parent("/a///b/"), "/a")); - assert(equals(lilv_path_parent("/a///b//"), "/a")); - assert(equals(lilv_path_parent("/a/b"), "/a")); - assert(equals(lilv_path_parent("/a/b/"), "/a")); - assert(equals(lilv_path_parent("/a/b/c"), "/a/b")); - assert(equals(lilv_path_parent("/a/b/c/"), "/a/b")); - assert(equals(lilv_path_parent("a"), ".")); -} - -static void -test_path_filename(void) -{ - // Cases from cppreference.com for std::filesystem::path::filename - assert(equals(lilv_path_filename("/foo/bar.txt"), "bar.txt")); - assert(equals(lilv_path_filename("/foo/.bar"), ".bar")); - assert(equals(lilv_path_filename("/foo/bar/"), "")); - assert(equals(lilv_path_filename("/foo/."), ".")); - assert(equals(lilv_path_filename("/foo/.."), "..")); - assert(equals(lilv_path_filename("."), ".")); - assert(equals(lilv_path_filename(".."), "..")); - assert(equals(lilv_path_filename("/"), "")); - assert(equals(lilv_path_filename("//host"), "host")); - -#ifdef _WIN32 - assert(equals(lilv_path_filename("C:/foo/bar.txt"), "bar.txt")); - assert(equals(lilv_path_filename("C:\\foo\\bar.txt"), "bar.txt")); - assert(equals(lilv_path_filename("foo/bar.txt"), "bar.txt")); - assert(equals(lilv_path_filename("foo\\bar.txt"), "bar.txt")); -#endif -} - -static void -test_path_join(void) -{ - assert(lilv_path_join(NULL, NULL) == NULL); - assert(lilv_path_join(NULL, "") == NULL); - -#ifdef _WIN32 - assert(equals(lilv_path_join("", NULL), "\\")); - assert(equals(lilv_path_join("", ""), "\\")); - assert(equals(lilv_path_join("a", ""), "a\\")); - assert(equals(lilv_path_join("a", NULL), "a\\")); - assert(equals(lilv_path_join("a", "b"), "a\\b")); -#else - assert(equals(lilv_path_join("", NULL), "/")); - assert(equals(lilv_path_join("", ""), "/")); - assert(equals(lilv_path_join("a", ""), "a/")); - assert(equals(lilv_path_join("a", NULL), "a/")); - assert(equals(lilv_path_join("a", "b"), "a/b")); -#endif - - assert(equals(lilv_path_join("/a", ""), "/a/")); - assert(equals(lilv_path_join("/a/b", ""), "/a/b/")); - assert(equals(lilv_path_join("/a/", ""), "/a/")); - assert(equals(lilv_path_join("/a/b/", ""), "/a/b/")); - assert(equals(lilv_path_join("a/b", ""), "a/b/")); - assert(equals(lilv_path_join("a/", ""), "a/")); - assert(equals(lilv_path_join("a/b/", ""), "a/b/")); - - assert(equals(lilv_path_join("/a", NULL), "/a/")); - assert(equals(lilv_path_join("/a/b", NULL), "/a/b/")); - assert(equals(lilv_path_join("/a/", NULL), "/a/")); - assert(equals(lilv_path_join("/a/b/", NULL), "/a/b/")); - assert(equals(lilv_path_join("a/b", NULL), "a/b/")); - assert(equals(lilv_path_join("a/", NULL), "a/")); - assert(equals(lilv_path_join("a/b/", NULL), "a/b/")); - - assert(equals(lilv_path_join("/a", "b"), "/a/b")); - assert(equals(lilv_path_join("/a/", "b"), "/a/b")); - assert(equals(lilv_path_join("a/", "b"), "a/b")); - - assert(equals(lilv_path_join("/a", "b/"), "/a/b/")); - assert(equals(lilv_path_join("/a/", "b/"), "/a/b/")); - assert(equals(lilv_path_join("a", "b/"), "a/b/")); - assert(equals(lilv_path_join("a/", "b/"), "a/b/")); - -#ifdef _WIN32 - assert(equals(lilv_path_join("C:/a", "b"), "C:/a/b")); - assert(equals(lilv_path_join("C:\\a", "b"), "C:\\a\\b")); - assert(equals(lilv_path_join("C:/a", "b/"), "C:/a/b/")); - assert(equals(lilv_path_join("C:\\a", "b\\"), "C:\\a\\b\\")); -#endif -} - -static void -test_path_canonical(void) -{ - char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX"); - char* const file_path = lilv_path_join(temp_dir, "lilv_test_file"); - - FILE* f = fopen(file_path, "w"); - fprintf(f, "test\n"); - fclose(f); - -#ifndef _WIN32 - // Test symlink resolution - - char* const link_path = lilv_path_join(temp_dir, "lilv_test_link"); - - assert(!lilv_symlink(file_path, link_path)); - - char* const real_file_path = lilv_path_canonical(file_path); - char* const real_link_path = lilv_path_canonical(link_path); - - assert(!strcmp(real_file_path, real_link_path)); - - assert(!lilv_remove(link_path)); - free(real_link_path); - free(real_file_path); - free(link_path); -#endif - - // Test dot segment resolution - - char* const parent_dir_1 = lilv_path_join(temp_dir, ".."); - char* const parent_dir_2 = lilv_path_parent(temp_dir); - char* const real_parent_dir_1 = lilv_path_canonical(parent_dir_1); - char* const real_parent_dir_2 = lilv_path_canonical(parent_dir_2); - - assert(!strcmp(real_parent_dir_1, real_parent_dir_2)); - - // Clean everything up - - assert(!lilv_remove(file_path)); - assert(!lilv_remove(temp_dir)); - - free(real_parent_dir_2); - free(real_parent_dir_1); - free(parent_dir_2); - free(parent_dir_1); - free(file_path); - free(temp_dir); -} - -static void -test_path_exists(void) -{ - char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX"); - char* const file_path = lilv_path_join(temp_dir, "lilv_test_file"); - - assert(!lilv_path_exists(file_path)); - - FILE* f = fopen(file_path, "w"); - fprintf(f, "test\n"); - fclose(f); - - assert(lilv_path_exists(file_path)); - - assert(!lilv_remove(file_path)); - assert(!lilv_remove(temp_dir)); - - free(file_path); - free(temp_dir); -} - -static void -test_is_directory(void) -{ - char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX"); - char* const file_path = lilv_path_join(temp_dir, "lilv_test_file"); - - assert(lilv_is_directory(temp_dir)); - assert(!lilv_is_directory(file_path)); // Nonexistent - - FILE* f = fopen(file_path, "w"); - fprintf(f, "test\n"); - fclose(f); - - assert(!lilv_is_directory(file_path)); // File - - assert(!lilv_remove(file_path)); - assert(!lilv_remove(temp_dir)); - - free(file_path); - free(temp_dir); -} - -static void -test_copy_file(void) -{ - char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX"); - char* const file_path = lilv_path_join(temp_dir, "lilv_test_file"); - char* const copy_path = lilv_path_join(temp_dir, "lilv_test_copy"); - - FILE* f = fopen(file_path, "w"); - fprintf(f, "test\n"); - fclose(f); - - assert(!lilv_copy_file(file_path, copy_path)); - assert(lilv_file_equals(file_path, copy_path)); - - if (lilv_path_exists("/dev/full")) { - // Copy short file (error after flushing) - assert(lilv_copy_file(file_path, "/dev/full") == ENOSPC); - - // Copy long file (error during writing) - f = fopen(file_path, "w"); - for (size_t i = 0; i < 4096; ++i) { - fprintf(f, "test\n"); - } - fclose(f); - assert(lilv_copy_file(file_path, "/dev/full") == ENOSPC); - } - - assert(!lilv_remove(copy_path)); - assert(!lilv_remove(file_path)); - assert(!lilv_remove(temp_dir)); - - free(copy_path); - free(file_path); - free(temp_dir); -} - -static void -test_flock(void) -{ - char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX"); - char* const file_path = lilv_path_join(temp_dir, "lilv_test_file"); - - FILE* const f1 = fopen(file_path, "w"); - FILE* const f2 = fopen(file_path, "w"); - - assert(!lilv_flock(f1, true, false)); - assert(lilv_flock(f2, true, false)); - assert(!lilv_flock(f1, false, false)); - - fclose(f2); - fclose(f1); - assert(!lilv_remove(file_path)); - assert(!lilv_remove(temp_dir)); - free(file_path); - free(temp_dir); -} - -typedef struct { - size_t n_names; - char** names; -} FileList; - -static void -visit(const char* const path, const char* const name, void* const data) -{ - (void)path; - - FileList* file_list = (FileList*)data; - - file_list->names = - (char**)realloc(file_list->names, sizeof(char*) * ++file_list->n_names); - - file_list->names[file_list->n_names - 1] = lilv_strdup(name); -} - -static void -test_dir_for_each(void) -{ - char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX"); - char* const path1 = lilv_path_join(temp_dir, "lilv_test_1"); - char* const path2 = lilv_path_join(temp_dir, "lilv_test_2"); - - FILE* const f1 = fopen(path1, "w"); - FILE* const f2 = fopen(path2, "w"); - fprintf(f1, "test\n"); - fprintf(f2, "test\n"); - fclose(f2); - fclose(f1); - - FileList file_list = {0, NULL}; - lilv_dir_for_each(temp_dir, &file_list, visit); - - assert((!strcmp(file_list.names[0], "lilv_test_1") && - !strcmp(file_list.names[1], "lilv_test_2")) || - (!strcmp(file_list.names[0], "lilv_test_2") && - !strcmp(file_list.names[1], "lilv_test_1"))); - - assert(!lilv_remove(path2)); - assert(!lilv_remove(path1)); - assert(!lilv_remove(temp_dir)); - - free(file_list.names[0]); - free(file_list.names[1]); - free(file_list.names); - free(path2); - free(path1); - free(temp_dir); -} - -static void -test_create_temporary_directory(void) -{ - char* const path1 = lilv_create_temporary_directory("lilvXXXXXX"); - - assert(lilv_is_directory(path1)); - - char* const path2 = lilv_create_temporary_directory("lilvXXXXXX"); - - assert(strcmp(path1, path2)); - assert(lilv_is_directory(path2)); - - assert(!lilv_remove(path2)); - assert(!lilv_remove(path1)); - free(path2); - free(path1); -} - -static void -test_create_directories(void) -{ - char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX"); - - assert(lilv_is_directory(temp_dir)); - - char* const child_dir = lilv_path_join(temp_dir, "child"); - char* const grandchild_dir = lilv_path_join(child_dir, "grandchild"); - - assert(!lilv_create_directories(grandchild_dir)); - assert(lilv_is_directory(grandchild_dir)); - assert(lilv_is_directory(child_dir)); - - char* const file_path = lilv_path_join(temp_dir, "lilv_test_file"); - FILE* const f = fopen(file_path, "w"); - - fprintf(f, "test\n"); - fclose(f); - - assert(lilv_create_directories(file_path)); - - assert(!lilv_remove(file_path)); - assert(!lilv_remove(grandchild_dir)); - assert(!lilv_remove(child_dir)); - assert(!lilv_remove(temp_dir)); - free(file_path); - free(child_dir); - free(grandchild_dir); - free(temp_dir); -} - -static void -test_file_equals(void) -{ - char* const temp_dir = lilv_create_temporary_directory("lilvXXXXXX"); - char* const path1 = lilv_path_join(temp_dir, "lilv_test_1"); - char* const path2 = lilv_path_join(temp_dir, "lilv_test_2"); - - FILE* const f1 = fopen(path1, "w"); - FILE* const f2 = fopen(path2, "w"); - fprintf(f1, "test\n"); - fprintf(f2, "test\n"); - - assert(lilv_file_equals(path1, path2)); - - fprintf(f2, "diff\n"); - fflush(f2); - - assert(!lilv_file_equals(path1, path2)); - - fclose(f2); - fclose(f1); - - assert(!lilv_remove(path2)); - assert(!lilv_remove(path1)); - assert(!lilv_remove(temp_dir)); - - free(path2); - free(path1); - free(temp_dir); -} - -int -main(void) -{ - test_temp_directory_path(); - test_path_is_absolute(); - test_path_is_child(); - test_path_current(); - test_path_absolute(); - test_path_absolute_child(); - test_path_relative_to(); - test_path_parent(); - test_path_filename(); - test_path_join(); - test_path_canonical(); - test_path_exists(); - test_is_directory(); - test_copy_file(); - test_flock(); - test_dir_for_each(); - test_create_temporary_directory(); - test_create_directories(); - test_file_equals(); - - return 0; -} diff --git a/test/test_get_symbol.c b/test/test_get_symbol.c index 5337c63..5dc5898 100644 --- a/test/test_get_symbol.c +++ b/test/test_get_symbol.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_no_author.c b/test/test_no_author.c index aa91198..396ae9e 100644 --- a/test/test_no_author.c +++ b/test/test_no_author.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_no_verify.c b/test/test_no_verify.c index e71c483..66f81e9 100644 --- a/test/test_no_verify.c +++ b/test/test_no_verify.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_plugin.c b/test/test_plugin.c index 2a427dc..e2b9b53 100644 --- a/test/test_plugin.c +++ b/test/test_plugin.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test.lv2/manifest.ttl.in b/test/test_plugin.lv2/manifest.ttl.in index bc3952c..48b009b 100644 --- a/test/test.lv2/manifest.ttl.in +++ b/test/test_plugin.lv2/manifest.ttl.in @@ -3,5 +3,5 @@ <http://example.org/lilv-test-plugin> a lv2:Plugin ; - lv2:binary <test@SHLIB_EXT@> ; - rdfs:seeAlso <test.ttl> . + lv2:binary <test_plugin@SHLIB_EXT@> ; + rdfs:seeAlso <test_plugin.ttl> . diff --git a/test/test_plugin.lv2/meson.build b/test/test_plugin.lv2/meson.build new file mode 100644 index 0000000..9b74245 --- /dev/null +++ b/test/test_plugin.lv2/meson.build @@ -0,0 +1,24 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +module = shared_module( + 'test_plugin', + files('test_plugin.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '', +) + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'test_plugin.ttl'] + +foreach f : ttl_files + configure_file( + input: files(f + '.in'), + output: f, + configuration: config, + ) +endforeach + diff --git a/test/test.lv2/test.c b/test/test_plugin.lv2/test_plugin.c index 2be34b4..81a6433 100644 --- a/test/test.lv2/test.c +++ b/test/test_plugin.lv2/test_plugin.c @@ -1,30 +1,14 @@ -/* - Lilv Test Plugin - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#define _POSIX_C_SOURCE 200809L +// Copyright 2011-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lv2/atom/atom.h" #include "lv2/core/lv2.h" #include "lv2/state/state.h" #include "lv2/urid/urid.h" -#ifdef _MSC_VER -# include <io.h> -# define mkstemp(pat) _mktemp(pat) +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include <windows.h> #endif #include <stdint.h> @@ -34,8 +18,6 @@ #define TEST_URI "http://example.org/lilv-test-plugin" -#define TMP_TEMPLATE "lilv_testXXXXXX" - enum { TEST_INPUT = 0, TEST_OUTPUT = 1, TEST_CONTROL = 2 }; typedef struct { @@ -46,7 +28,7 @@ typedef struct { LV2_URID atom_Float; } uris; - char tmp_file_path[sizeof(TMP_TEMPLATE)]; + char* tmp_dir_path; char* rec_file_path; FILE* rec_file; @@ -55,6 +37,35 @@ typedef struct { unsigned num_runs; } Test; +static char* +temp_directory_path(void) +{ +#ifdef _WIN32 + const DWORD len = GetTempPath(0, NULL); + char* const buf = (char*)calloc(len, 1); + if (GetTempPath(len, buf) == 0) { + free(buf); + return NULL; + } + + return buf; +#else + const char* const tmpdir = getenv("TMPDIR"); + if (tmpdir) { + const size_t tmpdir_len = strlen(tmpdir); + char* const result = (char*)calloc(tmpdir_len + 1, 1); + + memcpy(result, tmpdir, tmpdir_len + 1); + return result; + } + + char* const result = (char*)calloc(6, 1); + + memcpy(result, "/tmp/", 6); + return result; +#endif +} + static void cleanup(LV2_Handle instance) { @@ -67,6 +78,7 @@ cleanup(LV2_Handle instance) test->free_path->free_path(test->free_path->handle, test->rec_file_path); } + free(test->tmp_dir_path); free(instance); } @@ -104,8 +116,7 @@ instantiate(const LV2_Descriptor* descriptor, return NULL; } - strncpy(test->tmp_file_path, TMP_TEMPLATE, strlen(TMP_TEMPLATE) + 1); - mkstemp(test->tmp_file_path); + test->tmp_dir_path = temp_directory_path(); LV2_State_Make_Path* make_path = NULL; @@ -272,15 +283,30 @@ save(LV2_Handle instance, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); if (map_path) { - FILE* file = fopen(plugin->tmp_file_path, "w"); + const char* const file_name = "temp_file.txt"; + const size_t file_name_len = strlen(file_name); + const size_t dir_path_len = strlen(plugin->tmp_dir_path); + char* const tmp_file_path = + (char*)calloc(dir_path_len + file_name_len + 1, 1); + + memcpy(tmp_file_path, plugin->tmp_dir_path, dir_path_len); + memcpy(tmp_file_path + dir_path_len, file_name, file_name_len + 1); + + FILE* file = fopen(tmp_file_path, "w"); + if (!file) { + fprintf(stderr, "error: Failed to open file %s\n", tmp_file_path); + free(tmp_file_path); + return LV2_STATE_ERR_UNKNOWN; + } + fprintf(file, "Hello\n"); fclose(file); - char* apath = - map_path->abstract_path(map_path->handle, plugin->tmp_file_path); - char* apath2 = - map_path->abstract_path(map_path->handle, plugin->tmp_file_path); - if (strcmp(apath, apath2)) { - fprintf(stderr, "ERROR: Path %s != %s\n", apath, apath2); + + char* apath = map_path->abstract_path(map_path->handle, tmp_file_path); + char* apath2 = map_path->abstract_path(map_path->handle, tmp_file_path); + free(tmp_file_path); + if (!!strcmp(apath, apath2)) { + fprintf(stderr, "error: Path %s != %s\n", apath, apath2); } store(callback_data, @@ -381,7 +407,7 @@ restore(LV2_Handle instance, char str[8]; size_t n_read = fread(str, 1, sizeof(str), f); fclose(f); - if (strncmp(str, "Hello\n", n_read)) { + if (!!strncmp(str, "Hello\n", n_read)) { fprintf( stderr, "error: Restored bad file contents `%s' != `Hello'\n", str); } @@ -432,10 +458,5 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor(uint32_t index) { - switch (index) { - case 0: - return &descriptor; - default: - return NULL; - } + return index ? NULL : &descriptor; } diff --git a/test/test.lv2/test.ttl.in b/test/test_plugin.lv2/test_plugin.ttl.in index 1c16b4c..1c16b4c 100644 --- a/test/test.lv2/test.ttl.in +++ b/test/test_plugin.lv2/test_plugin.ttl.in diff --git a/test/test_port.c b/test/test_port.c index 3ea0abc..e05dcde 100644 --- a/test/test_port.c +++ b/test/test_port.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_preset.c b/test/test_preset.c index 151b0e6..d091318 100644 --- a/test/test_preset.c +++ b/test/test_preset.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_project.c b/test/test_project.c index 7da42bd..cfce35a 100644 --- a/test/test_project.c +++ b/test/test_project.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_project_no_author.c b/test/test_project_no_author.c index 3ee9c85..5b0e57d 100644 --- a/test/test_project_no_author.c +++ b/test/test_project_no_author.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_prototype.c b/test/test_prototype.c index 10a3657..4e17a63 100644 --- a/test/test_prototype.c +++ b/test/test_prototype.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_reload_bundle.c b/test/test_reload_bundle.c index a8f9044..a2630fc 100644 --- a/test/test_reload_bundle.c +++ b/test/test_reload_bundle.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_replace_version.c b/test/test_replace_version.c index 7ec5519..c6fb3e6 100644 --- a/test/test_replace_version.c +++ b/test/test_replace_version.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_state.c b/test/test_state.c index 533c3a9..cb84fb4 100644 --- a/test/test_state.c +++ b/test/test_state.c @@ -1,31 +1,19 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG #include "lilv_test_uri_map.h" #include "lilv_test_utils.h" -#include "../src/filesystem.h" - #include "lilv/lilv.h" #include "lv2/core/lv2.h" #include "lv2/state/state.h" #include "lv2/urid/urid.h" #include "serd/serd.h" +#include "zix/allocator.h" +#include "zix/filesystem.h" +#include "zix/path.h" #ifdef _WIN32 # include <direct.h> @@ -128,11 +116,11 @@ create_test_directories(void) /* On MacOS, temporary directories from mkdtemp involve symlinks, so resolve it here so that path comparisons in tests work. */ - dirs.top = lilv_path_canonical(top); - dirs.shared = lilv_path_join(dirs.top, "shared"); - dirs.scratch = lilv_path_join(dirs.shared, "scratch"); - dirs.copy = lilv_path_join(dirs.shared, "copy"); - dirs.link = lilv_path_join(dirs.shared, "link"); + dirs.top = zix_canonical_path(NULL, top); + dirs.shared = zix_path_join(NULL, dirs.top, "shared"); + dirs.scratch = zix_path_join(NULL, dirs.shared, "scratch"); + dirs.copy = zix_path_join(NULL, dirs.shared, "copy"); + dirs.link = zix_path_join(NULL, dirs.shared, "link"); assert(!mkdir(dirs.shared, 0700)); assert(!mkdir(dirs.scratch, 0700)); @@ -157,28 +145,28 @@ remove_file(const char* path, const char* name, void* data) { (void)data; - char* const full_path = lilv_path_join(path, name); - assert(!lilv_remove(full_path)); + char* const full_path = zix_path_join(NULL, path, name); + assert(!zix_remove(full_path)); free(full_path); } static void cleanup_test_directories(const TestDirectories dirs) { - lilv_dir_for_each(dirs.scratch, NULL, remove_file); - lilv_dir_for_each(dirs.copy, NULL, remove_file); - lilv_dir_for_each(dirs.link, NULL, remove_file); - - assert(!lilv_remove(dirs.link)); - assert(!lilv_remove(dirs.copy)); - assert(!lilv_remove(dirs.scratch)); - assert(!lilv_remove(dirs.shared)); - assert(!lilv_remove(dirs.top)); - - free(dirs.link); - free(dirs.copy); - free(dirs.scratch); - free(dirs.shared); + zix_dir_for_each(dirs.scratch, NULL, remove_file); + zix_dir_for_each(dirs.copy, NULL, remove_file); + zix_dir_for_each(dirs.link, NULL, remove_file); + + assert(!zix_remove(dirs.link)); + assert(!zix_remove(dirs.copy)); + assert(!zix_remove(dirs.scratch)); + assert(!zix_remove(dirs.shared)); + assert(!zix_remove(dirs.top)); + + zix_free(NULL, dirs.link); + zix_free(NULL, dirs.copy); + zix_free(NULL, dirs.scratch); + zix_free(NULL, dirs.shared); free(dirs.top); } @@ -194,20 +182,24 @@ get_port_value(const char* port_symbol, *size = sizeof(float); *type = ctx->atom_Float; return &ctx->in; - } else if (!strcmp(port_symbol, "output")) { + } + + if (!strcmp(port_symbol, "output")) { *size = sizeof(float); *type = ctx->atom_Float; return &ctx->out; - } else if (!strcmp(port_symbol, "control")) { + } + + if (!strcmp(port_symbol, "control")) { *size = sizeof(float); *type = ctx->atom_Float; return &ctx->control; - } else { - fprintf( - stderr, "error: get_port_value for nonexistent port `%s'\n", port_symbol); - *size = *type = 0; - return NULL; } + + fprintf( + stderr, "error: get_port_value for nonexistent port `%s'\n", port_symbol); + *size = *type = 0; + return NULL; } static void @@ -239,16 +231,14 @@ make_scratch_path(LV2_State_Make_Path_Handle handle, const char* path) { TestDirectories* dirs = (TestDirectories*)handle; - return lilv_path_join(dirs->scratch, path); + return zix_path_join(NULL, dirs->scratch, path); } static const LilvPlugin* load_test_plugin(const TestContext* const ctx) { LilvWorld* world = ctx->env->world; - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(LILV_TEST_BUNDLE); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, LILV_TEST_BUNDLE); LilvNode* plugin_uri = lilv_new_uri(world, TEST_PLUGIN_URI); lilv_world_load_bundle(world, bundle_uri); @@ -258,8 +248,6 @@ load_test_plugin(const TestContext* const ctx) lilv_node_free(plugin_uri); lilv_node_free(bundle_uri); - serd_node_free(&bundle); - free(abs_bundle); assert(plugin); return plugin; @@ -601,11 +589,11 @@ test_to_files(void) assert(ctx->out == 1.0); // Check that the test plugin has made its recording scratch file - char* const recfile_path = lilv_path_join(dirs.scratch, "recfile"); - assert(lilv_path_exists(recfile_path)); + char* const recfile_path = zix_path_join(NULL, dirs.scratch, "recfile"); + assert(zix_file_type(recfile_path) == ZIX_FILE_TYPE_REGULAR); // Get state - char* const bundle_1_path = lilv_path_join(dirs.top, "state1.lv2"); + char* const bundle_1_path = zix_path_join(NULL, dirs.top, "state1.lv2"); LilvState* const state_1 = state_from_instance(plugin, instance, ctx, &dirs, bundle_1_path); @@ -613,8 +601,8 @@ test_to_files(void) assert(lilv_state_get_num_properties(state_1) == 10); // Check that a snapshop of the recfile was created - char* const recfile_copy_1 = lilv_path_join(dirs.copy, "recfile"); - assert(lilv_path_exists(recfile_copy_1)); + char* const recfile_copy_1 = zix_path_join(NULL, dirs.copy, "recfile"); + assert(zix_file_type(recfile_copy_1) == ZIX_FILE_TYPE_REGULAR); // Save state to a bundle assert(!lilv_state_save(ctx->env->world, @@ -626,24 +614,28 @@ test_to_files(void) "state.ttl")); // Check that a manifest exists - char* const manifest_path = lilv_path_join(bundle_1_path, "manifest.ttl"); - assert(lilv_path_exists(manifest_path)); + char* const manifest_path = + zix_path_join(NULL, bundle_1_path, "manifest.ttl"); + assert(zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR); // Check that the expected statements are in the manifest file assert(count_statements(manifest_path) == 3); // Check that a link to the recfile exists in the saved bundle - char* const recfile_link_1 = lilv_path_join(bundle_1_path, "recfile"); - assert(lilv_path_exists(recfile_link_1)); + char* const recfile_link_1 = zix_path_join(NULL, bundle_1_path, "recfile"); + assert(zix_file_type(recfile_link_1) == ZIX_FILE_TYPE_REGULAR); +#ifndef _WIN32 + assert(zix_symlink_type(recfile_link_1) == ZIX_FILE_TYPE_SYMLINK); +#endif // Check that link points to the corresponding copy - assert(lilv_file_equals(recfile_link_1, recfile_copy_1)); + assert(zix_file_equals(NULL, recfile_link_1, recfile_copy_1)); // Run plugin again to modify recording file data lilv_instance_run(instance, 2); // Get updated state - char* const bundle_2_path = lilv_path_join(dirs.top, "state2.lv2"); + char* const bundle_2_path = zix_path_join(NULL, dirs.top, "state2.lv2"); LilvState* const state_2 = state_from_instance(plugin, instance, ctx, &dirs, bundle_2_path); @@ -657,33 +649,36 @@ test_to_files(void) "state.ttl")); // Check that a new snapshop of the recfile was created - char* const recfile_copy_2 = lilv_path_join(dirs.copy, "recfile.2"); - assert(lilv_path_exists(recfile_copy_2)); + char* const recfile_copy_2 = zix_path_join(NULL, dirs.copy, "recfile.2"); + assert(zix_file_type(recfile_copy_2) == ZIX_FILE_TYPE_REGULAR); // Check that a link to the recfile exists in the updated bundle - char* const recfile_link_2 = lilv_path_join(bundle_2_path, "recfile"); - assert(lilv_path_exists(recfile_link_2)); + char* const recfile_link_2 = zix_path_join(NULL, bundle_2_path, "recfile"); + assert(zix_file_type(recfile_link_2) == ZIX_FILE_TYPE_REGULAR); +#ifndef _WIN32 + assert(zix_symlink_type(recfile_link_2) == ZIX_FILE_TYPE_SYMLINK); +#endif // Check that link points to the corresponding copy - assert(lilv_file_equals(recfile_link_2, recfile_copy_2)); + assert(zix_file_equals(NULL, recfile_link_2, recfile_copy_2)); lilv_instance_free(instance); - lilv_dir_for_each(bundle_2_path, NULL, remove_file); - lilv_dir_for_each(bundle_1_path, NULL, remove_file); - assert(!lilv_remove(bundle_2_path)); - assert(!lilv_remove(bundle_1_path)); + zix_dir_for_each(bundle_2_path, NULL, remove_file); + zix_dir_for_each(bundle_1_path, NULL, remove_file); + assert(!zix_remove(bundle_2_path)); + assert(!zix_remove(bundle_1_path)); cleanup_test_directories(dirs); - free(recfile_link_2); - free(recfile_copy_2); + zix_free(NULL, recfile_link_2); + zix_free(NULL, recfile_copy_2); lilv_state_free(state_2); - free(bundle_2_path); - free(recfile_link_1); - free(manifest_path); - free(recfile_copy_1); + zix_free(NULL, bundle_2_path); + zix_free(NULL, recfile_link_1); + zix_free(NULL, manifest_path); + zix_free(NULL, recfile_copy_1); lilv_state_free(state_1); - free(bundle_1_path); - free(recfile_path); + zix_free(NULL, bundle_1_path); + zix_free(NULL, recfile_path); test_context_free(ctx); } @@ -706,7 +701,7 @@ test_multi_save(void) assert(instance); // Get state - char* const bundle_1_path = lilv_path_join(dirs.top, "state1.lv2"); + char* const bundle_1_path = zix_path_join(NULL, dirs.top, "state1.lv2"); LilvState* const state_1 = state_from_instance(plugin, instance, ctx, &dirs, bundle_1_path); @@ -720,12 +715,13 @@ test_multi_save(void) "state.ttl")); // Check that a manifest exists - char* const manifest_path = lilv_path_join(bundle_1_path, "manifest.ttl"); - assert(lilv_path_exists(manifest_path)); + char* const manifest_path = + zix_path_join(NULL, bundle_1_path, "manifest.ttl"); + assert(zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR); // Check that the state file exists - char* const state_path = lilv_path_join(bundle_1_path, "state.ttl"); - assert(lilv_path_exists(state_path)); + char* const state_path = zix_path_join(NULL, bundle_1_path, "state.ttl"); + assert(zix_file_type(state_path) == ZIX_FILE_TYPE_REGULAR); // Check that the expected statements are in the files assert(count_statements(manifest_path) == 3); @@ -741,14 +737,14 @@ test_multi_save(void) "state.ttl")); // Check that everything is the same - assert(lilv_path_exists(manifest_path)); - assert(lilv_path_exists(state_path)); + assert(zix_file_type(manifest_path) == ZIX_FILE_TYPE_REGULAR); + assert(zix_file_type(state_path) == ZIX_FILE_TYPE_REGULAR); assert(count_statements(manifest_path) == 3); assert(count_statements(state_path) == 21); lilv_instance_free(instance); - lilv_dir_for_each(bundle_1_path, NULL, remove_file); - lilv_remove(bundle_1_path); + zix_dir_for_each(bundle_1_path, NULL, remove_file); + zix_remove(bundle_1_path); cleanup_test_directories(dirs); free(state_path); @@ -786,7 +782,7 @@ test_files_round_trip(void) assert(ctx->out == 1.0); // Save first state to a bundle - char* const bundle_1_1_path = lilv_path_join(dirs.top, "state1_1.lv2"); + char* const bundle_1_1_path = zix_path_join(NULL, dirs.top, "state1_1.lv2"); LilvState* const state_1_1 = state_from_instance(plugin, instance, ctx, &dirs, bundle_1_1_path); @@ -799,7 +795,7 @@ test_files_round_trip(void) "state.ttl")); // Save first state to another bundle - char* const bundle_1_2_path = lilv_path_join(dirs.top, "state1_2.lv2"); + char* const bundle_1_2_path = zix_path_join(NULL, dirs.top, "state1_2.lv2"); LilvState* const state_1_2 = state_from_instance(plugin, instance, ctx, &dirs, bundle_1_2_path); @@ -812,8 +808,10 @@ test_files_round_trip(void) "state.ttl")); // Load both first state bundles and check that the results are equal - char* const state_1_1_path = lilv_path_join(bundle_1_1_path, "state.ttl"); - char* const state_1_2_path = lilv_path_join(bundle_1_2_path, "state.ttl"); + char* const state_1_1_path = + zix_path_join(NULL, bundle_1_1_path, "state.ttl"); + char* const state_1_2_path = + zix_path_join(NULL, bundle_1_2_path, "state.ttl"); LilvState* state_1_1_loaded = lilv_state_new_from_file(ctx->env->world, &ctx->map, NULL, state_1_1_path); @@ -829,7 +827,7 @@ test_files_round_trip(void) lilv_instance_run(instance, 2); // Save updated state to a bundle - char* const bundle_2_path = lilv_path_join(dirs.top, "state2.lv2"); + char* const bundle_2_path = zix_path_join(NULL, dirs.top, "state2.lv2"); LilvState* const state_2 = state_from_instance(plugin, instance, ctx, &dirs, bundle_2_path); @@ -842,7 +840,7 @@ test_files_round_trip(void) "state.ttl")); // Load updated state bundle and check that it differs from the others - char* const state_2_path = lilv_path_join(bundle_2_path, "state.ttl"); + char* const state_2_path = zix_path_join(NULL, bundle_2_path, "state.ttl"); LilvState* state_2_loaded = lilv_state_new_from_file(ctx->env->world, &ctx->map, NULL, state_2_path); @@ -851,12 +849,12 @@ test_files_round_trip(void) assert(!lilv_state_equals(state_1_1_loaded, state_2_loaded)); lilv_instance_free(instance); - lilv_dir_for_each(bundle_1_1_path, NULL, remove_file); - lilv_dir_for_each(bundle_1_2_path, NULL, remove_file); - lilv_dir_for_each(bundle_2_path, NULL, remove_file); - lilv_remove(bundle_1_1_path); - lilv_remove(bundle_1_2_path); - lilv_remove(bundle_2_path); + zix_dir_for_each(bundle_1_1_path, NULL, remove_file); + zix_dir_for_each(bundle_1_2_path, NULL, remove_file); + zix_dir_for_each(bundle_2_path, NULL, remove_file); + zix_remove(bundle_1_1_path); + zix_remove(bundle_1_2_path); + zix_remove(bundle_2_path); cleanup_test_directories(dirs); lilv_state_free(state_2_loaded); @@ -904,7 +902,7 @@ test_world_round_trip(void) assert(ctx->out == 1.0); // Save state to a bundle - char* const bundle_path = lilv_path_join(dirs.top, "state.lv2/"); + char* const bundle_path = zix_path_join(NULL, dirs.top, "state.lv2/"); LilvState* const start_state = state_from_instance(plugin, instance, ctx, &dirs, bundle_path); @@ -969,7 +967,7 @@ test_label_round_trip(void) lilv_state_set_label(state, "Monopoly on violence"); // Save to a bundle - char* const bundle_path = lilv_path_join(dirs.top, "state.lv2/"); + char* const bundle_path = zix_path_join(NULL, dirs.top, "state.lv2/"); assert(!lilv_state_save(ctx->env->world, &ctx->map, &ctx->unmap, @@ -979,7 +977,7 @@ test_label_round_trip(void) "state.ttl")); // Load bundle and check the label and that the states are equal - char* const state_path = lilv_path_join(bundle_path, "state.ttl"); + char* const state_path = zix_path_join(NULL, bundle_path, "state.ttl"); LilvState* const loaded = lilv_state_new_from_file(ctx->env->world, &ctx->map, NULL, state_path); @@ -1056,7 +1054,7 @@ test_delete(void) assert(ctx->out == 1.0); // Save state to a bundle - char* const bundle_path = lilv_path_join(dirs.top, "state.lv2/"); + char* const bundle_path = zix_path_join(NULL, dirs.top, "state.lv2/"); LilvState* const state = state_from_instance(plugin, instance, ctx, &dirs, bundle_path); @@ -1070,7 +1068,7 @@ test_delete(void) // Count the number of shared files before doing anything unsigned n_shared_files_before = 0; - lilv_dir_for_each(dirs.shared, &n_shared_files_before, count_file); + zix_dir_for_each(dirs.shared, &n_shared_files_before, count_file); lilv_instance_free(instance); @@ -1079,11 +1077,11 @@ test_delete(void) // Ensure the number of shared files is the same after deletion unsigned n_shared_files_after = 0; - lilv_dir_for_each(dirs.shared, &n_shared_files_after, count_file); + zix_dir_for_each(dirs.shared, &n_shared_files_after, count_file); assert(n_shared_files_before == n_shared_files_after); // Ensure the state directory has been deleted - assert(!lilv_path_exists(bundle_path)); + assert(zix_file_type(bundle_path) == ZIX_FILE_TYPE_NONE); cleanup_test_directories(dirs); diff --git a/test/test_string.c b/test/test_string.c index 2d610bb..48021ed 100644 --- a/test/test_string.c +++ b/test/test_string.c @@ -1,20 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#define _POSIX_C_SOURCE 200809L /* for setenv */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG @@ -36,19 +21,27 @@ main(void) #ifndef _WIN32 char* s = NULL; + const char* const home = getenv("HOME"); + setenv("LILV_TEST_1", "test", 1); - char* home_foo = lilv_strjoin(getenv("HOME"), "/foo", NULL); + assert(!strcmp((s = lilv_expand("$LILV_TEST_1")), "test")); free(s); - assert(!strcmp((s = lilv_expand("~")), getenv("HOME"))); - free(s); - assert(!strcmp((s = lilv_expand("~foo")), "~foo")); - free(s); - assert(!strcmp((s = lilv_expand("~/foo")), home_foo)); - free(s); + if (home) { + assert(!strcmp((s = lilv_expand("~")), home)); + free(s); + assert(!strcmp((s = lilv_expand("~foo")), "~foo")); + free(s); + + char* const home_foo = lilv_strjoin(home, "/foo", NULL); + assert(!strcmp((s = lilv_expand("~/foo")), home_foo)); + free(s); + free(home_foo); + } + assert(!strcmp((s = lilv_expand("$NOT_A_VAR")), "$NOT_A_VAR")); free(s); - free(home_foo); + unsetenv("LILV_TEST_1"); #endif diff --git a/test/test_ui.c b/test/test_ui.c index d14f54f..78ea871 100644 --- a/test/test_ui.c +++ b/test/test_ui.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_util.c b/test/test_util.c index 8c8f36a..2e609da 100644 --- a/test/test_util.c +++ b/test/test_util.c @@ -1,67 +1,38 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#define _XOPEN_SOURCE 600 /* for mkstemp */ +// Copyright 2007-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG -#ifdef _WIN32 -# include "lilv_internal.h" -#endif +#include "lilv_test_utils.h" -#include "../src/filesystem.h" - -#ifdef _WIN32 -# include <io.h> -# define mkstemp(pat) _mktemp(pat) -#endif +#include "lilv/lilv.h" +#include "zix/filesystem.h" +#include "zix/path.h" #include <assert.h> #include <stdio.h> -#include <stdlib.h> -#include <string.h> int main(void) { - assert(!lilv_path_canonical(NULL)); + char* const dir = lilv_create_temporary_directory("lilv_test_util_XXXXXX"); - char a_path[16]; - char b_path[16]; - strncpy(a_path, "copy_a_XXXXXX", sizeof(a_path)); - strncpy(b_path, "copy_b_XXXXXX", sizeof(b_path)); - mkstemp(a_path); - mkstemp(b_path); + char* const a_path = zix_path_join(NULL, dir, "copy_a_XXXXXX"); + char* const b_path = zix_path_join(NULL, dir, "copy_b_XXXXXX"); - FILE* fa = fopen(a_path, "w"); - FILE* fb = fopen(b_path, "w"); + FILE* const fa = fopen(a_path, "w"); + FILE* const fb = fopen(b_path, "w"); fprintf(fa, "AA\n"); fprintf(fb, "AB\n"); - fclose(fa); fclose(fb); + fclose(fa); - assert(lilv_copy_file("does/not/exist", "copy")); - assert(lilv_copy_file(a_path, "not/a/dir/copy")); - assert(!lilv_copy_file(a_path, "copy_c")); - assert(!lilv_file_equals(a_path, b_path)); - assert(lilv_file_equals(a_path, a_path)); - assert(lilv_file_equals(a_path, "copy_c")); - assert(!lilv_file_equals("does/not/exist", b_path)); - assert(!lilv_file_equals(a_path, "does/not/exist")); - assert(!lilv_file_equals("does/not/exist", "/does/not/either")); + assert(!zix_remove(a_path)); + assert(!zix_remove(b_path)); + assert(!zix_remove(dir)); + lilv_free(b_path); + lilv_free(a_path); + lilv_free(dir); return 0; } diff --git a/test/test_value.c b/test/test_value.c index 8061029..a37c886 100644 --- a/test/test_value.c +++ b/test/test_value.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_verify.c b/test/test_verify.c index d20712e..e066751 100644 --- a/test/test_verify.c +++ b/test/test_verify.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/test/test_world.c b/test/test_world.c index 762907f..fda8595 100644 --- a/test/test_world.c +++ b/test/test_world.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #undef NDEBUG diff --git a/tools/.clang-tidy b/tools/.clang-tidy new file mode 100644 index 0000000..d8434e2 --- /dev/null +++ b/tools/.clang-tidy @@ -0,0 +1,16 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +Checks: > + -*-magic-numbers, + -android-cloexec-fopen, + -bugprone-narrowing-conversions, + -cert-err33-c, + -cert-err34-c, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-narrowing-conversions, + -hicpp-signed-bitwise, + -llvm-header-guard, + -misc-no-recursion, + -readability-function-cognitive-complexity, +InheritParentConfig: true diff --git a/tools/bench.h b/tools/bench.h new file mode 100644 index 0000000..d87102e --- /dev/null +++ b/tools/bench.h @@ -0,0 +1,38 @@ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +/** + @file bench.h A simple real-time benchmarking API. +*/ + +#ifndef BENCH_H +#define BENCH_H + +#include <time.h> + +typedef struct timespec BenchmarkTime; + +static inline double +bench_elapsed_s(const BenchmarkTime* start, const BenchmarkTime* end) +{ + return ((end->tv_sec - start->tv_sec) + + ((end->tv_nsec - start->tv_nsec) * 0.000000001)); +} + +static inline BenchmarkTime +bench_start(void) +{ + BenchmarkTime start_t; + clock_gettime(CLOCK_REALTIME, &start_t); + return start_t; +} + +static inline double +bench_end(const BenchmarkTime* start_t) +{ + BenchmarkTime end_t; + clock_gettime(CLOCK_REALTIME, &end_t); + return bench_elapsed_s(start_t, &end_t); +} + +#endif /* BENCH_H */ diff --git a/utils/lilv.bash_completion b/tools/lilv.bash_completion index 4a553a7..d5de5e2 100644 --- a/utils/lilv.bash_completion +++ b/tools/lilv.bash_completion @@ -1,10 +1,9 @@ -# Bash auto-completion script written for lv2info and lv2jack. -# Could be adapted to any other program that takes an -# LV2 plugin URI as parameter. +# Copyright 2012-2022 David Robillard <d@drobilla.net> +# Copyright 2009 Lars Luthman <lars.luthman@gmail.com> +# SPDX-License-Identifier: 0BSD OR ISC -# Updated for Lilv by David Robillard <d@drobilla.net> on 2012-01-08. -# Written by Lars Luthman <lars.luthman@gmail.com> on 2009-10-12. -# No copyright claimed for this script. Do what you want with it. +# Bash auto-completion script written for lv2info. Could be adapted to any +# other program that takes an LV2 plugin URI as parameter. # For some reason Bash splits the command line not only at whitespace # but also at ':' signs before putting the parts into COMP_WORDS. @@ -54,6 +53,3 @@ function _lv2info() { } complete -F _lv2info lv2info - -# And the same for lv2jack. -complete -F _lv2info lv2jack diff --git a/utils/lv2apply.c b/tools/lv2apply.c index e042999..9c74bf3 100644 --- a/utils/lv2apply.c +++ b/tools/lv2apply.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv/lilv.h" @@ -219,11 +206,11 @@ print_usage(int status) fprintf(status ? stderr : stdout, "Usage: lv2apply [OPTION]... PLUGIN_URI\n" "Apply an LV2 plugin to an audio file.\n\n" - " -i IN_FILE Input file\n" - " -o OUT_FILE Output file\n" - " -c SYM VAL Control value\n" - " --help Display this help and exit\n" - " --version Display version information and exit\n"); + " -V, --version Display version information and exit\n" + " -c SYM VAL Control value\n" + " -h, --help Display this help and exit\n" + " -i IN_FILE Input file\n" + " -o OUT_FILE Output file\n"); return status; } @@ -236,13 +223,13 @@ main(int argc, char** argv) /* Parse command line arguments */ const char* plugin_uri = NULL; for (int i = 1; i < argc; ++i) { - if (!strcmp(argv[i], "--version")) { + if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) { free(self.params); print_version(); return 0; } - if (!strcmp(argv[i], "--help")) { + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { free(self.params); return print_usage(0); } diff --git a/utils/lv2bench.c b/tools/lv2bench.c index c355727..4b7eef7 100644 --- a/utils/lv2bench.c +++ b/tools/lv2bench.c @@ -1,20 +1,5 @@ -/* - Copyright 2012-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#define _POSIX_C_SOURCE 200809L +// Copyright 2012-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv/lilv.h" #include "lv2/atom/atom.h" @@ -60,11 +45,11 @@ print_usage(void) printf("lv2bench - Benchmark all installed and supported LV2 plugins.\n"); printf("Usage: lv2bench [OPTIONS] [PLUGIN_URI]\n"); printf("\n"); + printf(" -V, --version Display version information and exit\n"); printf(" -b BLOCK_SIZE Specify block size, in audio frames.\n"); printf(" -f, --full Full plottable output.\n"); printf(" -h, --help Display this help and exit.\n"); printf(" -n FRAMES Total number of audio frames to process\n"); - printf(" --version Display version information and exit\n"); } static double @@ -79,7 +64,7 @@ bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size) LV2_Feature unmap_feature = {LV2_URID_UNMAP_URI, &unmap}; const LV2_Feature* features[] = {&map_feature, &unmap_feature, NULL}; - float* const buf = (float*)calloc(block_size * 2, sizeof(float)); + float* const buf = (float*)calloc(block_size * 2UL, sizeof(float)); float* const in = buf; float* const out = buf + block_size; if (!buf) { @@ -216,12 +201,12 @@ main(int argc, char** argv) int a = 1; for (; a < argc; ++a) { - if (!strcmp(argv[a], "--version")) { + if (!strcmp(argv[a], "-V") || !strcmp(argv[a], "--version")) { print_version(); return 0; } - if (!strcmp(argv[a], "--help")) { + if (!strcmp(argv[a], "-h") || !strcmp(argv[a], "--help")) { print_usage(); return 0; } diff --git a/utils/lv2info.c b/tools/lv2info.c index 81a3ed4..55acd09 100644 --- a/utils/lv2info.c +++ b/tools/lv2info.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_config.h" @@ -343,10 +330,10 @@ print_usage(void) { printf("Usage: lv2info [OPTION]... PLUGIN_URI\n" "Print information about an installed LV2 plugin.\n\n" - " -p FILE Write Turtle description of plugin to FILE\n" - " -m FILE Add record of plugin to manifest FILE\n" - " --help Display this help and exit\n" - " --version Display version information and exit\n\n" + " -V, --version Display version information and exit\n" + " -h, --help Display this help and exit\n" + " -m FILE Add record of plugin to manifest FILE\n" + " -p FILE Write Turtle description of plugin to FILE\n\n" "For -p and -m, Turtle files are appended to (not overwritten),\n" "and @prefix directives are only written if the file was empty.\n" "This allows several plugins to be added to a single file.\n"); @@ -364,12 +351,12 @@ main(int argc, char** argv) const char* manifest_file = NULL; const char* plugin_uri = NULL; for (int i = 1; i < argc; ++i) { - if (!strcmp(argv[i], "--version")) { + if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) { print_version(); return 0; } - if (!strcmp(argv[i], "--help")) { + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(); return 0; } diff --git a/utils/lv2ls.c b/tools/lv2ls.c index 9226b89..8203262 100644 --- a/utils/lv2ls.c +++ b/tools/lv2ls.c @@ -1,18 +1,5 @@ -/* - Copyright 2007-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2007-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC #include "lilv_config.h" @@ -53,9 +40,9 @@ print_usage(void) printf("Usage: lv2ls [OPTION]...\n"); printf("List all installed LV2 plugins.\n"); printf("\n"); + printf(" -V, --version Display version information and exit\n"); + printf(" -h, --help Display this help and exit\n"); printf(" -n, --names Show names instead of URIs\n"); - printf(" --help Display this help and exit\n"); - printf(" --version Display version information and exit\n"); printf("\n"); printf("The environment variable LV2_PATH can be used to control where\n"); printf( @@ -69,10 +56,10 @@ main(int argc, char** argv) for (int i = 1; i < argc; ++i) { if (!strcmp(argv[i], "--names") || !strcmp(argv[i], "-n")) { show_names = true; - } else if (!strcmp(argv[i], "--version")) { + } else if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) { print_version(); return 0; - } else if (!strcmp(argv[i], "--help")) { + } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(); return 0; } else { diff --git a/tools/meson.build b/tools/meson.build new file mode 100644 index 0000000..0e93157 --- /dev/null +++ b/tools/meson.build @@ -0,0 +1,89 @@ +# Copyright 2021-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +include_dirs = include_directories('../src') + +############################# +# "Basic" (Lilv-Only) Tools # +############################# + +basic_tools = [ + 'lv2info', + 'lv2ls', +] + +foreach tool : basic_tools + exe = executable( + tool, + files(tool + '.c'), + c_args: c_suppressions, + dependencies: lilv_dep, + include_directories: include_dirs, + install: true, + ) + + meson.override_find_program(tool, exe) + + install_man(files('..' / 'doc' / tool + '.1')) +endforeach + +install_data( + files('lilv.bash_completion'), + install_dir: get_option('sysconfdir') / 'bash_completion.d', + rename: 'lilv', +) + +########################### +# lv2apply (uses sndfile) # +########################### + +sndfile_dep = dependency( + 'sndfile', + version: '>= 1.0.0', + required: get_option('tools'), +) + +if sndfile_dep.found() + lv2apply = executable( + 'lv2apply', + files('lv2apply.c'), + c_args: c_suppressions, + dependencies: [lilv_dep, sndfile_dep], + include_directories: include_dirs, + install: true, + ) + + meson.override_find_program('lv2apply', lv2apply) + + install_man(files('..' / 'doc' / 'lv2apply.1')) +endif + +################################# +# lv2bench (uses clock_gettime) # +################################# + +if host_machine.system() != 'windows' + rt_dep = cc.find_library('rt', required: false) + + clock_gettime_code = '''#include <time.h> +int main(void) { struct timespec t; return clock_gettime(CLOCK_MONOTONIC, &t); } +''' + + if cc.compiles(clock_gettime_code, + args: platform_defines, + dependencies: [rt_dep], + name: 'clock_gettime') + lv2bench = executable( + 'lv2bench', + files('lv2bench.c'), + c_args: c_suppressions, + dependencies: [lilv_dep, rt_dep, sndfile_dep], + include_directories: include_dirs, + install: true, + ) + + meson.override_find_program('lv2bench', lv2bench) + + install_man(files('..' / 'doc' / 'lv2bench.1')) + endif +endif diff --git a/utils/uri_table.h b/tools/uri_table.h index 5a337a3..e17b02a 100644 --- a/utils/uri_table.h +++ b/tools/uri_table.h @@ -1,18 +1,5 @@ -/* - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2011-2019 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC /** @file uri_table.h A toy URI map/unmap implementation. diff --git a/utils/bench.h b/utils/bench.h deleted file mode 100644 index 505631f..0000000 --- a/utils/bench.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright 2011-2019 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file bench.h A simple real-time benchmarking API. -*/ - -#ifndef BENCH_H -#define BENCH_H - -#define _POSIX_C_SOURCE 200809L - -#include <time.h> - -typedef struct timespec BenchmarkTime; - -static inline double -bench_elapsed_s(const BenchmarkTime* start, const BenchmarkTime* end) -{ - return ((end->tv_sec - start->tv_sec) + - ((end->tv_nsec - start->tv_nsec) * 0.000000001)); -} - -static inline BenchmarkTime -bench_start(void) -{ - BenchmarkTime start_t; - clock_gettime(CLOCK_REALTIME, &start_t); - return start_t; -} - -static inline double -bench_end(const BenchmarkTime* start_t) -{ - BenchmarkTime end_t; - clock_gettime(CLOCK_REALTIME, &end_t); - return bench_elapsed_s(start_t, &end_t); -} - -#endif /* BENCH_H */ diff --git a/utils/lilv-bench.c b/utils/lilv-bench.c deleted file mode 100644 index 56b7fee..0000000 --- a/utils/lilv-bench.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright 2007-2012 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "lilv/lilv.h" - -int -main(void) -{ - LilvWorld* world = lilv_world_new(); - lilv_world_load_all(world); - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - LILV_FOREACH (plugins, p, plugins) { - const LilvPlugin* plugin = lilv_plugins_get(plugins, p); - lilv_plugin_get_class(plugin); - } - - lilv_world_free(world); - - return 0; -} @@ -1,27 +0,0 @@ -#!/usr/bin/env python - -# Minimal waf script for projects that include waflib directly - -import sys -import inspect -import os - -try: - from waflib import Context, Scripting -except Exception as e: - sys.stderr.write('error: Failed to import waf (%s)\n' % e) - if os.path.exists('.git'): - sys.stderr.write("Are submodules up to date? " - "Try 'git submodule update --init --recursive'\n") - - sys.exit(1) - - -def main(): - script_path = os.path.abspath(inspect.getfile(inspect.getmodule(main))) - project_path = os.path.dirname(script_path) - Scripting.waf_entry_point(os.getcwd(), Context.WAFVERSION, project_path) - - -if __name__ == '__main__': - main() diff --git a/waflib b/waflib deleted file mode 160000 -Subproject b600c928b221a001faeab7bd92786d0b25714bc diff --git a/wscript b/wscript deleted file mode 100644 index 7005967..0000000 --- a/wscript +++ /dev/null @@ -1,633 +0,0 @@ -#!/usr/bin/env python - -import glob -import os -import shutil -import sys - -from waflib import Build, Options, Logs -from waflib.extras import autowaf - -# Library and package version (UNIX style major, minor, micro) -# major increment <=> incompatible changes -# minor increment <=> compatible changes (additions) -# micro increment <=> no interface changes -LILV_VERSION = '0.24.13' -LILV_MAJOR_VERSION = '0' - -# Mandatory waf variables -APPNAME = 'lilv' # Package name for waf dist -VERSION = LILV_VERSION # Package version for waf dist -top = '.' # Source directory -out = 'build' # Build directory - -# Release variables -uri = 'http://drobilla.net/sw/lilv' -dist_pattern = 'http://download.drobilla.net/lilv-%d.%d.%d.tar.bz2' -post_tags = ['Hacking', 'LAD', 'LV2', 'Lilv'] - -tests = [ - 'test_bad_port_index', - 'test_bad_port_symbol', - 'test_classes', - 'test_discovery', - 'test_filesystem', - 'test_get_symbol', - 'test_no_author', - 'test_no_verify', - 'test_plugin', - 'test_port', - 'test_preset', - 'test_project', - 'test_project_no_author', - 'test_prototype', - 'test_reload_bundle', - 'test_replace_version', - 'test_state', - 'test_string', - 'test_ui', - 'test_util', - 'test_value', - 'test_verify', - 'test_world', -] - -test_plugins = [ - 'bad_syntax', - 'failed_instantiation', - 'failed_lib_descriptor', - 'lib_descriptor', - 'missing_descriptor', - 'missing_name', - 'missing_plugin', - 'missing_port', - 'missing_port_name', - 'new_version', - 'old_version' -] - - -def options(ctx): - ctx.load('compiler_c') - ctx.load('compiler_cxx') - ctx.load('python') - opt = ctx.configuration_options() - ctx.add_flags( - opt, - {'no-utils': 'do not build command line utilities', - 'no-bindings': 'do not build python bindings', - 'dyn-manifest': 'build support for dynamic manifests', - 'no-bash-completion': 'do not install bash completion script', - 'static': 'build static library', - 'no-shared': 'do not build shared library', - 'static-progs': 'build programs as static binaries'}) - - opt.add_option('--default-lv2-path', type='string', default='', - dest='default_lv2_path', - help='default LV2 path to use if LV2_PATH is unset') - - -def configure(conf): - conf.load('compiler_c', cache=True) - try: - conf.load('compiler_cxx', cache=True) - conf.define('LILV_CXX', True) - except Exception: - pass - - if not Options.options.no_bindings: - try: - conf.load('python', cache=True) - conf.check_python_version((2, 6, 0)) - conf.env.LILV_PYTHON = 1 - except Exception as e: - Logs.warn('Failed to configure Python (%s)\n' % e) - - conf.load('autowaf', cache=True) - autowaf.set_c_lang(conf, 'c99') - - if conf.env.DOCS: - conf.load('sphinx') - - conf.env.BASH_COMPLETION = not Options.options.no_bash_completion - conf.env.BUILD_UTILS = not Options.options.no_utils - conf.env.BUILD_SHARED = not Options.options.no_shared - conf.env.STATIC_PROGS = Options.options.static_progs - conf.env.BUILD_STATIC = (Options.options.static or - Options.options.static_progs) - - if not conf.env.BUILD_SHARED and not conf.env.BUILD_STATIC: - conf.fatal('Neither a shared nor a static build requested') - - if Options.options.strict: - # Check for programs used by lint target - conf.find_program("flake8", var="FLAKE8", mandatory=False) - conf.find_program("clang-tidy", var="CLANG_TIDY", mandatory=False) - conf.find_program("iwyu_tool", var="IWYU_TOOL", mandatory=False) - - if Options.options.ultra_strict: - autowaf.add_compiler_flags(conf.env, '*', { - 'clang': [ - '-Wno-documentation-unknown-command', - '-Wno-nullability-extension', - ] - }) - - autowaf.add_compiler_flags(conf.env, 'c', { - 'clang': [ - '-Wno-cast-align', - '-Wno-cast-qual', - '-Wno-double-promotion', - '-Wno-float-equal', - '-Wno-format-nonliteral', - '-Wno-implicit-float-conversion', - '-Wno-implicit-int-conversion', - '-Wno-padded', - '-Wno-reserved-id-macro', - '-Wno-shorten-64-to-32', - '-Wno-sign-conversion', - '-Wno-switch-enum', - '-Wno-vla', - ], - 'gcc': [ - '-Wno-cast-align', - '-Wno-cast-qual', - '-Wno-conversion', - '-Wno-double-promotion', - '-Wno-float-equal', - '-Wno-padded', - '-Wno-stack-protector', - '-Wno-suggest-attribute=const', - '-Wno-suggest-attribute=pure', - '-Wno-switch-enum', - '-Wno-vla', - ], - 'msvc': [ - '/wd4061', # enumerator in switch is not explicitly handled - '/wd4365', # signed/unsigned mismatch - '/wd4514', # unreferenced inline function has been removed - '/wd4774', # format string is not a string literal - '/wd4820', # padding added after construct - '/wd4996', # POSIX name for this item is deprecated - ], - }) - - autowaf.add_compiler_flags(conf.env, 'cxx', { - 'clang': [ - '-Wno-extra-semi', - ], - 'gcc': [ - '-Wno-effc++', - '-Wno-extra-semi', - '-Wno-pedantic', - ], - }) - - conf.check_pkg('lv2 >= 1.18.0', uselib_store='LV2') - conf.check_pkg('serd-0 >= 0.30.0', uselib_store='SERD') - conf.check_pkg('sord-0 >= 0.14.0', uselib_store='SORD') - conf.check_pkg('sratom-0 >= 0.4.0', uselib_store='SRATOM') - conf.check_pkg('sndfile >= 1.0.0', uselib_store='SNDFILE', mandatory=False) - - defines = ['_POSIX_C_SOURCE=200809L', '_BSD_SOURCE', '_DEFAULT_SOURCE'] - if conf.env.DEST_OS == 'darwin': - defines += ['_DARWIN_C_SOURCE'] - - rt_lib = ['rt'] - if conf.env.DEST_OS == 'darwin' or conf.env.DEST_OS == 'win32': - rt_lib = [] - - conf.check_function('c', 'lstat', - header_name = ['sys/stat.h'], - defines = defines, - define_name = 'HAVE_LSTAT', - return_type = 'int', - arg_types = 'const char*, struct stat*', - mandatory = False) - - conf.check_function('c', 'flock', - header_name = 'sys/file.h', - defines = defines, - define_name = 'HAVE_FLOCK', - return_type = 'int', - arg_types = 'int, int', - mandatory = False) - - conf.check_function('c', 'fileno', - header_name = 'stdio.h', - defines = defines, - define_name = 'HAVE_FILENO', - return_type = 'int', - arg_types = 'FILE*', - mandatory = False) - - conf.check_function('c', 'clock_gettime', - header_name = ['sys/time.h', 'time.h'], - defines = ['_POSIX_C_SOURCE=200809L'], - define_name = 'HAVE_CLOCK_GETTIME', - uselib_store = 'CLOCK_GETTIME', - lib = rt_lib, - return_type = 'int', - arg_types = 'clockid_t, struct timespec*', - mandatory = False) - - conf.check_cc(define_name = 'HAVE_LIBDL', - lib = 'dl', - mandatory = False) - - if Options.options.dyn_manifest: - conf.define('LILV_DYN_MANIFEST', 1) - - lilv_path_sep = ':' - lilv_dir_sep = '/' - if conf.env.DEST_OS == 'win32': - lilv_path_sep = ';' - lilv_dir_sep = '\\\\' - - conf.define('LILV_PATH_SEP', lilv_path_sep) - conf.define('LILV_DIR_SEP', lilv_dir_sep) - - # Set default LV2 path - lv2_path = Options.options.default_lv2_path - if lv2_path == '': - if conf.env.DEST_OS == 'darwin': - lv2_path = lilv_path_sep.join(['~/Library/Audio/Plug-Ins/LV2', - '~/.lv2', - '/usr/local/lib/lv2', - '/usr/lib/lv2', - '/Library/Audio/Plug-Ins/LV2']) - elif conf.env.DEST_OS == 'haiku': - lv2_path = lilv_path_sep.join(['~/.lv2', - '/boot/common/add-ons/lv2']) - elif conf.env.DEST_OS == 'win32': - lv2_path = lilv_path_sep.join(['%APPDATA%\\\\LV2', - '%COMMONPROGRAMFILES%\\\\LV2']) - else: - libdirname = os.path.basename(conf.env.LIBDIR) - lv2_path = lilv_path_sep.join(['~/.lv2', - '/usr/%s/lv2' % libdirname, - '/usr/local/%s/lv2' % libdirname]) - - if sys.platform == 'win32': - lv2_path = lv2_path.replace('%', '%%') - - conf.define('LILV_DEFAULT_LV2_PATH', lv2_path) - - # Set up environment for building/using as a subproject - autowaf.set_lib_env(conf, 'lilv', LILV_VERSION, - include_path=str(conf.path.find_node('include'))) - - conf.define('LILV_NO_DEFAULT_CONFIG', 1) - - autowaf.display_summary( - conf, - {'Default LV2_PATH': lv2_path, - 'Utilities': bool(conf.env.BUILD_UTILS), - 'Unit tests': bool(conf.env.BUILD_TESTS), - 'Dynamic manifest support': conf.is_defined('LILV_DYN_MANIFEST'), - 'Python bindings': bool(conf.env.LILV_PYTHON)}) - - -def build_util(bld, name, defines, libs=''): - obj = bld(features = 'c cprogram', - source = name + '.c', - includes = ['.', 'include', './src', './utils'], - use = 'liblilv', - uselib = 'SERD SORD SRATOM LV2 ' + libs, - target = name, - defines = defines, - install_path = '${BINDIR}') - if not bld.env.BUILD_SHARED or bld.env.STATIC_PROGS: - obj.use = 'liblilv_static' - if bld.env.STATIC_PROGS: - if not bld.env.MSVC_COMPILER: - obj.lib = ['m'] - obj.env.SHLIB_MARKER = obj.env.STLIB_MARKER - obj.linkflags = ['-static', '-Wl,--start-group'] - return obj - - -def build(bld): - # C/C++ Headers - includedir = '${INCLUDEDIR}/lilv-%s/lilv' % LILV_MAJOR_VERSION - bld.install_files(includedir, bld.path.ant_glob('include/lilv/*.h')) - bld.install_files(includedir, bld.path.ant_glob('include/lilv/*.hpp')) - - lib_source = ''' - src/collections.c - src/filesystem.c - src/instance.c - src/lib.c - src/node.c - src/plugin.c - src/pluginclass.c - src/port.c - src/query.c - src/scalepoint.c - src/state.c - src/ui.c - src/util.c - src/world.c - src/zix/tree.c - '''.split() - - lib = [] - libflags = ['-fvisibility=hidden'] - defines = [] - if bld.is_defined('HAVE_LIBDL'): - lib += ['dl'] - if bld.env.DEST_OS == 'win32': - lib = [] - if bld.env.MSVC_COMPILER: - libflags = [] - - # Pkgconfig file - autowaf.build_pc(bld, 'LILV', LILV_VERSION, LILV_MAJOR_VERSION, [], - {'LILV_MAJOR_VERSION': LILV_MAJOR_VERSION, - 'LILV_PKG_DEPS': 'lv2 serd-0 sord-0 sratom-0', - 'LILV_PKG_LIBS': ' -l'.join([''] + lib)}) - - # Shared Library - if bld.env.BUILD_SHARED: - obj = bld(features = 'c cshlib', - export_includes = ['.', 'include'], - source = lib_source, - includes = ['.', 'include', './src'], - name = 'liblilv', - target = 'lilv-%s' % LILV_MAJOR_VERSION, - vnum = LILV_VERSION, - install_path = '${LIBDIR}', - defines = ['LILV_INTERNAL'], - cflags = libflags, - lib = lib, - uselib = 'SERD SORD SRATOM LV2') - - # Static library - if bld.env.BUILD_STATIC: - obj = bld(features = 'c cstlib', - export_includes = ['.', 'include'], - source = lib_source, - includes = ['.', 'include', './src'], - name = 'liblilv_static', - target = 'lilv-%s' % LILV_MAJOR_VERSION, - vnum = LILV_VERSION, - install_path = '${LIBDIR}', - defines = defines + ['LILV_STATIC', 'LILV_INTERNAL'], - uselib = 'SERD SORD SRATOM LV2') - - # Python bindings - if bld.env.LILV_PYTHON: - bld(features = 'subst', - is_copy = True, - source = 'bindings/python/lilv.py', - target = 'lilv.py', - install_path = '${PYTHONDIR}') - - if bld.env.BUILD_TESTS: - import re - - test_libs = lib - test_cflags = [''] - test_linkflags = [''] - if not bld.env.NO_COVERAGE: - test_cflags += ['--coverage'] - test_linkflags += ['--coverage'] - - # Copy skeleton LV2 bundle for tests - for name in ('manifest.ttl', 'lv2core.ttl'): - bld(features = 'subst', - is_copy = True, - source = 'test/core.lv2/' + name, - target = 'test/test_lv2_path/core.lv2/' + name, - install_path = None) - - # Make a pattern for shared objects without the 'lib' prefix - module_pattern = re.sub('^lib', '', bld.env.cshlib_PATTERN) - shlib_ext = module_pattern[module_pattern.rfind('.'):] - - for p in ['test'] + test_plugins: - obj = bld(features = 'c cshlib', - source = 'test/%s.lv2/%s.c' % (p, p), - name = p, - target = 'test/%s.lv2/%s' % (p, p), - install_path = None, - defines = defines + ['LILV_STATIC'], - cflags = test_cflags, - linkflags = test_linkflags, - lib = test_libs, - uselib = 'LV2') - obj.env.cshlib_PATTERN = module_pattern - - for p in test_plugins: - if not bld.path.find_node('test/%s.lv2/test_%s.c' % (p, p)): - continue - - obj = bld(features = 'c cprogram', - source = 'test/%s.lv2/test_%s.c' % (p, p), - target = 'test/test_%s' % p, - includes = ['.', 'include', './src'], - use = 'liblilv_profiled', - install_path = None, - defines = defines + ['LILV_STATIC'], - cflags = test_cflags, - linkflags = test_linkflags, - lib = test_libs, - uselib = 'SERD SORD SRATOM LV2') - - # Test plugin data files - for p in ['test'] + test_plugins: - for i in ['manifest.ttl.in', p + '.ttl.in']: - bundle = 'test/%s.lv2/' % p - bld(features = 'subst', - source = bundle + i, - target = bundle + i.replace('.in', ''), - install_path = None, - SHLIB_EXT = shlib_ext) - - # Static profiled library (for unit test code coverage) - obj = bld(features = 'c cstlib', - source = lib_source, - includes = ['.', 'include', './src'], - name = 'liblilv_profiled', - target = 'lilv_profiled', - install_path = None, - defines = defines + ['LILV_STATIC', 'LILV_INTERNAL'], - cflags = test_cflags, - linkflags = test_linkflags, - lib = test_libs, - uselib = 'SERD SORD SRATOM LV2') - - # Unit test program - testdir = bld.path.get_bld().make_node('test').abspath() - bpath = os.path.join(testdir, 'test.lv2') - bpath = bpath.replace('\\', '/') - testdir = testdir.replace('\\', '/') - for test in tests: - obj = bld(features = 'c cprogram', - source = ['test/%s.c' % test, - 'test/lilv_test_utils.c'], - includes = ['.', 'include', './src'], - use = 'liblilv_profiled', - lib = test_libs, - uselib = 'SERD SORD SRATOM LV2', - target = 'test/' + test, - install_path = None, - defines = (defines + - ['LILV_STATIC'] + - ['LILV_TEST_BUNDLE=\"%s/\"' % bpath] + - ['LILV_TEST_DIR=\"%s/\"' % testdir]), - cflags = test_cflags, - linkflags = test_linkflags) - - # C++ API test - if 'COMPILER_CXX' in bld.env: - obj = bld(features = 'cxx cxxprogram', - source = 'test/lilv_cxx_test.cpp', - includes = ['.', 'include', './src'], - use = 'liblilv_profiled', - lib = test_libs, - uselib = 'SERD SORD SRATOM LV2', - target = 'test/lilv_cxx_test', - install_path = None, - defines = ['LILV_STATIC'], - cxxflags = test_cflags, - linkflags = test_linkflags) - - if bld.env.LILV_PYTHON: - test_bundle = 'bindings/bindings_test_plugin.lv2/' - - # Copy Python unittest files - for i in ['test_api.py']: - bld(features = 'subst', - is_copy = True, - source = 'bindings/test/python/' + i, - target = 'bindings/' + i, - install_path = None) - - # Build bindings test plugin - obj = bld(features = 'c cshlib', - source = 'bindings/test/bindings_test_plugin.c', - name = 'bindings_test_plugin', - target = test_bundle + '/bindings_test_plugin', - install_path = None, - defines = defines, - cflags = test_cflags, - linkflags = test_linkflags, - lib = test_libs, - uselib = 'LV2') - obj.env.cshlib_PATTERN = module_pattern - - # Bindings test plugin data files - for i in ['manifest.ttl.in', 'bindings_test_plugin.ttl.in']: - bld(features = 'subst', - source = 'bindings/test/' + i, - target = test_bundle + i.replace('.in', ''), - install_path = None, - SHLIB_EXT = shlib_ext) - - # Utilities - if bld.env.BUILD_UTILS: - utils = ''' - utils/lilv-bench - utils/lv2info - utils/lv2ls - ''' - for i in utils.split(): - build_util(bld, i, defines) - - if bld.env.HAVE_SNDFILE: - obj = build_util(bld, 'utils/lv2apply', defines, 'SNDFILE') - - # lv2bench (less portable than other utilities) - if (bld.env.DEST_OS != 'win32' and - bld.is_defined('HAVE_CLOCK_GETTIME') and - not bld.env.STATIC_PROGS): - obj = build_util(bld, 'utils/lv2bench', defines) - if bld.env.DEST_OS != 'darwin': - obj.lib = ['rt'] - - # Documentation - if bld.env.DOCS: - bld.recurse('doc/c') - - # Man pages - bld.install_files('${MANDIR}/man1', bld.path.ant_glob('doc/*.1')) - - # Bash completion - if bld.env.BASH_COMPLETION: - bld.install_as('${SYSCONFDIR}/bash_completion.d/lilv', - 'utils/lilv.bash_completion') - - bld.add_post_fun(autowaf.run_ldconfig) - - -def test(tst): - with tst.group('unit') as check: - for test in tests: - check(['./test/' + test]) - - if tst.is_defined('LILV_CXX'): - check(['./test/lilv_cxx_test']) - - if tst.env.LILV_PYTHON: - with tst.group('python') as check: - check(['python', '-m', 'unittest', 'discover', 'bindings/']) - - with tst.group('plugin') as check: - for p in test_plugins: - prog_name = tst.env.cprogram_PATTERN % ('test_' + p) - if os.path.exists(os.path.join('test', prog_name)): - check(['./test/test_' + p, 'test/%s.lv2/' % p]) - - try: - shutil.rmtree('state') - except Exception: - pass - - -class LintContext(Build.BuildContext): - fun = cmd = 'lint' - - -def lint(ctx): - "checks code for style issues" - import subprocess - - st = 0 - - if "FLAKE8" in ctx.env: - Logs.info("Running flake8") - st = subprocess.call([ctx.env.FLAKE8[0], - "wscript", - "--ignore", - "E101,E129,W191,E221,W504,E251,E241,E741"]) - else: - Logs.warn("Not running flake8") - - if "IWYU_TOOL" in ctx.env: - Logs.info("Running include-what-you-use") - cmd = [ctx.env.IWYU_TOOL[0], "-o", "clang", "-p", "build"] - output = subprocess.check_output(cmd).decode('utf-8') - if 'error: ' in output: - sys.stdout.write(output) - st += 1 - else: - Logs.warn("Not running include-what-you-use") - - if "CLANG_TIDY" in ctx.env and "clang" in ctx.env.CC[0]: - Logs.info("Running clang-tidy") - sources = glob.glob('src/*.c') + glob.glob('tests/*.c') - sources = list(map(os.path.abspath, sources)) - procs = [] - for source in sources: - cmd = [ctx.env.CLANG_TIDY[0], "--quiet", "-p=.", source] - procs += [subprocess.Popen(cmd, cwd="build")] - - for proc in procs: - stdout, stderr = proc.communicate() - st += proc.returncode - else: - Logs.warn("Not running clang-tidy") - - if st != 0: - sys.exit(st) |