diff options
| author | ruki <[email protected]> | 2017-08-14 11:27:19 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2017-08-14 11:29:30 +0800 |
| commit | dba45d143d8aff047da82cbe1a881056e6e4bc00 (patch) | |
| tree | 7b80d5de264c17b538a7c9d0fbb234ded39ac683 /core/src | |
| parent | 34706ba053dda9dd86902cacf42a6c1878c85234 (diff) | |
merge repo and require codes
Diffstat (limited to 'core/src')
56 files changed, 5308 insertions, 16 deletions
diff --git a/core/src/demo/makefile b/core/src/demo/makefile index 3a474649f..084e525fe 100644 --- a/core/src/demo/makefile +++ b/core/src/demo/makefile @@ -15,9 +15,9 @@ demo_PKGS-$(TBOX) += tbox demo_PKGS-$(BASE) += base # others -demo_LIBS += xmake$(DTYPE) luajit$(DTYPE) -demo_INC_DIRS += ../ ../luajit/src -demo_LIB_DIRS += ../xmake ../luajit +demo_LIBS += xmake$(DTYPE) luajit$(DTYPE) sv$(DTYPE) +demo_INC_DIRS += ../ ../luajit/src ../sv/include +demo_LIB_DIRS += ../xmake ../luajit ../sv demo_CXFLAGS += -D__tb_prefix__=\"xmake\" # suffix diff --git a/core/src/demo/xmake.lua b/core/src/demo/xmake.lua index 40d089f7f..520241669 100644 --- a/core/src/demo/xmake.lua +++ b/core/src/demo/xmake.lua @@ -2,7 +2,7 @@ target("demo") -- add deps - add_deps("xmake") + add_deps("sv", "luajit", "xmake") -- make as a binary set_kind("binary") @@ -19,10 +19,6 @@ target("demo") -- add includes directory add_includedirs("$(projectdir)", "$(projectdir)/src", "$(buildir)/luajit") - -- add links and directory - add_links("xmake", "luajit") - add_linkdirs("$(buildir)") - -- link readline if not is_plat("windows") then add_links("readline") @@ -33,9 +29,14 @@ target("demo") -- add the common source files add_files("**.c") + + -- for macosx + if is_plat("macosx") then + add_ldflags("-all_load", "-pagezero_size 10000", "-image_base 100000000") + end -- add the resource files (it will be enabled after publishing new version) if is_plat("windows") then add_files("*.rc") end - + diff --git a/core/src/makefile b/core/src/makefile index 139d4ac64..6636d2ad6 100644 --- a/core/src/makefile +++ b/core/src/makefile @@ -3,7 +3,7 @@ include $(PRO_DIR)/prefix.mak # projects SUB_PROS += demo -DEP_PROS += luajit xmake +DEP_PROS += sv luajit xmake # suffix include $(PRO_DIR)/suffix.mak diff --git a/core/src/sv/.gitignore b/core/src/sv/.gitignore new file mode 100644 index 000000000..51272dc42 --- /dev/null +++ b/core/src/sv/.gitignore @@ -0,0 +1,149 @@ +# Created by .ignore support plugin (hsz.mobi) +### Autotools template +# http://www.gnu.org/software/automake + +Makefile.in +/ar-lib +/mdate-sh +/py-compile +/test-driver +/ylwrap + +# http://www.gnu.org/software/autoconf + +/autom4te.cache +/autoscan.log +/autoscan-*.log +/aclocal.m4 +/compile +/config.guess +/config.h.in +/config.sub +/configure +/configure.scan +/depcomp +/install-sh +/missing +/stamp-h1 + +# https://www.gnu.org/software/libtool/ + +/ltmain.sh + +# http://www.gnu.org/software/texinfo + +/texinfo.tex +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +modules.order +Module.symvers +Mkfile.old +dkms.conf +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Clion +.idea/ +cmake-build-debug/ + +# xmake +.xmake/ +build/ diff --git a/core/src/sv/.travis.yml b/core/src/sv/.travis.yml new file mode 100644 index 000000000..505409db5 --- /dev/null +++ b/core/src/sv/.travis.yml @@ -0,0 +1,107 @@ +sudo: false +language: c + +before_install: + - bash <(curl -s https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh) + +install: + - xmake + - cd build + - cmake .. + - make all + +script: + - ctest --verbose + - cd .. && xmake check + +matrix: + include: + - os: linux + - os: linux + compiler: gcc-4.9 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - os: linux + compiler: gcc-5 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-5 + - os: linux + compiler: gcc-6 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-6 + - os: linux + compiler: clang-3.5 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.5 + packages: + - clang-3.5 + - os: linux + compiler: clang-3.6 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.6 + packages: + - clang-3.6 + - os: linux + compiler: clang-3.7 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.7 + packages: + - clang-3.7 + - os: linux + compiler: clang-3.8 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.8 + packages: + - clang-3.8 + - os: linux + compiler: clang-3.9 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.9 + packages: + - clang-3.9 + - os: linux + dist: trusty + compiler: clang-4.0 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-4.0 + packages: + - clang-4.0 + - os: osx + osx_image: xcode6.4 + compiler: clang + - os: osx + osx_image: xcode7.3 + compiler: clang + - os: osx + osx_image: xcode8.3 + compiler: clang diff --git a/core/src/sv/CMakeLists.txt b/core/src/sv/CMakeLists.txt new file mode 100644 index 000000000..9a08b2b1c --- /dev/null +++ b/core/src/sv/CMakeLists.txt @@ -0,0 +1,93 @@ +cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR) +project(sv) + +option(SHARED "Build as shared library" OFF) +option(COVERAGE "Turn on COVERAGE support" OFF) + +if (COVERAGE AND NOT MSVC) + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} --coverage") +endif() + +if(CMAKE_VERSION VERSION_LESS "3.1") + if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + set(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}") + endif() +else() + set(CMAKE_C_STANDARD 99) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") +if(MSVC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3") +else() + if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g3 -DDEBUG") + else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra -Werror -fomit-frame-pointer") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unused-function") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable -Wno-unused-value -Wno-unused-result") +endif() + +set(sv_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/include) +set(sv_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/src) +set(sv_TEST_DIR ${CMAKE_CURRENT_LIST_DIR}/test) + +file(GLOB sv_HEADERS ${sv_HEADERS} ${sv_INCLUDE_DIR}/*.h) +file(GLOB sv_SOURCES ${sv_SOURCES} ${sv_SOURCE_DIR}/*.c) + +include_directories(${sv_INCLUDE_DIR}) +if(SHARED) + if(MSVC) + set(CMAKE_FLAGS + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE + ) + foreach(CMAKE_FLAG ${CMAKE_FLAGS}) + string(REPLACE "/MD" "/MT" ${CMAKE_FLAG} "${${CMAKE_FLAG}}") + string(REPLACE "/MDd" "/MTd" ${CMAKE_FLAG} "${${CMAKE_FLAG}}") + endforeach() + endif() + + add_library(${PROJECT_NAME} SHARED ${sv_SOURCES} ${sv_HEADERS}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSV_BUILD_DYNAMIC_LINK=1") +else() + add_library(${PROJECT_NAME} STATIC ${sv_SOURCES} ${sv_HEADERS}) +endif() +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSV_COMPILE=1") + +enable_testing() +add_subdirectory(${sv_TEST_DIR}) + +if(WIN32) + set(CPACK_GENERATOR "WIX") + set(CPACK_SOURCE_GENERATOR "ZIP") +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CPACK_GENERATOR "PackageMake") +else() + set(CPACK_GENERATOR "DEB;RPM") + set(CPACK_SOURCE_GENERATOR "TGZ") +endif() + +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Lucas Abel") + +set(CPACK_PACKAGE_VERSION "1.0.0") +set(CPACK_PACKAGE_VERSION_MAJOR "1") +set(CPACK_PACKAGE_VERSION_MINOR "0") +set(CPACK_PACKAGE_VERSION_PATCH "0") + +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/UNLICENSE") +set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") +set(CPACK_RESOURCE_FILE_WELCOME "${CMAKE_SOURCE_DIR}/README.md") + +set(CPACK_SOURCE_IGNORE_FILES "${CMAKE_SOURCE_DIR}/build/;${CMAKE_SOURCE_DIR}/.git/") + +set(CPACK_SYSTEM_NAME "") + +include(CPack) diff --git a/core/src/sv/INSTALL b/core/src/sv/INSTALL new file mode 100644 index 000000000..64c69372e --- /dev/null +++ b/core/src/sv/INSTALL @@ -0,0 +1,364 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `<wchar.h>' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. diff --git a/core/src/sv/LICENSE b/core/src/sv/LICENSE new file mode 100644 index 000000000..cf1ab25da --- /dev/null +++ b/core/src/sv/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org> diff --git a/core/src/sv/Makefile.am b/core/src/sv/Makefile.am new file mode 100644 index 000000000..a53382d22 --- /dev/null +++ b/core/src/sv/Makefile.am @@ -0,0 +1,105 @@ +## Process this file with automake to produce Makefile.in + +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = foreign +dist_doc_DATA = UNLICENSE README.md +AM_CFLAGS = -I$(srcdir)/src -I$(srcdir)/include -Wall $(AX_CFLAGS) + +## -------------------------------------------------------------------- + +EXTRA_DIST = scripts/libsv.pc.in +pkgconfigdir = $(libdir)/pkgconfig +nodist_pkgconfig_DATA = scripts/libsv.pc + +## -------------------------------------------------------------------- + +# Commented out because at present there is no Texinfo documentation +# included. It will come later. (Marco Maggi; May 17, 2017) +# +# AM_MAKEINFOFLAGS = --no-split +# info_TEXINFOS = doc/semver.texi +# doc_semver_TEXINFOS = doc/macros.texi + +#page +#### libraries + +libsv_CURRENT = @libsv_VERSION_INTERFACE_CURRENT@ +libsv_REVISION = @libsv_VERSION_INTERFACE_REVISION@ +libsv_AGE = @libsv_VERSION_INTERFACE_AGE@ + +include_HEADERS = include/semver.h + +lib_LTLIBRARIES = libsv.la +libsv_la_LDFLAGS = -version-info $(libsv_CURRENT):$(libsv_REVISION):$(libsv_AGE) +libsv_la_SOURCES = \ + src/comp.c \ + src/id.c \ + src/num.c \ + src/range.c \ + src/semvers.c \ + src/version.c \ + src/utils.c + +#page +#### test + +check_PROGRAMS = \ + test/version \ + test/comp \ + test/match \ + test/range \ + test/semvers \ + test/utils \ + test/usage + +TESTS = $(check_PROGRAMS) + +libsv_test_cppflags = -I$(srcdir)/src -I$(srcdir)/include +libsv_test_ldadd = libsv.la + +test_version_CPPFLAGS = $(libsv_test_cppflags) +test_version_LDADD = $(libsv_test_ldadd) + +test_comp_CPPFLAGS = $(libsv_test_cppflags) +test_comp_LDADD = $(libsv_test_ldadd) + +test_match_CPPFLAGS = $(libsv_test_cppflags) +test_match_LDADD = $(libsv_test_ldadd) + +test_range_CPPFLAGS = $(libsv_test_cppflags) +test_range_LDADD = $(libsv_test_ldadd) + +test_semvers_CPPFLAGS = $(libsv_test_cppflags) +test_semvers_LDADD = $(libsv_test_ldadd) + +test_utils_CPPFLAGS = $(libsv_test_cppflags) +test_utils_LDADD = $(libsv_test_ldadd) + +test_usage_CPPFLAGS = $(libsv_test_cppflags) +test_usage_LDADD = $(libsv_test_ldadd) + +installcheck-local: $(TEST) + @for f in $(TEST); do $(builddir)/$$f; done + +#page +#### Static analysis with Clang's Static Analyzer +# +# See the documentation for the command line tool at: +# +# <http://clang-analyzer.llvm.org/scan-build.html> +# +# To run the tool we must do: +# +# $ make clean +# $ make clang-static-analysis +# +# The program "scan-build" works by overriding the CC and CXX +# environment variables. +# + +.PHONY: clang-static-analysis + +clang-static-analysis: + scan-build make + +### end of file diff --git a/core/src/sv/README.md b/core/src/sv/README.md new file mode 100644 index 000000000..e55d9718d --- /dev/null +++ b/core/src/sv/README.md @@ -0,0 +1,330 @@ +# libsv +libsv - Public domain semantic versioning in c + +[](https://travis-ci.org/uael/sv) +[](https://ci.appveyor.com/project/uael/sv) +[](https://codecov.io/gh/uael/sv) +[](https://www.codacy.com/app/lucas.abel/sv?utm_source=github.com&utm_medium=referral&utm_content=uael/sv&utm_campaign=Badge_Grade) + +# Topics +- [Introduction](#introduction) +- [License](#license) +- [Install](#install) + - [xmake](#xmake) + - [cmake](#cmake) + - [autotools](#autotools) +- [Usage](#usage) +- [Credits](#credits) +- [Bugs, vulnerabilities and contributions](#bugs-vulnerabilities-and-contributions) +- [Resources](#resources) +- [Badges and static analysis](#badges-and-static-analysis) + - [Travis CI](#travis-ci) + - [Clang's Static Analyzer](#clangs-static-analyzer) + +## Introduction + +This is free and unencumbered software released into the public domain. +This package installs a C language library implementing semantic versioning for the C language. + +## License + +See the [UNLICENSE](https://github.com/uael/sv/blob/master/UNLICENSE) file. + +## Install + +### xmake + +[Install xmake build system (A make-like build utility based on Lua)](http://xmake.io) + +```bash +$ xmake +$ xmake check +$ xmake install +``` + +### cmake + +```bash +$ mkdir build && cd build +$ cmake .. +$ make +$ make test +$ make install +``` + +### autotools + +To install from a proper release tarball, do this: +```bash +$ cd libsv-3.1 +$ mkdir build +$ cd build +$ ../configure +$ make +$ make check +$ make install +``` +to inspect the available configuration options: +```bash +$ ../configure --help +``` +The Makefile is designed to allow parallel builds, so we can do: +```bash +$ make -j4 all && make -j4 check +``` +which, on a 4-core CPU, should speed up building and checking significantly. +The Makefile supports the DESTDIR environment variable to install files in a temporary location, example: to see what will happen: +```bash +$ make -n install DESTDIR=/tmp/libsv +``` +to really do it: +```bash +$ make install DESTDIR=/tmp/libsv +``` +After the installation it is possible to verify the installed library against the test suite with: +```bash +$ make installcheck +``` +From a repository checkout or snapshot (the ones from the Github site): we must install the GNU Autotools (GNU Automake, GNU Autoconf, GNU Libtool), then we must first run the script "autogen.sh" from the top source directory, to generate the needed files: +```bash +$ cd libsv +$ sh autogen.sh +``` +notice that "autogen.sh" will run the programs "autoreconf" and "libtoolize"; the latter is selected through the environment variable "LIBTOOLIZE", whose value can be customised; for example to run "glibtoolize" rather than "libtoolize" we do: +```bash +$ LIBTOOLIZE=glibtoolize sh autogen.sh +``` +After this the procedure is the same as the one for building from a proper release tarball, but we have to enable maintainer mode: +```bash +$ ../configure --enable-maintainer-mode [options] +$ make +$ make check +$ make install +``` + +## Usage + +```c +... +semver_t semver = {0}; + +semver(&semver, "v1.2.3-alpha.1"); + +assert(1 == semver.major); +assert(2 == semver.minor); +assert(3 == semver.patch); +assert(0 == memcmp("alpha", semver.prerelease.raw, sizeof("alpha")-1)); +assert(0 == memcmp("1", semver.prerelease.next->raw, sizeof("1")-1)); +assert(true == semver_rmatch(semver, "1.2.1 || >=1.2.3-alpha <1.2.5")); + +semver_dtor(&semver); +... +``` + +### Versions + +A "version" is described by the `v2.0.0` specification found at +<http://semver.org/>. + +A leading `"v"` character is stripped off and ignored. + +### Ranges + +A `version range` is a set of `comparators` which specify versions +that satisfy the range. + +A `comparator` is composed of an `operator` and a `version`. The set +of primitive `operators` is: + +* `<` Less than +* `<=` Less than or equal to +* `>` Greater than +* `>=` Greater than or equal to +* `=` Equal. If no operator is specified, then equality is assumed, + so this operator is optional, but MAY be included. + +For example, the comparator `>=1.2.7` would match the versions +`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6` +or `1.1.0`. + +Comparators can be joined by whitespace to form a `comparator set`, +which is satisfied by the **intersection** of all of the comparators +it includes. + +A range is composed of one or more comparator sets, joined by `||`. A +version matches a range if and only if every comparator in at least +one of the `||`-separated comparator sets is satisfied by the version. + +For example, the range `>=1.2.7 <1.3.0` would match the versions +`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`, +or `1.1.0`. + +The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`, +`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`. + +#### Prerelease Tags + +If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then +it will only be allowed to satisfy comparator sets if at least one +comparator with the same `[major, minor, patch]` tuple also has a +prerelease tag. + +For example, the range `>1.2.3-alpha.3` would be allowed to match the +version `1.2.3-alpha.7`, but it would *not* be satisfied by +`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater +than" `1.2.3-alpha.3` according to the SemVer sort rules. The version +range only accepts prerelease tags on the `1.2.3` version. The +version `3.4.5` *would* satisfy the range, because it does not have a +prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`. + +The purpose for this behavior is twofold. First, prerelease versions +frequently are updated very quickly, and contain many breaking changes +that are (by the author's design) not yet fit for public consumption. +Therefore, by default, they are excluded from range matching +semantics. + +Second, a user who has opted into using a prerelease version has +clearly indicated the intent to use *that specific* set of +alpha/beta/rc versions. By including a prerelease tag in the range, +the user is indicating that they are aware of the risk. However, it +is still not appropriate to assume that they have opted into taking a +similar risk on the *next* set of prerelease versions. + +#### Advanced Range Syntax + +Advanced range syntax desugars to primitive comparators in +deterministic ways. + +Advanced ranges may be combined in the same way as primitive +comparators using white space or `||`. + +##### Hyphen Ranges `X.Y.Z - A.B.C` + +Specifies an inclusive set. + +* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` + +If a partial version is provided as the first version in the inclusive +range, then the missing pieces are replaced with zeroes. + +* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4` + +If a partial version is provided as the second version in the +inclusive range, then all versions that start with the supplied parts +of the tuple are accepted, but nothing that would be greater than the +provided tuple parts. + +* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0` +* `1.2.3 - 2` := `>=1.2.3 <3.0.0` + +##### X-Ranges `1.2.x` `1.X` `1.2.*` `*` + +Any of `X`, `x`, or `*` may be used to "stand in" for one of the +numeric values in the `[major, minor, patch]` tuple. + +* `*` := `>=0.0.0` (Any version satisfies) +* `1.x` := `>=1.0.0 <2.0.0` (Matching major version) +* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions) + +A partial version range is treated as an X-Range, so the special +character is in fact optional. + +* `""` (empty string) := `*` := `>=0.0.0` +* `1` := `1.x.x` := `>=1.0.0 <2.0.0` +* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0` + +##### Tilde Ranges `~1.2.3` `~1.2` `~1` + +Allows patch-level changes if a minor version is specified on the +comparator. Allows minor-level changes if not. + +* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0` +* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`) +* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`) +* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0` +* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`) +* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`) +* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. + +#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4` + +Allows changes that do not modify the left-most non-zero digit in the +`[major, minor, patch]` tuple. In other words, this allows patch and +minor updates for versions `1.0.0` and above, patch updates for +versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`. + +Many authors treat a `0.x` version as if the `x` were the major +"breaking-change" indicator. + +Caret ranges are ideal when an author may make breaking changes +between `0.2.4` and `0.3.0` releases, which is a common practice. +However, it presumes that there will *not* be breaking changes between +`0.2.4` and `0.2.5`. It allows for changes that are presumed to be +additive (but non-breaking), according to commonly observed practices. + +* `^1.2.3` := `>=1.2.3 <2.0.0` +* `^0.2.3` := `>=0.2.3 <0.3.0` +* `^0.0.3` := `>=0.0.3 <0.0.4` +* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. +* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the + `0.0.3` version *only* will be allowed, if they are greater than or + equal to `beta`. So, `0.0.3-pr.2` would be allowed. + +When parsing caret ranges, a missing `patch` value desugars to the +number `0`, but will allow flexibility within that value, even if the +major and minor versions are both `0`. + +* `^1.2.x` := `>=1.2.0 <2.0.0` +* `^0.0.x` := `>=0.0.0 <0.1.0` +* `^0.0` := `>=0.0.0 <0.1.0` + +A missing `minor` and `patch` values will desugar to zero, but also +allow flexibility within those values, even if the major version is +zero. + +* `^1.x` := `>=1.0.0 <2.0.0` +* `^0.x` := `>=0.0.0 <1.0.0` + +## Credits + +The stuff was written by Lucas Abel <https://github.com/uael> and contributors +- Marco Maggi <https://github.com/marcomaggi> + +## Bugs, vulnerabilities and contributions + +Bug and vulnerability reports are appreciated, all the vulnerability reports are public; register them using the Issue Tracker at the project's Github site. For contributions and patches please use the Pull Requests feature at the project's Github site. + +Reports about the original code must be registered at: +<https://github.com/uael/sv/issues> + +## Resources + +Development of the original projects takes place at: +<https://github.com/uael/sv/> + +the GNU Project software can be found here: +<https://www.gnu.org/> + +## Badges and static analysis + +### Travis CI + +Travis CI is a hosted, distributed continuous integration service used to build and test software projects hosted at GitHub. We can find this project's dashboards at: +<https://travis-ci.org/uael/sv> + +Usage of this service is configured through the file ".travis.yml". + +### Clang's Static Analyzer + +The Clang Static Analyzer is a source code analysis tool that finds bugs in C, C++, and Objective-C programs. It is distributed along with Clang and we can find it at: +<http://clang-analyzer.llvm.org/> + +Usage of this service is implemented with make rules; see the relevant section in the file "Makefile.am". diff --git a/core/src/sv/UNLICENSE b/core/src/sv/UNLICENSE new file mode 100644 index 000000000..cf1ab25da --- /dev/null +++ b/core/src/sv/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org> diff --git a/core/src/sv/appveyor.yml b/core/src/sv/appveyor.yml new file mode 100644 index 000000000..fb1c88bd9 --- /dev/null +++ b/core/src/sv/appveyor.yml @@ -0,0 +1,40 @@ +version: "1.0.{build}" + +platform: + - Win32 + - x64 + +environment: + MSVC_DEFAULT_OPTIONS: ON + matrix: + - msvc: 'Visual Studio 12 2013' + - msvc: 'Visual Studio 14 2015' + +configuration: + - Debug + - Release + +init: + - cmd: cmake --version + - cmd: msbuild /version + +clone_folder: C:\projects\sv + +install: + - git submodule update --init --recursive + +before_build: + - cmd: cd C:\projects\sv + - cmd: md build + - cmd: cd build + - cmd: if "%platform%"=="Win32" set CMAKE_GENERATOR_NAME=%msvc% + - cmd: if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%msvc% Win64 + - cmd: cmake -G "%CMAKE_GENERATOR_NAME%" -DCMAKE_BUILD_TYPE=%configuration% .. + +build: + project: C:\projects\sv\build\sv.sln + verbosity: quiet + +test_script: + - ps: cd C:\projects\sv\build + - cmd: ctest -VV diff --git a/core/src/sv/autogen.sh b/core/src/sv/autogen.sh new file mode 100755 index 000000000..586ab6a35 --- /dev/null +++ b/core/src/sv/autogen.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# autogen.sh -- +# +# Run this in the top source directory to rebuild the infrastructure. + +LIBTOOLIZE=${LIBTOOLIZE:=libtoolize} + +set -xe +test -d m4 || mkdir -p m4 +test -f m4/libtool.m4 || "$LIBTOOLIZE" +autoreconf --warnings=all --install --verbose "$@" + +### end of file diff --git a/core/src/sv/codecov.yml b/core/src/sv/codecov.yml new file mode 100644 index 000000000..32f50be1c --- /dev/null +++ b/core/src/sv/codecov.yml @@ -0,0 +1,2 @@ +ignore: + - "test" # ignore test folder and all its contents diff --git a/core/src/sv/configure.ac b/core/src/sv/configure.ac new file mode 100644 index 000000000..c6cbb6f48 --- /dev/null +++ b/core/src/sv/configure.ac @@ -0,0 +1,77 @@ +dnl @configure_input@ +dnl + +AC_PREREQ([2.69]) +AC_INIT([libsv],[0.0.1],,[libsv],[http://github.com/uael/sv]) +AC_COPYRIGHT([This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any means. + +In jurisdictions that recognize copyright laws, the author or authors of +this software dedicate any and all copyright interest in the software to +the public domain. We make this dedication for the benefit of the public +at large and to the detriment of our heirs and successors. We intend +this dedication to be an overt act of relinquishment in perpetuity of +all present and future rights to this software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org> +]) +AC_CONFIG_SRCDIR([src]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([scripts]) +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE([foreign dist-xz no-dist-gzip subdir-objects]) +AM_MAINTAINER_MODE + +AM_PROG_AR +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_MKDIR_P + +LT_PREREQ([2.4]) +LT_INIT + +dnl This is the version stored in the pkg-config data file. +AC_SUBST([LIBSV_PKG_CONFIG_VERSION],[0.0.1]) + +dnl page +#### libraries interface version + +MM_LIBTOOL_LIBRARY_VERSIONS([libsv],1,0,0) + +dnl page +#### basic system inspection + +AC_LANG([C]) +AM_PROG_AS +AC_PROG_CC_C99 +AM_PROG_CC_C_O +AC_HEADER_STDC + +AC_CACHE_SAVE + +dnl page +#### finish + +AC_CONFIG_FILES([Makefile] + [scripts/libsv.pc]) +AC_OUTPUT + +### end of file +# Local Variables: +# mode: autoconf +# page-delimiter: "^dnl page" +# End: diff --git a/core/src/sv/include/semver.h b/core/src/sv/include/semver.h new file mode 100644 index 000000000..bdc005702 --- /dev/null +++ b/core/src/sv/include/semver.h @@ -0,0 +1,228 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#ifndef SV_H__ +# define SV_H__ + +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +#ifndef SV_COMPILE +# define SV_COMPILE (0) +#endif + +#ifndef SV_BUILD_DYNAMIC_LINK +# define SV_BUILD_DYNAMIC_LINK (0) +#endif + +#if SV_BUILD_DYNAMIC_LINK && defined(_MSC_VER) +# define SV_EXPORT_LINK __declspec(dllexport) +# define SV_IMPORT_LINK __declspec(dllimport) +#else +# define SV_EXPORT_LINK +# define SV_IMPORT_LINK +#endif +#if SV_COMPILE +# ifdef __cplusplus +# define SV_API extern "C" SV_EXPORT_LINK +# else +# define SV_API extern SV_EXPORT_LINK +# endif +#else +# ifdef __cplusplus +# define SV_API extern "C" SV_IMPORT_LINK +# else +# define SV_API extern SV_IMPORT_LINK +# endif +#endif + +#ifndef __cplusplus +# if defined(_MSC_VER) && _MSC_VER < 1900 +# define bool unsigned char +# define true 1 +# define false 0 +# define __bool_true_false_are_defined 1 +# else +# include <stdbool.h> +# endif +#endif + +#if defined(_MSC_VER) +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#ifdef _WIN64 +typedef __int64 intptr_t; +typedef unsigned __int64 uintptr_t; +#else +typedef __int32 intptr_t; +typedef unsigned __int32 uintptr_t; +#endif +#else +# include <stdint.h> +#endif + +#ifndef sv_malloc +# define sv_malloc malloc +#endif + +#ifndef sv_free +# define sv_free free +#endif + +#define SEMVER_NUM_X (-1) + +#define semver(self, str) semvern(self, str, strlen(str)) +#define semver_write(self, buffer, len) semver_pwrite(&(self), buffer, len) +#define semver_cmp(self, other) semver_pcmp(&(self), &(other)) +#define semver_comp(self, str) semver_compn(self, str, strlen(str)) +#define semver_comp_write(self, buffer, len) semver_comp_pwrite(&(self), buffer, len) +#define semver_comp_match(self, comp) semver_comp_pmatch(&(self), &(comp)) +#define semver_match(self, comp_str) semver_comp_matchn(&(self), comp_str, strlen(comp_str)) +#define semver_range(self, str) semver_rangen(self, str, strlen(str)) +#define semver_range_write(self, buffer, len) semver_range_pwrite(&(self), buffer, len) +#define semver_range_match(self, range) semver_range_pmatch(&(self), &(range)) +#define semver_rmatch(self, range_str) semver_range_matchn(&(self), range_str, strlen(range_str)) + +typedef struct semver semver_t; +typedef struct semver_id semver_id_t; +typedef struct semver_comp semver_comp_t; +typedef struct semver_range semver_range_t; +typedef struct semvers semvers_t; + +enum semver_op { + SEMVER_OP_EQ = 0, + SEMVER_OP_LT, + SEMVER_OP_LE, + SEMVER_OP_GT, + SEMVER_OP_GE, +}; + +struct semver_id { + bool numeric; + int num; + size_t len; + const char *raw; + struct semver_id *next; +}; + +struct semver { + int major, minor, patch; + semver_id_t prerelease, build; + size_t len; + const char *raw; +}; + +SV_API char semvern(semver_t *self, const char *str, size_t len); +SV_API char semver_tryn(semver_t *self, const char *str, size_t len); +SV_API void semver_dtor(semver_t *self); +SV_API int semver_pwrite(const semver_t *self, char *buffer, size_t len); +SV_API size_t semver_fwrite (const semver_t *self, FILE * stream); +SV_API char semver_pcmp(const semver_t *self, const semver_t *other); +SV_API bool semver_comp_pmatch(const semver_t *self, const semver_comp_t *comp); +SV_API bool semver_comp_matchn(const semver_t *self, const char *comp_str, size_t comp_len); +SV_API bool semver_range_pmatch(const semver_t *self, const semver_range_t *range); +SV_API bool semver_range_matchn(const semver_t *self, const char *range_str, size_t range_len); + +struct semver_comp { + struct semver_comp *next; + enum semver_op op; + semver_t version; +}; + +SV_API char semver_compn(semver_comp_t *self, const char *str, size_t len); +SV_API void semver_comp_dtor(semver_comp_t *self); +SV_API int semver_comp_pwrite(const semver_comp_t *self, char *buffer, size_t len); +SV_API size_t semver_comp_fwrite (const semver_comp_t *self, FILE *stream); +SV_API char semver_and(semver_comp_t *left, const char *str, size_t len); + +struct semver_range { + struct semver_range *next; + semver_comp_t comp; +}; + +SV_API char semver_rangen(semver_range_t *self, const char *str, size_t len); +SV_API void semver_range_dtor(semver_range_t *self); +SV_API int semver_range_pwrite(const semver_range_t *self, char *buffer, size_t len); +SV_API size_t semver_range_fwrite (const semver_range_t *rangep, FILE *stream); +SV_API char semver_or(semver_range_t *left, const char *str, size_t len); + +struct semvers { + uint32_t length, capacity; + semver_t *data; +}; + +SV_API uint32_t semvers_pgrowth(semvers_t *self, int32_t nmin); +SV_API semver_t semvers_perase(semvers_t *self, uint32_t i); +SV_API void semvers_psort(semvers_t *self); +SV_API void semvers_prsort(semvers_t *self); +SV_API void semvers_pdtor(semvers_t *self); +SV_API void semvers_pclear(semvers_t *self); + +#define semvers_dtor(s) \ + semvers_pdtor(&(s)) + +#define semvers_clear(s) \ + semvers_pclear(&(s)) + +#define semvers_growth(s, n) \ + semvers_pgrowth(&(s),n) + +#define semvers_grow(s, n) \ + semvers_pgrowth(&(s),(s).length+(n)) + +#define semvers_resize(s, n) \ + ((s).length=semvers_growth(s, n)) + +#define semvers_erase(s, i) \ + semvers_perase(&(s), i) + +#define semvers_push(s, x) \ + (semvers_grow(s,1),(s).data[(s).length++]=(x)) + +#define semvers_pop(s) \ + (s).data[--(s).length] + +#define semvers_unshift(s, x) \ + (semvers_grow(s,1),memmove((s).data+1,(s).data,(s).length++*sizeof(semver_t)),(s).data[0]=(x)) + +#define semvers_shift(s) \ + semvers_erase(s, 0) + +#define semvers_sort(s) \ + semvers_psort(&(s)) + +#define semvers_rsort(s) \ + semvers_prsort(&(s)) + +#endif /* SV_H__ */ diff --git a/core/src/sv/m4/mm-libtool-library-versions.m4 b/core/src/sv/m4/mm-libtool-library-versions.m4 new file mode 100644 index 000000000..26f4194b0 --- /dev/null +++ b/core/src/sv/m4/mm-libtool-library-versions.m4 @@ -0,0 +1,30 @@ +dnl mm-libtool-library-versions.m4 + +dnl Set version numbers for libraries built with GNU Libtool. +dnl +dnl MM_LIBTOOL_LIBRARY_VERSIONS(stem,current,revision,age) +dnl +AC_DEFUN([MM_LIBTOOL_LIBRARY_VERSIONS], + [$1_VERSION_INTERFACE_CURRENT=$2 + $1_VERSION_INTERFACE_REVISION=$3 + $1_VERSION_INTERFACE_AGE=$4 + AC_DEFINE_UNQUOTED([$1_VERSION_INTERFACE], + [$$1_VERSION_INTERFACE_CURRENT.$$1_VERSION_INTERFACE_REVISION.$$1_VERSION_INTERFACE_AGE], + [current interface number]) + AC_DEFINE_UNQUOTED([$1_VERSION_INTERFACE_CURRENT], + [$$1_VERSION_INTERFACE_CURRENT], + [current interface number]) + AC_DEFINE_UNQUOTED([$1_VERSION_INTERFACE_REVISION], + [$$1_VERSION_INTERFACE_REVISION], + [current interface implementation number]) + AC_DEFINE_UNQUOTED([$1_VERSION_INTERFACE_AGE], + [$$1_VERSION_INTERFACE_AGE], + [current interface age number]) + AC_DEFINE_UNQUOTED([$1_VERSION_INTERFACE_STRING], + ["$$1_VERSION_INTERFACE_CURRENT.$$1_VERSION_INTERFACE_REVISION"], + [library interface version]) + AC_SUBST([$1_VERSION_INTERFACE_CURRENT]) + AC_SUBST([$1_VERSION_INTERFACE_REVISION]) + AC_SUBST([$1_VERSION_INTERFACE_AGE])]) + +dnl end of file diff --git a/core/src/sv/makefile b/core/src/sv/makefile new file mode 100644 index 000000000..b7b8e543e --- /dev/null +++ b/core/src/sv/makefile @@ -0,0 +1,29 @@ +# prefix +include $(PRO_DIR)/prefix.mak + +# module name +NAMES = sv + +# module type +sv_TYPE = LIB + +# config +sv_CONFIG = n + +# core files +sv_C_FILES += \ + src/comp \ + src/id \ + src/num \ + src/range \ + src/semvers \ + src/utils \ + src/version + +# includes +sv_INC_DIRS += include + + +# suffix +include $(PRO_DIR)/suffix.mak + diff --git a/core/src/sv/scripts/libsv.pc.in b/core/src/sv/scripts/libsv.pc.in new file mode 100644 index 000000000..bce3e8982 --- /dev/null +++ b/core/src/sv/scripts/libsv.pc.in @@ -0,0 +1,30 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +bindir=@bindir@ +datarootdir=@datarootdir@ +datadir=@datadir@ +docdir=${prefix}/doc +includedir=@includedir@ +infodir=@infodir@ +htmldir=${docdir} +libdir=@libdir@ +libexecdir=@libexecdir@ +localstatedir=@localstatedir@ +mandir=@mandir@ +sbindir=@sbindir@ +sharedstatedir=@sharedstatedir@ +sysconfdir=@sysconfdir@ + +## ------------------------------------------------------------ + +Name: @PACKAGE_NAME@ +Description: semantic versioning for the C language +Version: @LIBSV_PKG_CONFIG_VERSION@ +Libs: -L${libdir} -lsv +Cflags: -I${includedir} + +### end of file +# Local Variables: +# mode: script +# End: diff --git a/core/src/sv/src/comp.c b/core/src/sv/src/comp.c new file mode 100644 index 000000000..d02fe4dfc --- /dev/null +++ b/core/src/sv/src/comp.c @@ -0,0 +1,382 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include "comp.h" +#include "num.h" +#include "id.h" +#include "utils.h" + +static void semver_xrevert(semver_t *semver) { + if (semver->major == SEMVER_NUM_X) { + semver->major = semver->minor = semver->patch = 0; + } else if (semver->minor == SEMVER_NUM_X) { + semver->minor = semver->patch = 0; + } else if (semver->patch == SEMVER_NUM_X) { + semver->patch = 0; + } +} + +static semver_comp_t *semver_xconvert(semver_comp_t *self) { + if (self->version.major == SEMVER_NUM_X) { + self->op = SEMVER_OP_GE; + semver_xrevert(&self->version); + return self; + } + if (self->version.minor == SEMVER_NUM_X) { + semver_xrevert(&self->version); + self->op = SEMVER_OP_GE; + self->next = (semver_comp_t *) sv_malloc(sizeof(semver_comp_t)); + if (self->next == NULL) { + return NULL; + } + semver_comp_ctor(self->next); + self->next->op = SEMVER_OP_LT; + self->next->version = self->version; + ++self->next->version.major; + return self->next; + } + if (self->version.patch == SEMVER_NUM_X) { + semver_xrevert(&self->version); + self->op = SEMVER_OP_GE; + self->next = (semver_comp_t *) sv_malloc(sizeof(semver_comp_t)); + if (self->next == NULL) { + return NULL; + } + semver_comp_ctor(self->next); + self->next->op = SEMVER_OP_LT; + self->next->version = self->version; + ++self->next->version.minor; + return self->next; + } + self->op = SEMVER_OP_EQ; + return self; +} + +static char parse_partial(semver_t *self, const char *str, size_t len, size_t *offset) { + semver_ctor(self); + self->major = self->minor = self->patch = SEMVER_NUM_X; + if (*offset < len) { + self->raw = str + *offset; + if (semver_num_read(&self->major, str, len, offset)) { + return 0; + } + if (*offset >= len || str[*offset] != '.') { + return 0; + } + ++*offset; + if (semver_num_read(&self->minor, str, len, offset)) { + return 1; + } + if (*offset >= len || str[*offset] != '.') { + return 0; + } + ++*offset; + if (semver_num_read(&self->patch, str, len, offset)) { + return 1; + } + if ((str[*offset] == '-' && semver_id_read(&self->prerelease, str, len, (++*offset, offset))) + || (str[*offset] == '+' && semver_id_read(&self->build, str, len, (++*offset, offset)))) { + return 1; + } + self->len = str + *offset - self->raw; + return 0; + } + return 0; +} + +static char parse_hiphen(semver_comp_t *self, const char *str, size_t len, size_t *offset) { + semver_t partial; + + if (parse_partial(&partial, str, len, offset)) { + return 1; + } + self->op = SEMVER_OP_GE; + semver_xrevert(&self->version); + self->next = (semver_comp_t *) sv_malloc(sizeof(semver_comp_t)); + if (self->next == NULL) { + return 1; + } + semver_comp_ctor(self->next); + self->next->op = SEMVER_OP_LT; + if (partial.minor == SEMVER_NUM_X) { + self->next->version.major = partial.major + 1; + } else if (partial.patch == SEMVER_NUM_X) { + self->next->version.major = partial.major; + self->next->version.minor = partial.minor + 1; + } else { + self->next->op = SEMVER_OP_LE; + self->next->version = partial; + } + + return 0; +} + +static char parse_tidle(semver_comp_t *self, const char *str, size_t len, size_t *offset) { + semver_t partial; + + if (parse_partial(&self->version, str, len, offset)) { + return 1; + } + semver_xrevert(&self->version); + self->op = SEMVER_OP_GE; + partial = self->version; + if (partial.major != 0) { + ++partial.major; + partial.minor = partial.patch = 0; + } else if (partial.minor != 0) { + ++partial.minor; + partial.patch = 0; + } else { + ++partial.patch; + } + self->next = (semver_comp_t *) sv_malloc(sizeof(semver_comp_t)); + if (self->next == NULL) { + return 1; + } + semver_comp_ctor(self->next); + self->next->op = SEMVER_OP_LT; + self->next->version = partial; + return 0; +} + +static char parse_caret(semver_comp_t *self, const char *str, size_t len, size_t *offset) { + semver_t partial; + + if (parse_partial(&self->version, str, len, offset)) { + return 1; + } + semver_xrevert(&self->version); + self->op = SEMVER_OP_GE; + partial = self->version; + if (partial.minor || partial.patch) { + ++partial.minor; + partial.patch = 0; + } else { + ++partial.major; + partial.minor = partial.patch = 0; + } + self->next = (semver_comp_t *) sv_malloc(sizeof(semver_comp_t)); + if (self->next == NULL) { + return 1; + } + semver_comp_ctor(self->next); + self->next->op = SEMVER_OP_LT; + self->next->version = partial; + return 0; +} + +void semver_comp_ctor(semver_comp_t *self) { +#ifndef _MSC_VER + *self = (semver_comp_t) {0}; +#else + self->next = NULL; + self->op = SEMVER_OP_EQ; + semver_ctor(&self->version); +#endif +} + +void semver_comp_dtor(semver_comp_t *self) { + if (self && self->next) { + semver_comp_dtor(self->next); + free(self->next); + self->next = NULL; + } +} + +char semver_compn(semver_comp_t *self, const char *str, size_t len) { + size_t offset = 0; + + if (len > SV_COMP_MAX_LEN) { + return 1; + } + if (semver_comp_read(self, str, len, &offset) || offset < len) { + semver_comp_dtor(self); + return 1; + } + return 0; +} + +char semver_comp_read(semver_comp_t *self, const char *str, size_t len, size_t *offset) { + semver_comp_ctor(self); + while (*offset < len) { + switch (str[*offset]) { + case '^': + ++*offset; + if (parse_tidle(self, str, len, offset)) { + return 1; + } + self = self->next; + goto next; + case '~': + ++*offset; + if (parse_caret(self, str, len, offset)) { + return 1; + } + self = self->next; + goto next; + case '>': + ++*offset; + if (*offset < len && str[*offset] == '=') { + ++*offset; + self->op = SEMVER_OP_GE; + } else { + self->op = SEMVER_OP_GT; + } + if (parse_partial(&self->version, str, len, offset)) { + return 1; + } + semver_xrevert(&self->version); + goto next; + case '<': + ++*offset; + if (*offset < len && str[*offset] == '=') { + ++*offset; + self->op = SEMVER_OP_LE; + } else { + self->op = SEMVER_OP_LT; + } + if (parse_partial(&self->version, str, len, offset)) { + return 1; + } + semver_xrevert(&self->version); + goto next; + case '=': + ++*offset; + self->op = SEMVER_OP_EQ; + if (parse_partial(&self->version, str, len, offset)) { + return 1; + } + semver_xrevert(&self->version); + goto next; + default: + goto range; + } + } + range: + if (parse_partial(&self->version, str, len, offset)) { + return 1; + } + if (*offset < len && str[*offset] == ' ' + && *offset + 1 < len && str[*offset + 1] == '-' + && *offset + 2 < len && str[*offset + 2] == ' ') { + *offset += 3; + if (parse_hiphen(self, str, len, offset)) { + return 1; + } + self = self->next; + } else { + self = semver_xconvert(self); + if (self == NULL) { + return 1; + } + } + next: + if (*offset < len && str[*offset] == ' ' + && *offset < len + 1 && str[*offset + 1] != ' ' && str[*offset + 1] != '|') { + ++*offset; + if (*offset < len) { + self->next = (semver_comp_t *) sv_malloc(sizeof(semver_comp_t)); + if (self->next == NULL) { + return 1; + } + return semver_comp_read(self->next, str, len, offset); + } + return 1; + } + return 0; +} + +char semver_and(semver_comp_t *left, const char *str, size_t len) { + semver_comp_t *comp, *tail; + + if (len > 0) { + comp = (semver_comp_t *) sv_malloc(sizeof(semver_comp_t)); + if (NULL == comp) { + return 1; + } + if (semver_compn(comp, str, len)) { + sv_free(comp); + return 1; + } + if (NULL == left->next) { + left->next = comp; + } else { + tail = left->next; + while (tail->next) tail = tail->next; + tail->next = comp; + } + return 0; + } + return 1; +} + +bool semver_comp_pmatch(const semver_t *self, const semver_comp_t *comp) { + char result = semver_pcmp(self, &comp->version); + + if (result < 0 && comp->op != SEMVER_OP_LT && comp->op != SEMVER_OP_LE) { + return false; + } + if (result > 0 && comp->op != SEMVER_OP_GT && comp->op != SEMVER_OP_GE) { + return false; + } + if (result == 0 && comp->op != SEMVER_OP_EQ && comp->op != SEMVER_OP_LE && comp->op != SEMVER_OP_GE) { + return false; + } + if (comp->next) { + return semver_comp_pmatch(self, comp->next); + } + return true; +} + +bool semver_comp_matchn(const semver_t *self, const char *comp_str, size_t comp_len) { + semver_comp_t comp; + bool result; + + if (semver_compn(&comp, comp_str, comp_len)) { + return false; + } + result = semver_comp_pmatch(self, &comp); + semver_comp_dtor(&comp); + return result; +} + +int semver_comp_pwrite(const semver_comp_t *self, char *buffer, size_t len) { + char semver[SV_COMP_MAX_LEN]; + + semver_write(self->version, semver, SV_COMP_MAX_LEN); + if (self->next) { + char next[SV_COMP_MAX_LEN]; + return snprintf(buffer, len, "%s%s %.*s", + semver_op_string(self->op), semver, semver_comp_pwrite(self->next, next, SV_COMP_MAX_LEN), next + ); + } + return snprintf(buffer, len, "%s%s", semver_op_string(self->op), semver); +} diff --git a/core/src/sv/src/comp.h b/core/src/sv/src/comp.h new file mode 100644 index 000000000..9130ee987 --- /dev/null +++ b/core/src/sv/src/comp.h @@ -0,0 +1,38 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#ifndef SV_COMP_H__ +# define SV_COMP_H__ + +#include "version.h" + +#define SV_COMP_MAX_LEN (512) + +void semver_comp_ctor(semver_comp_t *self); +char semver_comp_read(semver_comp_t *self, const char *str, size_t len, size_t *offset); + +#endif /* SV_COMP_H__ */ diff --git a/core/src/sv/src/id.c b/core/src/sv/src/id.c new file mode 100644 index 000000000..9341eb02c --- /dev/null +++ b/core/src/sv/src/id.c @@ -0,0 +1,141 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <stdio.h> + +#include "id.h" + +void semver_id_ctor(semver_id_t *self) { +#ifndef _MSC_VER + *self = (semver_id_t) {true}; +#else + self->next = NULL; + self->len = 0; + self->raw = NULL; + self->num = 0; + self->numeric = true; +#endif +} + +void semver_id_dtor(semver_id_t *self) { + if (self && self->next) { + semver_id_dtor(self->next); + sv_free(self->next); + self->next = NULL; + } +} + +char semver_id_read(semver_id_t *self, const char *str, size_t len, size_t *offset) { + size_t i = 0; + char is_zero = 0; + + semver_id_ctor(self); + while (*offset < len) { + if (isalnum(str[*offset]) || str[*offset] == '-') { + if (!isdigit(str[*offset])) { + is_zero = 0; + self->numeric = false; + } else { + if (i == 0) { + is_zero = str[*offset] == '0'; + } else if (is_zero) { + return 1; + } + } + ++i, ++*offset; + continue; + } + break; + } + if (!i) { + return 1; + } + self->raw = str + *offset - i; + self->len = i; + if (!is_zero && self->numeric) { + self->num = (int) strtol(self->raw, NULL, 0); + } + if (str[*offset] == '.') { + self->next = (semver_id_t *) sv_malloc(sizeof(semver_id_t)); + if (self->next == NULL) { + return 1; + } + ++*offset; + return semver_id_read(self->next, str, len, offset); + } + return 0; +} + +char semver_id_pcmp(const semver_id_t *self, const semver_id_t *other) { + char s; + + if (self->len && !other->len) { + return -1; + } + if (!self->len && other->len) { + return 1; + } + if (!self->len) { + return 0; + } + + if (self->numeric && other->numeric) { + if (self->num > other->num) { + return 1; + } + if (self->num < other->num) { + return -1; + } + } else if ((s = (char) memcmp(self->raw, other->raw, self->len > other->len ? self->len : other->len)) != 0) { + return s; + } + + if (!self->next && other->next) { + return -1; + } + if (self->next && !other->next) { + return 1; + } + if (!self->next) { + return 0; + } + + return semver_id_pcmp(self->next, other->next); +} + +int semver_id_pwrite(const semver_id_t *self, char *buffer, size_t len) { + if (self->next) { + char next[SV_MAX_LEN]; + return snprintf(buffer, len, "%.*s.%.*s", + (int) self->len, self->raw, semver_id_pwrite(self->next, next, SV_MAX_LEN), next + ); + } + return snprintf(buffer, len, "%.*s", (int) self->len, self->raw); +} diff --git a/core/src/sv/src/id.h b/core/src/sv/src/id.h new file mode 100644 index 000000000..914b4c237 --- /dev/null +++ b/core/src/sv/src/id.h @@ -0,0 +1,42 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#ifndef SV_ID_H__ +# define SV_ID_H__ + +#include "version.h" + +void semver_id_ctor(semver_id_t *self); +void semver_id_dtor(semver_id_t *self); +char semver_id_read(semver_id_t *self, const char *str, size_t len, size_t *offset); +int semver_id_pwrite(const semver_id_t *self, char *buffer, size_t len); +char semver_id_pcmp(const semver_id_t *self, const semver_id_t *other); + +#define semver_id_write(self, buffer, len) semver_id_pwrite(&(self), buffer, len) +#define semver_id_comp(self, other) semver_id_pcmp(&(self), &(other)) + +#endif /* SV_ID_H__ */ diff --git a/core/src/sv/src/num.c b/core/src/sv/src/num.c new file mode 100644 index 000000000..34410cbfa --- /dev/null +++ b/core/src/sv/src/num.c @@ -0,0 +1,75 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "num.h" + +char semver_num_read(int *self, const char *str, size_t len, size_t *offset) { + char *endptr; + + *self = 0; + if (*offset >= len) { + return 1; + } + switch (str[*offset]) { + case 'x': + case 'X': + case '*': + *self = SEMVER_NUM_X; + ++*offset; + break; + case '0': + ++*offset; + if (*offset < len && isdigit(str[*offset])) { + return 1; + } + *self = 0; + break; + default: + if (isdigit(str[*offset])) { + *self = (int) strtol(str + *offset, &endptr, 0); + *offset += endptr - str - *offset; + } else { + return 1; + } + break; + } + return 0; +} + +char semver_num_cmp(int self, int other) { + if (self > other) { + return 1; + } + if (self < other) { + return -1; + } + return 0; +} diff --git a/core/src/sv/src/num.h b/core/src/sv/src/num.h new file mode 100644 index 000000000..12c4b694c --- /dev/null +++ b/core/src/sv/src/num.h @@ -0,0 +1,36 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#ifndef SV_NUM_H__ +# define SV_NUM_H__ + +#include "version.h" + +char semver_num_read(int *self, const char *str, size_t len, size_t *offset); +char semver_num_cmp(int self, int other); + +#endif /* SV_NUM_H__ */ diff --git a/core/src/sv/src/range.c b/core/src/sv/src/range.c new file mode 100644 index 000000000..c23a9ae81 --- /dev/null +++ b/core/src/sv/src/range.c @@ -0,0 +1,135 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include "range.h" +#include "comp.h" + +void semver_range_ctor(semver_range_t *self) { +#ifndef _MSC_VER + *self = (semver_range_t) {0}; +#else + self->next = NULL; + semver_comp_ctor(&self->comp); +#endif +} + +void semver_range_dtor(semver_range_t *self) { + if (self && self->next) { + semver_range_dtor(self->next); + sv_free(self->next); + self->next = NULL; + } +} + +char semver_rangen(semver_range_t *self, const char *str, size_t len) { + size_t offset = 0; + + if (len > SV_RANGE_MAX_LEN) { + return 1; + } + if (semver_range_read(self, str, len, &offset) || offset < len) { + semver_range_dtor(self); + return 1; + } + return 0; +} + +char semver_range_read(semver_range_t *self, const char *str, size_t len, size_t *offset) { + semver_range_ctor(self); + if (semver_comp_read(&self->comp, str, len, offset)) { + return 1; + } + while (*offset < len && str[*offset] == ' ') ++*offset; + if (*offset < len && str[*offset] == '|' + && *offset + 1 < len && str[*offset + 1] == '|') { + *offset += 2; + while (*offset < len && str[*offset] == ' ') ++*offset; + self->next = (semver_range_t *) sv_malloc(sizeof(semver_range_t)); + if (self->next == NULL) { + return 1; + } + return semver_range_read(self->next, str, len, offset); + } + return 0; +} + +char semver_or(semver_range_t *left, const char *str, size_t len) { + semver_range_t *range, *tail; + + if (len > 0) { + range = (semver_range_t *) sv_malloc(sizeof(semver_range_t)); + if (NULL == range) { + return 1; + } + if (semver_rangen(range, str, len)) { + sv_free(range); + return 1; + } + if (NULL == left->next) { + left->next = range; + } else { + tail = left->next; + while (tail->next) tail = tail->next; + tail->next = range; + } + return 0; + } + return 1; +} + +bool semver_range_pmatch(const semver_t *self, const semver_range_t *range) { + return semver_comp_pmatch(self, &range->comp) ? true : range->next ? semver_range_pmatch(self, range->next) : false; +} + +bool semver_range_matchn(const semver_t *self, const char *range_str, size_t range_len) { + semver_range_t range; + bool result; + + if (semver_rangen(&range, range_str, range_len)) { + return false; + } + result = semver_range_pmatch(self, &range); + semver_range_dtor(&range); + return result; +} + +int semver_range_pwrite(const semver_range_t *self, char *buffer, size_t len) { + char comp[SV_RANGE_MAX_LEN]; + + if (self->next) { + char next[SV_RANGE_MAX_LEN]; + return snprintf(buffer, len, "%.*s || %.*s", + semver_comp_write(self->comp, comp, SV_RANGE_MAX_LEN), comp, + semver_range_pwrite(self->next, next, SV_RANGE_MAX_LEN), next + ); + } + return snprintf(buffer, len, "%.*s", semver_comp_write(self->comp, comp, SV_RANGE_MAX_LEN), comp); +} diff --git a/core/src/sv/src/range.h b/core/src/sv/src/range.h new file mode 100644 index 000000000..2c8f0974e --- /dev/null +++ b/core/src/sv/src/range.h @@ -0,0 +1,38 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#ifndef SV_RANGE_H__ +# define SV_RANGE_H__ + +#include "version.h" + +#define SV_RANGE_MAX_LEN (512) + +void semver_range_ctor(semver_range_t *self); +char semver_range_read(semver_range_t *self, const char *str, size_t len, size_t *offset); + +#endif /* SV_RANGE_H__ */ diff --git a/core/src/sv/src/semvers.c b/core/src/sv/src/semvers.c new file mode 100644 index 000000000..f8ce9ac9d --- /dev/null +++ b/core/src/sv/src/semvers.c @@ -0,0 +1,108 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "semvers.h" + +#define ISPOW2(n) (((n) & -(n)) == (n)) + +uint32_t semvers_pgrowth(semvers_t *self, const int32_t nmin) { + if (nmin > 0) { + uint32_t unmin = (uint32_t) nmin; + + if (self->capacity) { + if (self->capacity < unmin) { + if (ISPOW2(nmin)) { + self->capacity = unmin; + } else { + do self->capacity *= 2; while (self->capacity < unmin); + } + self->data = (semver_t *) realloc((char *) self->data, sizeof(semver_t) * self->capacity); + } + } else { + if (unmin == SEMVERS_MIN_CAP || (unmin > SEMVERS_MIN_CAP && ISPOW2(nmin))) { + self->capacity = unmin; + } else { + self->capacity = SEMVERS_MIN_CAP; + while (self->capacity < unmin) self->capacity *= 2; + } + self->data = (semver_t *) sv_malloc(sizeof(semver_t) * self->capacity); + } + return unmin; + } + return 0; +} + +semver_t semvers_perase(semvers_t *self, uint32_t i) { + semver_t x = self->data[i]; + + memmove(self->data + i, self->data + i + 1, --self->length * sizeof(semver_t)); + return x; +} + +static int semvers_qsort_fn(const void *a, const void *b) { + return semver_pcmp((semver_t *) a, (semver_t *) b); +} + +void semvers_psort(semvers_t *self) { + qsort((char *) self->data, self->length, sizeof(semver_t), semvers_qsort_fn); +} + +static int semvers_rqsort_fn(const void *a, const void *b) { + return semver_pcmp((semver_t *) b, (semver_t *) a); +} + +void semvers_prsort(semvers_t *self) { + qsort((char *) self->data, self->length, sizeof(semver_t), semvers_rqsort_fn); +} + +void semvers_pdtor(semvers_t *self) { + if (self->data) { + uint32_t i; + + for (i = 0; i < self->length; ++i) { + semver_dtor(self->data + i); + } + sv_free(self->data); + self->data = NULL; + } + self->length = self->capacity = 0; +} + +void semvers_pclear(semvers_t *self) { + if (self->data) { + uint32_t i; + + for (i = 0; i < self->length; ++i) { + semver_dtor(self->data + i); + } + memset((char *) self->data, 0, self->length * sizeof(semver_t)); + } + self->length = 0; +} diff --git a/core/src/sv/src/semvers.h b/core/src/sv/src/semvers.h new file mode 100644 index 000000000..6803380b4 --- /dev/null +++ b/core/src/sv/src/semvers.h @@ -0,0 +1,35 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#ifndef SV_SEMVERS_H__ +# define SV_SEMVERS_H__ + +#include "semver.h" + +#define SEMVERS_MIN_CAP (4) + +#endif /* SV_SEMVERS_H__ */ diff --git a/core/src/sv/src/utils.c b/core/src/sv/src/utils.c new file mode 100644 index 000000000..166cbe83f --- /dev/null +++ b/core/src/sv/src/utils.c @@ -0,0 +1,96 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +#include "utils.h" +#include "comp.h" +#include "range.h" + +/*!\brief Serialise the version to the STREAM. When successful: return the + * number of bytes written and set "errno" to zero. When unsuccessful: + * set "errno" to an error code. + */ +size_t semver_fwrite(const semver_t *self, FILE *stream) { + char buffer[SV_MAX_LEN]; + int cs; + + if ((cs = semver_pwrite(self, buffer, SV_MAX_LEN)) == 0) { + return 0; + } + errno = 0; + return fwrite(buffer, sizeof(char), (size_t) cs, stream); +} + +/*!\brief Serialise the comparator to the STREAM. When successful: return the + * number of bytes written and set "errno" to zero. When unsuccessful: + * set "errno" to an error code. + */ +size_t semver_comp_fwrite(const semver_comp_t *self, FILE *stream) { + char buffer[SV_COMP_MAX_LEN]; + int cs; + + if ((cs = semver_comp_pwrite(self, buffer, SV_COMP_MAX_LEN)) == 0) { + return 0; + } + errno = 0; + return fwrite(buffer, sizeof(char), (size_t) cs, stream); +} + +/*!\brief Serialise the range to the STREAM. When successful: return the + * number of bytes written and set "errno" to zero. When unsuccessful: + * set "errno" to an error code. + */ +size_t semver_range_fwrite(const semver_range_t *self, FILE *stream) { + char buffer[SV_RANGE_MAX_LEN]; + int cs; + + if ((cs = semver_range_pwrite(self, buffer, SV_RANGE_MAX_LEN)) == 0) { + return 0; + } + errno = 0; + return fwrite(buffer, sizeof(char), (size_t) cs, stream); +} + +const char *semver_op_string(enum semver_op op) { + switch (op) { + case SEMVER_OP_EQ: + return ""; + case SEMVER_OP_LT: + return "<"; + case SEMVER_OP_LE: + return "<="; + case SEMVER_OP_GT: + return ">"; + case SEMVER_OP_GE: + return ">="; + default: + return NULL; + } +} diff --git a/core/src/sv/src/utils.h b/core/src/sv/src/utils.h new file mode 100644 index 000000000..5f09529a6 --- /dev/null +++ b/core/src/sv/src/utils.h @@ -0,0 +1,35 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#ifndef SV_UTILS_H__ +# define SV_UTILS_H__ + +#include "version.h" + +const char *semver_op_string(enum semver_op op); + +#endif /* SV_UTILS_H__ */ diff --git a/core/src/sv/src/version.c b/core/src/sv/src/version.c new file mode 100644 index 000000000..6670a4287 --- /dev/null +++ b/core/src/sv/src/version.c @@ -0,0 +1,175 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <string.h> +#include <stdio.h> + +#include "version.h" +#include "num.h" +#include "id.h" + +void semver_ctor(semver_t *self) { +#ifndef _MSC_VER + *self = (semver_t) {0}; +#else + self->len = 0; + self->raw = NULL; + self->major = 0; + self->minor = 0; + self->patch = 0; + semver_id_ctor(&self->prerelease); + semver_id_ctor(&self->build); +#endif +} + +void semver_dtor(semver_t *self) { + semver_id_dtor(&self->prerelease); + semver_id_dtor(&self->build); +} + +char semvern(semver_t *self, const char *str, size_t len) { + size_t offset = 0; + + if (len > SV_MAX_LEN) { + return 1; + } + if (semver_read(self, str, len, &offset) || offset < len) { + semver_dtor(self); + return 1; + } + return 0; +} + +char semver_tryn(semver_t *self, const char *str, size_t len) { + size_t offset = 0; + + if (len > SV_MAX_LEN) { + return 1; + } + if (semver_try_read(self, str, len, &offset) || offset < len) { + semver_dtor(self); + return 1; + } + return 0; +} + +char semver_read(semver_t *self, const char *str, size_t len, size_t *offset) { + if (*offset < len) { + semver_ctor(self); + self->raw = str + *offset; + if (str[*offset] == 'v') { + ++*offset; + } + if (semver_num_read(&self->major, str, len, offset) || self->major == SEMVER_NUM_X + || *offset >= len || str[*offset] != '.' + || semver_num_read(&self->minor, str, len, (++*offset, offset)) || self->minor == SEMVER_NUM_X + || *offset >= len || str[*offset] != '.' + || semver_num_read(&self->patch, str, len, (++*offset, offset)) || self->patch == SEMVER_NUM_X + || (str[*offset] == '-' && semver_id_read(&self->prerelease, str, len, (++*offset, offset))) + || (str[*offset] == '+' && semver_id_read(&self->build, str, len, (++*offset, offset)))) { + self->len = str + *offset - self->raw; + return 1; + } + self->len = str + *offset - self->raw; + return 0; + } + return 1; +} + +char semver_try_read(semver_t *self, const char *str, size_t len, size_t *offset) { + if (*offset < len) { + semver_ctor(self); + self->raw = str + *offset; + if (str[*offset] == 'v') { + ++*offset; + } + if (semver_num_read(&self->major, str, len, offset) || self->major == SEMVER_NUM_X) { + fail: + self->len = str + *offset - self->raw; + return 1; + } + if (*offset < len && str[*offset] == '.' + && (semver_num_read(&self->minor, str, len, (++*offset, offset)) || self->minor == SEMVER_NUM_X)) { + goto fail; + } + if (*offset < len && str[*offset] == '.' + && (semver_num_read(&self->patch, str, len, (++*offset, offset)) || self->patch == SEMVER_NUM_X)) { + goto fail; + } + if (*offset < len && str[*offset] == '-') { + ++*offset; + } + semver_id_read(&self->prerelease, str, len, offset); + if (*offset < len && str[*offset] == '+') { + ++*offset; + } + semver_id_read(&self->build, str, len, offset); + self->len = str + *offset - self->raw; + return 0; + } + return 1; +} + +char semver_pcmp(const semver_t *self, const semver_t *other) { + char result; + + if ((result = semver_num_cmp(self->major, other->major)) != 0) { + return result; + } + if ((result = semver_num_cmp(self->minor, other->minor)) != 0) { + return result; + } + if ((result = semver_num_cmp(self->patch, other->patch)) != 0) { + return result; + } + return semver_id_comp(self->prerelease, other->prerelease); +} + +int semver_pwrite(const semver_t *self, char *buffer, size_t len) { + char prerelease[SV_MAX_LEN], build[SV_MAX_LEN]; + + if (self->prerelease.len && self->build.len) { + return snprintf(buffer, len, "%d.%d.%d-%.*s+%.*s", + self->major, self->minor, self->patch, + semver_id_write(self->prerelease, prerelease, SV_MAX_LEN), prerelease, + semver_id_write(self->build, build, SV_MAX_LEN), build + ); + } + if (self->prerelease.len) { + return snprintf(buffer, len, "%d.%d.%d-%.*s", + self->major, self->minor, self->patch, + semver_id_write(self->prerelease, prerelease, SV_MAX_LEN), prerelease + ); + } + if (self->build.len) { + return snprintf(buffer, len, "%d.%d.%d+%.*s", + self->major, self->minor, self->patch, + semver_id_write(self->build, build, SV_MAX_LEN), build + ); + } + return snprintf(buffer, len, "%d.%d.%d", self->major, self->minor, self->patch); +} diff --git a/core/src/sv/src/version.h b/core/src/sv/src/version.h new file mode 100644 index 000000000..df1abe5c2 --- /dev/null +++ b/core/src/sv/src/version.h @@ -0,0 +1,43 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#ifndef SV_VERSION_H__ +# define SV_VERSION_H__ + +#include "semver.h" + +#ifdef _MSC_VER +# define snprintf(s, maxlen, fmt, ...) _snprintf_s(s, _TRUNCATE, maxlen, fmt, __VA_ARGS__) +#endif + +#define SV_MAX_LEN (256) + +void semver_ctor(semver_t *self); +char semver_read(semver_t *self, const char *str, size_t len, size_t *offset); +char semver_try_read(semver_t *self, const char *str, size_t len, size_t *offset); + +#endif /* SV_VERSION_H__ */ diff --git a/core/src/sv/test/CMakeLists.txt b/core/src/sv/test/CMakeLists.txt new file mode 100644 index 000000000..89d4a0eec --- /dev/null +++ b/core/src/sv/test/CMakeLists.txt @@ -0,0 +1,27 @@ +add_executable(version version.c) +target_link_libraries(version ${PROJECT_NAME}) +add_test(version version) + +add_executable(comp comp.c) +target_link_libraries(comp ${PROJECT_NAME}) +add_test(comp comp) + +add_executable(range range.c) +target_link_libraries(range ${PROJECT_NAME}) +add_test(range range) + +add_executable(match match.c) +target_link_libraries(match ${PROJECT_NAME}) +add_test(match match) + +add_executable(utils utils.c) +target_link_libraries(utils ${PROJECT_NAME}) +add_test(utils utils) + +add_executable(usage usage.c) +target_link_libraries(usage ${PROJECT_NAME}) +add_test(usage usage) + +add_executable(semvers semvers.c) +target_link_libraries(semvers ${PROJECT_NAME}) +add_test(semvers semvers) diff --git a/core/src/sv/test/comp.c b/core/src/sv/test/comp.c new file mode 100644 index 000000000..faa68a500 --- /dev/null +++ b/core/src/sv/test/comp.c @@ -0,0 +1,333 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "semver.h" + +#define STRNSIZE(s) (s), sizeof(s)-1 + +int test_read(const char *expected, const char *str, size_t len) { + unsigned slen; + char buffer[1024]; + semver_comp_t comp = {0}; + + printf("test: `%.*s`", (int) len, str); + if (semver_compn(&comp, str, len)) { + puts(" \tcouldn't parse"); + return 1; + } + slen = (unsigned) semver_comp_write(comp, buffer, 1024); + printf(" \t=> \t`%.*s`", slen, buffer); + if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { + printf(" != `%s`\n", expected); + semver_comp_dtor(&comp); + return 1; + } + printf(" == `%s`\n", expected); + semver_comp_dtor(&comp); + return 0; +} + +int test_and(const char *expected, const char *base_str, size_t base_len, const char *str, size_t len) { + unsigned slen; + char buffer[1024]; + semver_comp_t comp = {0}; + + printf("test and: `%.*s`", (int) base_len, base_str); + if (semver_compn(&comp, base_str, base_len)) { + puts(" \tcouldn't parse"); + return 1; + } + if (semver_and(&comp, str, len)) { + puts(" \tand failed"); + return 1; + } + slen = (unsigned) semver_comp_write(comp, buffer, 1024); + printf(" \t=> \t`%.*s`", slen, buffer); + if (memcmp(expected, buffer, (size_t) slen > base_len + len + 1 ? slen : base_len + len + 1) != 0) { + printf(" != `%s`\n", expected); + semver_comp_dtor(&comp); + return 1; + } + printf(" == `%s`\n", expected); + semver_comp_dtor(&comp); + return 0; +} + +int main(void) { + puts("failure:"); + if (test_read("", STRNSIZE("* ")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("* ")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("* |")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("* || *")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("abc")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE(">")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("<=")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("~")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("^")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("=")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE(">a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("<a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("~a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("^a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("=a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE(">1.a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("<1.a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("~1.a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("^1.a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("=1.a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.3 ")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.3 -")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.3 - ")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.3 -a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.3 - a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.3 - 1.2.a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("a.2.3")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.a.3")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.3-")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.3-alpha+")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("1.2.3+")) == 0) { + return EXIT_FAILURE; + } + if (test_read("1.2.3", STRNSIZE("1.2.3"))) { + return EXIT_FAILURE; + } + + puts("\nsome prerelease and build:"); + if (test_read(">=0.0.0 1.2.3-alpha", STRNSIZE("* 1.2.3-alpha"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0 1.2.3-alpha.2", STRNSIZE("* 1.2.3-alpha.2"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0 1.2.3+77", STRNSIZE("* 1.2.3+77"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0 1.2.3+77.2", STRNSIZE("* 1.2.3+77.2"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0 1.2.3-alpha.2+77", STRNSIZE("* 1.2.3-alpha.2+77"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0 1.2.3-alpha.2+77.2", STRNSIZE("* 1.2.3-alpha.2+77.2"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0 1.2.3-al-pha.2+77", STRNSIZE("* 1.2.3-al-pha.2+77"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0 1.2.3-al-pha.2+77.2", STRNSIZE("* 1.2.3-al-pha.2+77.2"))) { + return EXIT_FAILURE; + } + + puts("\nx-range:"); + if (test_read(">=0.0.0", STRNSIZE("*"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.0.0 <2.0.0", STRNSIZE("1.x"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.0 <1.3.0", STRNSIZE("1.2.x"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0", STRNSIZE(""))) { + return EXIT_FAILURE; + } + if (test_read(">=1.0.0 <2.0.0", STRNSIZE("1"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.0 <1.3.0", STRNSIZE("1.2"))) { + return EXIT_FAILURE; + } + + puts("\nhyphen:"); + if (test_read(">=1.2.3 <=2.3.4", STRNSIZE("1.2.3 - 2.3.4"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.0 <=2.3.4", STRNSIZE("1.2 - 2.3.4"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.3 <2.4.0", STRNSIZE("1.2.3 - 2.3"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.3 <3.0.0", STRNSIZE("1.2.3 - 2"))) { + return EXIT_FAILURE; + } + + puts("\ntidle:"); + if (test_read(">=1.2.3 <1.3.0", STRNSIZE("~1.2.3"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.0 <1.3.0", STRNSIZE("~1.2"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.0.0 <2.0.0", STRNSIZE("~1"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.2.3 <0.3.0", STRNSIZE("~0.2.3"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.2.0 <0.3.0", STRNSIZE("~0.2"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0 <1.0.0", STRNSIZE("~0"))) { + return EXIT_FAILURE; + } + + puts("\ncaret:"); + if (test_read(">=1.2.3 <2.0.0", STRNSIZE("^1.2.3"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.2.3 <0.3.0", STRNSIZE("^0.2.3"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.3 <0.0.4", STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + + puts("\nprimitive:"); + if (test_read(">=1.2.3 <2.0.0", STRNSIZE(">=1.2.3 <2.0"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.2.3 <0.3.0", STRNSIZE(">=0.2.3 <0.3"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.5.0 <0.0.4", STRNSIZE(">=0.5 <0.0.4"))) { + return EXIT_FAILURE; + } + if (test_read(">0.0.3", STRNSIZE(">0.0.3"))) { + return EXIT_FAILURE; + } + if (test_read("0.0.3", STRNSIZE("=0.0.3"))) { + return EXIT_FAILURE; + } + if (test_read("9.0.0", STRNSIZE("=9"))) { + return EXIT_FAILURE; + } + + puts("\nand:"); + if (test_and(">=0.0.0 >=0.0.3 <0.0.4", STRNSIZE("*"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_and(">=1.0.0 <2.0.0 >=0.0.3 <0.0.4", STRNSIZE("1.x"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_and(">=1.2.0 <1.3.0 >=0.0.3 <0.0.4", STRNSIZE("1.2.x"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_and(">=1.2.0 <1.3.0 >=1.2.0 <1.3.0 >=0.0.3 <0.0.4", STRNSIZE("1.2 1.2.x"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_and(">=1.0.0 <2.0.0 >=0.0.3 <0.0.4", STRNSIZE("1"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_and(">=1.2.0 <1.3.0 >=0.0.3 <0.0.4", STRNSIZE("1.2"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_and("", STRNSIZE("1.2"), STRNSIZE("")) == 0) { + return EXIT_FAILURE; + } + if (test_and("", STRNSIZE("1.2"), STRNSIZE("a")) == 0) { + return EXIT_FAILURE; + } + if (test_and("", STRNSIZE("1.2"), STRNSIZE("1.2.x abc")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget " + "dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascet" + "ur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, s")) + == 0) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/core/src/sv/test/match.c b/core/src/sv/test/match.c new file mode 100644 index 000000000..d960bb7fc --- /dev/null +++ b/core/src/sv/test/match.c @@ -0,0 +1,357 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "semver.h" + +#define STRNSIZE(s) (s), sizeof(s)-1 + +int test_matchn(bool expected, const char *semver_str, size_t semver_len, const char *comp_str, size_t comp_len) { + bool result; + semver_t semver = {0}; + + printf("test: `%.*s` ^ `%.*s`", (int) semver_len, semver_str, (int) comp_len, comp_str); + if (semvern(&semver, semver_str, semver_len)) { + puts(" \tcouldn't parse semver"); + return 1; + } + result = semver_comp_matchn(&semver, comp_str, comp_len); + printf(" \t=> %d\t", result); + if (result != expected) { + printf(" != `%d`\n", expected); + semver_dtor(&semver); + return 1; + } + printf(" == `%d`\n", expected); + semver_dtor(&semver); + return 0; +} + +int test_rmatchn(bool expected, const char *semver_str, size_t semver_len, const char *range_str, size_t range_len) { + bool result; + semver_t semver = {0}; + + printf("test: `%.*s` ^ `%.*s`", (int) semver_len, semver_str, (int) range_len, range_str); + if (semvern(&semver, semver_str, semver_len)) { + puts(" \tcouldn't parse semver"); + return 1; + } + result = semver_range_matchn(&semver, range_str, range_len); + printf(" \t=> %d\t", result); + if (result != expected) { + printf(" != `%d`\n", expected); + semver_dtor(&semver); + return 1; + } + printf(" == `%d`\n", expected); + semver_dtor(&semver); + return 0; +} + +int main(void) { + if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1.2.3"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1.2.x"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1.x.x"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1.x"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("*"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE(">1"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE(">2"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE(">=2"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE("<1"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE("<=1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE(">=1.2.3"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE(">1.2.3"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE("<1.2.3"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("<=1.2.3"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE("2.x"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("<0.0.1-99"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("<=0.0.1-99"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("<=0.0.1-98"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("=0.0.1-98"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE(">=0.0.1-98"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE(">=0.0.1-97"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE(">0.0.1-97"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha"), STRNSIZE("0.0.1-alpha"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("<0.0.1-99"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<0.0.1-alpha.99"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<=0.0.1-alpha.99"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<=0.0.1-alpha.98"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("=0.0.1-alpha.98"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">=0.0.1-alpha.98"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">=0.0.1-alpha.97"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">0.0.1-alpha.97"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<0.0.1-alpha.99.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<=0.0.1-alpha.99.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">=0.0.1-alpha.97.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">0.0.1-alpha.97.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("<0.0.1-alpha.99.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("<=0.0.1-alpha.99.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("<=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(false, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE(">=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE(">=0.0.1-alpha.97.1"))) { + return EXIT_FAILURE; + } + if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE(">0.0.1-alpha.97.1"))) { + return EXIT_FAILURE; + } + + if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1.2.3"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1.2.x"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1.x.x"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1.x"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || *"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >2"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >=2"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || <1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || <=1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >=1.2.3"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >1.2.3"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || <1.2.3"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || <=1.2.3"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 2.x"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || <0.0.1-99"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || <=0.0.1-99"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || <=0.0.1-98"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || =0.0.1-98"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || >=0.0.1-98"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || >=0.0.1-97"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || >0.0.1-97"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha"), STRNSIZE("9.x || 0.0.1-alpha"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || <0.0.1-99"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <0.0.1-alpha.99"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <=0.0.1-alpha.99"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <=0.0.1-alpha.98"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || =0.0.1-alpha.98"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >=0.0.1-alpha.98"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >=0.0.1-alpha.97"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >0.0.1-alpha.97"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <0.0.1-alpha.99.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <=0.0.1-alpha.99.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || =0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >=0.0.1-alpha.97.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >0.0.1-alpha.97.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || <0.0.1-alpha.99.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || <=0.0.1-alpha.99.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || <=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(false, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || =0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || >=0.0.1-alpha.98.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || >=0.0.1-alpha.97.1"))) { + return EXIT_FAILURE; + } + if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || >0.0.1-alpha.97.1"))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/core/src/sv/test/range.c b/core/src/sv/test/range.c new file mode 100644 index 000000000..17611ab25 --- /dev/null +++ b/core/src/sv/test/range.c @@ -0,0 +1,200 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "semver.h" + +#define STRNSIZE(s) (s), sizeof(s)-1 + +int test_read(const char *expected, const char *str, size_t len) { + unsigned slen; + char buffer[1024]; + semver_range_t range = {0}; + + printf("test: `%.*s`", (int) len, str); + if (semver_rangen(&range, str, len)) { + puts(" \tcouldn't parse"); + return 1; + } + slen = (unsigned) semver_range_write(range, buffer, 1024); + printf(" \t=> \t`%.*s`", slen, buffer); + if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { + printf(" != `%s`\n", expected); + semver_range_dtor(&range); + return 1; + } + printf(" == `%s`\n", expected); + semver_range_dtor(&range); + return 0; +} + +int test_or(const char *expected, const char *base_str, size_t base_len, const char *str, size_t len) { + unsigned slen; + char buffer[1024]; + semver_range_t range = {0}; + + printf("test and: `%.*s`", (int) base_len, base_str); + if (semver_rangen(&range, base_str, base_len)) { + puts(" \tcouldn't parse base"); + return 1; + } + if (semver_or(&range, str, len)) { + puts(" \tand failed"); + return 1; + } + slen = (unsigned) semver_range_write(range, buffer, 1024); + printf(" \t=> \t`%.*s`", slen, buffer); + if (memcmp(expected, buffer, (size_t) slen > base_len + len + 1 ? slen : base_len + len + 1) != 0) { + printf(" != `%s`\n", expected); + semver_range_dtor(&range); + return 1; + } + printf(" == `%s`\n", expected); + semver_range_dtor(&range); + return 0; +} + +int main(void) { + puts("failure:"); + if (test_read("", STRNSIZE("* |")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("* ||a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("* || a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("* || 1.a")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget " + "dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascet" + "ur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, s")) + == 0) { + return EXIT_FAILURE; + } + + puts("\nx-range:"); + if (test_read(">=0.0.0 || 1.2.3", STRNSIZE("* || 1.2.3"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.0.0 <2.0.0 || >=2.0.0 <3.0.0", STRNSIZE("1.x || 2.x"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.0 <1.3.0 || 3.0.0", STRNSIZE("1.2.x || 3.0.0"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0", STRNSIZE(""))) { + return EXIT_FAILURE; + } + if (test_read(">=1.0.0 <2.0.0 || >=2.0.0 <3.0.0 || >=3.0.0 <4.0.0", STRNSIZE("1 || 2 || 3"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.0 <1.3.0 || >=5.0.0", STRNSIZE("1.2 || >=5"))) { + return EXIT_FAILURE; + } + + puts("\nhyphen:"); + if (test_read(">=1.2.3 <=2.3.4 || >=5.0.0", STRNSIZE("1.2.3 - 2.3.4 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.0 <=2.3.4 || >=5.0.0", STRNSIZE("1.2 - 2.3.4 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.3 <2.4.0 || >=5.0.0", STRNSIZE("1.2.3 - 2.3 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.3 <3.0.0 || >=5.0.0", STRNSIZE("1.2.3 - 2 || >=5"))) { + return EXIT_FAILURE; + } + + puts("\ntidle:"); + if (test_read(">=1.2.3 <1.3.0 || >=5.0.0", STRNSIZE("~1.2.3 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.2.0 <1.3.0 || >=5.0.0", STRNSIZE("~1.2 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=1.0.0 <2.0.0 || >=5.0.0", STRNSIZE("~1 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.2.3 <0.3.0 || >=5.0.0", STRNSIZE("~0.2.3 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.2.0 <0.3.0 || >=5.0.0", STRNSIZE("~0.2 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.0 <1.0.0 || >=5.0.0", STRNSIZE("~0 || >=5"))) { + return EXIT_FAILURE; + } + + puts("\ncaret:"); + if (test_read(">=1.2.3 <2.0.0 || >=5.0.0", STRNSIZE("^1.2.3 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.2.3 <0.3.0 || >=5.0.0", STRNSIZE("^0.2.3 || >=5"))) { + return EXIT_FAILURE; + } + if (test_read(">=0.0.3 <0.0.4 || >=5.0.0", STRNSIZE("^0.0.3 || >=5"))) { + return EXIT_FAILURE; + } + + puts("\nand:"); + if (test_or(">=0.0.0 || >=0.0.3 <0.0.4", STRNSIZE("*"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_or(">=1.0.0 <2.0.0 || >=0.0.3 <0.0.4", STRNSIZE("1.x"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_or(">=1.2.0 <1.3.0 || >=0.0.3 <0.0.4", STRNSIZE("1.2.x"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_or(">=1.2.0 <1.3.0 || >=1.2.0 <1.3.0 || >=0.0.3 <0.0.4", STRNSIZE("1.2 || 1.2.x"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_or(">=1.0.0 <2.0.0 || >=0.0.3 <0.0.4", STRNSIZE("1"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_or(">=1.2.0 <1.3.0 || >=0.0.3 <0.0.4", STRNSIZE("1.2"), STRNSIZE("^0.0.3"))) { + return EXIT_FAILURE; + } + if (test_or("", STRNSIZE("1.2"), STRNSIZE("")) == 0) { + return EXIT_FAILURE; + } + if (test_or("", STRNSIZE("1.2"), STRNSIZE("a")) == 0) { + return EXIT_FAILURE; + } + if (test_or("", STRNSIZE("1.2"), STRNSIZE("1.2.x || abc")) == 0) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/core/src/sv/test/semver.c b/core/src/sv/test/semver.c new file mode 100644 index 000000000..762f4ce40 --- /dev/null +++ b/core/src/sv/test/semver.c @@ -0,0 +1,106 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <semver.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define STRNSIZE(s) (s), sizeof(s)-1 + +int test_semver(const char *expected, const char *str, size_t len) { + size_t offset = 0; + unsigned slen; + char buffer[1024]; + semver_t semver = {0}; + + printf("test: `%.*s`", (int) len, str); + if (semver_read(&semver, str, len, &offset)) { + puts(" \tcouldn't parse"); + return 1; + } + slen = (unsigned) semver_write(semver, buffer, 1024); + printf(" \t=> \t`%.*s`", slen, buffer); + if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { + printf(" != `%s`\n", expected); + semver_dtor(&semver); + return 1; + } + printf(" == `%s`\n", expected); + semver_dtor(&semver); + return 0; +} + +int main(void) { + if (test_semver("1.2.3", STRNSIZE("1.2.3"))) { + return EXIT_FAILURE; + } + if (test_semver("1.2.3-alpha", STRNSIZE("v1.2.3-alpha"))) { + return EXIT_FAILURE; + } + if (test_semver("1.2.3-alpha.2", STRNSIZE("1.2.3-alpha.2"))) { + return EXIT_FAILURE; + } + if (test_semver("1.2.3+77", STRNSIZE("v1.2.3+77"))) { + return EXIT_FAILURE; + } + if (test_semver("1.2.3+77.2", STRNSIZE("1.2.3+77.2"))) { + return EXIT_FAILURE; + } + if (test_semver("1.2.3-alpha.2+77", STRNSIZE("v1.2.3-alpha.2+77"))) { + return EXIT_FAILURE; + } + if (test_semver("1.2.3-alpha.2+77.2", STRNSIZE("1.2.3-alpha.2+77.2"))) { + return EXIT_FAILURE; + } + if (test_semver("1.2.3-al-pha.2+77", STRNSIZE("v1.2.3-al-pha.2+77"))) { + return EXIT_FAILURE; + } + if (test_semver("1.2.3-al-pha.2+77.2", STRNSIZE("1.2.3-al-pha.2+77.2"))) { + return EXIT_FAILURE; + } + if (test_semver("", STRNSIZE("")) == 0) { + return EXIT_FAILURE; + } + if (test_semver("", STRNSIZE("vv1.2.3")) == 0) { + return EXIT_FAILURE; + } + if (test_semver("", STRNSIZE("v1.2")) == 0) { + return EXIT_FAILURE; + } + if (test_semver("", STRNSIZE("v1.2.x")) == 0) { + return EXIT_FAILURE; + } + if (test_semver("", STRNSIZE("v1.2.3-")) == 0) { + return EXIT_FAILURE; + } + if (test_semver("", STRNSIZE("v1.2.3+")) == 0) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/core/src/sv/test/semvers.c b/core/src/sv/test/semvers.c new file mode 100644 index 000000000..fec6072bd --- /dev/null +++ b/core/src/sv/test/semvers.c @@ -0,0 +1,115 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <stdlib.h> +#include <assert.h> + +#include "semver.h" + +#define STRNSIZE(s) (s), sizeof(s)-1 + +int main(void) { + semver_t v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10; + semvers_t semvers = {0}; + + semver_tryn(&v0, STRNSIZE("2.0.0")); + semver_tryn(&v1, STRNSIZE("2.0.1")); + semver_tryn(&v2, STRNSIZE("2.0.2")); + semver_tryn(&v3, STRNSIZE("v2.0.0")); + semver_tryn(&v4, STRNSIZE("v2.0.1")); + semver_tryn(&v5, STRNSIZE("v2.0.2")); + semver_tryn(&v6, STRNSIZE("v2.0.3")); + semver_tryn(&v7, STRNSIZE("v2.1.0-beta1")); + semver_tryn(&v8, STRNSIZE("v2.1.0-beta2")); + semver_tryn(&v9, STRNSIZE("v2.0")); + semver_tryn(&v10, STRNSIZE("v2.1")); + + if (semver_rmatch(v0, ">2.0.1")) semvers_push(semvers, v0); + if (semver_rmatch(v1, ">2.0.1")) semvers_unshift(semvers, v1); + if (semver_rmatch(v2, ">2.0.1")) semvers_push(semvers, v2); + if (semver_rmatch(v3, ">2.0.1")) semvers_unshift(semvers, v3); + if (semver_rmatch(v4, ">2.0.1")) semvers_push(semvers, v4); + if (semver_rmatch(v5, ">2.0.1")) semvers_unshift(semvers, v5); + if (semver_rmatch(v6, ">2.0.1")) semvers_push(semvers, v6); + if (semver_rmatch(v7, ">2.0.1")) semvers_unshift(semvers, v7); + if (semver_rmatch(v8, ">2.0.1")) semvers_push(semvers, v8); + if (semver_rmatch(v9, ">2.0.1")) semvers_unshift(semvers, v9); + if (semver_rmatch(v10, ">2.0.1")) semvers_push(semvers, v10); + if (semver_rmatch(v0, ">2.0.1")) semvers_push(semvers, v0); + if (semver_rmatch(v1, ">2.0.1")) semvers_unshift(semvers, v1); + if (semver_rmatch(v2, ">2.0.1")) semvers_push(semvers, v2); + if (semver_rmatch(v3, ">2.0.1")) semvers_unshift(semvers, v3); + if (semver_rmatch(v4, ">2.0.1")) semvers_push(semvers, v4); + if (semver_rmatch(v5, ">2.0.1")) semvers_unshift(semvers, v5); + if (semver_rmatch(v6, ">2.0.1")) semvers_push(semvers, v6); + if (semver_rmatch(v7, ">2.0.1")) semvers_unshift(semvers, v7); + if (semver_rmatch(v8, ">2.0.1")) semvers_push(semvers, v8); + if (semver_rmatch(v9, ">2.0.1")) semvers_unshift(semvers, v9); + if (semver_rmatch(v10, ">2.0.1")) semvers_push(semvers, v10); + if (semver_rmatch(v0, ">2.0.1")) semvers_push(semvers, v0); + if (semver_rmatch(v1, ">2.0.1")) semvers_unshift(semvers, v1); + if (semver_rmatch(v2, ">2.0.1")) semvers_push(semvers, v2); + if (semver_rmatch(v3, ">2.0.1")) semvers_unshift(semvers, v3); + if (semver_rmatch(v4, ">2.0.1")) semvers_push(semvers, v4); + if (semver_rmatch(v5, ">2.0.1")) semvers_unshift(semvers, v5); + if (semver_rmatch(v6, ">2.0.1")) semvers_push(semvers, v6); + if (semver_rmatch(v7, ">2.0.1")) semvers_unshift(semvers, v7); + if (semver_rmatch(v8, ">2.0.1")) semvers_push(semvers, v8); + if (semver_rmatch(v9, ">2.0.1")) semvers_unshift(semvers, v9); + if (semver_rmatch(v10, ">2.0.1")) semvers_push(semvers, v10); + + if (semvers.length != 18) { + return EXIT_FAILURE; + } + if (semvers.capacity != 32) { + return EXIT_FAILURE; + } + + semvers_sort(semvers); + + for (unsigned i = 0; i < semvers.length; ++i) { + semver_fwrite(semvers.data + i, stdout); + putc('\n', stdout); + } + + v0 = semvers_pop(semvers); + v1 = semvers_shift(semvers); + + assert(memcmp("v2.1", v0.raw, v0.len) == 0); + assert(memcmp("v2.0.2", v1.raw, v1.len) == 0 || memcmp("2.0.2", v1.raw, v1.len) == 0); + + semvers_rsort(semvers); + putc('\n', stdout); + for (unsigned i = 0; i < semvers.length; ++i) { + semver_fwrite(semvers.data + i, stdout); + putc('\n', stdout); + } + + semvers_dtor(semvers); + + return EXIT_SUCCESS; +} diff --git a/core/src/sv/test/usage.c b/core/src/sv/test/usage.c new file mode 100644 index 000000000..818608137 --- /dev/null +++ b/core/src/sv/test/usage.c @@ -0,0 +1,46 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <stdlib.h> +#include <assert.h> + +#include "semver.h" + +int main(void) { + semver_t semver = {0}; + + semver(&semver, "v1.2.3-alpha.1"); + + assert(1 == semver.major); + assert(2 == semver.minor); + assert(3 == semver.patch); + assert(0 == memcmp("alpha", semver.prerelease.raw, sizeof("alpha")-1)); + assert(0 == memcmp("1", semver.prerelease.next->raw, sizeof("1")-1)); + assert(true == semver_rmatch(semver, "1.2.1 || >=1.2.3-alpha <1.2.5")); + + semver_dtor(&semver); +} diff --git a/core/src/sv/test/utils.c b/core/src/sv/test/utils.c new file mode 100644 index 000000000..89ae4cd1b --- /dev/null +++ b/core/src/sv/test/utils.c @@ -0,0 +1,102 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "semver.h" + +int test_version_fwrite(void) { + static const char input_str[] = "1.2.3-alpha.1+x86-64"; + semver_t version; + int rv; + + rv = semver(&version, input_str); + if (0 == rv) { + printf("test_version_fwrite: "); + semver_fwrite(&version, stdout); + if (0 == errno) { + printf("\n"); + rv = 0; + } + } + semver_dtor(&version); + return rv; +} + +int test_comparator_fwrite(void) { + static const char input_str[] = "<=1.2.3"; + semver_comp_t comp; + int rv; + + rv = semver_comp(&comp, input_str); + if (0 == rv) { + printf("test_comparator_fwrite: "); + semver_comp_fwrite(&comp, stdout); + if (0 == errno) { + printf("\n"); + rv = 0; + } + } + semver_comp_dtor(&comp); + return rv; +} + +int test_range_fwrite(void) { + static const char input_str[] = ">=1.2.3 <4.0.0"; + semver_range_t range; + int rv; + + rv = semver_range(&range, input_str); + if (0 == rv) { + printf("test_range_fwrite: "); + semver_range_fwrite(&range, stdout); + if (0 == errno) { + printf("\n"); + rv = 0; + } + } + semver_range_dtor(&range); + return rv; +} + +int main(void) { + if (test_version_fwrite()) { + return EXIT_FAILURE; + } + + if (test_comparator_fwrite()) { + return EXIT_FAILURE; + } + + if (test_range_fwrite()) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/core/src/sv/test/version.c b/core/src/sv/test/version.c new file mode 100644 index 000000000..a10b6e645 --- /dev/null +++ b/core/src/sv/test/version.c @@ -0,0 +1,236 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to <http://unlicense.org> + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "semver.h" + +#define STRNSIZE(s) (s), sizeof(s)-1 + +int test_read(const char *expected, const char *str, size_t len) { + unsigned slen; + char buffer[1024]; + semver_t semver = {0}; + + printf("test: `%.*s`", (int) len, str); + if (semvern(&semver, str, len)) { + puts(" \tcouldn't parse"); + return 1; + } + slen = (unsigned) semver_write(semver, buffer, 1024); + printf(" \t=> \t`%.*s`", slen, buffer); + if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { + printf(" != `%s`\n", expected); + semver_dtor(&semver); + return 1; + } + printf(" == `%s`\n", expected); + semver_dtor(&semver); + return 0; +} + +int test_try_read(const char *expected, const char *str, size_t len) { + unsigned slen; + char buffer[1024]; + semver_t semver = {0}; + + printf("test: `%.*s`", (int) len, str); + if (semver_tryn(&semver, str, len)) { + puts(" \tcouldn't parse"); + return 1; + } + slen = (unsigned) semver_write(semver, buffer, 1024); + printf(" \t=> \t`%.*s`", slen, buffer); + if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { + printf(" != `%s`\n", expected); + semver_dtor(&semver); + return 1; + } + printf(" == `%s`\n", expected); + semver_dtor(&semver); + return 0; +} + +int main(void) { + puts("normal:"); + if (test_read("0.2.3", STRNSIZE("0.2.3"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3", STRNSIZE("1.2.3"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3-alpha", STRNSIZE("v1.2.3-alpha"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3-alpha.2", STRNSIZE("1.2.3-alpha.2"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3+77", STRNSIZE("v1.2.3+77"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3+0", STRNSIZE("v1.2.3+0"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3+77.2", STRNSIZE("1.2.3+77.2"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3-alpha.2+77", STRNSIZE("v1.2.3-alpha.2+77"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3-alpha.2+77.2", STRNSIZE("1.2.3-alpha.2+77.2"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3-al-pha.2+77", STRNSIZE("v1.2.3-al-pha.2+77"))) { + return EXIT_FAILURE; + } + if (test_read("1.2.3-al-pha.2+77.2", STRNSIZE("1.2.3-al-pha.2+77.2"))) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("vv1.2.3")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("v1.2")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("v1.2.x")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("v1.2.3-")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("v1.2.3+")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("v1.2.3+01")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("v0.01.3")) == 0) { + return EXIT_FAILURE; + } + if (test_read("", STRNSIZE("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget " + "dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascet" + "ur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, s")) + == 0) { + return EXIT_FAILURE; + } + + puts("try:"); + if (test_try_read("0.2.3", STRNSIZE("0.2.3"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3", STRNSIZE("1.2.3"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3-alpha", STRNSIZE("v1.2.3-alpha"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3-alpha.2", STRNSIZE("1.2.3-alpha.2"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3+77", STRNSIZE("v1.2.3+77"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3+0", STRNSIZE("v1.2.3+0"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3+77.2", STRNSIZE("1.2.3+77.2"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3-alpha.2+77", STRNSIZE("v1.2.3-alpha.2+77"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3-alpha.2+77.2", STRNSIZE("1.2.3-alpha.2+77.2"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3-al-pha.2+77", STRNSIZE("v1.2.3-al-pha.2+77"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3-al-pha.2+77.2", STRNSIZE("1.2.3-al-pha.2+77.2"))) { + return EXIT_FAILURE; + } + if (test_try_read("", STRNSIZE("")) == 0) { + return EXIT_FAILURE; + } + if (test_try_read("", STRNSIZE("vv1.2.3")) == 0) { + return EXIT_FAILURE; + } + if (test_try_read("", STRNSIZE("v1.2")) == 0) { + return EXIT_FAILURE; + } + if (test_try_read("", STRNSIZE("v1.2.x")) == 0) { + return EXIT_FAILURE; + } + if (test_try_read("", STRNSIZE("v1.2.3-")) == 0) { + return EXIT_FAILURE; + } + if (test_try_read("", STRNSIZE("v1.2.3+")) == 0) { + return EXIT_FAILURE; + } + if (test_try_read("", STRNSIZE("v1.2.3+01")) == 0) { + return EXIT_FAILURE; + } + if (test_try_read("", STRNSIZE("v0.01.3")) == 0) { + return EXIT_FAILURE; + } + if (test_try_read("", STRNSIZE("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget " + "dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascet" + "ur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, s")) + == 0) { + return EXIT_FAILURE; + } + if (test_try_read("0.2.0", STRNSIZE("0.2"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.0.0", STRNSIZE("v1"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.0-alpha", STRNSIZE("v1.2alpha"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3-alpha.2", STRNSIZE("1.2.3alpha.2"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.0.0+77", STRNSIZE("v1+77"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.0+0", STRNSIZE("v1.2+0"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.0.0+77.2", STRNSIZE("v1+77.2"))) { + return EXIT_FAILURE; + } + if (test_try_read("1.2.3-alpha.2+77", STRNSIZE("v1.2.3alpha.2+77"))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/core/src/sv/test/xmake.lua b/core/src/sv/test/xmake.lua new file mode 100644 index 000000000..4169560e8 --- /dev/null +++ b/core/src/sv/test/xmake.lua @@ -0,0 +1,45 @@ +set_default(false) +set_languages("c99") +set_kind("binary") +add_deps("sv") +add_links("sv") +add_includedirs("../include") +add_linkdirs("$(buildir)") + +target("version_test") + add_files("version.c") + +target("comp_test") + add_files("comp.c") + +target("range_test") + add_files("range.c") + +target("match_test") + add_files("match.c") + +target("semvers_test") + add_files("semvers.c") + +target("utils_test") + add_files("utils.c") + +target("usage_test") + add_files("usage.c") + +task("check") + on_run(function () + import("core.project.task") + task.run("run", {target = "version_test"}) + task.run("run", {target = "comp_test"}) + task.run("run", {target = "range_test"}) + task.run("run", {target = "match_test"}) + task.run("run", {target = "semvers_test"}) + task.run("run", {target = "utils_test"}) + task.run("run", {target = "usage_test"}) + end) + set_menu { + usage = "xmake check" + , description = "Run tests !" + , options = {} + } diff --git a/core/src/sv/xmake.lua b/core/src/sv/xmake.lua new file mode 100644 index 000000000..490c8bf01 --- /dev/null +++ b/core/src/sv/xmake.lua @@ -0,0 +1,31 @@ +set_project("libsv") +set_version("0.0.1") + +set_warnings("all", "error") + +if is_os("macosx") or is_os("ios") then + add_cflags("-Wno-nullability-completeness") + add_cxxflags("-Wno-nullability-completeness") +end + +if is_mode("release") then + set_symbols("hidden") + set_optimize("fastest") + set_strip("all") +end + +if is_mode("debug") then + set_symbols("debug") + set_optimize("none") +end + +target("sv") + set_default(true) + set_languages("c99") + set_kind("$(kind)") + set_headerdir("$(buildir)/include") + add_headers("include/(*.h)") + add_includedirs("$(buildir)", "include") + add_files("src/*.c") + +add_subdirs("test") diff --git a/core/src/xmake/hash/prefix.h b/core/src/xmake/hash/prefix.h new file mode 100644 index 000000000..5df85a1d3 --- /dev/null +++ b/core/src/xmake/hash/prefix.h @@ -0,0 +1,36 @@ +/*!The Make-like Build Utility based on Lua + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015 - 2017, TBOOX Open Source Group. + * + * @author ruki + * @file prefix.h + * + */ +#ifndef XM_HASH_PREFIX_H +#define XM_HASH_PREFIX_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "../prefix.h" + + +#endif + + diff --git a/core/src/xmake/hash/sha256.c b/core/src/xmake/hash/sha256.c new file mode 100644 index 000000000..6a9b1f5df --- /dev/null +++ b/core/src/xmake/hash/sha256.c @@ -0,0 +1,110 @@ +/*!The Make-like Build Utility based on Lua + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015 - 2017, TBOOX Open Source Group. + * + * @author ruki + * @file sha256.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "sha256" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_hash_sha256(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get the filename + tb_char_t const* filename = luaL_checkstring(lua, 1); + tb_check_return_val(filename, 0); + + // load data from file + tb_bool_t ok = tb_false; + tb_stream_ref_t stream = tb_stream_init_from_file(filename, TB_FILE_MODE_RO); + if (stream) + { + // open stream + if (tb_stream_open(stream)) + { + // init sha256 + tb_sha_t sha; + tb_sha_init(&sha, TB_SHA_MODE_SHA2_256); + + // read data and update sha256 + tb_byte_t data[TB_STREAM_BLOCK_MAXN]; + while (!tb_stream_beof(stream)) + { + // read data + tb_long_t real = tb_stream_read(stream, data, sizeof(data)); + + // ok? + if (real > 0) tb_sha_spak(&sha, data, real); + // no data? continue it + else if (!real) + { + // wait + real = tb_stream_wait(stream, TB_STREAM_WAIT_READ, tb_stream_timeout(stream)); + tb_check_break(real > 0); + + // has read? + tb_assert_and_check_break(real & TB_STREAM_WAIT_READ); + } + // failed or end? + else break; + } + + // exit sha256 + tb_byte_t buffer[32]; + tb_sha_exit(&sha, buffer, sizeof(buffer)); + + // make sha256 string + tb_size_t i = 0; + tb_size_t n = sha.digest_len << 2; + tb_char_t s[256] = {0}; + for (i = 0; i < n; ++i) tb_snprintf(s + (i << 1), 3, "%02x", buffer[i]); + + // save result + lua_pushstring(lua, s); + + // ok + ok = tb_true; + } + + // exit stream + tb_stream_exit(stream); + } + + // failed? return nil + if (!ok) lua_pushnil(lua); + + // ok + return 1; +} diff --git a/core/src/xmake/os/uuid.c b/core/src/xmake/hash/uuid.c index 044bbe83d..9dc8e0eb7 100644 --- a/core/src/xmake/os/uuid.c +++ b/core/src/xmake/hash/uuid.c @@ -37,7 +37,7 @@ /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ -tb_int_t xm_os_uuid(lua_State* lua) +tb_int_t xm_hash_uuid(lua_State* lua) { // check tb_assert_and_check_return_val(lua, 0); diff --git a/core/src/xmake/machine.c b/core/src/xmake/machine.c index 7f1acfbd0..e1a080d3a 100644 --- a/core/src/xmake/machine.c +++ b/core/src/xmake/machine.c @@ -60,13 +60,13 @@ typedef struct __xm_machine_impl_t // the os functions tb_int_t xm_os_argv(lua_State* lua); tb_int_t xm_os_find(lua_State* lua); -tb_int_t xm_os_uuid(lua_State* lua); tb_int_t xm_os_isdir(lua_State* lua); tb_int_t xm_os_rmdir(lua_State* lua); tb_int_t xm_os_mkdir(lua_State* lua); tb_int_t xm_os_cpdir(lua_State* lua); tb_int_t xm_os_chdir(lua_State* lua); tb_int_t xm_os_mtime(lua_State* lua); +tb_int_t xm_os_sleep(lua_State* lua); tb_int_t xm_os_mclock(lua_State* lua); tb_int_t xm_os_curdir(lua_State* lua); tb_int_t xm_os_tmpdir(lua_State* lua); @@ -93,6 +93,10 @@ tb_int_t xm_path_absolute(lua_State* lua); tb_int_t xm_path_translate(lua_State* lua); tb_int_t xm_path_is_absolute(lua_State* lua); +// the hash functions +tb_int_t xm_hash_uuid(lua_State* lua); +tb_int_t xm_hash_sha256(lua_State* lua); + // the winreg functions #ifdef TB_CONFIG_OS_WINDOWS tb_int_t xm_winreg_query(lua_State* lua); @@ -120,6 +124,11 @@ tb_int_t xm_readline_add_history(lua_State* lua); tb_int_t xm_readline_clear_history(lua_State* lua); #endif +// the semver functions +tb_int_t xm_semver_parse(lua_State* lua); +tb_int_t xm_semver_satisfies(lua_State* lua); +tb_int_t xm_semver_select(lua_State* lua); + /* ////////////////////////////////////////////////////////////////////////////////////// * globals */ @@ -129,13 +138,13 @@ static luaL_Reg const g_os_functions[] = { { "argv", xm_os_argv } , { "find", xm_os_find } -, { "uuid", xm_os_uuid } , { "isdir", xm_os_isdir } , { "rmdir", xm_os_rmdir } , { "mkdir", xm_os_mkdir } , { "cpdir", xm_os_cpdir } , { "chdir", xm_os_chdir } , { "mtime", xm_os_mtime } +, { "sleep", xm_os_sleep } , { "mclock", xm_os_mclock } , { "curdir", xm_os_curdir } , { "tmpdir", xm_os_tmpdir } @@ -168,6 +177,14 @@ static luaL_Reg const g_path_functions[] = , { tb_null, tb_null } }; +// the hash functions +static luaL_Reg const g_hash_functions[] = +{ + { "uuid", xm_hash_uuid } +, { "sha256", xm_hash_sha256 } +, { tb_null, tb_null } +}; + // the string functions static luaL_Reg const g_string_functions[] = { @@ -215,6 +232,15 @@ static luaL_Reg const g_readline_functions[] = }; #endif +// the semver functions +static luaL_Reg const g_semver_functions[] = +{ + { "parse", xm_semver_parse } +, { "satisfies", xm_semver_satisfies } +, { "select", xm_semver_select } +, { tb_null, tb_null } +}; + /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ @@ -422,6 +448,9 @@ xm_machine_ref_t xm_machine_init() // bind path functions luaL_register(impl->lua, "path", g_path_functions); + // bind hash functions + luaL_register(impl->lua, "hash", g_hash_functions); + // bind string functions luaL_register(impl->lua, "string", g_string_functions); @@ -441,6 +470,9 @@ xm_machine_ref_t xm_machine_init() luaL_register(impl->lua, "readline", g_readline_functions); #endif + // bind semver functions + luaL_register(impl->lua, "semver", g_semver_functions); + // init host #if defined(TB_CONFIG_OS_WINDOWS) lua_pushstring(impl->lua, "windows"); diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index e9f5badce..aa003cc35 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -16,13 +16,13 @@ xmake_C_FILES += \ machine \ os/argv \ os/find \ - os/uuid \ os/isdir \ os/rmdir \ os/mkdir \ os/cpdir \ os/chdir \ os/mtime \ + os/sleep \ os/mclock \ os/curdir \ os/tmpdir \ @@ -44,6 +44,8 @@ xmake_C_FILES += \ path/absolute \ path/translate \ path/is_absolute \ + hash/uuid \ + hash/sha256 \ winreg/query \ string/endswith \ string/startswith \ @@ -53,6 +55,10 @@ xmake_C_FILES += \ process/waitlist \ process/close \ sandbox/interactive \ + semver/parse \ + semver/satisfies \ + semver/select \ + semver/semver \ readline/readline \ readline/history_list \ readline/add_history \ @@ -65,7 +71,8 @@ xmake_CXFLAGS += $(if $(findstring readline,$(base_LIBNAMES)),-DXM_CONFIG_API # includes xmake_INC_DIRS += \ - ../luajit/src + ../luajit/src \ + ../sv/include # suffix diff --git a/core/src/xmake/os/sleep.c b/core/src/xmake/os/sleep.c new file mode 100644 index 000000000..4615c274f --- /dev/null +++ b/core/src/xmake/os/sleep.c @@ -0,0 +1,53 @@ +/*!The Make-like Build Utility based on Lua + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015 - 2017, TBOOX Open Source Group. + * + * @author ruki + * @file sleep.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "sleep" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_os_sleep(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get the interval (ms) + tb_long_t interval = (tb_long_t)luaL_checklong(lua, 1); + + // sleep it + if (interval >= 0) tb_msleep(interval); + + // ok + return 0; +} diff --git a/core/src/xmake/semver/parse.c b/core/src/xmake/semver/parse.c new file mode 100644 index 000000000..976f198fb --- /dev/null +++ b/core/src/xmake/semver/parse.c @@ -0,0 +1,65 @@ +/*!The Make-like Build Utility based on Lua + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015 - 2017, TBOOX Open Source Group. + * + * @author uael + * @file parse.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "parse" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +// parse wrapper +tb_int_t xm_semver_parse(lua_State* lua) +{ + semver_t semver = {0}; + + // check + tb_assert_and_check_return_val(lua, 0); + + // get the version string + tb_char_t const* str = luaL_checkstring(lua, 1); + tb_check_return_val(str, 0); + + if (semvern(&semver, str, tb_strlen(str))) { + lua_pushnil(lua); + lua_pushfstring(lua, "Unable to parse semver '%s'", str); + + return 2; + } + + lua_pushsemver(lua, semver); + semver_dtor(&semver); + + // ok + return 1; +} diff --git a/core/src/xmake/semver/prefix.h b/core/src/xmake/semver/prefix.h new file mode 100644 index 000000000..17c4e9f5a --- /dev/null +++ b/core/src/xmake/semver/prefix.h @@ -0,0 +1,37 @@ +/*!The Make-like Build Utility based on Lua + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015 - 2017, TBOOX Open Source Group. + * + * @author uael + * @file prefix.h + * + */ +#ifndef XM_SEMVER_PREFIX_H +#define XM_SEMVER_PREFIX_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "../prefix.h" + +#include "semver.h" + +void lua_pushsemver(lua_State *lua, semver_t semver); + +#endif diff --git a/core/src/xmake/semver/satisfies.c b/core/src/xmake/semver/satisfies.c new file mode 100644 index 000000000..f3b34890f --- /dev/null +++ b/core/src/xmake/semver/satisfies.c @@ -0,0 +1,78 @@ +/*!The Make-like Build Utility based on Lua + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015 - 2017, TBOOX Open Source Group. + * + * @author uael + * @file satisfies.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "satisfies" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +// satisfies wrapper +tb_int_t xm_semver_satisfies(lua_State* lua) +{ + semver_t semver = {0}; + semver_range_t range = {0}; + + // check + tb_assert_and_check_return_val(lua, 0); + + // get the version string + tb_char_t const* str = luaL_checkstring(lua, 1); + tb_char_t const* range_str = luaL_checkstring(lua, 2); + + tb_check_return_val(str, 0); + tb_check_return_val(range_str, 0); + + if (semvern(&semver, str, tb_strlen(str))) { + lua_pushnil(lua); + lua_pushfstring(lua, "Unable to parse semver '%s'", str); + + return 2; + } + + if (semver_rangen(&range, range_str, tb_strlen(range_str))) { + semver_dtor(&semver); + lua_pushnil(lua); + lua_pushfstring(lua, "Unable to parse semver range '%s'", range_str); + + return 2; + } + + lua_pushboolean(lua, semver_range_match(semver, range)); + semver_dtor(&semver); + semver_range_dtor(&range); + + // ok + return 1; +} diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c new file mode 100644 index 000000000..6400de6a8 --- /dev/null +++ b/core/src/xmake/semver/select.c @@ -0,0 +1,160 @@ +/*!The Make-like Build Utility based on Lua + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015 - 2017, TBOOX Open Source Group. + * + * @author uael + * @file select.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "select" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include <stdlib.h> +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +// satisfies wrapper +tb_int_t xm_semver_select(lua_State* lua) +{ + semver_t semver = {0}; + semvers_t matches = {0}; + semver_range_t range = {0}; + lua_Integer i; + size_t range_len = 0, source_len; + tb_char_t const* source_str; + tb_char_t const* source; + tb_bool_t is_range; + + lua_settop(lua, 4); + + // check + tb_assert_and_check_return_val(lua, 0); + + // get the version string + tb_char_t const* range_str = luaL_checkstring(lua, 1); + tb_check_return_val(range_str, 0); + range_len = tb_strlen(range_str); + + is_range = semver_rangen(&range, range_str, range_len) == 0; + if (is_range) { + source = "versions"; + luaL_checktype(lua, 2, LUA_TTABLE); + for (i = lua_objlen(lua, 2); i > 0; --i) { + lua_pushinteger(lua, i); + lua_gettable(lua, 2); + + source_str = luaL_checkstring(lua, -1); + tb_check_return_val(source_str, 0); + + if (semver_tryn(&semver, source_str, tb_strlen(source_str)) == 0) { + if (semver_range_match(semver, range)) { + semvers_push(matches, semver); + } else { + semver_dtor(&semver); + } + } + } + if (matches.length) { + goto match; + } + semvers_clear(matches); + source = "tags"; + luaL_checktype(lua, 3, LUA_TTABLE); + for (i = lua_objlen(lua, 3); i > 0; --i) { + lua_pushinteger(lua, i); + lua_gettable(lua, 3); + + source_str = luaL_checkstring(lua, -1); + tb_check_return_val(source_str, 0); + + if (semver_tryn(&semver, source_str, tb_strlen(source_str)) == 0) { + if (semver_range_match(semver, range)) { + semvers_push(matches, semver); + } else { + semver_dtor(&semver); + } + } + } + if (matches.length) { + goto match; + } + semvers_dtor(matches); + semver_range_dtor(&range); + } + + source = "branches"; + luaL_checktype(lua, 4, LUA_TTABLE); + for (i = lua_objlen(lua, 4); i > 0; --i) { + lua_pushinteger(lua, i); + lua_gettable(lua, 4); + + source_str = luaL_checkstring(lua, -1); + tb_check_return_val(source_str, 0); + source_len = tb_strlen(source_str); + + if (source_len == range_len && tb_memcmp(source_str, range_str, source_len) == 0) { + lua_createtable(lua, 0, 2); + + lua_pushlstring(lua, source_str, source_len); + lua_setfield(lua, -2, "version"); + + lua_pushstring(lua, source); + lua_setfield(lua, -2, "source"); + + return 1; + } + } + + if (!is_range) { + lua_pushnil(lua); + lua_pushfstring(lua, "Unable to parse semver range '%s'", range_str); + + return 2; + } + lua_pushnil(lua); + lua_pushfstring(lua, "Unable to select version for range '%s'", range_str); + + return 2; + match: + semvers_sort(matches); + semver = semvers_pop(matches); + lua_createtable(lua, 0, 2); + + lua_pushstring(lua, semver.raw); + lua_setfield(lua, -2, "version"); + + lua_pushstring(lua, source); + lua_setfield(lua, -2, "source"); + + semvers_dtor(matches); + semver_dtor(&semver); + semver_range_dtor(&range); + + return 1; +} diff --git a/core/src/xmake/semver/semver.c b/core/src/xmake/semver/semver.c new file mode 100644 index 000000000..27dfb3fb6 --- /dev/null +++ b/core/src/xmake/semver/semver.c @@ -0,0 +1,91 @@ +/*!The Make-like Build Utility based on Lua + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015 - 2017, TBOOX Open Source Group. + * + * @author uael + * @file semver.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "semver" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +void lua_pushsemver(lua_State *lua, const semver_t semver) +{ + semver_id_t const *id; + tb_uchar_t i = 0; + + lua_createtable(lua, 0, 7); + + lua_pushstring(lua, semver.raw); + lua_setfield(lua, -2, "raw"); + + lua_pushlstring(lua, semver.raw, semver.len); + lua_setfield(lua, -2, "version"); + + lua_pushinteger(lua, semver.major); + lua_setfield(lua, -2, "major"); + + lua_pushinteger(lua, semver.minor); + lua_setfield(lua, -2, "minor"); + + lua_pushinteger(lua, semver.patch); + lua_setfield(lua, -2, "patch"); + + lua_pushstring(lua, "prerelease"); + lua_newtable(lua); + id = &semver.prerelease; + while (id && id->len) { + if (id->numeric) { + lua_pushinteger(lua, id->num); + } else { + lua_pushlstring(lua, id->raw, id->len); + } + id = id->next; + lua_rawseti(lua, -2, ++i); + } + lua_settable(lua, -3); + + i = 0; + lua_pushstring(lua, "build"); + lua_newtable(lua); + id = &semver.build; + while (id && id->len) { + if (id->numeric) { + lua_pushinteger(lua, id->num); + } else { + lua_pushlstring(lua, id->raw, id->len); + } + id = id->next; + lua_rawseti(lua, -2, ++i); + } + lua_settable(lua, -3); +} diff --git a/core/src/xmake/xmake.lua b/core/src/xmake/xmake.lua index 484d94b98..acc71ed46 100644 --- a/core/src/xmake/xmake.lua +++ b/core/src/xmake/xmake.lua @@ -5,7 +5,7 @@ target("xmake") set_kind("static") -- add deps - add_deps("luajit") + add_deps("sv", "luajit") -- add defines add_defines("__tb_prefix__=\"xmake\"") |
