From 284cfe06ba99c66403c7cae9c225d9bde7510fd4 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Wed, 29 May 2024 18:24:15 +1200 Subject: [PATCH 001/112] CMake: some minor cleaning up. --- cmake/common.cmake | 3 ++- src/3rdparty/libCOMBINE/CMakeLists.txt | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/common.cmake b/cmake/common.cmake index 111a8b636..7062041a7 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -380,7 +380,8 @@ function(add_target_property TARGET PROPERTY VALUE) set(NEW_VALUE "${VALUE}") endif() - set_target_properties(${TARGET} PROPERTIES ${PROPERTY} "${NEW_VALUE}") + set_target_properties(${TARGET} PROPERTIES + ${PROPERTY} "${NEW_VALUE}") endfunction() function(prepare_test TARGET) diff --git a/src/3rdparty/libCOMBINE/CMakeLists.txt b/src/3rdparty/libCOMBINE/CMakeLists.txt index a359f9e83..a9717e4e1 100644 --- a/src/3rdparty/libCOMBINE/CMakeLists.txt +++ b/src/3rdparty/libCOMBINE/CMakeLists.txt @@ -67,7 +67,6 @@ else() -DBUILD_TEST=OFF ${CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} - -DCMAKE_POLICY_DEFAULT_CMP0074:STRING=NEW -DLIBCOMBINE_SHARED_VERSION=OFF -DLIBCOMBINE_SKIP_SHARED_LIBRARY=ON -DLIBSBML_INCLUDE_DIR=${LIBSBML_INCLUDE_DIR} From f97f2c7ec104e7dcf521c188ea7fe3656ad73bea Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Wed, 29 May 2024 18:09:40 +1200 Subject: [PATCH 002/112] libCOMBINE: use a version that allows to initialise a COMBINE archive from a buffer. --- src/3rdparty/libCOMBINE/CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/3rdparty/libCOMBINE/CMakeLists.txt b/src/3rdparty/libCOMBINE/CMakeLists.txt index a9717e4e1..a168e57e0 100644 --- a/src/3rdparty/libCOMBINE/CMakeLists.txt +++ b/src/3rdparty/libCOMBINE/CMakeLists.txt @@ -15,7 +15,7 @@ set(PACKAGE_NAME libCOMBINE) set(PACKAGE_VERSION 0.2.20) set(PACKAGE_REPOSITORY libCombine) -set(RELEASE_TAG v0.2.20b) +set(RELEASE_TAG v0.2.20-buffer) set(INSTALL_DIR ${PREBUILT_DIR}/${PACKAGE_NAME}) # Either retrieve or build our package. @@ -28,32 +28,32 @@ if(LIBOPENCOR_PREBUILT_LIBCOMBINE) if(EMSCRIPTEN) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - fb6d723cb1f1ef533f8254d450abf227882f0e0b) + e6f2c3c963b6a6b5e5cbc66919624327b9e36696) else() if(WIN32) if(RELEASE_MODE) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 9781459729e039c3275eae5da37ac2c1aa143032) + da9487061b1b816b49467a883c3d59e6ac029ccc) else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 8da2f4f272e49c79b4d87d8175fd5ccd966d4dab) + 8202f992c22c3d6f98b53b99bb0795f6348e634f) endif() elseif(APPLE) if(INTEL_MODE) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - ec6284679c7a85eafd3b92f4e97561383ffd2611) + 43906fcb976cd8187785a568ce0e489fc542b98f) else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 5e2faaf876dc6b4acfaf05a1b1c147ad5633b1d3) + d480d451fbc16189c0238fe3bff70db5fe5c0ba3) endif() else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - fb8a6411e2f33422e20aaa64093967fef5829a10) + 8b2773d0cf12e4a343380178d14af8e7d9984165) endif() endif() else() From 13041ddd4e7a611c98883ec89c4656a7923a2c03 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Wed, 29 May 2024 18:15:38 +1200 Subject: [PATCH 003/112] CMake: show the output of configuring and building a third-party package. --- cmake/packages.cmake | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmake/packages.cmake b/cmake/packages.cmake index 17ba41320..de2c30170 100644 --- a/cmake/packages.cmake +++ b/cmake/packages.cmake @@ -68,8 +68,7 @@ function(build_package PACKAGE_NAME) execute_process(COMMAND ${CONFIGURE_COMMAND} -G "${CMAKE_GENERATOR}" -S . -B build WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE RESULT - ERROR_VARIABLE ERROR - OUTPUT_QUIET) + ERROR_VARIABLE ERROR) if(NOT RESULT EQUAL 0) message(FATAL_ERROR "${ERROR}") @@ -78,8 +77,7 @@ function(build_package PACKAGE_NAME) execute_process(COMMAND ${CMAKE_COMMAND} --build build WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE RESULT - ERROR_VARIABLE ERROR - OUTPUT_QUIET) + ERROR_VARIABLE ERROR) if(NOT RESULT EQUAL 0) message(FATAL_ERROR "${ERROR}") From d4ce6ad02ad78477cdca60d209ca846d4225019f Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Wed, 29 May 2024 19:16:03 +1200 Subject: [PATCH 004/112] COMBINE support: initialise a COMBINE archive using a file contents rather than its filename. So that we can use it from JavaScript. --- src/support/combine/combinearchive.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/support/combine/combinearchive.cpp b/src/support/combine/combinearchive.cpp index 8fb1eb0ec..2bda46591 100644 --- a/src/support/combine/combinearchive.cpp +++ b/src/support/combine/combinearchive.cpp @@ -62,8 +62,9 @@ CombineArchivePtr CombineArchive::create(const FilePtr &pFile) // Try to retrieve a COMBINE archive. auto *archive = new libcombine::CombineArchive {}; + auto fileContents = pFile->contents(); - if (archive->initializeFromArchive(pFile->fileName())) { + if (archive->initializeFromArchive(fileContents)) { return CombineArchivePtr {new CombineArchive {archive}}; } From 1993a09ed2827bfc3dff700206f4dbecfdc9bc1b Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 30 May 2024 11:07:23 +1200 Subject: [PATCH 005/112] Added modp_b64 as an external project. --- extern/modp_b64/BUILD.gn | 11 + extern/modp_b64/DEPS | 3 + extern/modp_b64/DIR_METADATA | 6 + extern/modp_b64/LICENSE | 33 +++ extern/modp_b64/OWNERS | 1 + extern/modp_b64/README.chromium | 23 ++ extern/modp_b64/modp_b64.cc | 168 +++++++++++ extern/modp_b64/modp_b64.h | 159 +++++++++++ extern/modp_b64/modp_b64_data.h | 481 ++++++++++++++++++++++++++++++++ 9 files changed, 885 insertions(+) create mode 100644 extern/modp_b64/BUILD.gn create mode 100644 extern/modp_b64/DEPS create mode 100644 extern/modp_b64/DIR_METADATA create mode 100644 extern/modp_b64/LICENSE create mode 100644 extern/modp_b64/OWNERS create mode 100644 extern/modp_b64/README.chromium create mode 100644 extern/modp_b64/modp_b64.cc create mode 100644 extern/modp_b64/modp_b64.h create mode 100644 extern/modp_b64/modp_b64_data.h diff --git a/extern/modp_b64/BUILD.gn b/extern/modp_b64/BUILD.gn new file mode 100644 index 000000000..13ddaa184 --- /dev/null +++ b/extern/modp_b64/BUILD.gn @@ -0,0 +1,11 @@ +# Copyright 2013 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +static_library("modp_b64") { + sources = [ + "modp_b64.cc", + "modp_b64.h", + "modp_b64_data.h", + ] +} diff --git a/extern/modp_b64/DEPS b/extern/modp_b64/DEPS new file mode 100644 index 000000000..8061b5a3f --- /dev/null +++ b/extern/modp_b64/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + '+build', +] \ No newline at end of file diff --git a/extern/modp_b64/DIR_METADATA b/extern/modp_b64/DIR_METADATA new file mode 100644 index 000000000..45f7798a6 --- /dev/null +++ b/extern/modp_b64/DIR_METADATA @@ -0,0 +1,6 @@ +monorail: { + component: "Internals" +} +buganizer_public: { + component_id: 1456292 +} diff --git a/extern/modp_b64/LICENSE b/extern/modp_b64/LICENSE new file mode 100644 index 000000000..55af76f3e --- /dev/null +++ b/extern/modp_b64/LICENSE @@ -0,0 +1,33 @@ + * MODP_B64 - High performance base64 encoder/decoder + * Version 1.3 -- 17-Mar-2006 + * http://modp.com/release/base64 + * + * Copyright (c) 2005, 2006 Nick Galbreath -- nickg [at] modp [dot] com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the modp.com nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/extern/modp_b64/OWNERS b/extern/modp_b64/OWNERS new file mode 100644 index 000000000..663da7181 --- /dev/null +++ b/extern/modp_b64/OWNERS @@ -0,0 +1 @@ +pkasting@chromium.org \ No newline at end of file diff --git a/extern/modp_b64/README.chromium b/extern/modp_b64/README.chromium new file mode 100644 index 000000000..61ddfb1d2 --- /dev/null +++ b/extern/modp_b64/README.chromium @@ -0,0 +1,23 @@ +Name: modp base64 decoder +Short Name: stringencoders +URL: https://github.com/client9/stringencoders +Version: unknown +License: BSD +License File: LICENSE +Security Critical: yes +Shipped: yes + +Description: +The source code was modified from upstream as follows: +- Removed the inclusion of modp's config.h +- Fixed compilation errors that occur under VC8 +- Renamed modp_b64.c to modp_b64.cc to force it to be compiled as C++ and so + the inclusion of basictypes.h could be possible +- Made code safe on 64-bit systems +- Removed misaligned read/writes on little-endian systems +- Removed unreachable code +- Extended the API so callers can avoid overload for base64 encode +- Removed big endian support entirely +- Removed std::string APIs +- Added multiple decoding options to support Blink callers +- Added modp_b64_encode_data which doesn't append a null terminator diff --git a/extern/modp_b64/modp_b64.cc b/extern/modp_b64/modp_b64.cc new file mode 100644 index 000000000..9be58205f --- /dev/null +++ b/extern/modp_b64/modp_b64.cc @@ -0,0 +1,168 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ +/* vi: set expandtab shiftwidth=4 tabstop=4: */ +/** + * \file + *
+ * MODP_B64 - High performance base64 encoder/decoder
+ * Version 1.3 -- 17-Mar-2006
+ * http://modp.com/release/base64
+ *
+ * Copyright © 2005, 2006  Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ *   Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ *   Neither the name of the modp.com nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This is the standard "new" BSD license:
+ * http://www.opensource.org/licenses/bsd-license.php
+ * 
+ */ + +/* public header */ +#include "modp_b64.h" + +#include "modp_b64_data.h" + +#define BADCHAR 0x01FFFFFF + +size_t modp_b64_encode_data(char* dest, const char* str, size_t len) +{ + size_t i = 0; + uint8_t* p = (uint8_t*) dest; + + /* unsigned here is important! */ + uint8_t t1, t2, t3; + + if (len > 2) { + for (; i < len - 2; i += 3) { + t1 = str[i]; t2 = str[i+1]; t3 = str[i+2]; + *p++ = e0[t1]; + *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)]; + *p++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)]; + *p++ = e2[t3]; + } + } + + switch (len - i) { + case 0: + break; + case 1: + t1 = str[i]; + *p++ = e0[t1]; + *p++ = e1[(t1 & 0x03) << 4]; + *p++ = CHARPAD; + *p++ = CHARPAD; + break; + default: /* case 2 */ + t1 = str[i]; t2 = str[i+1]; + *p++ = e0[t1]; + *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)]; + *p++ = e2[(t2 & 0x0F) << 2]; + *p++ = CHARPAD; + } + + return p - (uint8_t*)dest; +} + +size_t modp_b64_encode(char* dest, const char* str, size_t len) { + size_t output_size = modp_b64_encode_data(dest, str, len); + dest[output_size] = '\0'; + return output_size; +} + +size_t do_decode_padding(const char* src, size_t len, ModpDecodePolicy policy) { + if (policy == ModpDecodePolicy::kNoPaddingValidation) { + while (len > 0 && src[len - 1] == CHARPAD) { + len--; + } + } else { + const size_t remainder = len % 4; + if (policy == ModpDecodePolicy::kStrict && (remainder != 0 || len < 4)) + return MODP_B64_ERROR; + if (remainder == 0) { + if (src[len - 1] == CHARPAD) { + len--; + if (src[len - 1] == CHARPAD) { + len--; + } + } + } + } + return len % 4 == 1 ? MODP_B64_ERROR : len; +} + +size_t modp_b64_decode(char* dest, const char* src, size_t len, ModpDecodePolicy policy) +{ + if (len != 0) + len = do_decode_padding(src, len, policy); + + if (len == 0 || len == MODP_B64_ERROR) + return len; + + size_t i; + int leftover = len % 4; + size_t chunks = (leftover == 0) ? len / 4 - 1 : len /4; + + uint8_t* p = (uint8_t*)dest; + uint32_t x = 0; + const uint8_t* y = (uint8_t*)src; + for (i = 0; i < chunks; ++i, y += 4) { + x = d0[y[0]] | d1[y[1]] | d2[y[2]] | d3[y[3]]; + if (x >= BADCHAR) return MODP_B64_ERROR; + *p++ = ((uint8_t*)(&x))[0]; + *p++ = ((uint8_t*)(&x))[1]; + *p++ = ((uint8_t*)(&x))[2]; + } + + switch (leftover) { + case 0: + x = d0[y[0]] | d1[y[1]] | d2[y[2]] | d3[y[3]]; + + if (x >= BADCHAR) return MODP_B64_ERROR; + *p++ = ((uint8_t*)(&x))[0]; + *p++ = ((uint8_t*)(&x))[1]; + *p = ((uint8_t*)(&x))[2]; + return (chunks+1)*3; + case 1: /* with padding this is an impossible case */ + x = d0[y[0]]; + *p = *((uint8_t*)(&x)); // i.e. first char/byte in int + break; + case 2: // * case 2, 1 output byte */ + x = d0[y[0]] | d1[y[1]]; + *p = *((uint8_t*)(&x)); // i.e. first char + break; + default: /* case 3, 2 output bytes */ + x = d0[y[0]] | d1[y[1]] | d2[y[2]]; /* 0x3c */ + *p++ = ((uint8_t*)(&x))[0]; + *p = ((uint8_t*)(&x))[1]; + break; + } + + if (x >= BADCHAR) return MODP_B64_ERROR; + + return 3*chunks + (6*leftover)/8; +} diff --git a/extern/modp_b64/modp_b64.h b/extern/modp_b64/modp_b64.h new file mode 100644 index 000000000..9d11f811d --- /dev/null +++ b/extern/modp_b64/modp_b64.h @@ -0,0 +1,159 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ +/* vi: set expandtab shiftwidth=4 tabstop=4: */ + +/** + * \file + *
+ * High performance base64 encoder / decoder
+ * Version 1.3 -- 17-Mar-2006
+ *
+ * Copyright © 2005, 2006, Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * http://modp.com/release/base64
+ *
+ * Released under bsd license.  See modp_b64.c for details.
+ * 
+ * + * The default implementation is the standard b64 encoding with padding. + * It's easy to change this to use "URL safe" characters and to remove + * padding. See the modp_b64.c source code for details. + * + */ + +#ifndef MODP_B64 +#define MODP_B64 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Encode a raw binary string into base 64. + * src contains the bytes + * len contains the number of bytes in the src + * dest should be allocated by the caller to contain + * at least modp_b64_encode_len(len) bytes (see below) + * This will contain the (non-null terminated) b64 bytes. + * returns length of the destination string. + * + * Example + * + * \code + * char* src = ...; + * int srclen = ...; //the length of number of bytes in src + * char* dest = (char*) malloc(modp_b64_encode_len); + * int len = modp_b64_encode_data(dest, src, sourcelen); + * if (len == -1) { + * printf("Error\n"); + * } else { + * printf("b64 = %s\n", dest); + * } + * \endcode + * + */ +size_t modp_b64_encode_data(char* dest, const char* str, size_t len); + +/** + * Same as modp_b64_encode_data, but additionally sets a null terminator at the + * end of `dest` (i.e. at dest[output_size]). + * Like modp_b64_encode_data, returns the length of the destination string (i.e. + * not counting the null terminator). + * + * TODO(csharrison): Consider removing this once all callers migrate to + * modp_b64_encode_data. + */ +size_t modp_b64_encode(char* dest, const char* str, size_t len); + +/** + * Decode a base64 encoded string + * + * src should contain exactly len bytes of b64 characters. + * if src contains -any- non-base characters (such as white + * space, -1 is returned. + * + * dest should be allocated by the caller to contain at least + * len * 3 / 4 bytes. + * + * Returns the length (strlen) of the output, or -1 if unable to + * decode + * + * \code + * char* src = ...; + * int srclen = ...; // or if you don't know use strlen(src) + * char* dest = (char*) malloc(modp_b64_decode_len(srclen)); + * int len = modp_b64_decode(dest, src, sourcelen); + * if (len == -1) { error } + * \endcode + */ +enum class ModpDecodePolicy { + // src length must be divisible by 4, with a max of 2 pad chars. + kStrict, + + // Matches the infra spec: https://infra.spec.whatwg.org/#forgiving-base64 + // _except_ for ignoring whitespace (Step 1). + kForgiving, + + // src length % 4 must not equal 1, after stripping all pad chars. + // Accepts any number of pad chars. + kNoPaddingValidation, +}; +size_t modp_b64_decode( + char* dest, + const char* src, + size_t len, + ModpDecodePolicy policy = ModpDecodePolicy::kStrict); + +/** + * The maximum input that can be passed into modp_b64_encode{_data}. + * Lengths beyond this will overflow modp_b64_encode_len. + * + * This works because modp_b64_encode_len(A) computes: + * ceiling[max_len / 3] * 4 + 1 + * = ceiling[floor[(SIZE_MAX-1)/4]*3 / 3] * 4 + 1 + * = floor[(SIZE_MAX-1)/4] * 4 + 1 + * <= SIZE_MAX-1 + 1 + * = SIZE_MAX + * + * Note: technically modp_b64_encode_data can take one extra byte, but for + * simplicity the bound is shared between the two functions. + */ +#define MODP_B64_MAX_INPUT_LEN ((SIZE_MAX - 1) / 4 * 3) + +/** + * Given a source string of length len, this returns the amount of + * memory the destination string should have, for modp_b64_encode_data and + * modp_b64_encode, respectively. + * + * remember, this is integer math + * 3 bytes turn into 4 chars + * ceiling[len / 3] * 4 + * + * + * WARNING: These expressions will overflow if the A is above + * MODP_B64_MAX_INPUT_LEN. The caller must check this bound first. + */ +#define modp_b64_encode_data_len(A) ((A + 2) / 3 * 4) +#define modp_b64_encode_len(A) (modp_b64_encode_data_len(A) + 1) + +/** + * Given a base64 string of length len, + * this returns the amount of memory required for output string + * It maybe be more than the actual number of bytes written. + * NOTE: remember this is integer math + * this allocates a bit more memory than traditional versions of b64 + * decode 4 chars turn into 3 bytes + * floor[len * 3/4] + 2 + */ +#define modp_b64_decode_len(A) (A / 4 * 3 + 2) + +#define MODP_B64_ERROR ((size_t)-1) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MODP_B64 */ diff --git a/extern/modp_b64/modp_b64_data.h b/extern/modp_b64/modp_b64_data.h new file mode 100644 index 000000000..2ecf5977b --- /dev/null +++ b/extern/modp_b64/modp_b64_data.h @@ -0,0 +1,481 @@ +#include + +#define CHAR62 '+' +#define CHAR63 '/' +#define CHARPAD '=' +static const char e0[256] = { + 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', + 'C', 'C', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E', + 'F', 'F', 'F', 'F', 'G', 'G', 'G', 'G', 'H', 'H', + 'H', 'H', 'I', 'I', 'I', 'I', 'J', 'J', 'J', 'J', + 'K', 'K', 'K', 'K', 'L', 'L', 'L', 'L', 'M', 'M', + 'M', 'M', 'N', 'N', 'N', 'N', 'O', 'O', 'O', 'O', + 'P', 'P', 'P', 'P', 'Q', 'Q', 'Q', 'Q', 'R', 'R', + 'R', 'R', 'S', 'S', 'S', 'S', 'T', 'T', 'T', 'T', + 'U', 'U', 'U', 'U', 'V', 'V', 'V', 'V', 'W', 'W', + 'W', 'W', 'X', 'X', 'X', 'X', 'Y', 'Y', 'Y', 'Y', + 'Z', 'Z', 'Z', 'Z', 'a', 'a', 'a', 'a', 'b', 'b', + 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd', + 'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g', + 'g', 'g', 'h', 'h', 'h', 'h', 'i', 'i', 'i', 'i', + 'j', 'j', 'j', 'j', 'k', 'k', 'k', 'k', 'l', 'l', + 'l', 'l', 'm', 'm', 'm', 'm', 'n', 'n', 'n', 'n', + 'o', 'o', 'o', 'o', 'p', 'p', 'p', 'p', 'q', 'q', + 'q', 'q', 'r', 'r', 'r', 'r', 's', 's', 's', 's', + 't', 't', 't', 't', 'u', 'u', 'u', 'u', 'v', 'v', + 'v', 'v', 'w', 'w', 'w', 'w', 'x', 'x', 'x', 'x', + 'y', 'y', 'y', 'y', 'z', 'z', 'z', 'z', '0', '0', + '0', '0', '1', '1', '1', '1', '2', '2', '2', '2', + '3', '3', '3', '3', '4', '4', '4', '4', '5', '5', + '5', '5', '6', '6', '6', '6', '7', '7', '7', '7', + '8', '8', '8', '8', '9', '9', '9', '9', '+', '+', + '+', '+', '/', '/', '/', '/' +}; + +static const char e1[256] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', + 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', '+', '/' +}; + +static const char e2[256] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', + 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', '+', '/' +}; + + + +#ifdef WORDS_BIGENDIAN + + +/* SPECIAL DECODE TABLES FOR BIG ENDIAN (IBM/MOTOROLA/SUN) CPUS */ + +static const uint32_t d0[256] = { +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x00f80000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00fc0000, +0x00d00000, 0x00d40000, 0x00d80000, 0x00dc0000, 0x00e00000, 0x00e40000, +0x00e80000, 0x00ec0000, 0x00f00000, 0x00f40000, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000, +0x00040000, 0x00080000, 0x000c0000, 0x00100000, 0x00140000, 0x00180000, +0x001c0000, 0x00200000, 0x00240000, 0x00280000, 0x002c0000, 0x00300000, +0x00340000, 0x00380000, 0x003c0000, 0x00400000, 0x00440000, 0x00480000, +0x004c0000, 0x00500000, 0x00540000, 0x00580000, 0x005c0000, 0x00600000, +0x00640000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x00680000, 0x006c0000, 0x00700000, 0x00740000, 0x00780000, +0x007c0000, 0x00800000, 0x00840000, 0x00880000, 0x008c0000, 0x00900000, +0x00940000, 0x00980000, 0x009c0000, 0x00a00000, 0x00a40000, 0x00a80000, +0x00ac0000, 0x00b00000, 0x00b40000, 0x00b80000, 0x00bc0000, 0x00c00000, +0x00c40000, 0x00c80000, 0x00cc0000, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff +}; + + +static const uint32_t d1[256] = { +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x0003e000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0003f000, +0x00034000, 0x00035000, 0x00036000, 0x00037000, 0x00038000, 0x00039000, +0x0003a000, 0x0003b000, 0x0003c000, 0x0003d000, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000, +0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000, +0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000, +0x0000d000, 0x0000e000, 0x0000f000, 0x00010000, 0x00011000, 0x00012000, +0x00013000, 0x00014000, 0x00015000, 0x00016000, 0x00017000, 0x00018000, +0x00019000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x0001a000, 0x0001b000, 0x0001c000, 0x0001d000, 0x0001e000, +0x0001f000, 0x00020000, 0x00021000, 0x00022000, 0x00023000, 0x00024000, +0x00025000, 0x00026000, 0x00027000, 0x00028000, 0x00029000, 0x0002a000, +0x0002b000, 0x0002c000, 0x0002d000, 0x0002e000, 0x0002f000, 0x00030000, +0x00031000, 0x00032000, 0x00033000, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff +}; + + +static const uint32_t d2[256] = { +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x00000f80, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000fc0, +0x00000d00, 0x00000d40, 0x00000d80, 0x00000dc0, 0x00000e00, 0x00000e40, +0x00000e80, 0x00000ec0, 0x00000f00, 0x00000f40, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000, +0x00000040, 0x00000080, 0x000000c0, 0x00000100, 0x00000140, 0x00000180, +0x000001c0, 0x00000200, 0x00000240, 0x00000280, 0x000002c0, 0x00000300, +0x00000340, 0x00000380, 0x000003c0, 0x00000400, 0x00000440, 0x00000480, +0x000004c0, 0x00000500, 0x00000540, 0x00000580, 0x000005c0, 0x00000600, +0x00000640, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x00000680, 0x000006c0, 0x00000700, 0x00000740, 0x00000780, +0x000007c0, 0x00000800, 0x00000840, 0x00000880, 0x000008c0, 0x00000900, +0x00000940, 0x00000980, 0x000009c0, 0x00000a00, 0x00000a40, 0x00000a80, +0x00000ac0, 0x00000b00, 0x00000b40, 0x00000b80, 0x00000bc0, 0x00000c00, +0x00000c40, 0x00000c80, 0x00000cc0, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff +}; + + +static const uint32_t d3[256] = { +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x0000003e, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000003f, +0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, +0x0000003a, 0x0000003b, 0x0000003c, 0x0000003d, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000, +0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, +0x00000007, 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c, +0x0000000d, 0x0000000e, 0x0000000f, 0x00000010, 0x00000011, 0x00000012, +0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, 0x00000018, +0x00000019, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, 0x0000001e, +0x0000001f, 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024, +0x00000025, 0x00000026, 0x00000027, 0x00000028, 0x00000029, 0x0000002a, +0x0000002b, 0x0000002c, 0x0000002d, 0x0000002e, 0x0000002f, 0x00000030, +0x00000031, 0x00000032, 0x00000033, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff +}; + + +#else + + +/* SPECIAL DECODE TABLES FOR LITTLE ENDIAN (INTEL) CPUS */ + +static const uint32_t d0[256] = { +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x000000f8, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x000000fc, +0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4, +0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000, +0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018, +0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030, +0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048, +0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060, +0x00000064, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078, +0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090, +0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8, +0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0, +0x000000c4, 0x000000c8, 0x000000cc, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff +}; + + +static const uint32_t d1[256] = { +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x0000e003, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000f003, +0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003, +0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000, +0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000, +0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000, +0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001, +0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001, +0x00009001, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001, +0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002, +0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002, +0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003, +0x00001003, 0x00002003, 0x00003003, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff +}; + + +static const uint32_t d2[256] = { +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x00800f00, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00c00f00, +0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00, +0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000, +0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100, +0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300, +0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400, +0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600, +0x00400600, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700, +0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900, +0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00, +0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00, +0x00400c00, 0x00800c00, 0x00c00c00, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff +}; + + +static const uint32_t d3[256] = { +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x003e0000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x003f0000, +0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000, +0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000, +0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000, +0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000, +0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000, +0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000, +0x00190000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000, +0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000, +0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000, +0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000, +0x00310000, 0x00320000, 0x00330000, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, +0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff +}; + + +#endif From 1373e11effa9736237c13174c7c5437f50e01a61 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 30 May 2024 11:22:23 +1200 Subject: [PATCH 006/112] extern: added a small README.rst file. --- extern/README.rst | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 extern/README.rst diff --git a/extern/README.rst b/extern/README.rst new file mode 100644 index 000000000..4ec805e5b --- /dev/null +++ b/extern/README.rst @@ -0,0 +1,5 @@ +`libOpenCOR `__ relies on the following external projects: + +- `GoogleTest `__ at commit `305e5a2 `__; +- `modp_b64 `__ at commit `5090e77 `__; and +- `pybind11 `__ `2.12.0 `__. From 08e37d04c2a9f4a29f8d23963bdfa96e7d2d0c09 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 30 May 2024 11:44:16 +1200 Subject: [PATCH 007/112] CMake: improved the way we build clcachewrapper. --- src/CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c443b66f..9ac2f9ef2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,13 +19,12 @@ if(LIBOPENCOR_COMPILER_CACHING) set(CMAKE_C_COMPILER_LAUNCHER ${BUILDCACHE_EXE}) set(CMAKE_CXX_COMPILER_LAUNCHER ${BUILDCACHE_EXE}) elseif(CLCACHE_EXE) - set(CLCACHEWRAPPER ${CMAKE_CURRENT_BINARY_DIR}/clcachewrapper) + set(CLCACHEWRAPPER ${CMAKE_BINARY_DIR}/clcachewrapper) - execute_process(COMMAND ${CMAKE_C_COMPILER} /O2 /Fe${CLCACHEWRAPPER} ${CMAKE_SOURCE_DIR}/cmake/clcachewrapper.c - RESULT_VARIABLE RESULT - OUTPUT_QUIET ERROR_QUIET) + try_compile(CLCACHEWRAPPER_EXE ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/cmake/clcachewrapper.c + COPY_FILE ${CLCACHEWRAPPER}) - if(RESULT EQUAL 0) + if(CLCACHEWRAPPER_EXE) set(CMAKE_C_COMPILER_LAUNCHER ${CLCACHEWRAPPER}) set(CMAKE_CXX_COMPILER_LAUNCHER ${CLCACHEWRAPPER}) endif() From 30c71176554301d4d9e9e9c9f026558ddb7bb305 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 30 May 2024 13:11:25 +1200 Subject: [PATCH 008/112] clcachewrapper: some minor cleaning up. --- cmake/clcachewrapper.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/clcachewrapper.c b/cmake/clcachewrapper.c index 2580787f6..cc6e57378 100644 --- a/cmake/clcachewrapper.c +++ b/cmake/clcachewrapper.c @@ -17,7 +17,7 @@ limitations under the License. #include #include -int main(int argc, char *argv[]) +int main(int pArgC, char *pArgV[]) { // Call clcache with the given arguments, except the first one, which is the // full path to the MSVC compiler. @@ -27,15 +27,15 @@ int main(int argc, char *argv[]) char clcacheCommand[STRING_SIZE] = "clcache"; int k = 6; - for (int i = 2; i < argc; ++i) { + for (int i = 2; i < pArgC; ++i) { clcacheCommand[++k] = ' '; - for (int j = 0; argv[i][j]; ++j) { - if (argv[i][j] == '\\') { + for (int j = 0; pArgV[i][j]; ++j) { + if (pArgV[i][j] == '\\') { clcacheCommand[++k] = '\\'; clcacheCommand[++k] = '\\'; } else { - clcacheCommand[++k] = argv[i][j]; + clcacheCommand[++k] = pArgV[i][j]; } } } From 347a258a8edfbba6caf2e2550d55192103db2d31 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 30 May 2024 13:59:14 +1200 Subject: [PATCH 009/112] CMake: added a small base64 encoder. --- cmake/base64encoder.cpp | 57 +++++++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 13 ++++++++++ 2 files changed, 70 insertions(+) create mode 100644 cmake/base64encoder.cpp diff --git a/cmake/base64encoder.cpp b/cmake/base64encoder.cpp new file mode 100644 index 000000000..0621bb70e --- /dev/null +++ b/cmake/base64encoder.cpp @@ -0,0 +1,57 @@ +/* +Copyright libOpenCOR contributors. + +Licensed 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. +*/ + +#include "../extern/modp_b64/modp_b64.h" + +#include +#include +#include + +int main(int pArgC, char *pArgV[]) +{ + // Convert the given file to a base64-encoded string. + + if (pArgC != 2) { + std::cerr << "Usage: " << pArgV[0] << " " << std::endl; + + return 1; + } + + std::uintmax_t fileSize = std::filesystem::file_size(pArgV[1]); + char *buffer = new char[fileSize]; + std::ifstream file(pArgV[1], std::ios::binary); + + file.read(buffer, fileSize); + + if (!file) { + std::cerr << "Error: the file could not be read." << std::endl; + + return 1; + } + + file.close(); + + char *base64 = new char[modp_b64_encode_len(fileSize)]; + + modp_b64_encode(base64, buffer, fileSize); + + std::cout << base64 << std::endl; + + delete[] base64; + delete[] buffer; + + return 0; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5f203b25f..ec67886ff 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,6 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Generate our base64 encoder. + +set(BASE64ENCODER ${CMAKE_BINARY_DIR}/base64encoder) + +try_compile(BASE64ENCODER_EXE ${CMAKE_BINARY_DIR} + SOURCES ${CMAKE_SOURCE_DIR}/cmake/base64encoder.cpp + ${CMAKE_SOURCE_DIR}/extern/modp_b64/modp_b64.cc + COPY_FILE ${BASE64ENCODER}) + +if(NOT BASE64ENCODER_EXE) + message(FATAL_ERROR "base64encoder could not be built...") +endif() + # Include our different tests. include(api/file/tests.cmake) From 4f7ccb0190cde9c0c4b43d318a84406b0b28f990 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 30 May 2024 19:07:53 +1200 Subject: [PATCH 010/112] Python: make the contents of a file a property. Rather than have both a setter and a getter. IOW, make it more Pythonic. --- src/bindings/python/file.cpp | 3 +-- tests/bindings/python/test_file_basic.py | 4 ++-- tests/bindings/python/test_file_coverage.py | 2 +- tests/bindings/python/test_file_type.py | 6 +++--- tests/bindings/python/test_sed_serialise.py | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/bindings/python/file.cpp b/src/bindings/python/file.cpp index 9e7a8940e..90c266c00 100644 --- a/src/bindings/python/file.cpp +++ b/src/bindings/python/file.cpp @@ -40,6 +40,5 @@ void fileApi(py::module_ &m) .def_property_readonly("file_name", &libOpenCOR::File::fileName, "Get the file name for this File object.") .def_property_readonly("url", &libOpenCOR::File::url, "Get the URL for this File object.") .def_property_readonly("path", &libOpenCOR::File::path, "Get the path for this File object.") - .def_property_readonly("contents", &libOpenCOR::File::contents, "Get the contents of this File object.") - .def("set_contents", &libOpenCOR::File::setContents, "Set the contents of this File object."); + .def_property("contents", &libOpenCOR::File::contents, &libOpenCOR::File::setContents, "The contents of this File object."); } diff --git a/tests/bindings/python/test_file_basic.py b/tests/bindings/python/test_file_basic.py index d3fafe002..eb5bebb3c 100644 --- a/tests/bindings/python/test_file_basic.py +++ b/tests/bindings/python/test_file_basic.py @@ -104,7 +104,7 @@ def test_local_virtual_file(): some_unknown_contents_list = utils.string_to_list(utils.SOME_UNKNOWN_CONTENTS) - file.set_contents(some_unknown_contents_list) + file.contents = some_unknown_contents_list assert file.type == File.Type.UnknownFile assert file.contents == some_unknown_contents_list @@ -123,7 +123,7 @@ def test_remote_virtual_file(): some_unknown_contents_list = utils.string_to_list(utils.SOME_UNKNOWN_CONTENTS) - file.set_contents(some_unknown_contents_list) + file.contents = some_unknown_contents_list assert file.type == File.Type.UnknownFile assert file.contents == some_unknown_contents_list diff --git a/tests/bindings/python/test_file_coverage.py b/tests/bindings/python/test_file_coverage.py index 0a7f84441..220081106 100644 --- a/tests/bindings/python/test_file_coverage.py +++ b/tests/bindings/python/test_file_coverage.py @@ -20,7 +20,7 @@ def test_empty_file(): file = File(utils.LOCAL_FILE) - file.set_contents(utils.string_to_list(utils.NO_CONTENTS)) + file.contents = utils.string_to_list(utils.NO_CONTENTS) assert file.type == File.Type.UnknownFile diff --git a/tests/bindings/python/test_file_type.py b/tests/bindings/python/test_file_type.py index 7e83eeadb..3469f46f2 100644 --- a/tests/bindings/python/test_file_type.py +++ b/tests/bindings/python/test_file_type.py @@ -96,7 +96,7 @@ def test_type_combine_2_archive(): def test_type_unknown_virtual_file(): file = File(utils.LOCAL_FILE) - file.set_contents(utils.string_to_list(utils.SOME_UNKNOWN_CONTENTS)) + file.contents = utils.string_to_list(utils.SOME_UNKNOWN_CONTENTS) assert file.type == File.Type.UnknownFile assert_issues(file, expected_unknown_file_issues) @@ -105,7 +105,7 @@ def test_type_unknown_virtual_file(): def test_type_cellml_virtual_file(): file = File(utils.LOCAL_FILE) - file.set_contents(utils.string_to_list(utils.SOME_CELLML_CONTENTS)) + file.contents = utils.string_to_list(utils.SOME_CELLML_CONTENTS) assert file.type == File.Type.CellmlFile @@ -113,6 +113,6 @@ def test_type_cellml_virtual_file(): def test_type_sedml_virtual_file(): file = File(utils.LOCAL_FILE) - file.set_contents(utils.string_to_list(utils.SOME_SEDML_CONTENTS)) + file.contents = utils.string_to_list(utils.SOME_SEDML_CONTENTS) assert file.type == File.Type.SedmlFile diff --git a/tests/bindings/python/test_sed_serialise.py b/tests/bindings/python/test_sed_serialise.py index 0a91a8eb2..feeaf7b24 100644 --- a/tests/bindings/python/test_sed_serialise.py +++ b/tests/bindings/python/test_sed_serialise.py @@ -126,7 +126,7 @@ def test_local_cellml_file_with_base_path(): def test_local_cellml_file_without_base_path(): file = File(utils.LOCAL_FILE) - file.set_contents(utils.string_to_list(utils.SOME_CELLML_CONTENTS)) + file.contents = utils.string_to_list(utils.SOME_CELLML_CONTENTS) document = SedDocument(file) @@ -152,7 +152,7 @@ def test_relative_local_cellml_file_with_base_path(): def test_relative_local_cellml_file_without_base_path(): file = File(utils.CELLML_2_FILE) - file.set_contents(utils.string_to_list(utils.SOME_CELLML_CONTENTS)) + file.contents = utils.string_to_list(utils.SOME_CELLML_CONTENTS) document = SedDocument(file) From dbcd3f0e127045cec039df4c2acde44c2820f959 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 30 May 2024 16:18:35 +1200 Subject: [PATCH 011/112] Tests: added a test for a virtual COMBINE archive. --- cmake/common.cmake | 11 +++++++++++ src/support/combine/combinearchive.cpp | 22 +++++++++++++-------- src/support/sedml/sedmlfile.cpp | 6 ++++-- tests/CMakeLists.txt | 8 +++++++- tests/api/file/typetests.cpp | 9 +++++++++ tests/bindings/javascript/file.type.test.js | 17 ++++++++++++++++ tests/bindings/javascript/sed.basic.test.js | 17 +++++++++------- tests/bindings/javascript/utils.js.in | 7 ++++--- tests/bindings/python/test_file_type.py | 8 ++++++++ tests/bindings/python/utils.py.in | 8 ++++++++ tests/utils.cpp | 13 ++++++++++++ tests/utils.h.in | 3 +++ 12 files changed, 108 insertions(+), 21 deletions(-) diff --git a/cmake/common.cmake b/cmake/common.cmake index 7062041a7..b638e4ae0 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -386,14 +386,25 @@ endfunction() function(prepare_test TARGET) # Prepare the given test. + # Note: we don't want modp_b64.cc to be subjected to Clang-Tidy, hence we compile it separately. From Cmake 3.27,, + # we could use the CXX_CLANG_TIDY property to exclude it from Clang-Tidy, but for some reasons it's not + # working, so we compile it separately (as suggested at https://stackoverflow.com/a/75858167). add_executable(${TARGET} ${ARGN}) add_dependencies(${TARGET} ${CMAKE_PROJECT_NAME}) + set(MODP_B64_TARGET ${TARGET}_modp_b64) + + add_library(${MODP_B64_TARGET} OBJECT ${CMAKE_SOURCE_DIR}/extern/modp_b64/modp_b64.cc) + + set_target_properties(${MODP_B64_TARGET} PROPERTIES + CXX_CLANG_TIDY "") + target_link_libraries(${TARGET} PRIVATE gtest_main + ${MODP_B64_TARGET} ${CMAKE_PROJECT_NAME}) configure_target(${TARGET}) diff --git a/src/support/combine/combinearchive.cpp b/src/support/combine/combinearchive.cpp index 2bda46591..6a84d5011 100644 --- a/src/support/combine/combinearchive.cpp +++ b/src/support/combine/combinearchive.cpp @@ -56,21 +56,27 @@ const CombineArchive::Impl *CombineArchive::pimpl() const CombineArchivePtr CombineArchive::create(const FilePtr &pFile) { -#ifdef __EMSCRIPTEN__ - (void)pFile; -#else // Try to retrieve a COMBINE archive. + // Note: a COMBINE archive is a ZIP file, so we make sure that it starts with 0x04034b50, which is the magic number + // used by a ZIP file (we ignore empty and spanned ZIP files). Indeed, libCOMBINE may crash depending on the + // file contents that is given to it. + + static const auto LS8 = 8U; + static const auto LS16 = 16U; + static const auto LS24 = 24U; + static const auto ZIP_MAGIC_NUMBER = 0x04034b50; - auto *archive = new libcombine::CombineArchive {}; auto fileContents = pFile->contents(); - if (archive->initializeFromArchive(fileContents)) { + if ((fileContents.size() > 4) + && (fileContents[0] + (fileContents[1] << LS8) + (fileContents[2] << LS16) + (fileContents[3] << LS24) == ZIP_MAGIC_NUMBER)) { + auto *archive = new libcombine::CombineArchive {}; + + archive->initializeFromArchive(fileContents); + return CombineArchivePtr {new CombineArchive {archive}}; } - delete archive; -#endif - return nullptr; } diff --git a/src/support/sedml/sedmlfile.cpp b/src/support/sedml/sedmlfile.cpp index b56b3b9d4..c7090bf54 100644 --- a/src/support/sedml/sedmlfile.cpp +++ b/src/support/sedml/sedmlfile.cpp @@ -63,8 +63,10 @@ SedmlFilePtr SedmlFile::create(const FilePtr &pFile) { // Try to retrieve a SED-ML document. - if (!pFile->contents().empty()) { - auto *document = libsedml::readSedMLFromString(toString(pFile->contents()).c_str()); + auto fileContents = pFile->contents(); + + if (!fileContents.empty()) { + auto *document = libsedml::readSedMLFromString(toString(fileContents).c_str()); // A non-SED-ML file results in our SED-ML document having at least one error, the first of which being of id // libsedml::SedNotSchemaConformant (e.g., a CellML file, i.e. an XML file, but not a SED-ML one) or diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ec67886ff..83b182bd9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -65,6 +65,10 @@ string(REGEX REPLACE "\n" "\" \\n\"" SOME_WARNING_CELLML_CONTENTS_C "${SOME_WARN string(REPLACE "\"" "\\\"" SOME_SEDML_CONTENTS "${SOME_SEDML_CONTENTS}") string(REGEX REPLACE "\n" "\" \\n\"" SOME_SEDML_CONTENTS_C "${SOME_SEDML_CONTENTS}") +execute_process(COMMAND ${BASE64ENCODER} "${CMAKE_CURRENT_SOURCE_DIR}/res/cellml_2.omex" + OUTPUT_VARIABLE SOME_BASE64_COMBINE_ARCHIVE_CONTENTS + OUTPUT_STRIP_TRAILING_WHITESPACE) + file(READ res/api/solver/ode/model.cellml SOME_ODE_MODEL_CONTENTS) file(READ res/api/solver/nla/model1.cellml SOME_DAE_MODEL1_CONTENTS) file(READ res/api/solver/nla/model2.cellml SOME_DAE_MODEL2_CONTENTS) @@ -100,7 +104,9 @@ foreach(TEST ${TESTS}) set(TEST_CATEGORY "${${TEST}_CATEGORY}_") endif() - prepare_test(${TEST_CATEGORY}${TEST}_tests ${${TEST}_SOURCE_FILES} ${UTILS_SOURCE_FILE}) + prepare_test(${TEST_CATEGORY}${TEST}_tests + ${${TEST}_SOURCE_FILES} + ${UTILS_SOURCE_FILE}) endif() list(APPEND GIT_TESTS_SOURCE_FILES ${${TEST}_SOURCE_FILES}) diff --git a/tests/api/file/typetests.cpp b/tests/api/file/typetests.cpp index 7b62572c0..7ca00e0a9 100644 --- a/tests/api/file/typetests.cpp +++ b/tests/api/file/typetests.cpp @@ -126,3 +126,12 @@ TEST(TypeFileTest, sedmlVirtualFile) EXPECT_EQ(file->type(), libOpenCOR::File::Type::SEDML_FILE); } + +TEST(TypeFileTest, combineVirtualArchive) +{ + auto file = libOpenCOR::File::create(libOpenCOR::LOCAL_FILE); + + file->setContents(libOpenCOR::base64Decode(libOpenCOR::SOME_BASE64_COMBINE_ARCHIVE_CONTENTS)); + + EXPECT_EQ(file->type(), libOpenCOR::File::Type::COMBINE_ARCHIVE); +} diff --git a/tests/bindings/javascript/file.type.test.js b/tests/bindings/javascript/file.type.test.js index c73703322..547876aa8 100644 --- a/tests/bindings/javascript/file.type.test.js +++ b/tests/bindings/javascript/file.type.test.js @@ -24,6 +24,7 @@ describe("File type tests", () => { let someUnknownContentsPtr; let someCellmlContentsPtr; let someSedmlContentsPtr; + let someCombineArchiveContentsPtr; beforeAll(() => { someUnknownContentsPtr = utils.allocateMemory( @@ -38,12 +39,17 @@ describe("File type tests", () => { libopencor, utils.SOME_SEDML_CONTENTS, ); + someCombineArchiveContentsPtr = utils.allocateMemory( + libopencor, + utils.SOME_COMBINE_ARCHIVE_CONTENTS, + ); }); afterAll(() => { utils.freeMemory(libopencor, someUnknownContentsPtr); utils.freeMemory(libopencor, someCellmlContentsPtr); utils.freeMemory(libopencor, someSedmlContentsPtr); + utils.freeMemory(libopencor, someCombineArchiveContentsPtr); }); test("Unknown file", () => { @@ -78,4 +84,15 @@ describe("File type tests", () => { expect(file.type().value).toBe(libopencor.File.Type.SEDML_FILE.value); }); + + test("COMBINE archive", () => { + const file = new libopencor.File(utils.LOCAL_FILE); + + file.setContents( + someCombineArchiveContentsPtr, + utils.SOME_COMBINE_ARCHIVE_CONTENTS.length, + ); + + expect(file.type().value).toBe(libopencor.File.Type.COMBINE_ARCHIVE.value); + }); }); diff --git a/tests/bindings/javascript/sed.basic.test.js b/tests/bindings/javascript/sed.basic.test.js index d7d71f51a..59edb5ba8 100644 --- a/tests/bindings/javascript/sed.basic.test.js +++ b/tests/bindings/javascript/sed.basic.test.js @@ -21,11 +21,15 @@ import { expectIssues } from "./utils.js"; const libopencor = await libOpenCOR(); describe("Sed basic tests", () => { + let someUnknownContentsPtr; let someCellmlContentsPtr; let someSedmlContentsPtr; - let someUnknownContentsPtr; beforeAll(() => { + someUnknownContentsPtr = utils.allocateMemory( + libopencor, + utils.SOME_UNKNOWN_CONTENTS, + ); someCellmlContentsPtr = utils.allocateMemory( libopencor, utils.SOME_CELLML_CONTENTS, @@ -34,16 +38,12 @@ describe("Sed basic tests", () => { libopencor, utils.SOME_SEDML_CONTENTS, ); - someUnknownContentsPtr = utils.allocateMemory( - libopencor, - utils.SOME_UNKNOWN_CONTENTS, - ); }); afterAll(() => { + utils.freeMemory(libopencor, someUnknownContentsPtr); utils.freeMemory(libopencor, someCellmlContentsPtr); utils.freeMemory(libopencor, someSedmlContentsPtr); - utils.freeMemory(libopencor, someUnknownContentsPtr); }); test("No file", () => { @@ -99,7 +99,10 @@ describe("Sed basic tests", () => { test("COMBINE archive", () => { const file = new libopencor.File(utils.LOCAL_FILE); - file.setContents(someCombineContentsPtr, utils.SOME_COMBINE_CONTENTS.length); + file.setContents( + utils.SOME_COMBINE_ARCHIVE_CONTENTS,//someCombineArchiveContentsPtr, + utils.SOME_COMBINE_ARCHIVE_CONTENTS.length, + ); const document = new libopencor.SedDocument(file); diff --git a/tests/bindings/javascript/utils.js.in b/tests/bindings/javascript/utils.js.in index 399714b27..9d26b2061 100644 --- a/tests/bindings/javascript/utils.js.in +++ b/tests/bindings/javascript/utils.js.in @@ -40,6 +40,9 @@ export const SOME_WARNING_CELLML_CONTENTS = stringToArrayBuffer( `@SOME_WARNING_CELLML_CONTENTS@`, ); export const SOME_SEDML_CONTENTS = stringToArrayBuffer(`@SOME_SEDML_CONTENTS@`); +export const SOME_COMBINE_ARCHIVE_CONTENTS = stringToArrayBuffer( + atob("@SOME_BASE64_COMBINE_ARCHIVE_CONTENTS@"), +); export const SOME_ODE_MODEL_CONTENTS = stringToArrayBuffer( `@SOME_ODE_MODEL_CONTENTS@`, @@ -124,7 +127,5 @@ export function freeMemory(module, memPtr) { } function stringToArrayBuffer(string) { - const encoder = new TextEncoder(); - - return encoder.encode(string); + return Uint8Array.from(string, (c) => c.charCodeAt(0)); } diff --git a/tests/bindings/python/test_file_type.py b/tests/bindings/python/test_file_type.py index 3469f46f2..ef8b4ef52 100644 --- a/tests/bindings/python/test_file_type.py +++ b/tests/bindings/python/test_file_type.py @@ -116,3 +116,11 @@ def test_type_sedml_virtual_file(): file.contents = utils.string_to_list(utils.SOME_SEDML_CONTENTS) assert file.type == File.Type.SedmlFile + + +def test_type_combine_virtual_archive(): + file = File(utils.LOCAL_FILE) + + file.contents = utils.binary_to_list(utils.SOME_COMBINE_ARCHIVE_CONTENTS) + + assert file.type == File.Type.CombineArchive diff --git a/tests/bindings/python/utils.py.in b/tests/bindings/python/utils.py.in index b6afe262b..d771a78b2 100644 --- a/tests/bindings/python/utils.py.in +++ b/tests/bindings/python/utils.py.in @@ -13,6 +13,7 @@ # limitations under the License. +import base64 from libopencor import ( Issue, ) @@ -56,6 +57,9 @@ SOME_CELLML_CONTENTS = """@SOME_CELLML_CONTENTS@""" SOME_ERROR_CELLML_CONTENTS = """@SOME_ERROR_CELLML_CONTENTS@""" SOME_WARNING_CELLML_CONTENTS = """@SOME_WARNING_CELLML_CONTENTS@""" SOME_SEDML_CONTENTS = """@SOME_SEDML_CONTENTS@""" +SOME_COMBINE_ARCHIVE_CONTENTS = base64.b64decode( + b"@SOME_BASE64_COMBINE_ARCHIVE_CONTENTS@" +) def assert_issues(logger, expected_issues): @@ -107,3 +111,7 @@ def resource_path(relative_path=""): def string_to_list(string): return [ord(x) for x in string] + + +def binary_to_list(string): + return [x for x in string] diff --git a/tests/utils.cpp b/tests/utils.cpp index 16763b07b..4619e42c4 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -18,6 +18,8 @@ limitations under the License. #include "tests/utils.h" +#include "../extern/modp_b64/modp_b64.h" + #include #include @@ -100,4 +102,15 @@ UnsignedChars charArrayToUnsignedChars(const char *pContents) return {pContents, pContents + strlen(pContents)}; // NOLINT } +UnsignedChars base64Decode(const char *pContents) +{ + char *buffer = new char[modp_b64_decode_len(strlen(pContents))]; + const size_t length = modp_b64_decode(buffer, pContents, strlen(pContents)); + UnsignedChars res(buffer, buffer + length); // NOLINT + + delete[] buffer; + + return res; +} + } // namespace libOpenCOR diff --git a/tests/utils.h.in b/tests/utils.h.in index fe31c4d3a..6bb8d815d 100644 --- a/tests/utils.h.in +++ b/tests/utils.h.in @@ -63,6 +63,7 @@ static constexpr auto SOME_CELLML_CONTENTS = "@SOME_CELLML_CONTENTS_C@"; static constexpr auto SOME_ERROR_CELLML_CONTENTS = "@SOME_ERROR_CELLML_CONTENTS_C@"; static constexpr auto SOME_WARNING_CELLML_CONTENTS = "@SOME_WARNING_CELLML_CONTENTS_C@"; static constexpr auto SOME_SEDML_CONTENTS = "@SOME_SEDML_CONTENTS_C@"; +static constexpr auto SOME_BASE64_COMBINE_ARCHIVE_CONTENTS = "@SOME_BASE64_COMBINE_ARCHIVE_CONTENTS@"; void printIssues(const LoggerPtr &pLogger); @@ -94,4 +95,6 @@ std::string textFileContents(const std::string &pFileName); UnsignedChars charArrayToUnsignedChars(const char *pContents); +UnsignedChars base64Decode(const char *pContents); + } // namespace libOpenCOR From f900bc96ba1dd2e53b69c679604bc82fa1c2ad73 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 4 Jun 2024 13:33:55 +1200 Subject: [PATCH 012/112] libCOMBINE: new binaries. After having added some buffer-related methods to libCOMBINE. --- src/3rdparty/libCOMBINE/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/3rdparty/libCOMBINE/CMakeLists.txt b/src/3rdparty/libCOMBINE/CMakeLists.txt index a168e57e0..2b7a0e992 100644 --- a/src/3rdparty/libCOMBINE/CMakeLists.txt +++ b/src/3rdparty/libCOMBINE/CMakeLists.txt @@ -28,32 +28,32 @@ if(LIBOPENCOR_PREBUILT_LIBCOMBINE) if(EMSCRIPTEN) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - e6f2c3c963b6a6b5e5cbc66919624327b9e36696) + a6d9d575c87fb803fe63680d2b039e4e2aa4baed) else() if(WIN32) if(RELEASE_MODE) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - da9487061b1b816b49467a883c3d59e6ac029ccc) + c4d636fa1427eb6bb702e1e94a1b7149efd2ffb8) else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 8202f992c22c3d6f98b53b99bb0795f6348e634f) + 6940a27fc80f5171072d7d3a0824e641811bc6b8) endif() elseif(APPLE) if(INTEL_MODE) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 43906fcb976cd8187785a568ce0e489fc542b98f) + 0ad5a14ebbffd57c126d777116fa1f22aaa47ab0) else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - d480d451fbc16189c0238fe3bff70db5fe5c0ba3) + 1eb9641b388e060e99cf52da93f83f5e17a4d78e) endif() else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 8b2773d0cf12e4a343380178d14af8e7d9984165) + 2e0a1cd907d3fad09c20b8378e230ac10ba4a913) endif() endif() else() From 687faeb4ffbcdc2ac85b52474d48587a1f7da26d Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 4 Jun 2024 13:43:37 +1200 Subject: [PATCH 013/112] Account for our new libCOMBINE binaries. --- src/support/combine/combinearchive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/support/combine/combinearchive.cpp b/src/support/combine/combinearchive.cpp index 6a84d5011..c143815e2 100644 --- a/src/support/combine/combinearchive.cpp +++ b/src/support/combine/combinearchive.cpp @@ -72,7 +72,7 @@ CombineArchivePtr CombineArchive::create(const FilePtr &pFile) && (fileContents[0] + (fileContents[1] << LS8) + (fileContents[2] << LS16) + (fileContents[3] << LS24) == ZIP_MAGIC_NUMBER)) { auto *archive = new libcombine::CombineArchive {}; - archive->initializeFromArchive(fileContents); + archive->initializeFromBuffer(fileContents); return CombineArchivePtr {new CombineArchive {archive}}; } From 142ecc105f70018bde7fd479db491a1567abb2e6 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 4 Jun 2024 14:59:11 +1200 Subject: [PATCH 014/112] Test page: use LightningChart 4.2.1. ... since our license key for version 5 has now expired (!!). --- tests/bindings/javascript/res/index.html | 2 +- tests/bindings/javascript/res/res/libopencor.js | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/bindings/javascript/res/index.html b/tests/bindings/javascript/res/index.html index 431f56841..7c6aba38b 100644 --- a/tests/bindings/javascript/res/index.html +++ b/tests/bindings/javascript/res/index.html @@ -178,7 +178,7 @@ - + From 6767fb6cd8c368f395d2a79427fd610888f63d6e Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Sat, 22 Jun 2024 22:10:50 +1200 Subject: [PATCH 059/112] Test page: only show the simulation UI when we have a known file. --- .../bindings/javascript/res/res/libopencor.js | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/bindings/javascript/res/res/libopencor.js b/tests/bindings/javascript/res/res/libopencor.js index eebc65bc7..57fdad2c9 100644 --- a/tests/bindings/javascript/res/res/libopencor.js +++ b/tests/bindings/javascript/res/res/libopencor.js @@ -33,7 +33,7 @@ function showError(error) { $("#errorMessage").html(error); - updateFileUi(false, false, true, true); + updateFileUi(false, false, true, true, false); } function updateFileUi( @@ -41,15 +41,15 @@ function updateFileUi( fileIssuesDisplay, fileErrorDisplay, resetButtonDisplay, + simulationDisplay, ) { $("#fileInfo").css("display", fileInfoDisplay ? "block" : "none"); $("#fileIssues").css("display", fileIssuesDisplay ? "block" : "none"); $("#fileError").css("display", fileErrorDisplay ? "block" : "none"); $("#resetFile").css("display", resetButtonDisplay ? "block" : "none"); - $("#simulation").css( - "display", - fileInfoDisplay && !fileIssuesDisplay ? "block" : "none", - ); + $("#simulation").css("display", simulationDisplay ? "block" : "none"); + + listFiles(); } function resetObjects() { @@ -75,7 +75,7 @@ function resetObjects() { export function resetFile() { $("#dropAreaInput").value = ""; - updateFileUi(false, false, false, false); + updateFileUi(false, false, false, false, false); resetObjects(); } @@ -211,6 +211,7 @@ $(() => { // Determine the type of the file. let fileType = "some unknown file"; + let knownFile = true; if (file.type() === libopencor.File.Type.CELLML_FILE) { fileType = "a CellML file"; @@ -218,6 +219,8 @@ $(() => { fileType = "a SED-ML file"; } else if (file.type() === libopencor.File.Type.COMBINE_ARCHIVE) { fileType = "a COMBINE archive"; + } else { + knownFile = false; } $("#fileName").html(inputFile.name); @@ -225,7 +228,7 @@ $(() => { // Display any issues with the file or run it. - let showIssues = false; + let hasIssues = false; if (file.type() === libopencor.File.Type.CELLML_FILE) { if (file.hasIssues()) { @@ -246,7 +249,7 @@ $(() => { ); } - showIssues = true; + hasIssues = true; } else { // Retrieve some information about the simulation. @@ -280,7 +283,7 @@ $(() => { } } - updateFileUi(true, showIssues, false, true); + updateFileUi(true, hasIssues, false, true, knownFile && !hasIssues); } catch (exception) { showError(exception.message); } From e3e17b1a28c7940fc6733bd0a640987c04de546c Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Sat, 22 Jun 2024 22:11:00 +1200 Subject: [PATCH 060/112] Test page: list files. --- .../bindings/javascript/res/res/libopencor.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/bindings/javascript/res/res/libopencor.js b/tests/bindings/javascript/res/res/libopencor.js index 57fdad2c9..b8c417f47 100644 --- a/tests/bindings/javascript/res/res/libopencor.js +++ b/tests/bindings/javascript/res/res/libopencor.js @@ -1,3 +1,4 @@ +let fileManager = null; let file = null; let document = null; let simulation = null; @@ -36,6 +37,20 @@ function showError(error) { updateFileUi(false, false, true, true, false); } +function listFiles() { + if (fileManager.hasFiles()) { + console.log("Files:"); + + const files = fileManager.files(); + + for (let i = 0; i < files.size(); ++i) { + console.log(" - " + files.get(i).fileName()); + } + } else { + console.log("No files."); + } +} + function updateFileUi( fileInfoDisplay, fileIssuesDisplay, @@ -78,6 +93,8 @@ export function resetFile() { updateFileUi(false, false, false, false, false); resetObjects(); + + listFiles(); } function addAxisElement(axis, name) { @@ -173,6 +190,10 @@ $(() => { // Make sure that libOpenCOR is loaded before we do anything else. libOpenCOR().then((libopencor) => { + // Keep track of the file manager. + + fileManager = libopencor.FileManager.instance(); + // Simulation page. const input = $("#dropAreaInput")[0]; From 1ea163dac99ba24de78735f6eb688a7e5719631a Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Sun, 23 Jun 2024 16:43:42 +1200 Subject: [PATCH 061/112] FileManager: some minor cleaning up. --- src/api/libopencor/filemanager.h | 20 ++++++++++---------- src/bindings/python/file.cpp | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/api/libopencor/filemanager.h b/src/api/libopencor/filemanager.h index 6fbe8181f..70dfb2b94 100644 --- a/src/api/libopencor/filemanager.h +++ b/src/api/libopencor/filemanager.h @@ -44,33 +44,33 @@ class LIBOPENCOR_EXPORT FileManager static FileManager &instance(); /** - * @brief Return whether there are some files. + * @brief Return whether there are managed files. * - * Return whether there are some files. + * Return whether there are managed files. * - * @return @c true if there are some files, @c false otherwise. + * @return @c true if there are managed files, @c false otherwise. */ bool hasFiles() const; /** - * @brief Return the files. + * @brief Return the managed files. * - * Return the files. + * Return the managed files. * - * @return The files, as an @ref FilePtrs. + * @return The managed files, as an @ref FilePtrs. */ FilePtrs files() const; /** - * @brief Get a given file. + * @brief Get a given managed file. * - * Get a given file. + * Get a given managed file. * - * @param pFileNameOrUrl The name of the file or its URL. + * @param pFileNameOrUrl The name of the managed file or its URL. * - * @return The file, as a @ref FilePtr, if it is managed by the file manager, @c nullptr otherwise. + * @return The managed file, as a @ref FilePtr, if it is managed by the file manager, @c nullptr otherwise. */ FilePtr file(const std::string &pFileNameOrUrl) const; diff --git a/src/bindings/python/file.cpp b/src/bindings/python/file.cpp index 2110c7e8f..5a7bdf6aa 100644 --- a/src/bindings/python/file.cpp +++ b/src/bindings/python/file.cpp @@ -50,7 +50,7 @@ void fileApi(py::module_ &m) py::class_> fileManager(m, "FileManager"); fileManager.def_static("instance", &libOpenCOR::FileManager::instance, "Get the file manager instance.") - .def("has_files", &libOpenCOR::FileManager::hasFiles, "Return whether there are some files.") - .def("files", &libOpenCOR::FileManager::files, "Return the files.") - .def("file", &libOpenCOR::FileManager::file, "Get the requested file.", py::arg("file_name_or_url")); + .def("has_files", &libOpenCOR::FileManager::hasFiles, "Return whether there are managed files.") + .def("files", &libOpenCOR::FileManager::files, "Return the managed files.") + .def("file", &libOpenCOR::FileManager::file, "Get the requested managed file.", py::arg("file_name_or_url")); } From efc4fbced3993a729ce545fcc8be0bdd209081d4 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Sun, 23 Jun 2024 22:00:21 +1200 Subject: [PATCH 062/112] Pimpl: some consistency. --- src/logger/issue.cpp | 47 +++++++++++++++++++++++++++++--------------- src/logger/issue_p.h | 4 ++++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/logger/issue.cpp b/src/logger/issue.cpp index 789466262..e99772976 100644 --- a/src/logger/issue.cpp +++ b/src/logger/issue.cpp @@ -24,32 +24,22 @@ Issue::Impl::Impl(Type pType, const std::string &pDescription) { } -Issue::Issue(Type pType, const std::string &pDescription) - : mPimpl(new Impl {pType, pDescription}) +Issue::Type Issue::Impl::type() const { + return mType; } -Issue::~Issue() -{ - delete mPimpl; -} - -Issue::Type Issue::type() const -{ - return mPimpl->mType; -} - -std::string Issue::typeAsString() const +std::string Issue::Impl::typeAsString() const { #ifdef CODE_COVERAGE_ENABLED - switch (mPimpl->mType) { + switch (mType) { case Type::ERROR: return "Error"; default: // Type::WARNING. return "Warning"; } #else - switch (mPimpl->mType) { + switch (mType) { case Type::ERROR: return "Error"; case Type::WARNING: @@ -60,9 +50,34 @@ std::string Issue::typeAsString() const #endif } +std::string Issue::Impl::description() const +{ + return mDescription; +} + +Issue::Issue(Type pType, const std::string &pDescription) + : mPimpl(new Impl {pType, pDescription}) +{ +} + +Issue::~Issue() +{ + delete mPimpl; +} + +Issue::Type Issue::type() const +{ + return mPimpl->type(); +} + +std::string Issue::typeAsString() const +{ + return mPimpl->typeAsString(); +} + std::string Issue::description() const { - return mPimpl->mDescription; + return mPimpl->description(); } } // namespace libOpenCOR diff --git a/src/logger/issue_p.h b/src/logger/issue_p.h index 0a5dd9258..824a9520f 100644 --- a/src/logger/issue_p.h +++ b/src/logger/issue_p.h @@ -28,6 +28,10 @@ class Issue::Impl explicit Impl(Type pType, const std::string &pDescription); ~Impl() = default; + + Type type() const; + std::string typeAsString() const; + std::string description() const; }; } // namespace libOpenCOR From 2137e25aa2b4650e092886b9ca9ee60969af8b92 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Sun, 23 Jun 2024 21:45:19 +1200 Subject: [PATCH 063/112] API: added an xxxCount() method to different classes. As well as to some internal classes. qwe qwe qwe qwe qwe qwe qwe --- src/api/libopencor/file.h | 10 ++++ src/api/libopencor/filemanager.h | 10 ++++ src/api/libopencor/logger.h | 40 +++++++++++++ src/api/libopencor/seddocument.h | 30 ++++++++++ src/bindings/javascript/file.cpp | 2 + src/bindings/javascript/logger.cpp | 4 ++ src/bindings/javascript/sed.cpp | 3 + src/bindings/python/file.cpp | 2 + src/bindings/python/logger.cpp | 4 ++ src/bindings/python/sed.cpp | 3 + src/file/file.cpp | 14 +++++ src/file/file_p.h | 1 + src/file/filemanager.cpp | 10 ++++ src/file/filemanager_p.h | 1 + src/logger/logger.cpp | 20 +++++++ src/sed/seddocument.cpp | 15 +++++ src/support/combine/combinearchive.cpp | 5 ++ src/support/combine/combinearchive.h | 1 + tests/api/file/basictests.cpp | 3 + tests/api/file/childtests.cpp | 2 + tests/api/logger/coveragetests.cpp | 42 +++++++++++++ tests/api/sed/coveragetests.cpp | 18 ++++++ tests/bindings/javascript/file.basic.test.js | 3 + tests/bindings/javascript/file.child.test.js | 2 + .../javascript/logger.coverage.test.js | 60 +++++++++++++++++++ .../bindings/javascript/sed.coverage.test.js | 18 ++++++ tests/bindings/python/test_file_basic.py | 3 + tests/bindings/python/test_file_child.py | 2 + tests/bindings/python/test_logger_coverage.py | 36 +++++++++++ tests/bindings/python/test_sed_coverage.py | 18 ++++++ 30 files changed, 382 insertions(+) diff --git a/src/api/libopencor/file.h b/src/api/libopencor/file.h index 7c0421d51..311ec5745 100644 --- a/src/api/libopencor/file.h +++ b/src/api/libopencor/file.h @@ -170,6 +170,16 @@ class LIBOPENCOR_EXPORT File: public Logger bool hasChildFiles() const; + /** + * @brief Return the number of child files. + * + * Return the number of child files. This method is only relevant for COMBINE archives. + * + * @return The number of child files. + */ + + size_t childFileCount() const; + /** * @brief Return the child file names. * diff --git a/src/api/libopencor/filemanager.h b/src/api/libopencor/filemanager.h index 70dfb2b94..19e327dd6 100644 --- a/src/api/libopencor/filemanager.h +++ b/src/api/libopencor/filemanager.h @@ -53,6 +53,16 @@ class LIBOPENCOR_EXPORT FileManager bool hasFiles() const; + /** + * @brief Return the number of managed files. + * + * Return the number of managed files. + * + * @return The number of managed files. + */ + + size_t fileCount() const; + /** * @brief Return the managed files. * diff --git a/src/api/libopencor/logger.h b/src/api/libopencor/logger.h index e8cd4d0bf..13bea9605 100644 --- a/src/api/libopencor/logger.h +++ b/src/api/libopencor/logger.h @@ -55,6 +55,16 @@ class LIBOPENCOR_EXPORT Logger bool hasIssues() const; + /** + * @brief Return the number of issues. + * + * Return the number of issues. + * + * @return The number of issues. + */ + + size_t issueCount() const; + /** * @brief Return the issues. * @@ -75,6 +85,16 @@ class LIBOPENCOR_EXPORT Logger bool hasErrors() const; + /** + * @brief Return the number of errors. + * + * Return the number of errors. + * + * @return The number of errors. + */ + + size_t errorCount() const; + /** * @brief Return the errors. * @@ -95,6 +115,16 @@ class LIBOPENCOR_EXPORT Logger bool hasWarnings() const; + /** + * @brief Return the number of warnings. + * + * Return the number of warnings. + * + * @return The number of warnings. + */ + + size_t warningCount() const; + /** * @brief Return the warnings. * @@ -115,6 +145,16 @@ class LIBOPENCOR_EXPORT Logger bool hasMessages() const; + /** + * @brief Return the number of messages. + * + * Return the number of messages. + * + * @return The number of messages. + */ + + size_t messageCount() const; + /** * @brief Return the messages. * diff --git a/src/api/libopencor/seddocument.h b/src/api/libopencor/seddocument.h index b554a7234..741b6326a 100644 --- a/src/api/libopencor/seddocument.h +++ b/src/api/libopencor/seddocument.h @@ -100,6 +100,16 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger bool hasModels() const; + /** + * @brief Return the number of models. + * + * Return the number of models. + * + * @return The number of models. + */ + + size_t modelCount() const; + /** * @brief Return the models. * @@ -144,6 +154,16 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger bool hasSimulations() const; + /** + * @brief Return the number of simulations. + * + * Return the number of simulations. + * + * @return The number of simulations. + */ + + size_t simulationCount() const; + /** * @brief Return the simulations. * @@ -188,6 +208,16 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger bool hasTasks() const; + /** + * @brief Return the number of tasks. + * + * Return the number of tasks. + * + * @return The number of tasks. + */ + + size_t taskCount() const; + /** * @brief Return the tasks. * diff --git a/src/bindings/javascript/file.cpp b/src/bindings/javascript/file.cpp index aa3991a61..6996b259b 100644 --- a/src/bindings/javascript/file.cpp +++ b/src/bindings/javascript/file.cpp @@ -47,6 +47,7 @@ void fileApi() pThis->setContents(libOpenCOR::UnsignedChars(contents, contents + pSize)); })) .function("hasChildFiles", &libOpenCOR::File::hasChildFiles) + .function("childFileCount", &libOpenCOR::File::childFileCount) .function("childFileNames", &libOpenCOR::File::childFileNames) .function("childFiles", &libOpenCOR::File::childFiles) .function("childFile", &libOpenCOR::File::childFile); @@ -62,6 +63,7 @@ void fileApi() emscripten::class_("FileManager") .class_function("instance", &libOpenCOR::FileManager::instance) .function("hasFiles", &libOpenCOR::FileManager::hasFiles) + .function("fileCount", &libOpenCOR::FileManager::fileCount) .function("files", &libOpenCOR::FileManager::files) .function("file", &libOpenCOR::FileManager::file); } diff --git a/src/bindings/javascript/logger.cpp b/src/bindings/javascript/logger.cpp index 6a321c806..1cba59b0f 100644 --- a/src/bindings/javascript/logger.cpp +++ b/src/bindings/javascript/logger.cpp @@ -22,12 +22,16 @@ void loggerApi() emscripten::class_("Logger") .function("hasIssues", &libOpenCOR::Logger::hasIssues) + .function("issueCount", &libOpenCOR::Logger::issueCount) .function("issues", &libOpenCOR::Logger::issues) .function("hasErrors", &libOpenCOR::Logger::hasErrors) + .function("errorCount", &libOpenCOR::Logger::errorCount) .function("errors", &libOpenCOR::Logger::errors) .function("hasWarnings", &libOpenCOR::Logger::hasWarnings) + .function("warningCount", &libOpenCOR::Logger::warningCount) .function("warnings", &libOpenCOR::Logger::warnings) .function("hasMessages", &libOpenCOR::Logger::hasMessages) + .function("messageCount", &libOpenCOR::Logger::messageCount) .function("messages", &libOpenCOR::Logger::messages); // Issue API. diff --git a/src/bindings/javascript/sed.cpp b/src/bindings/javascript/sed.cpp index 3882f4fdc..8af490c0a 100644 --- a/src/bindings/javascript/sed.cpp +++ b/src/bindings/javascript/sed.cpp @@ -44,14 +44,17 @@ void sedApi() .function("serialise", emscripten::select_overload(&libOpenCOR::SedDocument::serialise)) .function("serialise", emscripten::select_overload(&libOpenCOR::SedDocument::serialise)) .function("hasModels", &libOpenCOR::SedDocument::hasModels) + .function("modelCount", &libOpenCOR::SedDocument::modelCount) .function("models", &libOpenCOR::SedDocument::models) .function("addModel", &libOpenCOR::SedDocument::addModel) .function("removeModel", &libOpenCOR::SedDocument::removeModel) .function("hasSimulations", &libOpenCOR::SedDocument::hasSimulations) + .function("simulationCount", &libOpenCOR::SedDocument::simulationCount) .function("simulations", &libOpenCOR::SedDocument::simulations) .function("addSimulation", &libOpenCOR::SedDocument::addSimulation) .function("removeSimulation", &libOpenCOR::SedDocument::removeSimulation) .function("hasTasks", &libOpenCOR::SedDocument::hasTasks) + .function("taskCount", &libOpenCOR::SedDocument::taskCount) .function("tasks", &libOpenCOR::SedDocument::tasks) .function("addTask", &libOpenCOR::SedDocument::addTask) .function("removeTask", &libOpenCOR::SedDocument::removeTask) diff --git a/src/bindings/python/file.cpp b/src/bindings/python/file.cpp index 5a7bdf6aa..0ca33052b 100644 --- a/src/bindings/python/file.cpp +++ b/src/bindings/python/file.cpp @@ -41,6 +41,7 @@ void fileApi(py::module_ &m) .def_property_readonly("path", &libOpenCOR::File::path, "Get the path for this File object.") .def_property("contents", &libOpenCOR::File::contents, &libOpenCOR::File::setContents, "The contents of this File object.") .def_property_readonly("has_child_files", &libOpenCOR::File::hasChildFiles, "Return whether this File object has some child files.") + .def_property_readonly("child_file_count", &libOpenCOR::File::childFileCount, "Return the number of child files for this File object.") .def_property_readonly("child_file_names", &libOpenCOR::File::childFileNames, "Return the child file names for this File object.") .def_property_readonly("child_files", &libOpenCOR::File::childFiles, "Return the child files for this File object.") .def("child_file", &libOpenCOR::File::childFile, "Get the requested child file for this File object.", py::arg("file_name")); @@ -51,6 +52,7 @@ void fileApi(py::module_ &m) fileManager.def_static("instance", &libOpenCOR::FileManager::instance, "Get the file manager instance.") .def("has_files", &libOpenCOR::FileManager::hasFiles, "Return whether there are managed files.") + .def("file_count", &libOpenCOR::FileManager::fileCount, "Return the number of managed files.") .def("files", &libOpenCOR::FileManager::files, "Return the managed files.") .def("file", &libOpenCOR::FileManager::file, "Get the requested managed file.", py::arg("file_name_or_url")); } diff --git a/src/bindings/python/logger.cpp b/src/bindings/python/logger.cpp index 72e3f4bb3..b065fa1a5 100644 --- a/src/bindings/python/logger.cpp +++ b/src/bindings/python/logger.cpp @@ -27,12 +27,16 @@ void loggerApi(py::module_ &m) py::class_ logger(m, "Logger"); logger.def_property_readonly("has_issues", &libOpenCOR::Logger::hasIssues, "Return whether there are some issues.") + .def_property_readonly("issue_count", &libOpenCOR::Logger::issueCount, "Return the number of issues.") .def_property_readonly("issues", &libOpenCOR::Logger::issues, "Return the issues.") .def_property_readonly("has_errors", &libOpenCOR::Logger::hasErrors, "Return whether there are some errors.") + .def_property_readonly("error_count", &libOpenCOR::Logger::errorCount, "Return the number of errors.") .def_property_readonly("errors", &libOpenCOR::Logger::errors, "Return the errors.") .def_property_readonly("has_warnings", &libOpenCOR::Logger::hasWarnings, "Return whether there are some warnings.") + .def_property_readonly("warning_count", &libOpenCOR::Logger::warningCount, "Return the number of warnings.") .def_property_readonly("warnings", &libOpenCOR::Logger::warnings, "Return the warnings.") .def_property_readonly("has_messages", &libOpenCOR::Logger::hasMessages, "Return whether there are some messages.") + .def_property_readonly("message_count", &libOpenCOR::Logger::messageCount, "Return the number of messages.") .def_property_readonly("messages", &libOpenCOR::Logger::messages, "Return the messages."); // Issue API. diff --git a/src/bindings/python/sed.cpp b/src/bindings/python/sed.cpp index 33162ad0e..29b13c863 100644 --- a/src/bindings/python/sed.cpp +++ b/src/bindings/python/sed.cpp @@ -46,14 +46,17 @@ void sedApi(py::module_ &m) .def("serialise", py::overload_cast<>(&libOpenCOR::SedDocument::serialise, py::const_), "Get the serialised version of this SedDocument object.") .def("serialise", py::overload_cast(&libOpenCOR::SedDocument::serialise, py::const_), "Get the serialised version of this SedDocument object.", py::arg("base_path")) .def_property_readonly("has_models", &libOpenCOR::SedDocument::hasModels, "Return whether there are some models.") + .def_property_readonly("model_count", &libOpenCOR::SedDocument::modelCount, "Return the number of models.") .def_property_readonly("models", &libOpenCOR::SedDocument::models, "Return the models.") .def("add_model", &libOpenCOR::SedDocument::addModel, "Add a model.") .def("remove_model", &libOpenCOR::SedDocument::removeModel, "Remove a model.") .def_property_readonly("has_simulations", &libOpenCOR::SedDocument::hasSimulations, "Return whether there are some simulations.") + .def_property_readonly("simulation_count", &libOpenCOR::SedDocument::simulationCount, "Return the number of simulations.") .def_property_readonly("simulations", &libOpenCOR::SedDocument::simulations, "Return the simulations.") .def("add_simulation", &libOpenCOR::SedDocument::addSimulation, "Add a simulation.") .def("remove_simulation", &libOpenCOR::SedDocument::removeSimulation, "Remove a simulation.") .def_property_readonly("has_tasks", &libOpenCOR::SedDocument::hasTasks, "Return whether there are some tasks.") + .def_property_readonly("task_count", &libOpenCOR::SedDocument::taskCount, "Return the number of tasks.") .def_property_readonly("tasks", &libOpenCOR::SedDocument::tasks, "Return the tasks.") .def("add_task", &libOpenCOR::SedDocument::addTask, "Add a task.") .def("remove_task", &libOpenCOR::SedDocument::removeTask, "Remove a task.") diff --git a/src/file/file.cpp b/src/file/file.cpp index 57fdf3b44..5246df455 100644 --- a/src/file/file.cpp +++ b/src/file/file.cpp @@ -163,6 +163,15 @@ bool File::Impl::hasChildFiles() const return false; } +size_t File::Impl::childFileCount() const +{ + if (mType == Type::COMBINE_ARCHIVE) { + return mCombineArchive->fileCount(); + } + + return 0; +} + Strings File::Impl::childFileNames() const { if (mType == Type::COMBINE_ARCHIVE) { @@ -272,6 +281,11 @@ bool File::hasChildFiles() const return pimpl()->hasChildFiles(); } +size_t File::childFileCount() const +{ + return pimpl()->childFileCount(); +} + Strings File::childFileNames() const { return pimpl()->childFileNames(); diff --git a/src/file/file_p.h b/src/file/file_p.h index 4c993d7bb..76a7fa52c 100644 --- a/src/file/file_p.h +++ b/src/file/file_p.h @@ -58,6 +58,7 @@ class File::Impl: public Logger::Impl void setContents(const UnsignedChars &pContents); bool hasChildFiles() const; + size_t childFileCount() const; Strings childFileNames() const; FilePtrs childFiles() const; FilePtr childFile(const std::string &pFileName) const; diff --git a/src/file/filemanager.cpp b/src/file/filemanager.cpp index 66a968b20..756f06708 100644 --- a/src/file/filemanager.cpp +++ b/src/file/filemanager.cpp @@ -94,6 +94,11 @@ bool FileManager::Impl::hasFiles() const return !mFiles.empty(); } +size_t FileManager::Impl::fileCount() const +{ + return mFiles.size(); +} + FilePtrs FileManager::Impl::files() const { FilePtrs res; @@ -144,6 +149,11 @@ bool FileManager::hasFiles() const return mPimpl.hasFiles(); } +size_t FileManager::fileCount() const +{ + return mPimpl.fileCount(); +} + FilePtrs FileManager::files() const { return mPimpl.files(); diff --git a/src/file/filemanager_p.h b/src/file/filemanager_p.h index 0b60fc2a9..c5ba784a5 100644 --- a/src/file/filemanager_p.h +++ b/src/file/filemanager_p.h @@ -35,6 +35,7 @@ class FileManager::Impl void unmanage(File *pFile); bool hasFiles() const; + size_t fileCount() const; FilePtrs files() const; FilePtr file(const std::string &pFileNameOrUrl) const; }; diff --git a/src/logger/logger.cpp b/src/logger/logger.cpp index daed8901c..e9375bf5a 100644 --- a/src/logger/logger.cpp +++ b/src/logger/logger.cpp @@ -141,6 +141,11 @@ bool Logger::hasIssues() const return pimpl()->hasIssues(); } +size_t Logger::issueCount() const +{ + return pimpl()->mIssues.size(); +} + IssuePtrs Logger::issues() const { return pimpl()->mIssues; @@ -151,6 +156,11 @@ bool Logger::hasErrors() const return pimpl()->hasErrors(); } +size_t Logger::errorCount() const +{ + return pimpl()->mErrors.size(); +} + IssuePtrs Logger::errors() const { return pimpl()->mErrors; @@ -161,6 +171,11 @@ bool Logger::hasWarnings() const return pimpl()->hasWarnings(); } +size_t Logger::warningCount() const +{ + return pimpl()->mWarnings.size(); +} + IssuePtrs Logger::warnings() const { return pimpl()->mWarnings; @@ -171,6 +186,11 @@ bool Logger::hasMessages() const return pimpl()->hasMessages(); } +size_t Logger::messageCount() const +{ + return pimpl()->mMessages.size(); +} + IssuePtrs Logger::messages() const { return pimpl()->mMessages; diff --git a/src/sed/seddocument.cpp b/src/sed/seddocument.cpp index bcef0193e..ca9c26966 100644 --- a/src/sed/seddocument.cpp +++ b/src/sed/seddocument.cpp @@ -411,6 +411,11 @@ bool SedDocument::hasModels() const return pimpl()->hasModels(); } +size_t SedDocument::modelCount() const +{ + return pimpl()->mModels.size(); +} + SedModelPtrs SedDocument::models() const { return pimpl()->mModels; @@ -431,6 +436,11 @@ bool SedDocument::hasSimulations() const return pimpl()->hasSimulations(); } +size_t SedDocument::simulationCount() const +{ + return pimpl()->mSimulations.size(); +} + SedSimulationPtrs SedDocument::simulations() const { return pimpl()->mSimulations; @@ -451,6 +461,11 @@ bool SedDocument::hasTasks() const return pimpl()->hasTasks(); } +size_t SedDocument::taskCount() const +{ + return pimpl()->mTasks.size(); +} + SedAbstractTaskPtrs SedDocument::tasks() const { return pimpl()->mTasks; diff --git a/src/support/combine/combinearchive.cpp b/src/support/combine/combinearchive.cpp index 88851d602..eb09f75f2 100644 --- a/src/support/combine/combinearchive.cpp +++ b/src/support/combine/combinearchive.cpp @@ -130,6 +130,11 @@ bool CombineArchive::hasFiles() const return !pimpl()->mFiles.empty(); } +size_t CombineArchive::fileCount() const +{ + return pimpl()->mFiles.size(); +} + Strings CombineArchive::fileNames() const { return pimpl()->fileNames(); diff --git a/src/support/combine/combinearchive.h b/src/support/combine/combinearchive.h index 3407377a1..093ddb5e9 100644 --- a/src/support/combine/combinearchive.h +++ b/src/support/combine/combinearchive.h @@ -46,6 +46,7 @@ class CombineArchive: public Logger FilePtr masterFile() const; bool hasFiles() const; + size_t fileCount() const; Strings fileNames() const; FilePtrs files() const; FilePtr file(const std::string &pFileName) const; diff --git a/tests/api/file/basictests.cpp b/tests/api/file/basictests.cpp index 6b1cdac5f..f9306fb70 100644 --- a/tests/api/file/basictests.cpp +++ b/tests/api/file/basictests.cpp @@ -136,6 +136,7 @@ TEST(BasicFileTest, fileManager) auto fileManager = libOpenCOR::FileManager::instance(); EXPECT_FALSE(fileManager.hasFiles()); + EXPECT_EQ(fileManager.fileCount(), 0); EXPECT_TRUE(fileManager.files().empty()); EXPECT_EQ(fileManager.file(libOpenCOR::LOCAL_FILE), nullptr); @@ -143,12 +144,14 @@ TEST(BasicFileTest, fileManager) auto sameFileManager = libOpenCOR::FileManager::instance(); EXPECT_TRUE(sameFileManager.hasFiles()); + EXPECT_EQ(sameFileManager.fileCount(), 1); EXPECT_EQ(sameFileManager.files().size(), 1); EXPECT_EQ(sameFileManager.file(libOpenCOR::LOCAL_FILE), localFile); auto remoteFile = libOpenCOR::File::create(libOpenCOR::REMOTE_FILE); EXPECT_TRUE(fileManager.hasFiles()); + EXPECT_EQ(fileManager.fileCount(), 2); EXPECT_EQ(fileManager.files().size(), 2); EXPECT_EQ(fileManager.file(libOpenCOR::REMOTE_FILE), remoteFile); } diff --git a/tests/api/file/childtests.cpp b/tests/api/file/childtests.cpp index b4398991a..c3b19758d 100644 --- a/tests/api/file/childtests.cpp +++ b/tests/api/file/childtests.cpp @@ -27,6 +27,7 @@ void doTestDataset(const std::string &pNumber, const std::vector &p auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("api/file/dataset_" + pNumber + ".omex")); EXPECT_TRUE(file->hasChildFiles()); + EXPECT_EQ(file->childFileCount(), pSpecificChildFileNames.size() + 1); auto childFileNames = file->childFileNames(); @@ -59,6 +60,7 @@ TEST(ChildFileTest, noChildFiles) auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::UNKNOWN_FILE)); EXPECT_FALSE(file->hasChildFiles()); + EXPECT_EQ(file->childFileCount(), 0); EXPECT_EQ(file->childFileNames().size(), 0); EXPECT_EQ(file->childFiles().size(), 0); EXPECT_EQ(file->childFile(libOpenCOR::resourcePath(libOpenCOR::UNKNOWN_FILE)), nullptr); diff --git a/tests/api/logger/coveragetests.cpp b/tests/api/logger/coveragetests.cpp index 21c6ffd84..d780bb06c 100644 --- a/tests/api/logger/coveragetests.cpp +++ b/tests/api/logger/coveragetests.cpp @@ -18,6 +18,27 @@ limitations under the License. #include +TEST(CoverageLoggerTest, hasIssues) +{ + auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); + + EXPECT_FALSE(file->hasIssues()); +} + +TEST(CoverageLoggerTest, issueCount) +{ + auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); + + EXPECT_EQ(file->issueCount(), 0); +} + +TEST(CoverageLoggerTest, issues) +{ + auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); + + EXPECT_TRUE(file->issues().empty()); +} + TEST(CoverageLoggerTest, hasErrors) { auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); @@ -25,6 +46,13 @@ TEST(CoverageLoggerTest, hasErrors) EXPECT_FALSE(file->hasErrors()); } +TEST(CoverageLoggerTest, errorCount) +{ + auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); + + EXPECT_EQ(file->errorCount(), 0); +} + TEST(CoverageLoggerTest, errors) { auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); @@ -39,6 +67,13 @@ TEST(CoverageLoggerTest, hasWarnings) EXPECT_FALSE(file->hasWarnings()); } +TEST(CoverageLoggerTest, warningCount) +{ + auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); + + EXPECT_EQ(file->warningCount(), 0); +} + TEST(CoverageLoggerTest, warnings) { auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); @@ -53,6 +88,13 @@ TEST(CoverageLoggerTest, hasMessages) EXPECT_FALSE(file->hasMessages()); } +TEST(CoverageLoggerTest, messageCount) +{ + auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); + + EXPECT_EQ(file->messageCount(), 0); +} + TEST(CoverageLoggerTest, messages) { auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); diff --git a/tests/api/sed/coveragetests.cpp b/tests/api/sed/coveragetests.cpp index abd0978b6..dfed075a9 100644 --- a/tests/api/sed/coveragetests.cpp +++ b/tests/api/sed/coveragetests.cpp @@ -36,6 +36,8 @@ TEST(CoverageSedTest, models) auto document = libOpenCOR::SedDocument::create(); EXPECT_FALSE(document->hasModels()); + EXPECT_EQ(document->modelCount(), 0); + EXPECT_EQ(document->models().size(), 0); EXPECT_FALSE(document->addModel(nullptr)); auto file = libOpenCOR::File::create(libOpenCOR::LOCAL_FILE); @@ -43,6 +45,8 @@ TEST(CoverageSedTest, models) EXPECT_TRUE(document->addModel(model)); + EXPECT_TRUE(document->hasModels()); + EXPECT_EQ(document->modelCount(), 1); EXPECT_EQ(document->models().size(), 1); EXPECT_EQ(document->models()[0], model); @@ -50,6 +54,8 @@ TEST(CoverageSedTest, models) EXPECT_TRUE(document->removeModel(model)); EXPECT_FALSE(document->hasModels()); + EXPECT_EQ(document->modelCount(), 0); + EXPECT_EQ(document->models().size(), 0); EXPECT_FALSE(document->removeModel(nullptr)); } @@ -59,6 +65,8 @@ TEST(CoverageSedTest, simulations) auto document = libOpenCOR::SedDocument::create(); EXPECT_FALSE(document->hasSimulations()); + EXPECT_EQ(document->simulationCount(), 0); + EXPECT_EQ(document->simulations().size(), 0); EXPECT_FALSE(document->addSimulation(nullptr)); auto uniformTimeCourse = libOpenCOR::SedUniformTimeCourse::create(document); @@ -71,6 +79,8 @@ TEST(CoverageSedTest, simulations) EXPECT_TRUE(document->addSimulation(steadyState)); EXPECT_TRUE(document->addSimulation(analysis)); + EXPECT_TRUE(document->hasSimulations()); + EXPECT_EQ(document->simulationCount(), 4); EXPECT_EQ(document->simulations().size(), 4); EXPECT_EQ(document->simulations()[0], uniformTimeCourse); EXPECT_EQ(document->simulations()[1], oneStep); @@ -90,6 +100,8 @@ TEST(CoverageSedTest, simulations) EXPECT_TRUE(document->removeSimulation(analysis)); EXPECT_FALSE(document->hasSimulations()); + EXPECT_EQ(document->simulationCount(), 0); + EXPECT_EQ(document->simulations().size(), 0); EXPECT_FALSE(document->removeSimulation(nullptr)); } @@ -116,6 +128,8 @@ TEST(CoverageSedTest, tasks) auto document = libOpenCOR::SedDocument::create(); EXPECT_FALSE(document->hasTasks()); + EXPECT_EQ(document->taskCount(), 0); + EXPECT_EQ(document->tasks().size(), 0); EXPECT_FALSE(document->addTask(nullptr)); auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE)); @@ -128,6 +142,8 @@ TEST(CoverageSedTest, tasks) EXPECT_TRUE(document->addTask(task)); + EXPECT_TRUE(document->hasTasks()); + EXPECT_EQ(document->taskCount(), 1); EXPECT_EQ(document->tasks().size(), 1); EXPECT_EQ(document->tasks()[0], task); @@ -154,6 +170,8 @@ TEST(CoverageSedTest, tasks) EXPECT_TRUE(document->removeTask(task)); EXPECT_FALSE(document->hasTasks()); + EXPECT_EQ(document->taskCount(), 0); + EXPECT_EQ(document->tasks().size(), 0); EXPECT_FALSE(document->removeTask(nullptr)); } diff --git a/tests/bindings/javascript/file.basic.test.js b/tests/bindings/javascript/file.basic.test.js index 706632797..777c362ca 100644 --- a/tests/bindings/javascript/file.basic.test.js +++ b/tests/bindings/javascript/file.basic.test.js @@ -89,6 +89,7 @@ describe("File basic tests", () => { const fileManager = libopencor.FileManager.instance(); expect(fileManager.hasFiles()).toBe(false); + expect(fileManager.fileCount()).toBe(0); expect(fileManager.files().size()).toBe(0); expect(fileManager.file(utils.LOCAL_FILE)).toStrictEqual(null); @@ -96,12 +97,14 @@ describe("File basic tests", () => { const sameFileManager = libopencor.FileManager.instance(); expect(sameFileManager.hasFiles()).toBe(true); + expect(sameFileManager.fileCount()).toBe(1); expect(sameFileManager.files().size()).toBe(1); expect(sameFileManager.file(utils.LOCAL_FILE)).toStrictEqual(localFile); const remoteFile = new libopencor.File(utils.REMOTE_FILE); expect(fileManager.hasFiles()).toBe(true); + expect(fileManager.fileCount()).toBe(2); expect(fileManager.files().size()).toBe(2); expect(fileManager.file(utils.REMOTE_FILE)).toStrictEqual(remoteFile); diff --git a/tests/bindings/javascript/file.child.test.js b/tests/bindings/javascript/file.child.test.js index 398bd4ddb..3671f20ed 100644 --- a/tests/bindings/javascript/file.child.test.js +++ b/tests/bindings/javascript/file.child.test.js @@ -62,6 +62,7 @@ describe("File type tests", () => { file.setContents(omexContentsPtr, omexContents.length); expect(file.hasChildFiles()).toBe(true); + expect(file.childFileCount()).toBe(specificChildFileNames.length + 1); const childFileNames = file.childFileNames(); @@ -97,6 +98,7 @@ describe("File type tests", () => { const file = new libopencor.File(utils.UNKNOWN_FILE); expect(file.hasChildFiles()).toBe(false); + expect(file.childFileCount()).toBe(0); expect(file.childFileNames().size()).toBe(0); expect(file.childFiles().size()).toBe(0); expect(file.childFile(utils.UNKNOWN_FILE)).toBeNull(); diff --git a/tests/bindings/javascript/logger.coverage.test.js b/tests/bindings/javascript/logger.coverage.test.js index 6d3de5841..879ef384e 100644 --- a/tests/bindings/javascript/logger.coverage.test.js +++ b/tests/bindings/javascript/logger.coverage.test.js @@ -33,6 +33,36 @@ describe("Issue coverage tests", () => { utils.freeMemory(libopencor, someCellmlContentsPtr); }); + test("hasIssues()", () => { + const file = new libopencor.File(utils.CELLML_FILE); + + file.setContents(someCellmlContentsPtr, utils.SOME_CELLML_CONTENTS.length); + + expect(file.hasIssues()).toBe(false); + + file.delete(); + }); + + test("issueCount()", () => { + const file = new libopencor.File(utils.CELLML_FILE); + + file.setContents(someCellmlContentsPtr, utils.SOME_CELLML_CONTENTS.length); + + expect(file.issueCount()).toBe(0); + + file.delete(); + }); + + test("issues()", () => { + const file = new libopencor.File(utils.CELLML_FILE); + + file.setContents(someCellmlContentsPtr, utils.SOME_CELLML_CONTENTS.length); + + expect(file.issues().size()).toBe(0); + + file.delete(); + }); + test("hasErrors()", () => { const file = new libopencor.File(utils.CELLML_FILE); @@ -43,6 +73,16 @@ describe("Issue coverage tests", () => { file.delete(); }); + test("errorCount()", () => { + const file = new libopencor.File(utils.CELLML_FILE); + + file.setContents(someCellmlContentsPtr, utils.SOME_CELLML_CONTENTS.length); + + expect(file.errorCount()).toBe(0); + + file.delete(); + }); + test("errors()", () => { const file = new libopencor.File(utils.CELLML_FILE); @@ -63,6 +103,16 @@ describe("Issue coverage tests", () => { file.delete(); }); + test("warningCount()", () => { + const file = new libopencor.File(utils.CELLML_FILE); + + file.setContents(someCellmlContentsPtr, utils.SOME_CELLML_CONTENTS.length); + + expect(file.warningCount()).toBe(0); + + file.delete(); + }); + test("warnings()", () => { const file = new libopencor.File(utils.CELLML_FILE); @@ -83,6 +133,16 @@ describe("Issue coverage tests", () => { file.delete(); }); + test("messageCount()", () => { + const file = new libopencor.File(utils.CELLML_FILE); + + file.setContents(someCellmlContentsPtr, utils.SOME_CELLML_CONTENTS.length); + + expect(file.messageCount()).toBe(0); + + file.delete(); + }); + test("messages()", () => { const file = new libopencor.File(utils.CELLML_FILE); diff --git a/tests/bindings/javascript/sed.coverage.test.js b/tests/bindings/javascript/sed.coverage.test.js index 2671417e5..754fccc4f 100644 --- a/tests/bindings/javascript/sed.coverage.test.js +++ b/tests/bindings/javascript/sed.coverage.test.js @@ -65,6 +65,8 @@ describe("Sed coverage tests", () => { const document = new libopencor.SedDocument(); expect(document.hasModels()).toBe(false); + expect(document.modelCount()).toBe(0); + expect(document.models().size()).toBe(0); expect(document.addModel(null)).toBe(false); const file = new libopencor.File(utils.SEDML_FILE); @@ -72,6 +74,8 @@ describe("Sed coverage tests", () => { expect(document.addModel(model)).toBe(true); + expect(document.hasModels()).toBe(true); + expect(document.modelCount()).toBe(1); expect(document.models().size()).toBe(1); expect(document.models().get(0)).toStrictEqual(model); @@ -79,6 +83,8 @@ describe("Sed coverage tests", () => { expect(document.removeModel(model)).toBe(true); expect(document.hasModels()).toBe(false); + expect(document.modelCount()).toBe(0); + expect(document.models().size()).toBe(0); expect(document.removeModel(null)).toBe(false); @@ -91,6 +97,8 @@ describe("Sed coverage tests", () => { const document = new libopencor.SedDocument(); expect(document.hasSimulations()).toBe(false); + expect(document.simulationCount()).toBe(0); + expect(document.simulations().size()).toBe(0); expect(document.addSimulation(null)).toBe(false); const uniform_time_course = new libopencor.SedUniformTimeCourse(document); @@ -103,6 +111,8 @@ describe("Sed coverage tests", () => { expect(document.addSimulation(steady_state)).toBe(true); expect(document.addSimulation(analysis)).toBe(true); + expect(document.hasSimulations()).toBe(true); + expect(document.simulationCount()).toBe(4); expect(document.simulations().size()).toBe(4); expect(document.simulations().get(0)).toStrictEqual(uniform_time_course); expect(document.simulations().get(1)).toStrictEqual(one_step); @@ -122,6 +132,8 @@ describe("Sed coverage tests", () => { expect(document.removeSimulation(analysis)).toBe(true); expect(document.hasSimulations()).toBe(false); + expect(document.simulationCount()).toBe(0); + expect(document.simulations().size()).toBe(0); expect(document.removeSimulation(null)).toBe(false); @@ -134,6 +146,8 @@ describe("Sed coverage tests", () => { const document = new libopencor.SedDocument(); expect(document.hasTasks()).toBe(false); + expect(document.taskCount()).toBe(0); + expect(document.tasks().size()).toBe(0); expect(document.addTask(null)).toBe(false); const file = new libopencor.File(utils.SEDML_FILE); @@ -146,6 +160,8 @@ describe("Sed coverage tests", () => { expect(document.addTask(task)).toBe(true); + expect(document.hasTasks()).toBe(true); + expect(document.taskCount()).toBe(1); expect(document.tasks().size()).toBe(1); expect(document.tasks().get(0)).toStrictEqual(task); @@ -170,6 +186,8 @@ describe("Sed coverage tests", () => { expect(document.removeTask(task)).toBe(true); expect(document.hasTasks()).toBe(false); + expect(document.taskCount()).toBe(0); + expect(document.tasks().size()).toBe(0); expect(document.removeTask(null)).toBe(false); diff --git a/tests/bindings/python/test_file_basic.py b/tests/bindings/python/test_file_basic.py index 3d9104436..a1880e573 100644 --- a/tests/bindings/python/test_file_basic.py +++ b/tests/bindings/python/test_file_basic.py @@ -134,6 +134,7 @@ def test_file_manager(): file_manager = FileManager.instance() assert file_manager.has_files() == False + assert file_manager.file_count == 0 assert len(file_manager.files()) == 0 assert file_manager.file(utils.LocalFile) == None @@ -141,11 +142,13 @@ def test_file_manager(): same_file_manager = FileManager.instance() assert same_file_manager.has_files() == True + assert same_file_manager.file_count == 1 assert len(file_manager.files()) == 1 assert same_file_manager.file(utils.LocalFile) == local_file remote_file = File(utils.RemoteFile) assert file_manager.has_files() == True + assert file_manager.file_count == 2 assert len(file_manager.files()) == 2 assert file_manager.file(utils.RemoteFile) == remote_file diff --git a/tests/bindings/python/test_file_child.py b/tests/bindings/python/test_file_child.py index c90d9ae7f..f6c6ff007 100644 --- a/tests/bindings/python/test_file_child.py +++ b/tests/bindings/python/test_file_child.py @@ -22,6 +22,7 @@ def do_test_dataset(number, specific_child_file_names): file = File(utils.resource_path("api/file/dataset_" + str(number) + ".omex")) assert file.has_child_files == True + assert file.child_file_count == len(specific_child_file_names) + 1 child_file_names = file.child_file_names @@ -56,6 +57,7 @@ def test_type_no_child_files(): file = File(utils.resource_path(utils.UnknownFile)) assert file.has_child_files == False + assert file.child_file_count == 0 assert len(file.child_file_names) == 0 assert len(file.child_files) == 0 assert file.child_file("unknown_file") is None diff --git a/tests/bindings/python/test_logger_coverage.py b/tests/bindings/python/test_logger_coverage.py index f93c97f4e..fe45481dd 100644 --- a/tests/bindings/python/test_logger_coverage.py +++ b/tests/bindings/python/test_logger_coverage.py @@ -17,12 +17,36 @@ import utils +def test_has_issues(): + file = File(utils.resource_path(utils.Cellml2File)) + + assert not file.has_issues + + +def test_issue_count(): + file = File(utils.resource_path(utils.Cellml2File)) + + assert file.issue_count == 0 + + +def test_issues(): + file = File(utils.resource_path(utils.Cellml2File)) + + assert len(file.issues) == 0 + + def test_has_errors(): file = File(utils.resource_path(utils.Cellml2File)) assert not file.has_errors +def test_error_count(): + file = File(utils.resource_path(utils.Cellml2File)) + + assert file.error_count == 0 + + def test_errors(): file = File(utils.resource_path(utils.Cellml2File)) @@ -35,6 +59,12 @@ def test_has_warnings(): assert not file.has_warnings +def test_warning_count(): + file = File(utils.resource_path(utils.Cellml2File)) + + assert file.warning_count == 0 + + def test_warnings(): file = File(utils.resource_path(utils.Cellml2File)) @@ -47,6 +77,12 @@ def test_has_messages(): assert not file.has_messages +def test_message_count(): + file = File(utils.resource_path(utils.Cellml2File)) + + assert file.message_count == 0 + + def test_messages(): file = File(utils.resource_path(utils.Cellml2File)) diff --git a/tests/bindings/python/test_sed_coverage.py b/tests/bindings/python/test_sed_coverage.py index fe4ddfa3d..79fd52560 100644 --- a/tests/bindings/python/test_sed_coverage.py +++ b/tests/bindings/python/test_sed_coverage.py @@ -48,6 +48,8 @@ def test_models(): document = SedDocument() assert document.has_models == False + assert document.model_count == 0 + assert len(document.models) == 0 assert document.add_model(None) == False file = File(utils.LocalFile) @@ -55,6 +57,8 @@ def test_models(): assert document.add_model(model) == True + assert document.has_models == True + assert document.model_count == 1 assert len(document.models) == 1 assert document.models[0] == model @@ -62,6 +66,8 @@ def test_models(): assert document.remove_model(model) == True assert document.has_models == False + assert document.model_count == 0 + assert len(document.models) == 0 assert document.remove_model(None) == False @@ -70,6 +76,8 @@ def test_simulations(): document = SedDocument() assert document.has_simulations == False + assert document.simulation_count == 0 + assert len(document.simulations) == 0 assert document.add_simulation(None) == False uniformTimeCourse = SedUniformTimeCourse(document) @@ -82,6 +90,8 @@ def test_simulations(): assert document.add_simulation(steadyState) == True assert document.add_simulation(analysis) == True + assert document.has_simulations == True + assert document.simulation_count == 4 assert len(document.simulations) == 4 assert document.simulations[0] == uniformTimeCourse assert document.simulations[1] == oneStep @@ -101,6 +111,8 @@ def test_simulations(): assert document.remove_simulation(analysis) == True assert document.has_simulations == False + assert document.simulation_count == 0 + assert len(document.simulations) == 0 assert document.remove_simulation(None) == False @@ -125,6 +137,8 @@ def test_tasks(): document = SedDocument() assert document.has_tasks == False + assert document.task_count == 0 + assert len(document.tasks) == 0 assert document.add_task(None) == False file = File(utils.LocalFile) @@ -137,6 +151,8 @@ def test_tasks(): assert document.add_task(task) == True + assert document.has_tasks == True + assert document.task_count == 1 assert len(document.tasks) == 1 assert document.tasks[0] == task @@ -169,6 +185,8 @@ def test_tasks(): assert document.remove_task(task) == True assert document.has_tasks == False + assert document.task_count == 0 + assert len(document.tasks) == 0 assert document.remove_task(None) == False From a0ceda7ec3f86500e28b2d9f344d6d65bb958cc2 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Sun, 23 Jun 2024 22:48:12 +1200 Subject: [PATCH 064/112] Python: whenever possible, use def_property_readonly() rather than def(). --- src/bindings/python/file.cpp | 6 +++--- tests/bindings/python/test_file_basic.py | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/bindings/python/file.cpp b/src/bindings/python/file.cpp index 0ca33052b..25fd576b4 100644 --- a/src/bindings/python/file.cpp +++ b/src/bindings/python/file.cpp @@ -51,8 +51,8 @@ void fileApi(py::module_ &m) py::class_> fileManager(m, "FileManager"); fileManager.def_static("instance", &libOpenCOR::FileManager::instance, "Get the file manager instance.") - .def("has_files", &libOpenCOR::FileManager::hasFiles, "Return whether there are managed files.") - .def("file_count", &libOpenCOR::FileManager::fileCount, "Return the number of managed files.") - .def("files", &libOpenCOR::FileManager::files, "Return the managed files.") + .def_property_readonly("has_files", &libOpenCOR::FileManager::hasFiles, "Return whether there are managed files.") + .def_property_readonly("file_count", &libOpenCOR::FileManager::fileCount, "Return the number of managed files.") + .def_property_readonly("files", &libOpenCOR::FileManager::files, "Return the managed files.") .def("file", &libOpenCOR::FileManager::file, "Get the requested managed file.", py::arg("file_name_or_url")); } diff --git a/tests/bindings/python/test_file_basic.py b/tests/bindings/python/test_file_basic.py index a1880e573..c009c059d 100644 --- a/tests/bindings/python/test_file_basic.py +++ b/tests/bindings/python/test_file_basic.py @@ -133,22 +133,22 @@ def test_remote_virtual_file(): def test_file_manager(): file_manager = FileManager.instance() - assert file_manager.has_files() == False + assert file_manager.has_files == False assert file_manager.file_count == 0 - assert len(file_manager.files()) == 0 + assert len(file_manager.files) == 0 assert file_manager.file(utils.LocalFile) == None local_file = File(utils.LocalFile) same_file_manager = FileManager.instance() - assert same_file_manager.has_files() == True + assert same_file_manager.has_files == True assert same_file_manager.file_count == 1 - assert len(file_manager.files()) == 1 + assert len(file_manager.files) == 1 assert same_file_manager.file(utils.LocalFile) == local_file remote_file = File(utils.RemoteFile) - assert file_manager.has_files() == True + assert file_manager.has_files == True assert file_manager.file_count == 2 - assert len(file_manager.files()) == 2 + assert len(file_manager.files) == 2 assert file_manager.file(utils.RemoteFile) == remote_file From 140369fe56a010c0fa128958e25f234f3cbc2189 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 24 Jun 2024 12:42:40 +1200 Subject: [PATCH 065/112] Pimpl: some consistency. --- src/api/libopencor/sedsimulation.h | 28 ++--- src/file/file.cpp | 14 ++- src/file/file_p.h | 2 + src/logger/logger.cpp | 56 +++++++-- src/logger/logger_p.h | 11 ++ src/sed/sedbase.cpp | 14 ++- src/sed/sedbase_p.h | 3 + src/sed/seddocument.cpp | 42 ++++++- src/sed/seddocument_p.h | 6 + src/sed/sedinstance.cpp | 7 +- src/sed/sedinstance_p.h | 2 + src/sed/sedinstancetask.cpp | 28 ++++- src/sed/sedinstancetask_p.h | 4 + src/sed/sedonestep.cpp | 14 ++- src/sed/sedonestep_p.h | 3 + src/sed/sedsimulation.cpp | 36 ++++-- src/sed/sedsimulation_p.h | 6 + src/sed/sedtask.cpp | 28 ++++- src/sed/sedtask_p.h | 6 + src/sed/seduniformtimecourse.cpp | 56 +++++++-- src/sed/seduniformtimecourse_p.h | 12 ++ src/solver/solver.cpp | 14 ++- src/solver/solver_p.h | 3 + src/solver/solvercvode.cpp | 154 +++++++++++++++++++---- src/solver/solvercvode_p.h | 33 +++++ src/solver/solverkinsol.cpp | 56 +++++++-- src/solver/solverkinsol_p.h | 12 ++ src/solver/solverodefixedstep.cpp | 14 ++- src/solver/solverodefixedstep_p.h | 3 + src/support/cellml/cellmlfile.cpp | 29 ++++- src/support/cellml/cellmlfile_p.h | 7 ++ src/support/cellml/cellmlfileruntime.cpp | 84 +++++++++++-- src/support/cellml/cellmlfileruntime_p.h | 14 +++ src/support/combine/combinearchive.cpp | 28 ++++- src/support/combine/combinearchive_p.h | 4 + 35 files changed, 720 insertions(+), 113 deletions(-) diff --git a/src/api/libopencor/sedsimulation.h b/src/api/libopencor/sedsimulation.h index 1d6f6554e..2eb26d113 100644 --- a/src/api/libopencor/sedsimulation.h +++ b/src/api/libopencor/sedsimulation.h @@ -44,16 +44,6 @@ class LIBOPENCOR_EXPORT SedSimulation: public SedBase SedSimulation &operator=(const SedSimulation &pRhs) = delete; /**< No copy assignment operator allowed, @private. */ SedSimulation &operator=(SedSimulation &&pRhs) noexcept = delete; /**< No move assignment operator allowed, @private. */ - /** - * @brief Set the ODE solver for this simulation. - * - * Set the ODE solver for this simulation. - * - * @param pOdeSolver The ODE solver, as a @ref SolverOdePtr, for this simulation. - */ - - void setOdeSolver(const SolverOdePtr &pOdeSolver); - /** * @brief Get the ODE solver for this simulation. * @@ -65,14 +55,14 @@ class LIBOPENCOR_EXPORT SedSimulation: public SedBase SolverOdePtr odeSolver() const; /** - * @brief Set the NLA solver for this simulation. + * @brief Set the ODE solver for this simulation. * - * Set the NLA solver for this simulation. + * Set the ODE solver for this simulation. * - * @param pNlaSolver The NLA solver, as a @ref SolverNlaPtr, for this simulation. + * @param pOdeSolver The ODE solver, as a @ref SolverOdePtr, for this simulation. */ - void setNlaSolver(const SolverNlaPtr &pNlaSolver); + void setOdeSolver(const SolverOdePtr &pOdeSolver); /** * @brief Get the NLA solver for this simulation. @@ -84,6 +74,16 @@ class LIBOPENCOR_EXPORT SedSimulation: public SedBase SolverNlaPtr nlaSolver() const; + /** + * @brief Set the NLA solver for this simulation. + * + * Set the NLA solver for this simulation. + * + * @param pNlaSolver The NLA solver, as a @ref SolverNlaPtr, for this simulation. + */ + + void setNlaSolver(const SolverNlaPtr &pNlaSolver); + protected: class Impl; /**< Forward declaration of the implementation class, @private. */ diff --git a/src/file/file.cpp b/src/file/file.cpp index 5246df455..fdfcaae03 100644 --- a/src/file/file.cpp +++ b/src/file/file.cpp @@ -117,11 +117,21 @@ void File::Impl::checkType(const FilePtr &pOwner, bool pResetType) } } +File::Type File::Impl::type() const +{ + return mType; +} + std::string File::Impl::fileName() const { return pathToString(mFilePath); } +std::string File::Impl::url() const +{ + return mUrl; +} + std::string File::Impl::path() const { return mUrl.empty() ? fileName() : mUrl; @@ -246,7 +256,7 @@ FilePtr File::create(const std::string &pFileNameOrUrl) File::Type File::type() const { - return pimpl()->mType; + return pimpl()->type(); } std::string File::fileName() const @@ -256,7 +266,7 @@ std::string File::fileName() const std::string File::url() const { - return pimpl()->mUrl; + return pimpl()->url(); } std::string File::path() const diff --git a/src/file/file_p.h b/src/file/file_p.h index 76a7fa52c..58b244352 100644 --- a/src/file/file_p.h +++ b/src/file/file_p.h @@ -47,7 +47,9 @@ class File::Impl: public Logger::Impl void checkType(const FilePtr &pOwner, bool pResetType = false); + Type type() const; std::string fileName() const; + std::string url() const; std::string path() const; #ifndef __EMSCRIPTEN__ diff --git a/src/logger/logger.cpp b/src/logger/logger.cpp index e9375bf5a..e0a052967 100644 --- a/src/logger/logger.cpp +++ b/src/logger/logger.cpp @@ -25,21 +25,61 @@ bool Logger::Impl::hasIssues() const return !mIssues.empty(); } +size_t Logger::Impl::issueCount() const +{ + return mIssues.size(); +} + +IssuePtrs Logger::Impl::issues() const +{ + return mIssues; +} + bool Logger::Impl::hasErrors() const { return !mErrors.empty(); } +size_t Logger::Impl::errorCount() const +{ + return mErrors.size(); +} + +IssuePtrs Logger::Impl::errors() const +{ + return mErrors; +} + bool Logger::Impl::hasWarnings() const { return !mWarnings.empty(); } +size_t Logger::Impl::warningCount() const +{ + return mWarnings.size(); +} + +IssuePtrs Logger::Impl::warnings() const +{ + return mWarnings; +} + bool Logger::Impl::hasMessages() const { return !mMessages.empty(); } +size_t Logger::Impl::messageCount() const +{ + return mMessages.size(); +} + +IssuePtrs Logger::Impl::messages() const +{ + return mMessages; +} + void Logger::Impl::addIssues(const LoggerPtr &pLogger) { for (const auto &issue : pLogger->issues()) { @@ -143,12 +183,12 @@ bool Logger::hasIssues() const size_t Logger::issueCount() const { - return pimpl()->mIssues.size(); + return pimpl()->issueCount(); } IssuePtrs Logger::issues() const { - return pimpl()->mIssues; + return pimpl()->issues(); } bool Logger::hasErrors() const @@ -158,12 +198,12 @@ bool Logger::hasErrors() const size_t Logger::errorCount() const { - return pimpl()->mErrors.size(); + return pimpl()->errorCount(); } IssuePtrs Logger::errors() const { - return pimpl()->mErrors; + return pimpl()->errors(); } bool Logger::hasWarnings() const @@ -173,12 +213,12 @@ bool Logger::hasWarnings() const size_t Logger::warningCount() const { - return pimpl()->mWarnings.size(); + return pimpl()->warningCount(); } IssuePtrs Logger::warnings() const { - return pimpl()->mWarnings; + return pimpl()->warnings(); } bool Logger::hasMessages() const @@ -188,12 +228,12 @@ bool Logger::hasMessages() const size_t Logger::messageCount() const { - return pimpl()->mMessages.size(); + return pimpl()->messageCount(); } IssuePtrs Logger::messages() const { - return pimpl()->mMessages; + return pimpl()->messages(); } } // namespace libOpenCOR diff --git a/src/logger/logger_p.h b/src/logger/logger_p.h index 9372c3a70..5f0bc1131 100644 --- a/src/logger/logger_p.h +++ b/src/logger/logger_p.h @@ -34,9 +34,20 @@ class Logger::Impl IssuePtrs mMessages; bool hasIssues() const; + size_t issueCount() const; + IssuePtrs issues() const; + bool hasErrors() const; + size_t errorCount() const; + IssuePtrs errors() const; + bool hasWarnings() const; + size_t warningCount() const; + IssuePtrs warnings() const; + bool hasMessages() const; + size_t messageCount() const; + IssuePtrs messages() const; void addIssues(const LoggerPtr &pLogger); void addIssues(const libcellml::LoggerPtr &pLogger); diff --git a/src/sed/sedbase.cpp b/src/sed/sedbase.cpp index ad5e3392d..3da237c1a 100644 --- a/src/sed/sedbase.cpp +++ b/src/sed/sedbase.cpp @@ -25,6 +25,16 @@ SedBase::Impl::Impl(const std::string &pId) { } +std::string SedBase::Impl::id() const +{ + return mId; +} + +void SedBase::Impl::setId(const std::string &pId) +{ + mId = pId; +} + void SedBase::Impl::serialise(xmlNodePtr pNode) const { xmlNewProp(pNode, toConstXmlCharPtr("id"), toConstXmlCharPtr(mId)); @@ -47,12 +57,12 @@ const SedBase::Impl *SedBase::pimpl() const std::string SedBase::id() const { - return pimpl()->mId; + return pimpl()->id(); } void SedBase::setId(const std::string &pId) { - pimpl()->mId = pId; + pimpl()->setId(pId); } } // namespace libOpenCOR diff --git a/src/sed/sedbase_p.h b/src/sed/sedbase_p.h index fe930978a..0f319b037 100644 --- a/src/sed/sedbase_p.h +++ b/src/sed/sedbase_p.h @@ -34,6 +34,9 @@ class SedBase::Impl: public Logger::Impl explicit Impl(const std::string &pId = {}); virtual ~Impl() = default; + std::string id() const; + void setId(const std::string &pId); + virtual void serialise(xmlNodePtr pNode) const; }; diff --git a/src/sed/seddocument.cpp b/src/sed/seddocument.cpp index ca9c26966..a6c9fa652 100644 --- a/src/sed/seddocument.cpp +++ b/src/sed/seddocument.cpp @@ -245,6 +245,16 @@ bool SedDocument::Impl::hasModels() const return !mModels.empty(); } +size_t SedDocument::Impl::modelCount() const +{ + return mModels.size(); +} + +SedModelPtrs SedDocument::Impl::models() const +{ + return mModels; +} + bool SedDocument::Impl::addModel(const SedModelPtr &pModel) { if (pModel == nullptr) { @@ -285,6 +295,16 @@ bool SedDocument::Impl::hasSimulations() const return !mSimulations.empty(); } +size_t SedDocument::Impl::simulationCount() const +{ + return mSimulations.size(); +} + +SedSimulationPtrs SedDocument::Impl::simulations() const +{ + return mSimulations; +} + bool SedDocument::Impl::addSimulation(const SedSimulationPtr &pSimulation) { if (pSimulation == nullptr) { @@ -325,6 +345,16 @@ bool SedDocument::Impl::hasTasks() const return !mTasks.empty(); } +size_t SedDocument::Impl::taskCount() const +{ + return mTasks.size(); +} + +SedAbstractTaskPtrs SedDocument::Impl::tasks() const +{ + return mTasks; +} + bool SedDocument::Impl::addTask(const SedAbstractTaskPtr &pTask) { if (pTask == nullptr) { @@ -413,12 +443,12 @@ bool SedDocument::hasModels() const size_t SedDocument::modelCount() const { - return pimpl()->mModels.size(); + return pimpl()->modelCount(); } SedModelPtrs SedDocument::models() const { - return pimpl()->mModels; + return pimpl()->models(); } bool SedDocument::addModel(const SedModelPtr &pModel) @@ -438,12 +468,12 @@ bool SedDocument::hasSimulations() const size_t SedDocument::simulationCount() const { - return pimpl()->mSimulations.size(); + return pimpl()->simulationCount(); } SedSimulationPtrs SedDocument::simulations() const { - return pimpl()->mSimulations; + return pimpl()->simulations(); } bool SedDocument::addSimulation(const SedSimulationPtr &pSimulation) @@ -463,12 +493,12 @@ bool SedDocument::hasTasks() const size_t SedDocument::taskCount() const { - return pimpl()->mTasks.size(); + return pimpl()->taskCount(); } SedAbstractTaskPtrs SedDocument::tasks() const { - return pimpl()->mTasks; + return pimpl()->tasks(); } bool SedDocument::addTask(const SedAbstractTaskPtr &pTask) diff --git a/src/sed/seddocument_p.h b/src/sed/seddocument_p.h index 4155ff850..e41be39e8 100644 --- a/src/sed/seddocument_p.h +++ b/src/sed/seddocument_p.h @@ -53,14 +53,20 @@ class SedDocument::Impl: public Logger::Impl std::string serialise(const std::string &pBasePath = {}) const; bool hasModels() const; + size_t modelCount() const; + SedModelPtrs models() const; bool addModel(const SedModelPtr &pModel); bool removeModel(const SedModelPtr &pModel); bool hasSimulations() const; + size_t simulationCount() const; + SedSimulationPtrs simulations() const; bool addSimulation(const SedSimulationPtr &pSimulation); bool removeSimulation(const SedSimulationPtr &pSimulation); bool hasTasks() const; + size_t taskCount() const; + SedAbstractTaskPtrs tasks() const; bool addTask(const SedAbstractTaskPtr &pTask); bool removeTask(const SedAbstractTaskPtr &pTask); }; diff --git a/src/sed/sedinstance.cpp b/src/sed/sedinstance.cpp index 7a0598473..955ff3ec0 100644 --- a/src/sed/sedinstance.cpp +++ b/src/sed/sedinstance.cpp @@ -88,6 +88,11 @@ void SedInstance::Impl::run() } } +SedInstanceTaskPtrs SedInstance::Impl::tasks() const +{ + return mTasks; +} + SedInstance::SedInstance(const SedDocumentPtr &pDocument, bool pCompiled) : Logger(new Impl(pDocument, pCompiled)) { @@ -115,7 +120,7 @@ void SedInstance::run() SedInstanceTaskPtrs SedInstance::tasks() const { - return pimpl()->mTasks; + return pimpl()->tasks(); } } // namespace libOpenCOR diff --git a/src/sed/sedinstance_p.h b/src/sed/sedinstance_p.h index e472e2dca..f7071fef6 100644 --- a/src/sed/sedinstance_p.h +++ b/src/sed/sedinstance_p.h @@ -32,6 +32,8 @@ class SedInstance::Impl: public Logger::Impl explicit Impl(const SedDocumentPtr &pDocument, bool pCompiled); void run(); + + SedInstanceTaskPtrs tasks() const; }; } // namespace libOpenCOR diff --git a/src/sed/sedinstancetask.cpp b/src/sed/sedinstancetask.cpp index 55363ec32..dffa04094 100644 --- a/src/sed/sedinstancetask.cpp +++ b/src/sed/sedinstancetask.cpp @@ -330,6 +330,11 @@ std::string name(const libcellml::VariablePtr &pVariable) } // namespace +Doubles SedInstanceTask::Impl::voi() const +{ + return mResults.voi; +} + std::string SedInstanceTask::Impl::voiName() const { return name(mAnalyserModel->voi()->variable()); @@ -340,6 +345,11 @@ std::string SedInstanceTask::Impl::voiUnit() const return mAnalyserModel->voi()->variable()->units()->name(); } +size_t SedInstanceTask::Impl::stateCount() const +{ + return mAnalyserModel->stateCount(); +} + std::string SedInstanceTask::Impl::stateName(size_t pIndex) const { if (pIndex >= mAnalyserModel->stateCount()) { @@ -358,6 +368,11 @@ std::string SedInstanceTask::Impl::stateUnit(size_t pIndex) const return mAnalyserModel->states()[pIndex]->variable()->units()->name(); } +size_t SedInstanceTask::Impl::rateCount() const +{ + return stateCount(); +} + std::string SedInstanceTask::Impl::rateName(size_t pIndex) const { if (pIndex >= mAnalyserModel->stateCount()) { @@ -376,6 +391,11 @@ std::string SedInstanceTask::Impl::rateUnit(size_t pIndex) const return mAnalyserModel->states()[pIndex]->variable()->units()->name() + "/" + voiUnit(); } +size_t SedInstanceTask::Impl::variableCount() const +{ + return mAnalyserModel->variableCount(); +} + std::string SedInstanceTask::Impl::variableName(size_t pIndex) const { if (pIndex >= mAnalyserModel->variableCount()) { @@ -416,7 +436,7 @@ const SedInstanceTask::Impl *SedInstanceTask::pimpl() const Doubles SedInstanceTask::voi() const { - return pimpl()->mResults.voi; + return pimpl()->voi(); } #ifdef __EMSCRIPTEN__ @@ -438,7 +458,7 @@ std::string SedInstanceTask::voiUnit() const size_t SedInstanceTask::stateCount() const { - return pimpl()->mAnalyserModel->stateCount(); + return pimpl()->stateCount(); } Doubles SedInstanceTask::state(size_t pIndex) const @@ -465,7 +485,7 @@ std::string SedInstanceTask::stateUnit(size_t pIndex) const size_t SedInstanceTask::rateCount() const { - return stateCount(); + return pimpl()->rateCount(); } Doubles SedInstanceTask::rate(size_t pIndex) const @@ -492,7 +512,7 @@ std::string SedInstanceTask::rateUnit(size_t pIndex) const size_t SedInstanceTask::variableCount() const { - return pimpl()->mAnalyserModel->variableCount(); + return pimpl()->variableCount(); } Doubles SedInstanceTask::variable(size_t pIndex) const diff --git a/src/sed/sedinstancetask_p.h b/src/sed/sedinstancetask_p.h index 276c0c9a5..c788d6f9d 100644 --- a/src/sed/sedinstancetask_p.h +++ b/src/sed/sedinstancetask_p.h @@ -69,15 +69,19 @@ class SedInstanceTask::Impl: public Logger::Impl Doubles rate(size_t pIndex) const; Doubles variable(size_t pIndex) const; + Doubles voi() const; std::string voiName() const; std::string voiUnit() const; + size_t stateCount() const; std::string stateName(size_t pIndex) const; std::string stateUnit(size_t pIndex) const; + size_t rateCount() const; std::string rateName(size_t pIndex) const; std::string rateUnit(size_t pIndex) const; + size_t variableCount() const; std::string variableName(size_t pIndex) const; std::string variableUnit(size_t pIndex) const; }; diff --git a/src/sed/sedonestep.cpp b/src/sed/sedonestep.cpp index 5b2cdac89..c673d9ab6 100644 --- a/src/sed/sedonestep.cpp +++ b/src/sed/sedonestep.cpp @@ -27,6 +27,16 @@ SedOneStep::Impl::Impl(const SedDocumentPtr &pDocument) { } +double SedOneStep::Impl::step() const +{ + return mStep; +} + +void SedOneStep::Impl::setStep(double pStep) +{ + mStep = pStep; +} + void SedOneStep::Impl::serialise(xmlNodePtr pNode) const { auto *node = xmlNewNode(nullptr, toConstXmlCharPtr("oneStep")); @@ -65,12 +75,12 @@ SedOneStepPtr SedOneStep::create(const SedDocumentPtr &pDocument) double SedOneStep::step() const { - return pimpl()->mStep; + return pimpl()->step(); } void SedOneStep::setStep(double pStep) { - pimpl()->mStep = pStep; + pimpl()->setStep(pStep); } } // namespace libOpenCOR diff --git a/src/sed/sedonestep_p.h b/src/sed/sedonestep_p.h index dd367e961..5a4984684 100644 --- a/src/sed/sedonestep_p.h +++ b/src/sed/sedonestep_p.h @@ -29,6 +29,9 @@ class SedOneStep::Impl: public SedSimulation::Impl explicit Impl(const SedDocumentPtr &pDocument); + double step() const; + void setStep(double pStep); + void serialise(xmlNodePtr pNode) const override; }; diff --git a/src/sed/sedsimulation.cpp b/src/sed/sedsimulation.cpp index 318490d80..056fbad6f 100644 --- a/src/sed/sedsimulation.cpp +++ b/src/sed/sedsimulation.cpp @@ -52,6 +52,26 @@ bool SedSimulation::Impl::isValid(const SedModelPtr &pModel) return !hasErrors(); } +SolverOdePtr SedSimulation::Impl::odeSolver() const +{ + return mOdeSolver; +} + +void SedSimulation::Impl::setOdeSolver(const SolverOdePtr &pOdeSolver) +{ + mOdeSolver = pOdeSolver; +} + +SolverNlaPtr SedSimulation::Impl::nlaSolver() const +{ + return mNlaSolver; +} + +void SedSimulation::Impl::setNlaSolver(const SolverNlaPtr &pNlaSolver) +{ + mNlaSolver = pNlaSolver; +} + void SedSimulation::Impl::serialise(xmlNodePtr pNode) const { SedBase::Impl::serialise(pNode); @@ -82,24 +102,24 @@ const SedSimulation::Impl *SedSimulation::pimpl() const return reinterpret_cast(SedBase::pimpl()); } -void SedSimulation::setOdeSolver(const SolverOdePtr &pOdeSolver) +SolverOdePtr SedSimulation::odeSolver() const { - pimpl()->mOdeSolver = pOdeSolver; + return pimpl()->odeSolver(); } -SolverOdePtr SedSimulation::odeSolver() const +void SedSimulation::setOdeSolver(const SolverOdePtr &pOdeSolver) { - return pimpl()->mOdeSolver; + pimpl()->setOdeSolver(pOdeSolver); } -void SedSimulation::setNlaSolver(const SolverNlaPtr &pNlaSolver) +SolverNlaPtr SedSimulation::nlaSolver() const { - pimpl()->mNlaSolver = pNlaSolver; + return pimpl()->nlaSolver(); } -SolverNlaPtr SedSimulation::nlaSolver() const +void SedSimulation::setNlaSolver(const SolverNlaPtr &pNlaSolver) { - return pimpl()->mNlaSolver; + pimpl()->setNlaSolver(pNlaSolver); } } // namespace libOpenCOR diff --git a/src/sed/sedsimulation_p.h b/src/sed/sedsimulation_p.h index c3a2188fe..cf3d034da 100644 --- a/src/sed/sedsimulation_p.h +++ b/src/sed/sedsimulation_p.h @@ -34,6 +34,12 @@ class SedSimulation::Impl: public SedBase::Impl bool isValid(const SedModelPtr &pModel); + SolverOdePtr odeSolver() const; + void setOdeSolver(const SolverOdePtr &pOdeSolver); + + SolverNlaPtr nlaSolver() const; + void setNlaSolver(const SolverNlaPtr &pNlaSolver); + void serialise(xmlNodePtr pNode) const override; }; diff --git a/src/sed/sedtask.cpp b/src/sed/sedtask.cpp index d263de79c..162f0a143 100644 --- a/src/sed/sedtask.cpp +++ b/src/sed/sedtask.cpp @@ -63,6 +63,26 @@ bool SedTask::Impl::isValid() return !hasIssues(); } +SedModelPtr SedTask::Impl::model() const +{ + return mModel; +} + +void SedTask::Impl::setModel(const SedModelPtr &pModel) +{ + mModel = pModel; +} + +SedSimulationPtr SedTask::Impl::simulation() const +{ + return mSimulation; +} + +void SedTask::Impl::setSimulation(const SedSimulationPtr &pSimulation) +{ + mSimulation = pSimulation; +} + void SedTask::Impl::serialise(xmlNodePtr pNode) const { auto *node = xmlNewNode(nullptr, toConstXmlCharPtr("task")); @@ -108,22 +128,22 @@ SedTaskPtr SedTask::create(const SedDocumentPtr &pDocument, const SedModelPtr &p SedModelPtr SedTask::model() const { - return pimpl()->mModel; + return pimpl()->model(); } void SedTask::setModel(const SedModelPtr &pModel) { - pimpl()->mModel = pModel; + pimpl()->setModel(pModel); } SedSimulationPtr SedTask::simulation() const { - return pimpl()->mSimulation; + return pimpl()->simulation(); } void SedTask::setSimulation(const SedSimulationPtr &pSimulation) { - pimpl()->mSimulation = pSimulation; + pimpl()->setSimulation(pSimulation); } } // namespace libOpenCOR diff --git a/src/sed/sedtask_p.h b/src/sed/sedtask_p.h index 0bf8e5913..11f0722a9 100644 --- a/src/sed/sedtask_p.h +++ b/src/sed/sedtask_p.h @@ -32,6 +32,12 @@ class SedTask::Impl: public SedAbstractTask::Impl bool isValid() override; + SedModelPtr model() const; + void setModel(const SedModelPtr &pModel); + + SedSimulationPtr simulation() const; + void setSimulation(const SedSimulationPtr &pSimulation); + void serialise(xmlNodePtr pNode) const override; }; diff --git a/src/sed/seduniformtimecourse.cpp b/src/sed/seduniformtimecourse.cpp index 74a531ab4..8f7acc0b9 100644 --- a/src/sed/seduniformtimecourse.cpp +++ b/src/sed/seduniformtimecourse.cpp @@ -27,6 +27,46 @@ SedUniformTimeCourse::Impl::Impl(const SedDocumentPtr &pDocument) { } +double SedUniformTimeCourse::Impl::initialTime() const +{ + return mInitialTime; +} + +void SedUniformTimeCourse::Impl::setInitialTime(double pInitialTime) +{ + mInitialTime = pInitialTime; +} + +double SedUniformTimeCourse::Impl::outputStartTime() const +{ + return mOutputStartTime; +} + +void SedUniformTimeCourse::Impl::setOutputStartTime(double pOutputStartTime) +{ + mOutputStartTime = pOutputStartTime; +} + +double SedUniformTimeCourse::Impl::outputEndTime() const +{ + return mOutputEndTime; +} + +void SedUniformTimeCourse::Impl::setOutputEndTime(double pOutputEndTime) +{ + mOutputEndTime = pOutputEndTime; +} + +int SedUniformTimeCourse::Impl::numberOfSteps() const +{ + return mNumberOfSteps; +} + +void SedUniformTimeCourse::Impl::setNumberOfSteps(int pNumberOfSteps) +{ + mNumberOfSteps = pNumberOfSteps; +} + void SedUniformTimeCourse::Impl::serialise(xmlNodePtr pNode) const { auto *node = xmlNewNode(nullptr, toConstXmlCharPtr("uniformTimeCourse")); @@ -68,42 +108,42 @@ SedUniformTimeCoursePtr SedUniformTimeCourse::create(const SedDocumentPtr &pDocu double SedUniformTimeCourse::initialTime() const { - return pimpl()->mInitialTime; + return pimpl()->initialTime(); } void SedUniformTimeCourse::setInitialTime(double pInitialTime) { - pimpl()->mInitialTime = pInitialTime; + pimpl()->setInitialTime(pInitialTime); } double SedUniformTimeCourse::outputStartTime() const { - return pimpl()->mOutputStartTime; + return pimpl()->outputStartTime(); } void SedUniformTimeCourse::setOutputStartTime(double pOutputStartTime) { - pimpl()->mOutputStartTime = pOutputStartTime; + pimpl()->setOutputStartTime(pOutputStartTime); } double SedUniformTimeCourse::outputEndTime() const { - return pimpl()->mOutputEndTime; + return pimpl()->outputEndTime(); } void SedUniformTimeCourse::setOutputEndTime(double pOutputEndTime) { - pimpl()->mOutputEndTime = pOutputEndTime; + pimpl()->setOutputEndTime(pOutputEndTime); } int SedUniformTimeCourse::numberOfSteps() const { - return pimpl()->mNumberOfSteps; + return pimpl()->numberOfSteps(); } void SedUniformTimeCourse::setNumberOfSteps(int pNumberOfSteps) { - pimpl()->mNumberOfSteps = pNumberOfSteps; + pimpl()->setNumberOfSteps(pNumberOfSteps); } } // namespace libOpenCOR diff --git a/src/sed/seduniformtimecourse_p.h b/src/sed/seduniformtimecourse_p.h index 572a6dd99..081416037 100644 --- a/src/sed/seduniformtimecourse_p.h +++ b/src/sed/seduniformtimecourse_p.h @@ -32,6 +32,18 @@ class SedUniformTimeCourse::Impl: public SedSimulation::Impl explicit Impl(const SedDocumentPtr &pDocument); + double initialTime() const; + void setInitialTime(double pInitialTime); + + double outputStartTime() const; + void setOutputStartTime(double pOutputStartTime); + + double outputEndTime() const; + void setOutputEndTime(double pOutputEndTime); + + int numberOfSteps() const; + void setNumberOfSteps(int pNumberOfSteps); + void serialise(xmlNodePtr pNode) const override; }; diff --git a/src/solver/solver.cpp b/src/solver/solver.cpp index 3596f5265..6685f988f 100644 --- a/src/solver/solver.cpp +++ b/src/solver/solver.cpp @@ -24,6 +24,16 @@ Solver::Impl::Impl(const std::string &pId, const std::string &pName) { } +std::string Solver::Impl::id() const +{ + return mId; +} + +std::string Solver::Impl::name() const +{ + return mName; +} + void Solver::Impl::serialise(xmlNodePtr pNode, bool pNlaAlgorithm) const { // Solver information. @@ -71,12 +81,12 @@ const Solver::Impl *Solver::pimpl() const std::string Solver::id() const { - return pimpl()->mId; + return pimpl()->id(); } std::string Solver::name() const { - return pimpl()->mName; + return pimpl()->name(); } } // namespace libOpenCOR diff --git a/src/solver/solver_p.h b/src/solver/solver_p.h index 4ad3300a2..a3657d1e2 100644 --- a/src/solver/solver_p.h +++ b/src/solver/solver_p.h @@ -45,6 +45,9 @@ class Solver::Impl: public Logger::Impl virtual void populate(libsedml::SedAlgorithm *pAlgorithm) = 0; + std::string id() const; + std::string name() const; + void serialise(xmlNodePtr pNode, bool pNlaAlgorithm = false) const; virtual StringStringMap properties() const = 0; diff --git a/src/solver/solvercvode.cpp b/src/solver/solvercvode.cpp index 4d324aeeb..168de11eb 100644 --- a/src/solver/solvercvode.cpp +++ b/src/solver/solvercvode.cpp @@ -438,6 +438,116 @@ bool SolverCvode::Impl::reinitialise(double pVoi) } */ +double SolverCvode::Impl::maximumStep() const +{ + return mMaximumStep; +} + +void SolverCvode::Impl::setMaximumStep(double pMaximumStep) +{ + mMaximumStep = pMaximumStep; +} + +int SolverCvode::Impl::maximumNumberOfSteps() const +{ + return mMaximumNumberOfSteps; +} + +void SolverCvode::Impl::setMaximumNumberOfSteps(int pMaximumNumberOfSteps) +{ + mMaximumNumberOfSteps = pMaximumNumberOfSteps; +} + +SolverCvode::IntegrationMethod SolverCvode::Impl::integrationMethod() const +{ + return mIntegrationMethod; +} + +void SolverCvode::Impl::setIntegrationMethod(SolverCvode::IntegrationMethod pIntegrationMethod) +{ + mIntegrationMethod = pIntegrationMethod; +} + +SolverCvode::IterationType SolverCvode::Impl::iterationType() const +{ + return mIterationType; +} + +void SolverCvode::Impl::setIterationType(SolverCvode::IterationType pIterationType) +{ + mIterationType = pIterationType; +} + +SolverCvode::LinearSolver SolverCvode::Impl::linearSolver() const +{ + return mLinearSolver; +} + +void SolverCvode::Impl::setLinearSolver(SolverCvode::LinearSolver pLinearSolver) +{ + mLinearSolver = pLinearSolver; +} + +SolverCvode::Preconditioner SolverCvode::Impl::preconditioner() const +{ + return mPreconditioner; +} + +void SolverCvode::Impl::setPreconditioner(SolverCvode::Preconditioner pPreconditioner) +{ + mPreconditioner = pPreconditioner; +} + +int SolverCvode::Impl::upperHalfBandwidth() const +{ + return mUpperHalfBandwidth; +} + +void SolverCvode::Impl::setUpperHalfBandwidth(int pUpperHalfBandwidth) +{ + mUpperHalfBandwidth = pUpperHalfBandwidth; +} + +int SolverCvode::Impl::lowerHalfBandwidth() const +{ + return mLowerHalfBandwidth; +} + +void SolverCvode::Impl::setLowerHalfBandwidth(int pLowerHalfBandwidth) +{ + mLowerHalfBandwidth = pLowerHalfBandwidth; +} + +double SolverCvode::Impl::relativeTolerance() const +{ + return mRelativeTolerance; +} + +void SolverCvode::Impl::setRelativeTolerance(double pRelativeTolerance) +{ + mRelativeTolerance = pRelativeTolerance; +} + +double SolverCvode::Impl::absoluteTolerance() const +{ + return mAbsoluteTolerance; +} + +void SolverCvode::Impl::setAbsoluteTolerance(double pAbsoluteTolerance) +{ + mAbsoluteTolerance = pAbsoluteTolerance; +} + +bool SolverCvode::Impl::interpolateSolution() const +{ + return mInterpolateSolution; +} + +void SolverCvode::Impl::setInterpolateSolution(bool pInterpolateSolution) +{ + mInterpolateSolution = pInterpolateSolution; +} + bool SolverCvode::Impl::solve(double &pVoi, double pVoiEnd) { // Note: rate values are computed and handled internally by CVODE, so we can't access them and therefore need to @@ -507,112 +617,112 @@ SolverCvodePtr SolverCvode::create() double SolverCvode::maximumStep() const { - return pimpl()->mMaximumStep; + return pimpl()->maximumStep(); } void SolverCvode::setMaximumStep(double pMaximumStep) { - pimpl()->mMaximumStep = pMaximumStep; + pimpl()->setMaximumStep(pMaximumStep); } int SolverCvode::maximumNumberOfSteps() const { - return pimpl()->mMaximumNumberOfSteps; + return pimpl()->maximumNumberOfSteps(); } void SolverCvode::setMaximumNumberOfSteps(int pMaximumNumberOfSteps) { - pimpl()->mMaximumNumberOfSteps = pMaximumNumberOfSteps; + pimpl()->setMaximumNumberOfSteps(pMaximumNumberOfSteps); } SolverCvode::IntegrationMethod SolverCvode::integrationMethod() const { - return pimpl()->mIntegrationMethod; + return pimpl()->integrationMethod(); } void SolverCvode::setIntegrationMethod(SolverCvode::IntegrationMethod pIntegrationMethod) { - pimpl()->mIntegrationMethod = pIntegrationMethod; + pimpl()->setIntegrationMethod(pIntegrationMethod); } SolverCvode::IterationType SolverCvode::iterationType() const { - return pimpl()->mIterationType; + return pimpl()->iterationType(); } void SolverCvode::setIterationType(SolverCvode::IterationType pIterationType) { - pimpl()->mIterationType = pIterationType; + pimpl()->setIterationType(pIterationType); } SolverCvode::LinearSolver SolverCvode::linearSolver() const { - return pimpl()->mLinearSolver; + return pimpl()->linearSolver(); } void SolverCvode::setLinearSolver(SolverCvode::LinearSolver pLinearSolver) { - pimpl()->mLinearSolver = pLinearSolver; + pimpl()->setLinearSolver(pLinearSolver); } SolverCvode::Preconditioner SolverCvode::preconditioner() const { - return pimpl()->mPreconditioner; + return pimpl()->preconditioner(); } void SolverCvode::setPreconditioner(SolverCvode::Preconditioner pPreconditioner) { - pimpl()->mPreconditioner = pPreconditioner; + pimpl()->setPreconditioner(pPreconditioner); } int SolverCvode::upperHalfBandwidth() const { - return pimpl()->mUpperHalfBandwidth; + return pimpl()->upperHalfBandwidth(); } void SolverCvode::setUpperHalfBandwidth(int pUpperHalfBandwidth) { - pimpl()->mUpperHalfBandwidth = pUpperHalfBandwidth; + pimpl()->setUpperHalfBandwidth(pUpperHalfBandwidth); } int SolverCvode::lowerHalfBandwidth() const { - return pimpl()->mLowerHalfBandwidth; + return pimpl()->lowerHalfBandwidth(); } void SolverCvode::setLowerHalfBandwidth(int pLowerHalfBandwidth) { - pimpl()->mLowerHalfBandwidth = pLowerHalfBandwidth; + pimpl()->setLowerHalfBandwidth(pLowerHalfBandwidth); } double SolverCvode::relativeTolerance() const { - return pimpl()->mRelativeTolerance; + return pimpl()->relativeTolerance(); } void SolverCvode::setRelativeTolerance(double pRelativeTolerance) { - pimpl()->mRelativeTolerance = pRelativeTolerance; + pimpl()->setRelativeTolerance(pRelativeTolerance); } double SolverCvode::absoluteTolerance() const { - return pimpl()->mAbsoluteTolerance; + return pimpl()->absoluteTolerance(); } void SolverCvode::setAbsoluteTolerance(double pAbsoluteTolerance) { - pimpl()->mAbsoluteTolerance = pAbsoluteTolerance; + pimpl()->setAbsoluteTolerance(pAbsoluteTolerance); } bool SolverCvode::interpolateSolution() const { - return pimpl()->mInterpolateSolution; + return pimpl()->interpolateSolution(); } void SolverCvode::setInterpolateSolution(bool pInterpolateSolution) { - pimpl()->mInterpolateSolution = pInterpolateSolution; + pimpl()->setInterpolateSolution(pInterpolateSolution); } } // namespace libOpenCOR diff --git a/src/solver/solvercvode_p.h b/src/solver/solvercvode_p.h index 658c12b0e..f88f2f2c7 100644 --- a/src/solver/solvercvode_p.h +++ b/src/solver/solvercvode_p.h @@ -95,6 +95,39 @@ class SolverCvode::Impl: public SolverOde::Impl bool reinitialise(double pVoi) override; */ + double maximumStep() const; + void setMaximumStep(double pMaximumStep); + + int maximumNumberOfSteps() const; + void setMaximumNumberOfSteps(int pMaximumNumberOfSteps); + + IntegrationMethod integrationMethod() const; + void setIntegrationMethod(IntegrationMethod pIntegrationMethod); + + IterationType iterationType() const; + void setIterationType(IterationType pIterationType); + + LinearSolver linearSolver() const; + void setLinearSolver(LinearSolver pLinearSolver); + + Preconditioner preconditioner() const; + void setPreconditioner(Preconditioner pPreconditioner); + + int upperHalfBandwidth() const; + void setUpperHalfBandwidth(int pUpperHalfBandwidth); + + int lowerHalfBandwidth() const; + void setLowerHalfBandwidth(int pLowerHalfBandwidth); + + double relativeTolerance() const; + void setRelativeTolerance(double pRelativeTolerance); + + double absoluteTolerance() const; + void setAbsoluteTolerance(double pAbsoluteTolerance); + + bool interpolateSolution() const; + void setInterpolateSolution(bool pInterpolateSolution); + bool solve(double &pVoi, double pVoiEnd) override; }; diff --git a/src/solver/solverkinsol.cpp b/src/solver/solverkinsol.cpp index 6254ecba4..a37fdab2a 100644 --- a/src/solver/solverkinsol.cpp +++ b/src/solver/solverkinsol.cpp @@ -148,6 +148,46 @@ StringStringMap SolverKinsol::Impl::properties() const return res; } +int SolverKinsol::Impl::maximumNumberOfIterations() const +{ + return mMaximumNumberOfIterations; +} + +void SolverKinsol::Impl::setMaximumNumberOfIterations(int pMaximumNumberOfIterations) +{ + mMaximumNumberOfIterations = pMaximumNumberOfIterations; +} + +SolverKinsol::LinearSolver SolverKinsol::Impl::linearSolver() const +{ + return mLinearSolver; +} + +void SolverKinsol::Impl::setLinearSolver(LinearSolver pLinearSolver) +{ + mLinearSolver = pLinearSolver; +} + +int SolverKinsol::Impl::upperHalfBandwidth() const +{ + return mUpperHalfBandwidth; +} + +void SolverKinsol::Impl::setUpperHalfBandwidth(int pUpperHalfBandwidth) +{ + mUpperHalfBandwidth = pUpperHalfBandwidth; +} + +int SolverKinsol::Impl::lowerHalfBandwidth() const +{ + return mLowerHalfBandwidth; +} + +void SolverKinsol::Impl::setLowerHalfBandwidth(int pLowerHalfBandwidth) +{ + mLowerHalfBandwidth = pLowerHalfBandwidth; +} + bool SolverKinsol::Impl::solve(ComputeSystem pComputeSystem, double *pU, size_t pN, void *pUserData) { removeAllIssues(); @@ -322,42 +362,42 @@ SolverKinsolPtr SolverKinsol::create() int SolverKinsol::maximumNumberOfIterations() const { - return pimpl()->mMaximumNumberOfIterations; + return pimpl()->maximumNumberOfIterations(); } void SolverKinsol::setMaximumNumberOfIterations(int pMaximumNumberOfIterations) { - pimpl()->mMaximumNumberOfIterations = pMaximumNumberOfIterations; + pimpl()->setMaximumNumberOfIterations(pMaximumNumberOfIterations); } SolverKinsol::LinearSolver SolverKinsol::linearSolver() const { - return pimpl()->mLinearSolver; + return pimpl()->linearSolver(); } void SolverKinsol::setLinearSolver(LinearSolver pLinearSolver) { - pimpl()->mLinearSolver = pLinearSolver; + pimpl()->setLinearSolver(pLinearSolver); } int SolverKinsol::upperHalfBandwidth() const { - return pimpl()->mUpperHalfBandwidth; + return pimpl()->upperHalfBandwidth(); } void SolverKinsol::setUpperHalfBandwidth(int pUpperHalfBandwidth) { - pimpl()->mUpperHalfBandwidth = pUpperHalfBandwidth; + pimpl()->setUpperHalfBandwidth(pUpperHalfBandwidth); } int SolverKinsol::lowerHalfBandwidth() const { - return pimpl()->mLowerHalfBandwidth; + return pimpl()->lowerHalfBandwidth(); } void SolverKinsol::setLowerHalfBandwidth(int pLowerHalfBandwidth) { - pimpl()->mLowerHalfBandwidth = pLowerHalfBandwidth; + pimpl()->setLowerHalfBandwidth(pLowerHalfBandwidth); } } // namespace libOpenCOR diff --git a/src/solver/solverkinsol_p.h b/src/solver/solverkinsol_p.h index b859b0be0..f0e930003 100644 --- a/src/solver/solverkinsol_p.h +++ b/src/solver/solverkinsol_p.h @@ -50,6 +50,18 @@ class SolverKinsol::Impl: public SolverNla::Impl StringStringMap properties() const override; + int maximumNumberOfIterations() const; + void setMaximumNumberOfIterations(int pMaximumNumberOfIterations); + + LinearSolver linearSolver() const; + void setLinearSolver(LinearSolver pLinearSolver); + + int upperHalfBandwidth() const; + void setUpperHalfBandwidth(int pUpperHalfBandwidth); + + int lowerHalfBandwidth() const; + void setLowerHalfBandwidth(int pLowerHalfBandwidth); + bool solve(ComputeSystem pComputeSystem, double *pU, size_t pN, void *pUserData) override; }; diff --git a/src/solver/solverodefixedstep.cpp b/src/solver/solverodefixedstep.cpp index c8cef298c..451597e56 100644 --- a/src/solver/solverodefixedstep.cpp +++ b/src/solver/solverodefixedstep.cpp @@ -91,6 +91,16 @@ bool SolverOdeFixedStep::Impl::initialise(double pVoi, size_t pSize, double *pSt return true; } +double SolverOdeFixedStep::Impl::step() const +{ + return mStep; +} + +void SolverOdeFixedStep::Impl::setStep(double pStep) +{ + mStep = pStep; +} + SolverOdeFixedStep::SolverOdeFixedStep(Impl *pPimpl) : SolverOde(pPimpl) { @@ -108,12 +118,12 @@ const SolverOdeFixedStep::Impl *SolverOdeFixedStep::pimpl() const double SolverOdeFixedStep::step() const { - return pimpl()->mStep; + return pimpl()->step(); } void SolverOdeFixedStep::setStep(double pStep) { - pimpl()->mStep = pStep; + pimpl()->setStep(pStep); } } // namespace libOpenCOR diff --git a/src/solver/solverodefixedstep_p.h b/src/solver/solverodefixedstep_p.h index dbc13a11b..880499050 100644 --- a/src/solver/solverodefixedstep_p.h +++ b/src/solver/solverodefixedstep_p.h @@ -42,6 +42,9 @@ class SolverOdeFixedStep::Impl: public SolverOde::Impl bool initialise(double pVoi, size_t pSize, double *pStates, double *pRates, double *pVariables, CellmlFileRuntime::ComputeCompiledRates pComputeCompiledRates, CellmlFileRuntime::ComputeInterpretedRates pComputeInterpretedRates) override; + + double step() const; + void setStep(double pStep); }; } // namespace libOpenCOR diff --git a/src/support/cellml/cellmlfile.cpp b/src/support/cellml/cellmlfile.cpp index 1974bf5eb..e68aaaf2e 100644 --- a/src/support/cellml/cellmlfile.cpp +++ b/src/support/cellml/cellmlfile.cpp @@ -108,6 +108,27 @@ void CellmlFile::Impl::populateDocument(const SedDocumentPtr &pDocument) const pDocument->addTask(SedTask::create(pDocument, model, simulation)); } +libcellml::AnalyserModel::Type CellmlFile::Impl::type() const +{ + return mAnalyserModel->type(); +} + +libcellml::AnalyserPtr CellmlFile::Impl::analyser() const +{ + return mAnalyser; +} + +libcellml::AnalyserModelPtr CellmlFile::Impl::analyserModel() const +{ + return mAnalyserModel; +} + +CellmlFileRuntimePtr CellmlFile::Impl::runtime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver, + bool pCompiled) +{ + return CellmlFileRuntime::create(pCellmlFile, pNlaSolver, pCompiled); +} + CellmlFile::CellmlFile(const FilePtr &pFile, const libcellml::ModelPtr &pModel, bool pStrict) : Logger(new Impl {pFile, pModel, pStrict}) { @@ -167,22 +188,22 @@ void CellmlFile::populateDocument(const SedDocumentPtr &pDocument) libcellml::AnalyserModel::Type CellmlFile::type() const { - return pimpl()->mAnalyserModel->type(); + return pimpl()->type(); } libcellml::AnalyserPtr CellmlFile::analyser() const { - return pimpl()->mAnalyser; + return pimpl()->analyser(); } libcellml::AnalyserModelPtr CellmlFile::analyserModel() const { - return pimpl()->mAnalyserModel; + return pimpl()->analyserModel(); } CellmlFileRuntimePtr CellmlFile::runtime(const SolverNlaPtr &pNlaSolver, bool pCompiled) { - return CellmlFileRuntime::create(shared_from_this(), pNlaSolver, pCompiled); + return CellmlFile::Impl::runtime(shared_from_this(), pNlaSolver, pCompiled); } } // namespace libOpenCOR diff --git a/src/support/cellml/cellmlfile_p.h b/src/support/cellml/cellmlfile_p.h index 305b15e09..d7f12fcda 100644 --- a/src/support/cellml/cellmlfile_p.h +++ b/src/support/cellml/cellmlfile_p.h @@ -38,6 +38,13 @@ class CellmlFile::Impl: public Logger::Impl ~Impl() = default; void populateDocument(const SedDocumentPtr &pDocument) const; + + libcellml::AnalyserModel::Type type() const; + libcellml::AnalyserPtr analyser() const; + libcellml::AnalyserModelPtr analyserModel() const; + + static CellmlFileRuntimePtr runtime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver, + bool pCompiled); }; } // namespace libOpenCOR diff --git a/src/support/cellml/cellmlfileruntime.cpp b/src/support/cellml/cellmlfileruntime.cpp index 56e305744..2d5e2fe9d 100644 --- a/src/support/cellml/cellmlfileruntime.cpp +++ b/src/support/cellml/cellmlfileruntime.cpp @@ -181,6 +181,66 @@ CellmlFileRuntime::Impl::~Impl() delete[] mNlaSolverAddress; } +CellmlFileRuntime::InitialiseCompiledVariablesForAlgebraicModel CellmlFileRuntime::Impl::initialiseCompiledVariablesForAlgebraicModel() const +{ + return mInitialiseCompiledVariablesForAlgebraicModel; +} + +CellmlFileRuntime::InitialiseCompiledVariablesForDifferentialModel CellmlFileRuntime::Impl::initialiseCompiledVariablesForDifferentialModel() const +{ + return mInitialiseCompiledVariablesForDifferentialModel; +} + +CellmlFileRuntime::ComputeCompiledComputedConstants CellmlFileRuntime::Impl::computeCompiledComputedConstants() const +{ + return mComputeCompiledComputedConstants; +} + +CellmlFileRuntime::ComputeCompiledRates CellmlFileRuntime::Impl::computeCompiledRates() const +{ + return mComputeCompiledRates; +} + +CellmlFileRuntime::ComputeCompiledVariablesForAlgebraicModel CellmlFileRuntime::Impl::computeCompiledVariablesForAlgebraicModel() const +{ + return mComputeCompiledVariablesForAlgebraicModel; +} + +CellmlFileRuntime::ComputeCompiledVariablesForDifferentialModel CellmlFileRuntime::Impl::computeCompiledVariablesForDifferentialModel() const +{ + return mComputeCompiledVariablesForDifferentialModel; +} + +CellmlFileRuntime::InitialiseInterpretedVariablesForAlgebraicModel CellmlFileRuntime::Impl::initialiseInterpretedVariablesForAlgebraicModel() const +{ + return mInitialiseInterpretedVariablesForAlgebraicModel; +} + +CellmlFileRuntime::InitialiseInterpretedVariablesForDifferentialModel CellmlFileRuntime::Impl::initialiseInterpretedVariablesForDifferentialModel() const +{ + return mInitialiseInterpretedVariablesForDifferentialModel; +} + +CellmlFileRuntime::ComputeInterpretedComputedConstants CellmlFileRuntime::Impl::computeInterpretedComputedConstants() const +{ + return mComputeInterpretedComputedConstants; +} + +CellmlFileRuntime::ComputeInterpretedRates CellmlFileRuntime::Impl::computeInterpretedRates() const +{ + return mComputeInterpretedRates; +} + +CellmlFileRuntime::ComputeInterpretedVariablesForAlgebraicModel CellmlFileRuntime::Impl::computeInterpretedVariablesForAlgebraicModel() const +{ + return mComputeInterpretedVariablesForAlgebraicModel; +} + +CellmlFileRuntime::ComputeInterpretedVariablesForDifferentialModel CellmlFileRuntime::Impl::computeInterpretedVariablesForDifferentialModel() const +{ + return mComputeInterpretedVariablesForDifferentialModel; +} + CellmlFileRuntime::CellmlFileRuntime(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver, bool pCompiled) : Logger(new Impl {pCellmlFile, pNlaSolver, pCompiled}) { @@ -209,62 +269,62 @@ CellmlFileRuntimePtr CellmlFileRuntime::create(const CellmlFilePtr &pCellmlFile, CellmlFileRuntime::InitialiseCompiledVariablesForAlgebraicModel CellmlFileRuntime::initialiseCompiledVariablesForAlgebraicModel() const { - return pimpl()->mInitialiseCompiledVariablesForAlgebraicModel; + return pimpl()->initialiseCompiledVariablesForAlgebraicModel(); } CellmlFileRuntime::InitialiseCompiledVariablesForDifferentialModel CellmlFileRuntime::initialiseCompiledVariablesForDifferentialModel() const { - return pimpl()->mInitialiseCompiledVariablesForDifferentialModel; + return pimpl()->initialiseCompiledVariablesForDifferentialModel(); } CellmlFileRuntime::ComputeCompiledComputedConstants CellmlFileRuntime::computeCompiledComputedConstants() const { - return pimpl()->mComputeCompiledComputedConstants; + return pimpl()->computeCompiledComputedConstants(); } CellmlFileRuntime::ComputeCompiledRates CellmlFileRuntime::computeCompiledRates() const { - return pimpl()->mComputeCompiledRates; + return pimpl()->computeCompiledRates(); } CellmlFileRuntime::ComputeCompiledVariablesForAlgebraicModel CellmlFileRuntime::computeCompiledVariablesForAlgebraicModel() const { - return pimpl()->mComputeCompiledVariablesForAlgebraicModel; + return pimpl()->computeCompiledVariablesForAlgebraicModel(); } CellmlFileRuntime::ComputeCompiledVariablesForDifferentialModel CellmlFileRuntime::computeCompiledVariablesForDifferentialModel() const { - return pimpl()->mComputeCompiledVariablesForDifferentialModel; + return pimpl()->computeCompiledVariablesForDifferentialModel(); } CellmlFileRuntime::InitialiseInterpretedVariablesForAlgebraicModel CellmlFileRuntime::initialiseInterpretedVariablesForAlgebraicModel() const { - return pimpl()->mInitialiseInterpretedVariablesForAlgebraicModel; + return pimpl()->initialiseInterpretedVariablesForAlgebraicModel(); } CellmlFileRuntime::InitialiseInterpretedVariablesForDifferentialModel CellmlFileRuntime::initialiseInterpretedVariablesForDifferentialModel() const { - return pimpl()->mInitialiseInterpretedVariablesForDifferentialModel; + return pimpl()->initialiseInterpretedVariablesForDifferentialModel(); } CellmlFileRuntime::ComputeInterpretedComputedConstants CellmlFileRuntime::computeInterpretedComputedConstants() const { - return pimpl()->mComputeInterpretedComputedConstants; + return pimpl()->computeInterpretedComputedConstants(); } CellmlFileRuntime::ComputeInterpretedRates CellmlFileRuntime::computeInterpretedRates() const { - return pimpl()->mComputeInterpretedRates; + return pimpl()->computeInterpretedRates(); } CellmlFileRuntime::ComputeInterpretedVariablesForAlgebraicModel CellmlFileRuntime::computeInterpretedVariablesForAlgebraicModel() const { - return pimpl()->mComputeInterpretedVariablesForAlgebraicModel; + return pimpl()->computeInterpretedVariablesForAlgebraicModel(); } CellmlFileRuntime::ComputeInterpretedVariablesForDifferentialModel CellmlFileRuntime::computeInterpretedVariablesForDifferentialModel() const { - return pimpl()->mComputeInterpretedVariablesForDifferentialModel; + return pimpl()->computeInterpretedVariablesForDifferentialModel(); } } // namespace libOpenCOR diff --git a/src/support/cellml/cellmlfileruntime_p.h b/src/support/cellml/cellmlfileruntime_p.h index f75586874..26455ced0 100644 --- a/src/support/cellml/cellmlfileruntime_p.h +++ b/src/support/cellml/cellmlfileruntime_p.h @@ -49,6 +49,20 @@ class CellmlFileRuntime::Impl: public Logger::Impl explicit Impl(const CellmlFilePtr &pCellmlFile, const SolverNlaPtr &pNlaSolver, bool pCompiled); ~Impl(); + + CellmlFileRuntime::InitialiseCompiledVariablesForAlgebraicModel initialiseCompiledVariablesForAlgebraicModel() const; + CellmlFileRuntime::InitialiseCompiledVariablesForDifferentialModel initialiseCompiledVariablesForDifferentialModel() const; + CellmlFileRuntime::ComputeCompiledComputedConstants computeCompiledComputedConstants() const; + CellmlFileRuntime::ComputeCompiledRates computeCompiledRates() const; + CellmlFileRuntime::ComputeCompiledVariablesForAlgebraicModel computeCompiledVariablesForAlgebraicModel() const; + CellmlFileRuntime::ComputeCompiledVariablesForDifferentialModel computeCompiledVariablesForDifferentialModel() const; + + CellmlFileRuntime::InitialiseInterpretedVariablesForAlgebraicModel initialiseInterpretedVariablesForAlgebraicModel() const; + CellmlFileRuntime::InitialiseInterpretedVariablesForDifferentialModel initialiseInterpretedVariablesForDifferentialModel() const; + CellmlFileRuntime::ComputeInterpretedComputedConstants computeInterpretedComputedConstants() const; + CellmlFileRuntime::ComputeInterpretedRates computeInterpretedRates() const; + CellmlFileRuntime::ComputeInterpretedVariablesForAlgebraicModel computeInterpretedVariablesForAlgebraicModel() const; + CellmlFileRuntime::ComputeInterpretedVariablesForDifferentialModel computeInterpretedVariablesForDifferentialModel() const; }; } // namespace libOpenCOR diff --git a/src/support/combine/combinearchive.cpp b/src/support/combine/combinearchive.cpp index eb09f75f2..9c6e8db24 100644 --- a/src/support/combine/combinearchive.cpp +++ b/src/support/combine/combinearchive.cpp @@ -52,6 +52,21 @@ CombineArchive::Impl::~Impl() delete mArchive; } +FilePtr CombineArchive::Impl::masterFile() const +{ + return mMasterFile; +} + +bool CombineArchive::Impl::hasFiles() const +{ + return mFiles.empty(); +} + +size_t CombineArchive::Impl::fileCount() const +{ + return mFiles.size(); +} + Strings CombineArchive::Impl::fileNames() const { Strings res; @@ -63,6 +78,11 @@ Strings CombineArchive::Impl::fileNames() const return res; } +FilePtrs CombineArchive::Impl::files() const +{ + return mFiles; +} + FilePtr CombineArchive::Impl::file(const std::string &pFileName) const { for (const auto &file : mFiles) { @@ -122,17 +142,17 @@ CombineArchivePtr CombineArchive::create(const FilePtr &pFile) FilePtr CombineArchive::masterFile() const { - return pimpl()->mMasterFile; + return pimpl()->masterFile(); } bool CombineArchive::hasFiles() const { - return !pimpl()->mFiles.empty(); + return !pimpl()->hasFiles(); } size_t CombineArchive::fileCount() const { - return pimpl()->mFiles.size(); + return pimpl()->fileCount(); } Strings CombineArchive::fileNames() const @@ -142,7 +162,7 @@ Strings CombineArchive::fileNames() const FilePtrs CombineArchive::files() const { - return pimpl()->mFiles; + return pimpl()->files(); } FilePtr CombineArchive::file(const std::string &pFileName) const diff --git a/src/support/combine/combinearchive_p.h b/src/support/combine/combinearchive_p.h index 21694450a..9cf2589a2 100644 --- a/src/support/combine/combinearchive_p.h +++ b/src/support/combine/combinearchive_p.h @@ -32,7 +32,11 @@ class CombineArchive::Impl: public Logger::Impl explicit Impl(const FilePtr &pFile, libcombine::CombineArchive *pArchive); ~Impl(); + FilePtr masterFile() const; + bool hasFiles() const; + size_t fileCount() const; Strings fileNames() const; + FilePtrs files() const; FilePtr file(const std::string &pFileName) const; }; From 48337852b0f859b5f561f3e5cd4455aac6d75a19 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 24 Jun 2024 13:43:27 +1200 Subject: [PATCH 066/112] Spell check. --- .codespellexclude | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.codespellexclude b/.codespellexclude index 3cc630a02..cf4378bae 100644 --- a/.codespellexclude +++ b/.codespellexclude @@ -1,7 +1,7 @@ afterAll(() => { IssuePtrs mErrors; return !mErrors.empty(); - mErrors.push_back(issue); + return mErrors.size(); + return mErrors; mErrors.push_back(issue); mErrors.clear(); - return pimpl()->mErrors; From c0290ebf2e5c2a1ea55ff37f9218ba264af89aab Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 24 Jun 2024 14:02:37 +1200 Subject: [PATCH 067/112] GHA: GitHub Actions' Windows runner has been fixed, so don't need our hack anymore. --- src/bindings/python/CMakeLists.txt | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/bindings/python/CMakeLists.txt b/src/bindings/python/CMakeLists.txt index 949b21d35..23edb3738 100644 --- a/src/bindings/python/CMakeLists.txt +++ b/src/bindings/python/CMakeLists.txt @@ -52,26 +52,6 @@ if(LIBOPENCOR_PYTHON_BINDINGS) target_link_libraries(${PYTHON_BINDINGS_TARGET} PRIVATE $) - if($ENV{GITHUB_ACTIONS}) - set(GITHUB_ACTIONS ON) - else() - set(GITHUB_ACTIONS OFF) - endif() - - if(GITHUB_ACTIONS AND WIN32 AND SKBUILD) - # Note: this is to account for the fact that the `pip install libOpenCOR` step in our CI doesn't, on GitHub - # Actions' Windows runner, generate the library in the correct place while it used to be fine before (see - # https://github.com/actions/runner-images/issues/10004). Normally, we would expect the library to be - # created in _skbuild/win-amd64-3.12/cmake-build/src/bindings/python/Release/libopencor but for some - # reasons it is created in _skbuild/win-amd64-3.12/cmake-build/src/bindings/python/Release. So, we need to - # copy it to the correct place otherwise its installation will fail (besides the fact that we want to copy - # it to our test directory so that we can test things properly). - - add_custom_command(TARGET ${PYTHON_BINDINGS_TARGET} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $/../$ - $) - endif() - add_custom_command(TARGET ${PYTHON_BINDINGS_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${PYTHON_BINDINGS_DIR}/${CMAKE_PROJECT_NAME_LC}/$) From 9f326a92d644a55cf1804d405b52d9c6e257c9c3 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 24 Jun 2024 15:00:05 +1200 Subject: [PATCH 068/112] API: slight improvement to our documentation. --- src/api/libopencor/file.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/libopencor/file.h b/src/api/libopencor/file.h index 311ec5745..def1e88ff 100644 --- a/src/api/libopencor/file.h +++ b/src/api/libopencor/file.h @@ -106,8 +106,8 @@ class LIBOPENCOR_EXPORT File: public Logger * * Return the file name of this file. If the file is remote then we return the file name of its local copy. * - * @sa url - * @sa path + * @sa url() + * @sa path() * * @return The file name, as a @c std::string, of this file. */ @@ -119,8 +119,8 @@ class LIBOPENCOR_EXPORT File: public Logger * * Return the URL of this file. If the file is local then we return an empty string. * - * @sa fileName - * @sa path + * @sa fileName() + * @sa path() * * @return The URL, as a @c std::string, of this file. */ @@ -132,8 +132,8 @@ class LIBOPENCOR_EXPORT File: public Logger * * Return the path of this file. If the file is local then we return its file name otherwise its URL. * - * @sa fileName - * @sa url + * @sa fileName() + * @sa url() * * @return The path, as a @c std::string, of this file. */ From 3293fe3d7c7c7b7dae463ee37f300b5f94cdae51 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 24 Jun 2024 22:37:17 +1200 Subject: [PATCH 069/112] SedInstance tests: re-enabled a check now that we can run a COMBINE archive. --- tests/api/sed/instancetests.cpp | 3 +-- tests/bindings/javascript/sed.instance.test.js | 3 +-- tests/bindings/python/test_sed_instance.py | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/api/sed/instancetests.cpp b/tests/api/sed/instancetests.cpp index 58792f403..80d978d15 100644 --- a/tests/api/sed/instancetests.cpp +++ b/tests/api/sed/instancetests.cpp @@ -282,8 +282,7 @@ TEST(InstanceSedTest, combineArchive) instance->run(); - //---GRY--- TO BE UNCOMMENTED ONCE WE CAN RUN A COMBINE ARCHIVE. - // EXPECT_FALSE(instance->hasIssues()); + EXPECT_FALSE(instance->hasIssues()); } TEST(InstanceSedTest, combineArchiveWithCellmlFileAsMasterFile) diff --git a/tests/bindings/javascript/sed.instance.test.js b/tests/bindings/javascript/sed.instance.test.js index 545525c63..c24329134 100644 --- a/tests/bindings/javascript/sed.instance.test.js +++ b/tests/bindings/javascript/sed.instance.test.js @@ -442,8 +442,7 @@ describe("Sed instance tests", () => { instance.run(); - //---GRY--- TO BE UNCOMMENTED ONCE WE CAN RUN A COMBINE ARCHIVE. - // expect(instance.hasIssues()).toBe(false); + expect(instance.hasIssues()).toBe(false); instance.delete(); document.delete(); diff --git a/tests/bindings/python/test_sed_instance.py b/tests/bindings/python/test_sed_instance.py index 4a91f2f77..93f70a479 100644 --- a/tests/bindings/python/test_sed_instance.py +++ b/tests/bindings/python/test_sed_instance.py @@ -302,8 +302,7 @@ def test_combine_archive(): instance.run() - # ---GRY--- TO BE UNCOMMENTED ONCE WE CAN RUN A COMBINE ARCHIVE. - # assert instance.has_issues == False + assert instance.has_issues == False def test_combine_archive_with_cellml_file_as_master_file(): From 7301a2763d79e106e8882875f4abcfca681c400a Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 24 Jun 2024 17:37:17 +1200 Subject: [PATCH 070/112] FileManager: allow to manually manage/unmanage a file. --- src/api/libopencor/file.h | 9 ++++-- src/api/libopencor/filemanager.h | 24 +++++++++++++++ src/bindings/javascript/file.cpp | 6 +++- src/bindings/python/file.cpp | 4 ++- src/file/file.cpp | 32 ++++++++++++++------ src/file/file_p.h | 4 ++- src/file/filemanager.cpp | 16 +++++++++- tests/api/file/basictests.cpp | 25 +++++++++++++++ tests/bindings/javascript/file.basic.test.js | 26 ++++++++++++++++ tests/bindings/python/test_file_basic.py | 25 +++++++++++++++ 10 files changed, 155 insertions(+), 16 deletions(-) diff --git a/src/api/libopencor/file.h b/src/api/libopencor/file.h index def1e88ff..5c7e0295d 100644 --- a/src/api/libopencor/file.h +++ b/src/api/libopencor/file.h @@ -85,11 +85,16 @@ class LIBOPENCOR_EXPORT File: public Logger * its contents and type. * * @param pFileNameOrUrl The @c std::string file name or URL. + * @param pManaged Whether the file should be managed (by default, it is). * * @return A smart pointer to a @ref File object. */ - static FilePtr create(const std::string &pFileNameOrUrl); + static FilePtr create(const std::string &pFileNameOrUrl, bool pManaged = true); + +#ifdef __EMSCRIPTEN__ + static FilePtr defaultCreate(const std::string &pFileNameOrUrl); +#endif /** * @brief Get the type of this file. @@ -218,7 +223,7 @@ class LIBOPENCOR_EXPORT File: public Logger Impl *pimpl(); /**< Private implementation pointer, @private. */ const Impl *pimpl() const; /**< Constant private implementation pointer, @private. */ - explicit File(const std::string &pFileNameOrUrl); /**< Constructor, @private. */ + explicit File(const std::string &pFileNameOrUrl, bool pManaged); /**< Constructor, @private. */ }; } // namespace libOpenCOR diff --git a/src/api/libopencor/filemanager.h b/src/api/libopencor/filemanager.h index 19e327dd6..2a7d3accd 100644 --- a/src/api/libopencor/filemanager.h +++ b/src/api/libopencor/filemanager.h @@ -43,6 +43,30 @@ class LIBOPENCOR_EXPORT FileManager static FileManager &instance(); + /** + * @brief Manage a file. + * + * Manage a file. + * + * @param pFile The file to be managed. + * + * @sa unmanage() + */ + + void manage(const FilePtr &pFile); + + /** + * @brief Unmanage a file. + * + * Unmanage a file. + * + * @param pFile The file to be unmanaged. + * + * @sa manage() + */ + + void unmanage(const FilePtr &pFile); + /** * @brief Return whether there are managed files. * diff --git a/src/bindings/javascript/file.cpp b/src/bindings/javascript/file.cpp index 6996b259b..e37bec404 100644 --- a/src/bindings/javascript/file.cpp +++ b/src/bindings/javascript/file.cpp @@ -27,7 +27,9 @@ void fileApi() .value("COMBINE_ARCHIVE", libOpenCOR::File::Type::COMBINE_ARCHIVE); emscripten::class_>("File") - .smart_ptr_constructor("File", &libOpenCOR::File::create) + .smart_ptr("File") + .constructor(&libOpenCOR::File::create) + .constructor(&libOpenCOR::File::defaultCreate) .function("type", &libOpenCOR::File::type) .function("fileName", &libOpenCOR::File::fileName) .function("url", &libOpenCOR::File::url) @@ -62,6 +64,8 @@ void fileApi() emscripten::class_("FileManager") .class_function("instance", &libOpenCOR::FileManager::instance) + .function("manage", &libOpenCOR::FileManager::manage) + .function("unmanage", &libOpenCOR::FileManager::unmanage) .function("hasFiles", &libOpenCOR::FileManager::hasFiles) .function("fileCount", &libOpenCOR::FileManager::fileCount) .function("files", &libOpenCOR::FileManager::files) diff --git a/src/bindings/python/file.cpp b/src/bindings/python/file.cpp index 25fd576b4..bc51f3496 100644 --- a/src/bindings/python/file.cpp +++ b/src/bindings/python/file.cpp @@ -34,7 +34,7 @@ void fileApi(py::module_ &m) .value("IrretrievableFile", libOpenCOR::File::Type::IRRETRIEVABLE_FILE) .export_values(); - file.def(py::init(&libOpenCOR::File::create), "Create a File object.", py::arg("file_name_or_url")) + file.def(py::init(&libOpenCOR::File::create), "Create a File object.", py::arg("file_name_or_url"), py::arg("managed") = true) .def_property_readonly("type", &libOpenCOR::File::type, "Get the type of this File object.") .def_property_readonly("file_name", &libOpenCOR::File::fileName, "Get the file name for this File object.") .def_property_readonly("url", &libOpenCOR::File::url, "Get the URL for this File object.") @@ -51,6 +51,8 @@ void fileApi(py::module_ &m) py::class_> fileManager(m, "FileManager"); fileManager.def_static("instance", &libOpenCOR::FileManager::instance, "Get the file manager instance.") + .def("manage", &libOpenCOR::FileManager::manage, "Manage the requested file.", py::arg("file")) + .def("unmanage", &libOpenCOR::FileManager::unmanage, "Unmanage the requested file.", py::arg("file")) .def_property_readonly("has_files", &libOpenCOR::FileManager::hasFiles, "Return whether there are managed files.") .def_property_readonly("file_count", &libOpenCOR::FileManager::fileCount, "Return the number of managed files.") .def_property_readonly("files", &libOpenCOR::FileManager::files, "Return the managed files.") diff --git a/src/file/file.cpp b/src/file/file.cpp index fdfcaae03..732d6845a 100644 --- a/src/file/file.cpp +++ b/src/file/file.cpp @@ -27,8 +27,9 @@ limitations under the License. namespace libOpenCOR { -File::Impl::Impl(const std::string &pFileNameOrUrl) +File::Impl::Impl(const std::string &pFileNameOrUrl, bool pManaged) : Logger::Impl() + , mManaged(pManaged) { // Check whether we are dealing with a local file or a URL. @@ -209,16 +210,18 @@ FilePtr File::Impl::childFile(const std::string &pFileName) const return {}; } -File::File(const std::string &pFileNameOrUrl) - : Logger(new Impl {pFileNameOrUrl}) +File::File(const std::string &pFileNameOrUrl, bool pManaged) + : Logger(new Impl {pFileNameOrUrl, pManaged}) { } File::~File() { - // Have ourselves unmanaged. + // Have ourselves unmanaged, if needed. - FileManager::instance().mPimpl.unmanage(this); + if (pimpl()->mManaged) { + FileManager::instance().mPimpl.unmanage(this); + } delete pimpl(); } @@ -233,10 +236,10 @@ const File::Impl *File::pimpl() const return static_cast(Logger::pimpl()); } -FilePtr File::create(const std::string &pFileNameOrUrl) +FilePtr File::create(const std::string &pFileNameOrUrl, bool pManaged) { - // Check whether the given file name or URL is already managed and if so then return it otherwise create, manage, - // and return a new file object. + // Check whether the given file name or URL is already managed and if so then return it otherwise create, manage (if + // requested), and return a new file object. auto fileManager = FileManager::instance(); auto file = fileManager.file(pFileNameOrUrl); @@ -245,15 +248,24 @@ FilePtr File::create(const std::string &pFileNameOrUrl) return file; } - auto res = FilePtr {new File {pFileNameOrUrl}}; + auto res = FilePtr {new File {pFileNameOrUrl, pManaged}}; res->pimpl()->checkType(res); - fileManager.mPimpl.manage(res.get()); + if (pManaged) { + fileManager.mPimpl.manage(res.get()); + } return res; } +#ifdef __EMSCRIPTEN__ +FilePtr File::defaultCreate(const std::string &pFileNameOrUrl) +{ + return create(pFileNameOrUrl); +} +#endif + File::Type File::type() const { return pimpl()->type(); diff --git a/src/file/file_p.h b/src/file/file_p.h index 58b244352..cfec1887f 100644 --- a/src/file/file_p.h +++ b/src/file/file_p.h @@ -30,6 +30,8 @@ namespace libOpenCOR { class File::Impl: public Logger::Impl { public: + bool mManaged = false; + Type mType = Type::UNKNOWN_FILE; std::filesystem::path mFilePath; @@ -42,7 +44,7 @@ class File::Impl: public Logger::Impl SedmlFilePtr mSedmlFile; CombineArchivePtr mCombineArchive; - explicit Impl(const std::string &pFileNameOrUrl); + explicit Impl(const std::string &pFileNameOrUrl, bool pManaged); ~Impl(); void checkType(const FilePtr &pOwner, bool pResetType = false); diff --git a/src/file/filemanager.cpp b/src/file/filemanager.cpp index 756f06708..e7e1590e6 100644 --- a/src/file/filemanager.cpp +++ b/src/file/filemanager.cpp @@ -82,7 +82,11 @@ void FileManager::Impl::manage(File *pFile) void FileManager::Impl::unmanage(File *pFile) { - mFiles.erase(std::find(mFiles.cbegin(), mFiles.cend(), pFile)); + auto iter = std::find(mFiles.cbegin(), mFiles.cend(), pFile); + + if (iter != mFiles.cend()) { + mFiles.erase(iter); + } #ifdef PRINT_MANAGED_FILES printListOfFiles(std::string("Unmanage ") + pFile->fileName(), mFiles); @@ -144,6 +148,16 @@ FileManager::FileManager() { } +void FileManager::manage(const FilePtr &pFile) +{ + mPimpl.manage(pFile.get()); +} + +void FileManager::unmanage(const FilePtr &pFile) +{ + mPimpl.unmanage(pFile.get()); +} + bool FileManager::hasFiles() const { return mPimpl.hasFiles(); diff --git a/tests/api/file/basictests.cpp b/tests/api/file/basictests.cpp index f9306fb70..eb408ac10 100644 --- a/tests/api/file/basictests.cpp +++ b/tests/api/file/basictests.cpp @@ -154,4 +154,29 @@ TEST(BasicFileTest, fileManager) EXPECT_EQ(fileManager.fileCount(), 2); EXPECT_EQ(fileManager.files().size(), 2); EXPECT_EQ(fileManager.file(libOpenCOR::REMOTE_FILE), remoteFile); + + auto unknownFile = libOpenCOR::File::create(libOpenCOR::UNKNOWN_FILE, false); + + EXPECT_TRUE(sameFileManager.hasFiles()); + EXPECT_EQ(sameFileManager.fileCount(), 2); + EXPECT_EQ(sameFileManager.files().size(), 2); + EXPECT_EQ(sameFileManager.file(libOpenCOR::UNKNOWN_FILE), nullptr); + + fileManager.manage(unknownFile); + + EXPECT_TRUE(fileManager.hasFiles()); + EXPECT_EQ(fileManager.fileCount(), 3); + EXPECT_EQ(fileManager.files().size(), 3); + EXPECT_EQ(fileManager.file(libOpenCOR::UNKNOWN_FILE), unknownFile); + + sameFileManager.unmanage(localFile); + sameFileManager.unmanage(remoteFile); + sameFileManager.unmanage(unknownFile); + + EXPECT_FALSE(sameFileManager.hasFiles()); + EXPECT_EQ(sameFileManager.fileCount(), 0); + EXPECT_EQ(sameFileManager.files().size(), 0); + EXPECT_EQ(sameFileManager.file(libOpenCOR::LOCAL_FILE), nullptr); + EXPECT_EQ(sameFileManager.file(libOpenCOR::REMOTE_FILE), nullptr); + EXPECT_EQ(sameFileManager.file(libOpenCOR::UNKNOWN_FILE), nullptr); } diff --git a/tests/bindings/javascript/file.basic.test.js b/tests/bindings/javascript/file.basic.test.js index 777c362ca..16487b7dc 100644 --- a/tests/bindings/javascript/file.basic.test.js +++ b/tests/bindings/javascript/file.basic.test.js @@ -108,7 +108,33 @@ describe("File basic tests", () => { expect(fileManager.files().size()).toBe(2); expect(fileManager.file(utils.REMOTE_FILE)).toStrictEqual(remoteFile); + const unknownFile = new libopencor.File(utils.UNKNOWN_FILE, false); + + expect(sameFileManager.hasFiles()).toBe(true); + expect(sameFileManager.fileCount()).toBe(2); + expect(sameFileManager.files().size()).toBe(2); + expect(sameFileManager.file(utils.UNKNOWN_FILE)).toStrictEqual(null); + + fileManager.manage(unknownFile); + + expect(fileManager.hasFiles()).toBe(true); + expect(fileManager.fileCount()).toBe(3); + expect(fileManager.files().size()).toBe(3); + expect(fileManager.file(utils.UNKNOWN_FILE)).toStrictEqual(unknownFile); + + sameFileManager.unmanage(localFile); + sameFileManager.unmanage(remoteFile); + sameFileManager.unmanage(unknownFile); + + expect(sameFileManager.hasFiles()).toBe(false); + expect(sameFileManager.fileCount()).toBe(0); + expect(sameFileManager.files().size()).toBe(0); + expect(sameFileManager.file(utils.LOCAL_FILE)).toStrictEqual(null); + expect(sameFileManager.file(utils.REMOTE_FILE)).toStrictEqual(null); + expect(sameFileManager.file(utils.UNKNOWN_FILE)).toStrictEqual(null); + localFile.delete(); remoteFile.delete(); + unknownFile.delete(); }); }); diff --git a/tests/bindings/python/test_file_basic.py b/tests/bindings/python/test_file_basic.py index c009c059d..e6c5c8760 100644 --- a/tests/bindings/python/test_file_basic.py +++ b/tests/bindings/python/test_file_basic.py @@ -152,3 +152,28 @@ def test_file_manager(): assert file_manager.file_count == 2 assert len(file_manager.files) == 2 assert file_manager.file(utils.RemoteFile) == remote_file + + unknown_file = File(utils.UnknownFile, False) + + assert same_file_manager.has_files == True + assert same_file_manager.file_count == 2 + assert len(file_manager.files) == 2 + assert same_file_manager.file(utils.UnknownFile) == None + + file_manager.manage(unknown_file) + + assert file_manager.has_files == True + assert file_manager.file_count == 3 + assert len(file_manager.files) == 3 + assert file_manager.file(utils.UnknownFile) == unknown_file + + same_file_manager.unmanage(local_file) + same_file_manager.unmanage(remote_file) + same_file_manager.unmanage(unknown_file) + + assert same_file_manager.has_files == False + assert same_file_manager.file_count == 0 + assert len(file_manager.files) == 0 + assert same_file_manager.file(utils.LocalFile) == None + assert same_file_manager.file(utils.RemoteFile) == None + assert same_file_manager.file(utils.UnknownFile) == None From c8f516312524c5bc7b4da5edaaaf33dc633e64de Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 24 Jun 2024 22:36:35 +1200 Subject: [PATCH 071/112] FileManager: added a reset() method. --- src/api/libopencor/filemanager.h | 10 ++++++++++ src/bindings/javascript/file.cpp | 1 + src/bindings/python/file.cpp | 1 + src/file/filemanager.cpp | 12 ++++++++++++ src/file/filemanager_p.h | 2 ++ tests/api/file/basictests.cpp | 18 +++++++++++------- tests/bindings/javascript/file.basic.test.js | 18 +++++++++++------- tests/bindings/python/test_file_basic.py | 18 +++++++++++------- 8 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/api/libopencor/filemanager.h b/src/api/libopencor/filemanager.h index 2a7d3accd..5aaffeef2 100644 --- a/src/api/libopencor/filemanager.h +++ b/src/api/libopencor/filemanager.h @@ -67,6 +67,16 @@ class LIBOPENCOR_EXPORT FileManager void unmanage(const FilePtr &pFile); + /** + * @brief Reset the file manager. + * + * Reset the file manager by unmanaging all the files. + * + * @sa unmanage() + */ + + void reset(); + /** * @brief Return whether there are managed files. * diff --git a/src/bindings/javascript/file.cpp b/src/bindings/javascript/file.cpp index e37bec404..d64fbbf4a 100644 --- a/src/bindings/javascript/file.cpp +++ b/src/bindings/javascript/file.cpp @@ -66,6 +66,7 @@ void fileApi() .class_function("instance", &libOpenCOR::FileManager::instance) .function("manage", &libOpenCOR::FileManager::manage) .function("unmanage", &libOpenCOR::FileManager::unmanage) + .function("reset", &libOpenCOR::FileManager::reset) .function("hasFiles", &libOpenCOR::FileManager::hasFiles) .function("fileCount", &libOpenCOR::FileManager::fileCount) .function("files", &libOpenCOR::FileManager::files) diff --git a/src/bindings/python/file.cpp b/src/bindings/python/file.cpp index bc51f3496..03fc6a63b 100644 --- a/src/bindings/python/file.cpp +++ b/src/bindings/python/file.cpp @@ -53,6 +53,7 @@ void fileApi(py::module_ &m) fileManager.def_static("instance", &libOpenCOR::FileManager::instance, "Get the file manager instance.") .def("manage", &libOpenCOR::FileManager::manage, "Manage the requested file.", py::arg("file")) .def("unmanage", &libOpenCOR::FileManager::unmanage, "Unmanage the requested file.", py::arg("file")) + .def("reset", &libOpenCOR::FileManager::reset, "Reset the file manager.") .def_property_readonly("has_files", &libOpenCOR::FileManager::hasFiles, "Return whether there are managed files.") .def_property_readonly("file_count", &libOpenCOR::FileManager::fileCount, "Return the number of managed files.") .def_property_readonly("files", &libOpenCOR::FileManager::files, "Return the managed files.") diff --git a/src/file/filemanager.cpp b/src/file/filemanager.cpp index e7e1590e6..e27b24b1b 100644 --- a/src/file/filemanager.cpp +++ b/src/file/filemanager.cpp @@ -93,6 +93,13 @@ void FileManager::Impl::unmanage(File *pFile) #endif } +void FileManager::Impl::reset() +{ + for (const auto &file : mFiles) { + unmanage(file); + } +} + bool FileManager::Impl::hasFiles() const { return !mFiles.empty(); @@ -158,6 +165,11 @@ void FileManager::unmanage(const FilePtr &pFile) mPimpl.unmanage(pFile.get()); } +void FileManager::reset() +{ + mPimpl.reset(); +} + bool FileManager::hasFiles() const { return mPimpl.hasFiles(); diff --git a/src/file/filemanager_p.h b/src/file/filemanager_p.h index c5ba784a5..ed29da381 100644 --- a/src/file/filemanager_p.h +++ b/src/file/filemanager_p.h @@ -34,6 +34,8 @@ class FileManager::Impl void manage(File *pFile); void unmanage(File *pFile); + void reset(); + bool hasFiles() const; size_t fileCount() const; FilePtrs files() const; diff --git a/tests/api/file/basictests.cpp b/tests/api/file/basictests.cpp index eb408ac10..b57edcfc0 100644 --- a/tests/api/file/basictests.cpp +++ b/tests/api/file/basictests.cpp @@ -170,13 +170,17 @@ TEST(BasicFileTest, fileManager) EXPECT_EQ(fileManager.file(libOpenCOR::UNKNOWN_FILE), unknownFile); sameFileManager.unmanage(localFile); - sameFileManager.unmanage(remoteFile); - sameFileManager.unmanage(unknownFile); - EXPECT_FALSE(sameFileManager.hasFiles()); - EXPECT_EQ(sameFileManager.fileCount(), 0); - EXPECT_EQ(sameFileManager.files().size(), 0); + EXPECT_TRUE(sameFileManager.hasFiles()); + EXPECT_EQ(sameFileManager.fileCount(), 2); + EXPECT_EQ(sameFileManager.files().size(), 2); EXPECT_EQ(sameFileManager.file(libOpenCOR::LOCAL_FILE), nullptr); - EXPECT_EQ(sameFileManager.file(libOpenCOR::REMOTE_FILE), nullptr); - EXPECT_EQ(sameFileManager.file(libOpenCOR::UNKNOWN_FILE), nullptr); + + fileManager.reset(); + + EXPECT_FALSE(fileManager.hasFiles()); + EXPECT_EQ(fileManager.fileCount(), 0); + EXPECT_EQ(fileManager.files().size(), 0); + EXPECT_EQ(fileManager.file(libOpenCOR::REMOTE_FILE), nullptr); + EXPECT_EQ(fileManager.file(libOpenCOR::UNKNOWN_FILE), nullptr); } diff --git a/tests/bindings/javascript/file.basic.test.js b/tests/bindings/javascript/file.basic.test.js index 16487b7dc..688f1e5b7 100644 --- a/tests/bindings/javascript/file.basic.test.js +++ b/tests/bindings/javascript/file.basic.test.js @@ -123,15 +123,19 @@ describe("File basic tests", () => { expect(fileManager.file(utils.UNKNOWN_FILE)).toStrictEqual(unknownFile); sameFileManager.unmanage(localFile); - sameFileManager.unmanage(remoteFile); - sameFileManager.unmanage(unknownFile); - expect(sameFileManager.hasFiles()).toBe(false); - expect(sameFileManager.fileCount()).toBe(0); - expect(sameFileManager.files().size()).toBe(0); + expect(sameFileManager.hasFiles()).toBe(true); + expect(sameFileManager.fileCount()).toBe(2); + expect(sameFileManager.files().size()).toBe(2); expect(sameFileManager.file(utils.LOCAL_FILE)).toStrictEqual(null); - expect(sameFileManager.file(utils.REMOTE_FILE)).toStrictEqual(null); - expect(sameFileManager.file(utils.UNKNOWN_FILE)).toStrictEqual(null); + + fileManager.reset(); + + expect(fileManager.hasFiles()).toBe(false); + expect(fileManager.fileCount()).toBe(0); + expect(fileManager.files().size()).toBe(0); + expect(fileManager.file(utils.REMOTE_FILE)).toStrictEqual(null); + expect(fileManager.file(utils.UNKNOWN_FILE)).toStrictEqual(null); localFile.delete(); remoteFile.delete(); diff --git a/tests/bindings/python/test_file_basic.py b/tests/bindings/python/test_file_basic.py index e6c5c8760..e32aecc27 100644 --- a/tests/bindings/python/test_file_basic.py +++ b/tests/bindings/python/test_file_basic.py @@ -168,12 +168,16 @@ def test_file_manager(): assert file_manager.file(utils.UnknownFile) == unknown_file same_file_manager.unmanage(local_file) - same_file_manager.unmanage(remote_file) - same_file_manager.unmanage(unknown_file) - assert same_file_manager.has_files == False - assert same_file_manager.file_count == 0 - assert len(file_manager.files) == 0 + assert same_file_manager.has_files == True + assert same_file_manager.file_count == 2 + assert len(file_manager.files) == 2 assert same_file_manager.file(utils.LocalFile) == None - assert same_file_manager.file(utils.RemoteFile) == None - assert same_file_manager.file(utils.UnknownFile) == None + + file_manager.reset() + + assert file_manager.has_files == False + assert file_manager.file_count == 0 + assert len(file_manager.files) == 0 + assert file_manager.file(utils.RemoteFile) == None + assert file_manager.file(utils.UnknownFile) == None From 07e84738355dea32033d8c6f696921b22b4fbfee Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 24 Jun 2024 22:45:55 +1200 Subject: [PATCH 072/112] GHA --- .github/workflows/SUNDIALS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/SUNDIALS.yml b/.github/workflows/SUNDIALS.yml index ac3a52cbe..623957f59 100644 --- a/.github/workflows/SUNDIALS.yml +++ b/.github/workflows/SUNDIALS.yml @@ -5,7 +5,7 @@ on: jobs: sundials: - name: SUNDIALS + name: SUNDIALS uses: ./.github/workflows/buildThirdPartyLibrary.yml with: third_party_library_name: SUNDIALS From 1c860f57a1dc5429ed66d9c748cd43bff91d398e Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 24 Jun 2024 23:38:09 +1200 Subject: [PATCH 073/112] Test page: reset the file manager using the reset button. --- tests/bindings/javascript/res/index.html | 8 +++---- .../bindings/javascript/res/res/libopencor.js | 24 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/bindings/javascript/res/index.html b/tests/bindings/javascript/res/index.html index f3a4a2440..8e0d1ae38 100644 --- a/tests/bindings/javascript/res/index.html +++ b/tests/bindings/javascript/res/index.html @@ -65,7 +65,7 @@ - +

@@ -181,7 +181,7 @@