diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a7f22d9..f457627 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,55 +12,69 @@ concurrency: cancel-in-progress: true env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true BUILD_TYPE: Release BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed jobs: - build: - name: Build & Test - runs-on: macos-26 + # Build the engine + Catch2 unit tests with CMake/Ninja + Clang/libc++ and run + # them through ctest on both macOS (Homebrew LLVM) and Ubuntu (apt.llvm.org + # Clang + libc++) — the multi-platform proof. The macOS leg also produces the + # SonarCloud coverage report from Clang source-based coverage. + build-and-test: + name: Build & Test (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macos-26, ubuntu-latest] steps: - name: Checkout repository uses: actions/checkout@v5 + with: + submodules: recursive - name: Set up Homebrew - id: set-up-homebrew + if: runner.os == 'macOS' uses: Homebrew/actions/setup-homebrew@main - - name: Install dependencies + - name: Install dependencies (macOS) + if: runner.os == 'macOS' run: bash ./.github/workflows/scripts/brew.sh + - name: Install dependencies (Ubuntu) + if: runner.os == 'Linux' + run: bash ./.github/workflows/scripts/ubuntu_deps.sh + + # Pin CMake (and a matching Ninja) to 4.3.3 so CI matches local dev and + # lands in the [4.3, 4.4) CMAKE_EXPERIMENTAL_CXX_IMPORT_STD UUID branch in + # CMakeLists.txt. The runner's default CMake (3.31.x) has no pinned UUID and + # fails configuration. Runs before build_dep.sh since that also calls cmake. + - name: Setup CMake & Ninja + uses: lukka/get-cmake@v4.3.3 + - name: Build C++ Libraries run: bash ./scripts/build_dep.sh - - name: Select Xcode version - run: sudo xcode-select -switch /Applications/Xcode.app + # scripts/build.sh selects the toolchain per platform (Homebrew LLVM on + # macOS, clang/clang++ on Linux), configures with Ninja, and builds the + # library, executable, and unit_tests. ENABLE_COVERAGE instruments the + # macOS build for the coverage report below. + - name: Configure & build + run: ENABLE_COVERAGE=${{ runner.os == 'macOS' && 'ON' || 'OFF' }} bash ./scripts/build.sh - name: Run tests + run: ctest --test-dir build --output-on-failure + + - name: Generate coverage report + if: runner.os == 'macOS' run: > - OTHER_CFLAGS="-fprofile-instr-generate -fcoverage-mapping" - OTHER_CPLUSPLUSFLAGS="-fprofile-instr-generate -fcoverage-mapping" - OTHER_SWIFT_FLAGS="-profile-generate -profile-coverage-mapping" - LLVM_PROFILE_FILE="/tmp/coverage.profraw" - CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO - xcodebuild - -scheme tests - -destination 'platform=macOS,arch=arm64' - -resultBundlePath TestResult/ - -enableCodeCoverage YES - -derivedDataPath "${RUNNER_TEMP}/Build/DerivedData" - -parallelizeTargets - -jobs "$(sysctl -n hw.logicalcpu)" - clean build test - | xcpretty -r junit && exit ${PIPESTATUS[0]} - - - name: Convert coverage report to sonarqube format - run: > - bash ./.github/workflows/scripts/xccov-to-sonarqube-generic.sh *.xcresult/ > sonarqube-generic-coverage.xml + bash ./.github/workflows/scripts/llvmcov-to-sonarqube-generic.sh build + > sonarqube-generic-coverage.xml - name: Upload coverage report + if: runner.os == 'macOS' uses: actions/upload-artifact@v7 with: name: sonarqube-coverage @@ -69,7 +83,7 @@ jobs: sonar-scan: name: SonarCloud Scan - needs: build + needs: build-and-test runs-on: ubuntu-latest steps: @@ -78,45 +92,27 @@ jobs: uses: actions/checkout@v5 with: fetch-depth: 0 + submodules: recursive + + # Same Clang + libc++ + Boost toolchain as the Ubuntu test leg, so the + # build-wrapper captures a build identical to the one that is tested. - name: Install dependencies - run: sudo apt install -y libssl-dev libpq-dev libcurl4-openssl-dev - # ubuntu-latest (24.04) defaults to GCC 13, whose libstdc++ lacks the - # C++23 header (std::print/std::println). That header was added - # in GCC 14, so install it and make it the default compiler for every - # subsequent step (dependency build, CMake configure, build-wrapper). - - name: Install GCC 14 (for C++23 ) - run: | - sudo apt install -y gcc-14 g++-14 - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 100 - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 100 - # Ubuntu's apt Boost (1.83 on 24.04) predates Boost.Redis, which was added - # in Boost 1.84, so is absent. Install a newer Boost. - # Boost.Redis/Asio are header-only, so we only need the headers plus the - # CMake package config — building just Boost.System generates both quickly. - - name: Install Boost >= 1.84 (for Boost.Redis) - run: | - BOOST_VERSION=1.86.0 - BOOST_DIR="boost_${BOOST_VERSION//./_}" - wget -q "https://archives.boost.io/release/${BOOST_VERSION}/source/${BOOST_DIR}.tar.gz" - tar xzf "${BOOST_DIR}.tar.gz" - cd "${BOOST_DIR}" - ./bootstrap.sh > /dev/null - # -d0 silences per-action output (otherwise b2 prints one line per - # copied header — ~15k lines just for the header install). - sudo ./b2 install -d0 --prefix=/usr/local --with-system -j"$(nproc)" - - name: Check compiler version, for debugging - run: | - g++ --version - cmake --version + run: bash ./.github/workflows/scripts/ubuntu_deps.sh + + # Match local dev / the [4.3, 4.4) import-std UUID branch in CMakeLists.txt; + # the runner's default CMake (3.31.x) has no pinned UUID. See the build job. + - name: Setup CMake & Ninja + uses: lukka/get-cmake@v4.3.3 + - name: Build C++ Libraries run: bash ./scripts/build_dep.sh - # SonarQube Server and Cloud (formerly SonarQube and SonarCloud) is a widely used static - # analysis solution for continuous code quality and security inspection. - # This action now supports and is the official entrypoint for scanning C++ projects via GitHub actions. + + # SonarQube Server and Cloud is a widely used static analysis solution for + # continuous code quality and security inspection, and the official + # entrypoint for scanning C++ projects via GitHub actions. # https://github.com/SonarSource/sonarqube-scan-action - name: Install Build Wrapper uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v4.2.1 - # This step installs the SonarQube build wrapper, which is necessary for analyzing C/C++ projects. # Lands at ./artifact/sonarqube-generic-coverage.xml so the existing # sonar.coverageReportPaths argument keeps working unchanged. @@ -126,16 +122,21 @@ jobs: name: sonarqube-coverage path: artifact - # Configures the CMake build system, specifying the source directory and build directory, and setting the build type - - name: Configure CMake - run: cmake -S ${{github.workspace}} -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - - # Runs the build wrapper to capture build commands and outputs them to the specified directory. Then builds the project using CMake - - name: Run build-wrapper - run: | - build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --clean-first - - # Performs the SonarQube scan using the scan action. Uses captured build commands for analysis and requires GitHub and SonarQube tokens for authentication + # Build through scripts/build.sh under the build-wrapper so the analyzed + # build uses the exact same toolchain as the tested build (apt.llvm.org + # Clang + libc++ + OpenMP). A bare `cmake -DCMAKE_CXX_COMPILER=clang++` + # picked up the runner's system Clang 18 — which has no libc++ `std` module + # and no matching libomp, so find_package(OpenMP REQUIRED) failed. The + # build-wrapper intercepts the Ninja compile commands for the scan; deps + # were already built above so build.sh skips them and only our TUs are + # captured. + - name: Build under build-wrapper + run: > + build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} + bash ./scripts/build.sh + + # Performs the SonarQube scan using the captured build commands and the + # downloaded coverage report. Requires GitHub and SonarQube tokens. - name: SonarQube Scan uses: SonarSource/sonarqube-scan-action@v4.2.1 env: diff --git a/.github/workflows/scripts/brew.sh b/.github/workflows/scripts/brew.sh index 40c828c..0dce455 100644 --- a/.github/workflows/scripts/brew.sh +++ b/.github/workflows/scripts/brew.sh @@ -13,4 +13,7 @@ check_and_install() { # Install packages if they don't exist check_and_install postgresql@18 # Check and install PostgreSQL (which includes libpq) check_and_install pkg-config # Check and install pkg-config -check_and_install boost # Check and install pkg-config \ No newline at end of file +check_and_install boost # Check and install Boost +check_and_install llvm # Clang + libc++ with the `std` module (import std) +check_and_install ninja # Ninja generator (required for C++23 modules / import std) +check_and_install libomp # OpenMP runtime (linked by the engine library) \ No newline at end of file diff --git a/.github/workflows/scripts/cpp_coverage.sh b/.github/workflows/scripts/cpp_coverage.sh deleted file mode 100644 index 70b6c2b..0000000 --- a/.github/workflows/scripts/cpp_coverage.sh +++ /dev/null @@ -1,6 +0,0 @@ -PROFILE_DIR=$(ls -t /tmp/Build/ProfileData | head -n 1); -xcrun llvm-cov show \ - /tmp/Build/Products/Debug/tests.xctest/Contents/MacOS/tests \ - -instr-profile="/tmp/Build/ProfileData/${PROFILE_DIR}/Coverage.profdata" \ - -format=text \ - > coverage.txt \ No newline at end of file diff --git a/.github/workflows/scripts/llvmcov-to-sonarqube-generic.sh b/.github/workflows/scripts/llvmcov-to-sonarqube-generic.sh new file mode 100755 index 0000000..9e0047e --- /dev/null +++ b/.github/workflows/scripts/llvmcov-to-sonarqube-generic.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +# Generate a SonarQube "generic test coverage" report from the Catch2 unit tests +# using Clang source-based coverage (replaces the xcodebuild + xccov path). +# +# Pipeline: run the instrumented unit_tests binary -> llvm-profdata merge -> +# llvm-cov export (lcov) -> convert lcov to Sonar generic XML on stdout. +# +# Usage: bash llvmcov-to-sonarqube-generic.sh [BUILD_DIR] > coverage.xml +# BUILD_DIR defaults to "build". Progress goes to stderr; only the XML is +# written to stdout, so the caller can redirect it straight to a file (matching +# how xccov-to-sonarqube-generic.sh was invoked). +# +# llvm-cov / llvm-profdata are taken from $LLVM_COV / $LLVM_PROFDATA if set, +# else from Homebrew LLVM on macOS, else from PATH (apt.llvm.org on Linux puts +# versioned tools on PATH via update-alternatives). +set -euo pipefail + +BUILD_DIR="${1:-build}" +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" +TEST_BIN="${BUILD_DIR}/tests/unit_tests" + +if [[ ! -x "$TEST_BIN" ]]; then + echo "Test binary not found at $TEST_BIN — build the unit_tests target with -DENABLE_COVERAGE=ON first" 1>&2 + exit 1 +fi + +# Resolve the LLVM coverage tools. +if [[ -n "${LLVM_COV:-}" ]]; then + : # caller-provided +elif [[ "$(uname)" == "Darwin" ]] && command -v brew &>/dev/null; then + LLVM_BIN="$(brew --prefix llvm)/bin" + LLVM_COV="${LLVM_BIN}/llvm-cov" + LLVM_PROFDATA="${LLVM_BIN}/llvm-profdata" +else + LLVM_COV="llvm-cov" + LLVM_PROFDATA="llvm-profdata" +fi +LLVM_PROFDATA="${LLVM_PROFDATA:-llvm-profdata}" + +PROFRAW="${BUILD_DIR}/coverage/unit_tests.profraw" +PROFDATA="${BUILD_DIR}/coverage/unit_tests.profdata" +mkdir -p "${BUILD_DIR}/coverage" + +echo "Running instrumented tests..." 1>&2 +LLVM_PROFILE_FILE="$PROFRAW" "$TEST_BIN" 1>&2 + +echo "Merging profile data..." 1>&2 +"$LLVM_PROFDATA" merge -sparse "$PROFRAW" -o "$PROFDATA" + +echo "Exporting coverage and converting to Sonar generic XML..." 1>&2 +# Only the project's own source is relevant — keep files under source/ and drop +# system headers, Catch2, and the test files themselves. +"$LLVM_COV" export -format=lcov -instr-profile="$PROFDATA" "$TEST_BIN" \ + | awk -v root="${REPO_ROOT}/" ' + function xml_escape(s) { + gsub(/&/, "\\&", s); gsub(//, "\\>", s); + gsub(/"/, "\\"", s); return s; + } + BEGIN { print "" } + /^SF:/ { + path = substr($0, 4); + sub("^" root, "", path); # make repo-relative + keep = (path ~ /^source\//); # project source only + if (keep) printf " \n", xml_escape(path); + next; + } + /^DA:/ { + if (!keep) next; + split(substr($0, 4), a, ","); + covered = (a[2] + 0 > 0) ? "true" : "false"; + printf " \n", a[1], covered; + next; + } + /^end_of_record/ { + if (keep) print " "; + keep = 0; + next; + } + END { print "" }' diff --git a/.github/workflows/scripts/ubuntu_deps.sh b/.github/workflows/scripts/ubuntu_deps.sh new file mode 100755 index 0000000..2bb6670 --- /dev/null +++ b/.github/workflows/scripts/ubuntu_deps.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Install the Ubuntu CI toolchain: Clang + libc++ from apt.llvm.org (the Linux +# equivalent of the macOS Homebrew-LLVM setup), Ninja, the engine's system +# dependencies, and a Boost new enough for Boost.Redis. Mirrors the toolchain +# scripts/build.sh expects so `import std` works the same on both platforms. +set -euo pipefail + +LLVM_VERSION="${LLVM_VERSION:-20}" +BOOST_VERSION="${BOOST_VERSION:-1.90.0}" + +echo "== Installing Clang ${LLVM_VERSION} + libc++ from apt.llvm.org ==" +wget -q https://apt.llvm.org/llvm.sh +chmod +x llvm.sh +sudo ./llvm.sh "${LLVM_VERSION}" + +sudo apt-get update +sudo apt-get install -y \ + "libc++-${LLVM_VERSION}-dev" "libc++abi-${LLVM_VERSION}-dev" \ + "libomp-${LLVM_VERSION}-dev" \ + ninja-build \ + libssl-dev libpq-dev libcurl4-openssl-dev + +# Make the pinned Clang the default `clang`/`clang++` so scripts/build.sh and the +# build-wrapper pick it up via the unversioned names. +sudo update-alternatives --install /usr/bin/clang clang "/usr/bin/clang-${LLVM_VERSION}" 100 +sudo update-alternatives --install /usr/bin/clang++ clang++ "/usr/bin/clang++-${LLVM_VERSION}" 100 + +# update-alternatives doesn't reliably repoint /usr/bin/clang on the runner (the +# image ships its own system Clang 18 at that path), so scripts/build.sh fell +# back to it — and libomp-18-dev is never installed, breaking +# find_package(OpenMP REQUIRED). Pin $CC/$CXX to the versioned binaries for every +# later workflow step; build.sh honours them over the unversioned fallback. +if [ -n "${GITHUB_ENV:-}" ]; then + echo "CC=clang-${LLVM_VERSION}" >> "$GITHUB_ENV" + echo "CXX=clang++-${LLVM_VERSION}" >> "$GITHUB_ENV" +fi + +# Ubuntu's apt Boost predates Boost.Redis (added in 1.84). Boost.Redis/Asio are +# header-only, so only the headers + CMake config are needed — building just +# Boost.System generates both quickly. (-d0 silences per-action output.) +echo "== Installing Boost ${BOOST_VERSION} (for Boost.Redis) ==" +BOOST_DIR="boost_${BOOST_VERSION//./_}" +wget -q "https://archives.boost.io/release/${BOOST_VERSION}/source/${BOOST_DIR}.tar.gz" +tar xzf "${BOOST_DIR}.tar.gz" +cd "${BOOST_DIR}" +./bootstrap.sh > /dev/null +sudo ./b2 install -d0 --prefix=/usr/local --with-system -j"$(nproc)" diff --git a/.github/workflows/scripts/xccov-to-sonarqube-generic.sh b/.github/workflows/scripts/xccov-to-sonarqube-generic.sh deleted file mode 100644 index fc3d2a8..0000000 --- a/.github/workflows/scripts/xccov-to-sonarqube-generic.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -function convert_xccov_to_xml { - sed -n \ - -e '/:$/s/&/\&/g;s/^\(.*\):$/ /p' \ - -e 's/^ *\([0-9][0-9]*\): 0.*$/ /p' \ - -e 's/^ *\([0-9][0-9]*\): [1-9].*$/ /p' \ - -e 's/^$/ <\/file>/p' -} - -function xccov_to_generic { - local xcresult="$1" - - echo '' - # https://github.com/SonarSource/sonar-scanning-examples/issues/146 - # xcrun xccov view --archive "$xcresult" | convert_xccov_to_xml - xcrun xccov view --archive "$xcresult" | while read -r line; do echo "${line#$PWD/}"; done | convert_xccov_to_xml - echo '' -} - -function check_xcode_version() { - local major=${1:-0} minor=${2:-0} - return $(( (major >= 14) || (major == 13 && minor >= 3) )) -} - -if ! xcode_version="$(xcodebuild -version | sed -n '1s/^Xcode \([0-9.]*\)$/\1/p')"; then - echo 'Failed to get Xcode version' 1>&2 - exit 1 -elif check_xcode_version ${xcode_version//./ }; then - echo "Xcode version '$xcode_version' not supported, version 13.3 or above is required" 1>&2; - exit 1 -fi - -xcresult="$1" -if [[ $# -ne 1 ]]; then - echo "Invalid number of arguments. Expecting 1 path matching '*.xcresult'" - exit 1 -elif [[ ! -d $xcresult ]]; then - echo "Path not found: $xcresult" 1>&2; - exit 1 -elif [[ $xcresult != *".xcresult"* ]]; then - echo "Expecting input to match '*.xcresult', got: $xcresult" 1>&2; - exit 1 -fi - -xccov_to_generic "$xcresult" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3abd6bb..e71ada3 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ sonarqube-generic-coverage.xml .clangd dump.rdb .infisical.json +cmake-build-debug +.idea/ +.clang-tidy \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 3ed4a98..27faf9d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "external/boost-decimal"] path = external/boost-decimal url = https://github.com/boostorg/decimal +[submodule "external/Catch2"] + path = external/Catch2 + url = https://github.com/catchorg/Catch2.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b01e8e..6105888 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,12 +9,90 @@ if(APPLE) ) endif() +# Enable `import std;` in C++23 modules. This is gated behind CMake's +# experimental flag whose activation UUID is pinned to the exact CMake version, +# so the value differs between the terminal's CMake and CLion's bundled CMake. +# Select it by version to keep both environments configuring cleanly. MUST be set +# before project()/CXX language enablement so the toolchain is detected with +# import-std support. Requires the Ninja generator plus a toolchain that ships a +# libc++ `std` module. Configure with: cmake -G Ninja -B build +if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.3" AND CMAKE_VERSION VERSION_LESS "4.4") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "451f2fe2-a8a2-47c3-bc32-94786d8fc91b") +elseif(CMAKE_VERSION VERSION_GREATER_EQUAL "4.2" AND CMAKE_VERSION VERSION_LESS "4.3") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") +elseif(CMAKE_VERSION VERSION_GREATER_EQUAL "3.30" AND CMAKE_VERSION VERSION_LESS "3.31") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") +else() + message(FATAL_ERROR + "No pinned CMAKE_EXPERIMENTAL_CXX_IMPORT_STD UUID for CMake " + "${CMAKE_VERSION}. Find the value next to the " + "CMAKE_EXPERIMENTAL_CXX_IMPORT_STD symbol in this CMake's binary and add " + "a branch above.") +endif() + +# CMake 4.2 locates the libc++ `std` module via a `libc++.modules.json` manifest, +# discovered through `clang++ -print-file-name=libc++.modules.json`. Homebrew LLVM +# ships the manifest under /lib/c++/, which is not a -print-file-name search +# path, so discovery returns the bare filename and import-std detection fails with +# "`libc++.modules.json` resource does not exist". Point CMake straight at the +# manifest. (CMake 3.30 didn't require this, so the terminal build was unaffected.) +# Must be set before project()/CXX enablement, like the experimental flag above. +if(APPLE AND NOT CMAKE_CXX_STDLIB_MODULES_JSON) + execute_process( + COMMAND brew --prefix llvm + OUTPUT_VARIABLE _llvm_prefix + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + if(_llvm_prefix AND EXISTS "${_llvm_prefix}/lib/c++/libc++.modules.json") + set(CMAKE_CXX_STDLIB_MODULES_JSON "${_llvm_prefix}/lib/c++/libc++.modules.json") + endif() +endif() + +# On Linux the import-std toolchain is Clang + libc++ (apt.llvm.org), mirroring +# the macOS Homebrew-LLVM setup so both platforms share one story. Stock Clang on +# Linux defaults to libstdc++, which has no usable `std` module, so force libc++ +# and locate its module manifest the same way the Apple branch does — Clang's +# `-print-file-name` search path does not include libc++'s install dir, so fall +# back to the well-known apt.llvm.org locations. Gated on the compiler name +# (passed via -DCMAKE_CXX_COMPILER before project()) since the compiler id is not +# known until project()/CXX enablement below. MUST run before project(), like the +# Apple block, so the toolchain is detected with libc++/import-std support. +if(NOT APPLE AND CMAKE_CXX_COMPILER MATCHES "clang") + string(APPEND CMAKE_CXX_FLAGS " -stdlib=libc++") + if(NOT CMAKE_CXX_STDLIB_MODULES_JSON) + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} -stdlib=libc++ -print-file-name=libc++.modules.json + OUTPUT_VARIABLE _libcxx_modules_json + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + if(NOT (_libcxx_modules_json AND EXISTS "${_libcxx_modules_json}")) + file(GLOB _libcxx_modules_json + /usr/lib/llvm-*/lib/c++/libc++.modules.json + /usr/lib/*/c++/libc++.modules.json + /usr/local/lib/c++/libc++.modules.json) + if(_libcxx_modules_json) + list(GET _libcxx_modules_json 0 _libcxx_modules_json) # first match + endif() + endif() + if(_libcxx_modules_json AND EXISTS "${_libcxx_modules_json}") + set(CMAKE_CXX_STDLIB_MODULES_JSON "${_libcxx_modules_json}") + endif() + endif() +endif() + project(BacktestingEngine) # Set the C++ standard set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) +# Emit build/compile_commands.json for clangd/IntelliSense. Forced on here (not +# left to a configure-time flag) so the project's own source/ entries — and the +# module flags for loadCommand.cppm — are always present for the editor. +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + # Configure libpqxx build set(PQXX_LIBRARIES_INSTALL ON) set(SKIP_BUILD_TEST ON) @@ -32,11 +110,28 @@ endif() set(CMAKE_INSTALL_MESSAGE NEVER) set(CMAKE_MESSAGE_LOG_LEVEL "WARNING") +# Homebrew's libpq is keg-only, so CMake's FindPostgreSQL module can't locate it +# on its own. Without a hint, libpqxx's config.cmake falls back to pkg-config, +# which sets PostgreSQL_FOUND but never creates the PostgreSQL::PostgreSQL imported +# target that src/CMakeLists.txt links against — producing a "target not found" +# generate error. Point FindPostgreSQL at the keg and resolve the target here so it +# exists before libpqxx is configured. +if(APPLE AND NOT PostgreSQL_ROOT) + execute_process( + COMMAND brew --prefix libpq + OUTPUT_VARIABLE PostgreSQL_ROOT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif() +find_package(PostgreSQL REQUIRED) + # Build libpqxx from source add_subdirectory(external/libpqxx EXCLUDE_FROM_ALL) -# Collect all .cpp files in the src directory -file(GLOB_RECURSE SOURCES "source/*.cpp") +# Collect all .cpp files in the src directory. CONFIGURE_DEPENDS re-runs the +# glob when .cpp files are added/removed (matching the MODULE_INTERFACES glob +# below), so a new translation unit is picked up without a manual reconfigure. +file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS "source/*.cpp") # main.cpp belongs to the executable only — keeping it in the library too # means it gets compiled twice and the lib carries a competing main(). @@ -45,19 +140,30 @@ list(REMOVE_ITEM SOURCES ${CMAKE_SOURCE_DIR}/source/main.cpp) # Create a library of your project's code add_library(BacktestingEngineLib STATIC ${SOURCES}) +# C++23 module interface units. The SOURCES glob only matches *.cpp, so the +# .cppm modules are collected separately. CONFIGURE_DEPENDS re-runs the glob when +# files are added/removed. PUBLIC so linked consumers can `import` them. +file(GLOB_RECURSE MODULE_INTERFACES CONFIGURE_DEPENDS + "${CMAKE_SOURCE_DIR}/source/*.cppm") +target_sources(BacktestingEngineLib + PUBLIC FILE_SET CXX_MODULES FILES + ${MODULE_INTERFACES}) + +# Enable `import std;` for this target only (NOT globally — that would force it +# onto the third-party libpqxx/pqxx targets). Request C++23 as a compile feature +# so import-std support propagates to consumers that link this library. +set_target_properties(BacktestingEngineLib PROPERTIES CXX_MODULE_STD ON) +target_compile_features(BacktestingEngineLib PUBLIC cxx_std_23) + # Include directories — PUBLIC so they propagate to the executable (and any -# other consumer) through target_link_libraries. +# other consumer) through target_link_libraries. Every project #include is +# source-relative and path-qualified (e.g. "shared/utilities/decimalJson.hpp", +# "run/reporting/tradingResults.hpp"), so a single source root makes each +# #include / module GMF dependency self-describing. The external root is kept +# only for the vendored header-only nlohmann/json (no CMake target ships it). target_include_directories(BacktestingEngineLib PUBLIC - ${CMAKE_SOURCE_DIR}/include - ${CMAKE_SOURCE_DIR}/include/commands - ${CMAKE_SOURCE_DIR}/include/utilities - ${CMAKE_SOURCE_DIR}/include/models - ${CMAKE_SOURCE_DIR}/include/reporting - ${CMAKE_SOURCE_DIR}/include/trading - ${CMAKE_SOURCE_DIR}/include/trading_definitions - ${CMAKE_SOURCE_DIR}/include/strategies - ${CMAKE_SOURCE_DIR}/include/sweep - ${CMAKE_SOURCE_DIR}/external + ${CMAKE_SOURCE_DIR}/source + ${CMAKE_SOURCE_DIR}/external # vendored header-only nlohmann/json ) # Configure OpenMP. On Apple, provide Homebrew libomp hints before discovery. @@ -78,6 +184,16 @@ if(APPLE) endif() find_package(OpenMP REQUIRED) +# OpenMP is linked PUBLIC below, so `-Xclang -fopenmp` is applied to every TU in +# the library — including the `.cppm` modules. CMake builds the `import std;` +# standard-library module WITHOUT OpenMP, so importing std from an OpenMP-enabled +# module is rejected by Clang as a BMI config mismatch. That CMake-managed std +# target ignores target_compile_options and linked usage requirements — it honors +# only the global CMAKE_CXX_FLAGS. So put the OpenMP flag there too, making the +# std module's OpenMP configuration match every consumer's. (It then appears twice +# on normal TUs, via this flag and the linked target; a harmless duplicate.) +string(APPEND CMAKE_CXX_FLAGS " ${OpenMP_CXX_FLAGS}") + # Boost (Homebrew) — Boost.Redis is header-only but its implementation is # compiled into one dedicated TU via (source/ # boostRedisImpl.cpp), which isolates its macro/SSL pollution from the rest of @@ -101,3 +217,21 @@ target_link_libraries(BacktestingEngineLib PUBLIC pqxx OpenMP::OpenMP_CXX) # Main executable add_executable(BacktestingEngine source/main.cpp) target_link_libraries(BacktestingEngine BacktestingEngineLib) + +# Clang source-based coverage. Opt-in (CI sets -DENABLE_COVERAGE=ON) so local +# builds aren't instrumented. PUBLIC on the library so the flags also reach the +# test executable that links it — that's the TU set we actually measure. +option(ENABLE_COVERAGE "Instrument with Clang source-based coverage" OFF) +if(ENABLE_COVERAGE) + target_compile_options(BacktestingEngineLib PUBLIC -fprofile-instr-generate -fcoverage-mapping) + target_link_options(BacktestingEngineLib PUBLIC -fprofile-instr-generate -fcoverage-mapping) +endif() + +# Unit tests (Catch2). include(CTest) defines BUILD_TESTING (default ON) and +# enables `ctest`. Catch2 is a vendored submodule; EXCLUDE_FROM_ALL keeps it out +# of the default `all` build until the test target pulls it in. +include(CTest) +if(BUILD_TESTING) + add_subdirectory(external/Catch2 EXCLUDE_FROM_ALL) + add_subdirectory(tests) +endif() diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 509d17d..0adc3ba 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -1,8 +1,16 @@ -### Headers folder (./source/include) -Header-only headers in include/ are globally available and source/*.cpp is globbed automatically. +### Source layout & includes +Plain headers live next to the code they belong to under `source/` (e.g. +`source/shared/utilities/`, `source/shared/tradingDefinitions/`) — there is no +separate `include/` folder. The build exposes a single source root (`source/`), +so every project `#include` is **source-relative and path-qualified**, e.g. +`#include "shared/utilities/env.hpp"`. This makes each include / module global +module fragment dependency self-describing. Both `source/*.cpp` and +`source/*.cppm` are globbed automatically (`CONFIGURE_DEPENDS`), so a new file is +picked up without editing `CMakeLists.txt`. ### Pragma once Headers should use `#pragma once` directive to guard to prevent multiple inclusions of the same header file. -### Lower Camel Case file names -application.cpp / class Application() \ No newline at end of file +### Lower Camel Case names +camelCase applies to file names, types, and namespaces. +application.cpp / class Application() / namespace tradingDefinitions diff --git a/README.md b/README.md index 90b4947..e7b8da6 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ For ArchLinux: pacman -S postgresql-libs ### Install Boost, OpenSSL, and Redis -Boost.Redis is header-only but its single translation unit (compiled via `` from `source/redisRunner.cpp`) pulls in Boost.Asio's SSL layer, so OpenSSL is a transitive requirement. A local `redis-server` on `127.0.0.1:6379` is also needed for the default `load`/`run` workflow. +Boost.Redis is header-only but its single translation unit (compiled via `` from `source/shared/redis/boostRedisImpl.cpp`) pulls in Boost.Asio's SSL layer, so OpenSSL is a transitive requirement. A local `redis-server` on `127.0.0.1:6379` is also needed for the default `load`/`run` workflow. ``` For Mac Homebrew: brew install boost openssl redis @@ -115,7 +115,7 @@ The `BacktestingEngine` binary exposes a subcommand CLI: ``` BacktestingEngine load Base64-encode a built-in strategy JSON (defined in - source/commands/loadCommand.cpp) and LPUSH it onto the Redis + source/load/loadCommand.cppm) and LPUSH it onto the Redis `strategy_queue` list. BacktestingEngine run @@ -127,7 +127,7 @@ BacktestingEngine run Redis. ``` -Defaults are `127.0.0.1:6379` for the Redis endpoint and `strategy_queue` for the list key (see `include/redisRunner.hpp` and `include/redisLoader.hpp`). +Defaults are `127.0.0.1:6379` for the Redis endpoint and `strategy_queue` for the list key (see `source/shared/redis/redisRunner.hpp` and `source/shared/redis/redisLoader.hpp`). ### Run tests via terminal diff --git a/backtesting-engine-cpp.xcodeproj/project.pbxproj b/backtesting-engine-cpp.xcodeproj/project.pbxproj deleted file mode 100644 index 56fa503..0000000 --- a/backtesting-engine-cpp.xcodeproj/project.pbxproj +++ /dev/null @@ -1,4123 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - 940F6E532FD9479800B0364A /* randomStrategySweep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E502FD9479800B0364A /* randomStrategySweep.cpp */; }; - 940F6E542FD9479800B0364A /* runConfigurationBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E512FD9479800B0364A /* runConfigurationBuilder.cpp */; }; - 940F6E552FD9479800B0364A /* randomStrategySweep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E502FD9479800B0364A /* randomStrategySweep.cpp */; }; - 940F6E562FD9479800B0364A /* runConfigurationBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E512FD9479800B0364A /* runConfigurationBuilder.cpp */; }; - 940F6E582FD947A900B0364A /* decimalConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E572FD947A900B0364A /* decimalConvert.cpp */; }; - 940F6E592FD947A900B0364A /* decimalConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E572FD947A900B0364A /* decimalConvert.cpp */; }; - 940F6E5B2FD947C000B0364A /* sweep.mm in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E5A2FD947B800B0364A /* sweep.mm */; }; - 941408AE2D59F93F000ED1F9 /* sqlManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941408AD2D59F93F000ED1F9 /* sqlManager.cpp */; }; - 941408AF2D59F93F000ED1F9 /* sqlManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941408AD2D59F93F000ED1F9 /* sqlManager.cpp */; }; - 941B549A2D3BBADE00E3BF64 /* trading_definitions_json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941B54992D3BBADD00E3BF64 /* trading_definitions_json.cpp */; }; - 941B549B2D3BBADE00E3BF64 /* trading_definitions_json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941B54992D3BBADD00E3BF64 /* trading_definitions_json.cpp */; }; - 94280BA32D2FC00200F1CF56 /* base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94280BA22D2FC00200F1CF56 /* base64.cpp */; }; - 94280BA42D2FC00200F1CF56 /* base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94280BA22D2FC00200F1CF56 /* base64.cpp */; }; - 942EC5622FBEF94700CCBB5D /* redisConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942EC5612FBEF94700CCBB5D /* redisConnection.cpp */; }; - 942EC5632FBEF94700CCBB5D /* redisConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942EC5612FBEF94700CCBB5D /* redisConnection.cpp */; }; - 942EC5672FBEF95000CCBB5D /* backtestRunner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942EC5642FBEF95000CCBB5D /* backtestRunner.cpp */; }; - 942EC5682FBEF95000CCBB5D /* redisLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942EC5652FBEF95000CCBB5D /* redisLoader.cpp */; }; - 942EC5692FBEF95000CCBB5D /* redisRunner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942EC5662FBEF95000CCBB5D /* redisRunner.cpp */; }; - 942EC56A2FBEF95000CCBB5D /* backtestRunner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942EC5642FBEF95000CCBB5D /* backtestRunner.cpp */; }; - 942EC56B2FBEF95000CCBB5D /* redisLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942EC5652FBEF95000CCBB5D /* redisLoader.cpp */; }; - 942EC56C2FBEF95000CCBB5D /* redisRunner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942EC5662FBEF95000CCBB5D /* redisRunner.cpp */; }; - 942FDDE02FC5C8B20096F318 /* tradingResults.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942FDDDF2FC5C8B20096F318 /* tradingResults.cpp */; }; - 942FDDE22FC5C8B20096F318 /* tradingResults.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942FDDDF2FC5C8B20096F318 /* tradingResults.cpp */; }; - 942FDDE52FC5C9D30096F318 /* libcurl.4.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 942FDDE42FC5C9D30096F318 /* libcurl.4.tbd */; }; - 942FDDE62FC5C9DB0096F318 /* libcurl.4.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 942FDDE42FC5C9D30096F318 /* libcurl.4.tbd */; }; - 943398242D57E53400287A2D /* jsonParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 943398232D57E53400287A2D /* jsonParser.cpp */; }; - 943398252D57E53400287A2D /* jsonParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 943398232D57E53400287A2D /* jsonParser.cpp */; }; - 943398272D57E54000287A2D /* jsonParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 943398262D57E54000287A2D /* jsonParser.mm */; }; - 94364CB62D416D8D00F35B55 /* db.mm in Sources */ = {isa = PBXBuildFile; fileRef = 94364CB52D416D8000F35B55 /* db.mm */; }; - 9437703F2FD42FC000317424 /* elasticClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9437703D2FD42FC000317424 /* elasticClient.cpp */; }; - 943770402FD42FC000317424 /* elasticClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9437703D2FD42FC000317424 /* elasticClient.cpp */; }; - 943770452FD4396F00317424 /* boostRedisImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 943770442FD4396F00317424 /* boostRedisImpl.cpp */; }; - 943770462FD4396F00317424 /* boostRedisImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 943770442FD4396F00317424 /* boostRedisImpl.cpp */; }; - 9464E5F12FA7467200D82BAD /* symbolScale.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9464E5F02FA7467200D82BAD /* symbolScale.mm */; }; - 94674B872D533B4000973137 /* tradeManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94674B852D533B4000973137 /* tradeManager.cpp */; }; - 94674B882D533B4000973137 /* tradeManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94674B852D533B4000973137 /* tradeManager.cpp */; }; - 94674B8A2D533BDA00973137 /* tradeManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 94674B892D533BDA00973137 /* tradeManager.mm */; }; - 946EFF7E2FB9F44E008D9647 /* reporting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 946EFF7D2FB9F44E008D9647 /* reporting.cpp */; }; - 946EFF7F2FB9F44E008D9647 /* reporting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 946EFF7D2FB9F44E008D9647 /* reporting.cpp */; }; - 9470B5A42C8C5AD0007D9CC6 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9470B5A32C8C5AD0007D9CC6 /* main.cpp */; }; - 9470B5B62C8C5BFD007D9CC6 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9470B5A32C8C5AD0007D9CC6 /* main.cpp */; }; - 94724A832F8B92C10029B940 /* operations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94724A822F8B92C10029B940 /* operations.cpp */; }; - 94724A842F8B92C10029B940 /* operations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94724A822F8B92C10029B940 /* operations.cpp */; }; - 94829FC52FCC1D1A00710E6E /* env.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94829FC42FCC1D1A00710E6E /* env.cpp */; }; - 94829FC62FCC1D1A00710E6E /* env.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94829FC42FCC1D1A00710E6E /* env.cpp */; }; - 94CD8BA02D2E8CE500041BBA /* databaseConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD8B9F2D2E8CE500041BBA /* databaseConnection.cpp */; }; - 94CD8BA12D2E8CE500041BBA /* databaseConnection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD8B9F2D2E8CE500041BBA /* databaseConnection.cpp */; }; - 94D3A7262FC1B3AD00EBEA32 /* loadCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D3A7242FC1B3AD00EBEA32 /* loadCommand.cpp */; }; - 94D3A7272FC1B3AD00EBEA32 /* loadCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D3A7242FC1B3AD00EBEA32 /* loadCommand.cpp */; }; - 94D3A7292FC1B41500EBEA32 /* runCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D3A7282FC1B41500EBEA32 /* runCommand.cpp */; }; - 94D3A72A2FC1B41500EBEA32 /* runCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D3A7282FC1B41500EBEA32 /* runCommand.cpp */; }; - 94D601102FA9CD700066F51A /* randomStrategy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6010E2FA9CD700066F51A /* randomStrategy.cpp */; }; - 94D601112FA9CD700066F51A /* randomStrategy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6010E2FA9CD700066F51A /* randomStrategy.cpp */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9470B59F2C8C5AD0007D9CC6 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 9409A61B2FAA6411002C30FF /* strategy.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = strategy.hpp; sourceTree = ""; }; - 940F6E4C2FD9477E00B0364A /* randomStrategySweep.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = randomStrategySweep.hpp; sourceTree = ""; }; - 940F6E4D2FD9477E00B0364A /* runConfigurationBuilder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = runConfigurationBuilder.hpp; sourceTree = ""; }; - 940F6E4F2FD9478800B0364A /* decimalConvert.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = decimalConvert.hpp; sourceTree = ""; }; - 940F6E502FD9479800B0364A /* randomStrategySweep.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = randomStrategySweep.cpp; sourceTree = ""; }; - 940F6E512FD9479800B0364A /* runConfigurationBuilder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = runConfigurationBuilder.cpp; sourceTree = ""; }; - 940F6E572FD947A900B0364A /* decimalConvert.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = decimalConvert.cpp; sourceTree = ""; }; - 940F6E5A2FD947B800B0364A /* sweep.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = sweep.mm; sourceTree = ""; }; - 941408AD2D59F93F000ED1F9 /* sqlManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = sqlManager.cpp; sourceTree = ""; }; - 941408B02D59F954000ED1F9 /* sqlManager.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = sqlManager.hpp; sourceTree = ""; }; - 941B54902D3BBA4900E3BF64 /* ohlc_variables.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ohlc_variables.hpp; sourceTree = ""; }; - 941B54912D3BBA5600E3BF64 /* ohlc_rsi_variables.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ohlc_rsi_variables.hpp; sourceTree = ""; }; - 941B54922D3BBA6500E3BF64 /* trading_variables.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = trading_variables.hpp; sourceTree = ""; }; - 941B54932D3BBA7300E3BF64 /* strategy_variables.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = strategy_variables.hpp; sourceTree = ""; }; - 941B54942D3BBA8300E3BF64 /* strategy.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = strategy.hpp; sourceTree = ""; }; - 941B54972D3BBAA200E3BF64 /* configuration.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = configuration.hpp; sourceTree = ""; }; - 941B54992D3BBADD00E3BF64 /* trading_definitions_json.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = trading_definitions_json.cpp; sourceTree = ""; }; - 941B549C2D3BBFB900E3BF64 /* trading_definitions.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = trading_definitions.hpp; sourceTree = ""; }; - 94280BA12D2FC00200F1CF56 /* base64.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = base64.hpp; sourceTree = ""; }; - 94280BA22D2FC00200F1CF56 /* base64.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = base64.cpp; sourceTree = ""; }; - 942966D82D48E84A00532862 /* priceData.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = priceData.hpp; sourceTree = ""; }; - 942EC55D2FBEF92F00CCBB5D /* redisConnection.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = redisConnection.hpp; sourceTree = ""; }; - 942EC55E2FBEF93A00CCBB5D /* backtestRunner.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = backtestRunner.hpp; sourceTree = ""; }; - 942EC55F2FBEF93A00CCBB5D /* redisLoader.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = redisLoader.hpp; sourceTree = ""; }; - 942EC5602FBEF93A00CCBB5D /* redisRunner.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = redisRunner.hpp; sourceTree = ""; }; - 942EC5612FBEF94700CCBB5D /* redisConnection.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = redisConnection.cpp; sourceTree = ""; }; - 942EC5642FBEF95000CCBB5D /* backtestRunner.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = backtestRunner.cpp; sourceTree = ""; }; - 942EC5652FBEF95000CCBB5D /* redisLoader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = redisLoader.cpp; sourceTree = ""; }; - 942EC5662FBEF95000CCBB5D /* redisRunner.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = redisRunner.cpp; sourceTree = ""; }; - 942FDDDD2FC5C8A30096F318 /* tradingResults.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = tradingResults.hpp; sourceTree = ""; }; - 942FDDDF2FC5C8B20096F318 /* tradingResults.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = tradingResults.cpp; sourceTree = ""; }; - 942FDDE42FC5C9D30096F318 /* libcurl.4.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.4.tbd; path = usr/lib/libcurl.4.tbd; sourceTree = SDKROOT; }; - 943398222D57E52900287A2D /* jsonParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = jsonParser.hpp; sourceTree = ""; }; - 943398232D57E53400287A2D /* jsonParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = jsonParser.cpp; sourceTree = ""; }; - 943398262D57E54000287A2D /* jsonParser.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = jsonParser.mm; sourceTree = ""; }; - 94364CB52D416D8000F35B55 /* db.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = db.mm; sourceTree = ""; }; - 9437703D2FD42FC000317424 /* elasticClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = elasticClient.cpp; sourceTree = ""; }; - 943770412FD42FDD00317424 /* elasticClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = elasticClient.hpp; sourceTree = ""; }; - 943770432FD4351100317424 /* parameterSweep.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = parameterSweep.hpp; sourceTree = ""; }; - 943770442FD4396F00317424 /* boostRedisImpl.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = boostRedisImpl.cpp; sourceTree = ""; }; - 944D0DC82C8C3704004DD0FC /* LICENSE.MD */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.MD; sourceTree = ""; }; - 944D0DC92C8C3704004DD0FC /* build.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = build.sh; sourceTree = ""; }; - 944D0DCA2C8C3704004DD0FC /* clean.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = clean.sh; sourceTree = ""; }; - 944D0DCC2C8C3704004DD0FC /* run.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = run.sh; sourceTree = ""; }; - 944D0DCD2C8C3704004DD0FC /* test.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = test.sh; sourceTree = ""; }; - 944D0DD02C8C3704004DD0FC /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - 944D0DD32C8C3704004DD0FC /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 945F475C2FD5607E00D19164 /* queueKeys.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = queueKeys.hpp; sourceTree = ""; }; - 945F475D2FD5614600D19164 /* run_configuration.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = run_configuration.hpp; sourceTree = ""; }; - 9464E5EF2FA7466900D82BAD /* symbolScale.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = symbolScale.hpp; sourceTree = ""; }; - 9464E5F02FA7467200D82BAD /* symbolScale.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = symbolScale.mm; sourceTree = ""; }; - 94674B822D533B1D00973137 /* trade.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = trade.hpp; sourceTree = ""; }; - 94674B832D533B2F00973137 /* tradeManager.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = tradeManager.hpp; sourceTree = ""; }; - 94674B852D533B4000973137 /* tradeManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = tradeManager.cpp; sourceTree = ""; }; - 94674B892D533BDA00973137 /* tradeManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = tradeManager.mm; sourceTree = ""; }; - 94674BA02D533B2F00973137 /* exitRules.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = exitRules.hpp; sourceTree = ""; }; - 94674BA12F8B92C10029B940 /* reviewStopAndLimit.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = reviewStopAndLimit.hpp; sourceTree = ""; }; - 94685CCE2D384A8B00863D04 /* json.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = json.hpp; sourceTree = ""; }; - 946EFF7D2FB9F44E008D9647 /* reporting.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = reporting.cpp; sourceTree = ""; }; - 946EFF802FB9F457008D9647 /* reporting.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = reporting.hpp; sourceTree = ""; }; - 9470B5A12C8C5AD0007D9CC6 /* source */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = source; sourceTree = BUILT_PRODUCTS_DIR; }; - 9470B5A32C8C5AD0007D9CC6 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; - 9470B5AC2C8C5B99007D9CC6 /* tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 94724A822F8B92C10029B940 /* operations.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = operations.cpp; sourceTree = ""; }; - 94724A852F8B92E30029B940 /* operations.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = operations.hpp; sourceTree = ""; }; - 94829FC32FCC1D1200710E6E /* env.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = env.hpp; sourceTree = ""; }; - 94829FC42FCC1D1A00710E6E /* env.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = env.cpp; sourceTree = ""; }; - 948A9CCD2C906A5600E23669 /* CONVENTIONS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CONVENTIONS.md; sourceTree = ""; }; - 94B1A5992FD735F100CB7C9F /* runLoop.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = runLoop.hpp; sourceTree = ""; }; - 94B4F02A2FD618B300B08FB4 /* backtestLog.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = backtestLog.hpp; sourceTree = ""; }; - 94B4F02B2FD618B300B08FB4 /* threadPool.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = threadPool.hpp; sourceTree = ""; }; - 94BBA4512D2EA2640010E04D /* build.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build.sh; sourceTree = ""; }; - 94C331A02FA899A8006BD690 /* decimal_json.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = decimal_json.hpp; sourceTree = ""; }; - 94CD832A2D2D22C900041BBA /* config.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = config.yml; sourceTree = ""; }; - 94CD832C2D2D22C900041BBA /* codeql.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = codeql.yml; sourceTree = ""; }; - 94CD832D2D2D22C900041BBA /* stale.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = stale.yml; sourceTree = ""; }; - 94CD83302D2D22C900041BBA /* ignoreFiles */ = {isa = PBXFileReference; lastKnownFileType = text; path = ignoreFiles; sourceTree = ""; }; - 94CD83322D2D22C900041BBA /* config.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = config.cmake; sourceTree = ""; }; - 94CD83332D2D22C900041BBA /* libpqxx-config.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-config.cmake"; sourceTree = ""; }; - 94CD83342D2D22C900041BBA /* pqxx_cxx_feature_checks.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = pqxx_cxx_feature_checks.cmake; sourceTree = ""; }; - 94CD83362D2D22C900041BBA /* libtool.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = libtool.m4; sourceTree = ""; }; - 94CD83372D2D22C900041BBA /* lt~obsolete.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = "lt~obsolete.m4"; sourceTree = ""; }; - 94CD83382D2D22C900041BBA /* ltoptions.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ltoptions.m4; sourceTree = ""; }; - 94CD83392D2D22C900041BBA /* ltsugar.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ltsugar.m4; sourceTree = ""; }; - 94CD833A2D2D22C900041BBA /* ltversion.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ltversion.m4; sourceTree = ""; }; - 94CD833B2D2D22C900041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD833D2D2D22C900041BBA /* compile */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = compile; sourceTree = ""; }; - 94CD833E2D2D22C900041BBA /* config.guess */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = config.guess; sourceTree = ""; }; - 94CD833F2D2D22C900041BBA /* config.sub */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = config.sub; sourceTree = ""; }; - 94CD83402D2D22C900041BBA /* depcomp */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = depcomp; sourceTree = ""; }; - 94CD83412D2D22C900041BBA /* install-sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = ""; }; - 94CD83422D2D22C900041BBA /* ltmain.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ltmain.sh; sourceTree = ""; }; - 94CD83432D2D22C900041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD83442D2D22C900041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD83452D2D22C900041BBA /* missing */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = missing; sourceTree = ""; }; - 94CD83462D2D22C900041BBA /* mkinstalldirs */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = mkinstalldirs; sourceTree = ""; }; - 94CD83472D2D22C900041BBA /* test-driver */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "test-driver"; sourceTree = ""; }; - 94CD83492D2D22C900041BBA /* no_need_fslib.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = no_need_fslib.cxx; sourceTree = ""; }; - 94CD834A2D2D22C900041BBA /* PQXX_HAVE_ASSUME.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_ASSUME.cxx; sourceTree = ""; }; - 94CD834B2D2D22C900041BBA /* PQXX_HAVE_CHARCONV_FLOAT.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CHARCONV_FLOAT.cxx; sourceTree = ""; }; - 94CD834C2D2D22C900041BBA /* PQXX_HAVE_CHARCONV_INT.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CHARCONV_INT.cxx; sourceTree = ""; }; - 94CD834D2D2D22C900041BBA /* PQXX_HAVE_CMP.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CMP.cxx; sourceTree = ""; }; - 94CD834E2D2D22C900041BBA /* PQXX_HAVE_CONCEPTS.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CONCEPTS.cxx; sourceTree = ""; }; - 94CD834F2D2D22C900041BBA /* PQXX_HAVE_CXA_DEMANGLE.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CXA_DEMANGLE.cxx; sourceTree = ""; }; - 94CD83502D2D22C900041BBA /* PQXX_HAVE_GCC_PURE.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_GCC_PURE.cxx; sourceTree = ""; }; - 94CD83512D2D22C900041BBA /* PQXX_HAVE_GCC_VISIBILITY.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_GCC_VISIBILITY.cxx; sourceTree = ""; }; - 94CD83522D2D22C900041BBA /* PQXX_HAVE_LIKELY.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_LIKELY.cxx; sourceTree = ""; }; - 94CD83532D2D22C900041BBA /* PQXX_HAVE_MULTIDIM.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_MULTIDIM.cxx; sourceTree = ""; }; - 94CD83542D2D22C900041BBA /* PQXX_HAVE_PATH.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_PATH.cxx; sourceTree = ""; }; - 94CD83552D2D22C900041BBA /* PQXX_HAVE_POLL.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_POLL.cxx; sourceTree = ""; }; - 94CD83562D2D22C900041BBA /* PQXX_HAVE_SLEEP_FOR.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_SLEEP_FOR.cxx; sourceTree = ""; }; - 94CD83572D2D22C900041BBA /* PQXX_HAVE_SOURCE_LOCATION.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_SOURCE_LOCATION.cxx; sourceTree = ""; }; - 94CD83582D2D22C900041BBA /* PQXX_HAVE_SPAN.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_SPAN.cxx; sourceTree = ""; }; - 94CD83592D2D22C900041BBA /* PQXX_HAVE_SSIZE.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_SSIZE.cxx; sourceTree = ""; }; - 94CD835A2D2D22C900041BBA /* PQXX_HAVE_STRERROR_R.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_STRERROR_R.cxx; sourceTree = ""; }; - 94CD835B2D2D22C900041BBA /* PQXX_HAVE_STRERROR_S.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_STRERROR_S.cxx; sourceTree = ""; }; - 94CD835C2D2D22C900041BBA /* PQXX_HAVE_THREAD_LOCAL.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_THREAD_LOCAL.cxx; sourceTree = ""; }; - 94CD835D2D2D22C900041BBA /* PQXX_HAVE_YEAR_MONTH_DAY.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_YEAR_MONTH_DAY.cxx; sourceTree = ""; }; - 94CD835E2D2D22C900041BBA /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - 94CD83602D2D22C900041BBA /* conf.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = conf.py; sourceTree = ""; }; - 94CD83612D2D22C900041BBA /* index.rst */ = {isa = PBXFileReference; lastKnownFileType = text; path = index.rst; sourceTree = ""; }; - 94CD83632D2D22C900041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD83642D2D22C900041BBA /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Doxyfile; sourceTree = ""; }; - 94CD83652D2D22C900041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD83662D2D22C900041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD83672D2D22C900041BBA /* requirements.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = requirements.txt; sourceTree = ""; }; - 94CD83692D2D22C900041BBA /* accessing-results.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "accessing-results.md"; sourceTree = ""; }; - 94CD836A2D2D22C900041BBA /* binary-data.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "binary-data.md"; sourceTree = ""; }; - 94CD836B2D2D22C900041BBA /* datatypes.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = datatypes.md; sourceTree = ""; }; - 94CD836C2D2D22C900041BBA /* escaping.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = escaping.md; sourceTree = ""; }; - 94CD836D2D2D22C900041BBA /* getting-started.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "getting-started.md"; sourceTree = ""; }; - 94CD836E2D2D22C900041BBA /* mainpage.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = mainpage.md; sourceTree = ""; }; - 94CD836F2D2D22C900041BBA /* mainpage.md.template */ = {isa = PBXFileReference; lastKnownFileType = text; path = mainpage.md.template; sourceTree = ""; }; - 94CD83702D2D22C900041BBA /* parameters.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = parameters.md; sourceTree = ""; }; - 94CD83712D2D22C900041BBA /* performance.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = performance.md; sourceTree = ""; }; - 94CD83722D2D22C900041BBA /* prepared-statement.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "prepared-statement.md"; sourceTree = ""; }; - 94CD83732D2D22C900041BBA /* streams.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = streams.md; sourceTree = ""; }; - 94CD83742D2D22C900041BBA /* thread-safety.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "thread-safety.md"; sourceTree = ""; }; - 94CD83762D2D22C900041BBA /* connection-errorhandler.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-errorhandler.hxx"; sourceTree = ""; }; - 94CD83772D2D22C900041BBA /* connection-largeobject.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-largeobject.hxx"; sourceTree = ""; }; - 94CD83782D2D22C900041BBA /* connection-notification_receiver.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-notification_receiver.hxx"; sourceTree = ""; }; - 94CD83792D2D22C900041BBA /* connection-pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-pipeline.hxx"; sourceTree = ""; }; - 94CD837A2D2D22C900041BBA /* connection-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-sql_cursor.hxx"; sourceTree = ""; }; - 94CD837B2D2D22C900041BBA /* connection-stream_from.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-stream_from.hxx"; sourceTree = ""; }; - 94CD837C2D2D22C900041BBA /* connection-stream_to.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-stream_to.hxx"; sourceTree = ""; }; - 94CD837D2D2D22C900041BBA /* connection-transaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-transaction.hxx"; sourceTree = ""; }; - 94CD837E2D2D22C900041BBA /* errorhandler-connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "errorhandler-connection.hxx"; sourceTree = ""; }; - 94CD837F2D2D22C900041BBA /* icursor_iterator-icursorstream.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "icursor_iterator-icursorstream.hxx"; sourceTree = ""; }; - 94CD83802D2D22C900041BBA /* icursorstream-icursor_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "icursorstream-icursor_iterator.hxx"; sourceTree = ""; }; - 94CD83812D2D22C900041BBA /* result-connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-connection.hxx"; sourceTree = ""; }; - 94CD83822D2D22C900041BBA /* result-creation.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-creation.hxx"; sourceTree = ""; }; - 94CD83832D2D22C900041BBA /* result-pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-pipeline.hxx"; sourceTree = ""; }; - 94CD83842D2D22C900041BBA /* result-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-sql_cursor.hxx"; sourceTree = ""; }; - 94CD83852D2D22C900041BBA /* transaction-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "transaction-sql_cursor.hxx"; sourceTree = ""; }; - 94CD83862D2D22C900041BBA /* transaction-transaction_focus.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "transaction-transaction_focus.hxx"; sourceTree = ""; }; - 94CD83882D2D22C900041BBA /* array-composite.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "array-composite.hxx"; sourceTree = ""; }; - 94CD83892D2D22C900041BBA /* callgate.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = callgate.hxx; sourceTree = ""; }; - 94CD838A2D2D22C900041BBA /* concat.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = concat.hxx; sourceTree = ""; }; - 94CD838B2D2D22C900041BBA /* conversions.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = conversions.hxx; sourceTree = ""; }; - 94CD838C2D2D22C900041BBA /* encoding_group.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = encoding_group.hxx; sourceTree = ""; }; - 94CD838D2D2D22C900041BBA /* encodings.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = encodings.hxx; sourceTree = ""; }; - 94CD838E2D2D22C900041BBA /* header-post.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "header-post.hxx"; sourceTree = ""; }; - 94CD838F2D2D22C900041BBA /* header-pre.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "header-pre.hxx"; sourceTree = ""; }; - 94CD83902D2D22C900041BBA /* ignore-deprecated-post.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "ignore-deprecated-post.hxx"; sourceTree = ""; }; - 94CD83912D2D22C900041BBA /* ignore-deprecated-pre.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "ignore-deprecated-pre.hxx"; sourceTree = ""; }; - 94CD83922D2D22C900041BBA /* libpq-forward.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "libpq-forward.hxx"; sourceTree = ""; }; - 94CD83932D2D22C900041BBA /* result_iter.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = result_iter.hxx; sourceTree = ""; }; - 94CD83942D2D22C900041BBA /* result_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = result_iterator.hxx; sourceTree = ""; }; - 94CD83952D2D22C900041BBA /* sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = sql_cursor.hxx; sourceTree = ""; }; - 94CD83962D2D22C900041BBA /* statement_parameters.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = statement_parameters.hxx; sourceTree = ""; }; - 94CD83972D2D22C900041BBA /* stream_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_iterator.hxx; sourceTree = ""; }; - 94CD83982D2D22C900041BBA /* stream_query.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_query.hxx; sourceTree = ""; }; - 94CD83992D2D22C900041BBA /* stream_query_impl.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_query_impl.hxx; sourceTree = ""; }; - 94CD839A2D2D22C900041BBA /* wait.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = wait.hxx; sourceTree = ""; }; - 94CD839C2D2D22C900041BBA /* array.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = array.hxx; sourceTree = ""; }; - 94CD839D2D2D22C900041BBA /* array */ = {isa = PBXFileReference; lastKnownFileType = text; path = array; sourceTree = ""; }; - 94CD839E2D2D22C900041BBA /* binarystring.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = binarystring.hxx; sourceTree = ""; }; - 94CD839F2D2D22C900041BBA /* binarystring */ = {isa = PBXFileReference; lastKnownFileType = text; path = binarystring; sourceTree = ""; }; - 94CD83A02D2D22C900041BBA /* blob.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = blob.hxx; sourceTree = ""; }; - 94CD83A12D2D22C900041BBA /* blob */ = {isa = PBXFileReference; lastKnownFileType = text; path = blob; sourceTree = ""; }; - 94CD83A22D2D22C900041BBA /* composite.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = composite.hxx; sourceTree = ""; }; - 94CD83A32D2D22C900041BBA /* composite */ = {isa = PBXFileReference; lastKnownFileType = text; path = composite; sourceTree = ""; }; - 94CD83A42D2D22C900041BBA /* config.h.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = config.h.in; sourceTree = ""; }; - 94CD83A52D2D22C900041BBA /* connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = connection.hxx; sourceTree = ""; }; - 94CD83A62D2D22C900041BBA /* connection */ = {isa = PBXFileReference; lastKnownFileType = text; path = connection; sourceTree = ""; }; - 94CD83A72D2D22C900041BBA /* cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = cursor.hxx; sourceTree = ""; }; - 94CD83A82D2D22C900041BBA /* cursor */ = {isa = PBXFileReference; lastKnownFileType = text; path = cursor; sourceTree = ""; }; - 94CD83A92D2D22C900041BBA /* dbtransaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = dbtransaction.hxx; sourceTree = ""; }; - 94CD83AA2D2D22C900041BBA /* dbtransaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = dbtransaction; sourceTree = ""; }; - 94CD83AB2D2D22C900041BBA /* errorhandler.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = errorhandler.hxx; sourceTree = ""; }; - 94CD83AC2D2D22C900041BBA /* errorhandler */ = {isa = PBXFileReference; lastKnownFileType = text; path = errorhandler; sourceTree = ""; }; - 94CD83AD2D2D22C900041BBA /* except.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = except.hxx; sourceTree = ""; }; - 94CD83AE2D2D22C900041BBA /* except */ = {isa = PBXFileReference; lastKnownFileType = text; path = except; sourceTree = ""; }; - 94CD83AF2D2D22C900041BBA /* field.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = field.hxx; sourceTree = ""; }; - 94CD83B02D2D22C900041BBA /* field */ = {isa = PBXFileReference; lastKnownFileType = text; path = field; sourceTree = ""; }; - 94CD83B12D2D22C900041BBA /* isolation.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = isolation.hxx; sourceTree = ""; }; - 94CD83B22D2D22C900041BBA /* isolation */ = {isa = PBXFileReference; lastKnownFileType = text; path = isolation; sourceTree = ""; }; - 94CD83B32D2D22C900041BBA /* largeobject.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = largeobject.hxx; sourceTree = ""; }; - 94CD83B42D2D22C900041BBA /* largeobject */ = {isa = PBXFileReference; lastKnownFileType = text; path = largeobject; sourceTree = ""; }; - 94CD83B52D2D22C900041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD83B62D2D22C900041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD83B72D2D22C900041BBA /* nontransaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = nontransaction.hxx; sourceTree = ""; }; - 94CD83B82D2D22C900041BBA /* nontransaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = nontransaction; sourceTree = ""; }; - 94CD83B92D2D22C900041BBA /* notification.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = notification.hxx; sourceTree = ""; }; - 94CD83BA2D2D22C900041BBA /* notification */ = {isa = PBXFileReference; lastKnownFileType = text; path = notification; sourceTree = ""; }; - 94CD83BB2D2D22C900041BBA /* params.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = params.hxx; sourceTree = ""; }; - 94CD83BC2D2D22C900041BBA /* params */ = {isa = PBXFileReference; lastKnownFileType = text; path = params; sourceTree = ""; }; - 94CD83BD2D2D22C900041BBA /* pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = pipeline.hxx; sourceTree = ""; }; - 94CD83BE2D2D22C900041BBA /* pipeline */ = {isa = PBXFileReference; lastKnownFileType = text; path = pipeline; sourceTree = ""; }; - 94CD83BF2D2D22C900041BBA /* pqxx */ = {isa = PBXFileReference; lastKnownFileType = text; path = pqxx; sourceTree = ""; }; - 94CD83C02D2D22C900041BBA /* prepared_statement.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = prepared_statement.hxx; sourceTree = ""; }; - 94CD83C12D2D22C900041BBA /* prepared_statement */ = {isa = PBXFileReference; lastKnownFileType = text; path = prepared_statement; sourceTree = ""; }; - 94CD83C22D2D22C900041BBA /* range.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = range.hxx; sourceTree = ""; }; - 94CD83C32D2D22C900041BBA /* range */ = {isa = PBXFileReference; lastKnownFileType = text; path = range; sourceTree = ""; }; - 94CD83C42D2D22C900041BBA /* result.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = result.hxx; sourceTree = ""; }; - 94CD83C52D2D22C900041BBA /* result */ = {isa = PBXFileReference; lastKnownFileType = text; path = result; sourceTree = ""; }; - 94CD83C62D2D22C900041BBA /* robusttransaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = robusttransaction.hxx; sourceTree = ""; }; - 94CD83C72D2D22C900041BBA /* robusttransaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = robusttransaction; sourceTree = ""; }; - 94CD83C82D2D22C900041BBA /* row.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = row.hxx; sourceTree = ""; }; - 94CD83C92D2D22C900041BBA /* row */ = {isa = PBXFileReference; lastKnownFileType = text; path = row; sourceTree = ""; }; - 94CD83CA2D2D22C900041BBA /* separated_list.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = separated_list.hxx; sourceTree = ""; }; - 94CD83CB2D2D22C900041BBA /* separated_list */ = {isa = PBXFileReference; lastKnownFileType = text; path = separated_list; sourceTree = ""; }; - 94CD83CC2D2D22C900041BBA /* strconv.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = strconv.hxx; sourceTree = ""; }; - 94CD83CD2D2D22C900041BBA /* strconv */ = {isa = PBXFileReference; lastKnownFileType = text; path = strconv; sourceTree = ""; }; - 94CD83CE2D2D22C900041BBA /* stream_from.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_from.hxx; sourceTree = ""; }; - 94CD83CF2D2D22C900041BBA /* stream_from */ = {isa = PBXFileReference; lastKnownFileType = text; path = stream_from; sourceTree = ""; }; - 94CD83D02D2D22C900041BBA /* stream_to.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_to.hxx; sourceTree = ""; }; - 94CD83D12D2D22C900041BBA /* stream_to */ = {isa = PBXFileReference; lastKnownFileType = text; path = stream_to; sourceTree = ""; }; - 94CD83D22D2D22C900041BBA /* subtransaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = subtransaction.hxx; sourceTree = ""; }; - 94CD83D32D2D22C900041BBA /* subtransaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = subtransaction; sourceTree = ""; }; - 94CD83D42D2D22C900041BBA /* time.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = time.hxx; sourceTree = ""; }; - 94CD83D52D2D22C900041BBA /* time */ = {isa = PBXFileReference; lastKnownFileType = text; path = time; sourceTree = ""; }; - 94CD83D62D2D22C900041BBA /* transaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = transaction.hxx; sourceTree = ""; }; - 94CD83D72D2D22C900041BBA /* transaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = transaction; sourceTree = ""; }; - 94CD83D82D2D22C900041BBA /* transaction_base.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = transaction_base.hxx; sourceTree = ""; }; - 94CD83D92D2D22C900041BBA /* transaction_base */ = {isa = PBXFileReference; lastKnownFileType = text; path = transaction_base; sourceTree = ""; }; - 94CD83DA2D2D22C900041BBA /* transaction_focus.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = transaction_focus.hxx; sourceTree = ""; }; - 94CD83DB2D2D22C900041BBA /* transaction_focus */ = {isa = PBXFileReference; lastKnownFileType = text; path = transaction_focus; sourceTree = ""; }; - 94CD83DC2D2D22C900041BBA /* transactor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = transactor.hxx; sourceTree = ""; }; - 94CD83DD2D2D22C900041BBA /* transactor */ = {isa = PBXFileReference; lastKnownFileType = text; path = transactor; sourceTree = ""; }; - 94CD83DE2D2D22C900041BBA /* types.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = types.hxx; sourceTree = ""; }; - 94CD83DF2D2D22C900041BBA /* types */ = {isa = PBXFileReference; lastKnownFileType = text; path = types; sourceTree = ""; }; - 94CD83E02D2D22C900041BBA /* util.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = util.hxx; sourceTree = ""; }; - 94CD83E12D2D22C900041BBA /* util */ = {isa = PBXFileReference; lastKnownFileType = text; path = util; sourceTree = ""; }; - 94CD83E22D2D22C900041BBA /* version.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = version.hxx; sourceTree = ""; }; - 94CD83E32D2D22C900041BBA /* version */ = {isa = PBXFileReference; lastKnownFileType = text; path = version; sourceTree = ""; }; - 94CD83E42D2D22C900041BBA /* version.hxx.template */ = {isa = PBXFileReference; lastKnownFileType = text; path = version.hxx.template; sourceTree = ""; }; - 94CD83E52D2D22C900041BBA /* zview.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = zview.hxx; sourceTree = ""; }; - 94CD83E62D2D22C900041BBA /* zview */ = {isa = PBXFileReference; lastKnownFileType = text; path = zview; sourceTree = ""; }; - 94CD83E82D2D22C900041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD83E92D2D22C900041BBA /* CMakeLists.txt.template */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt.template; sourceTree = ""; }; - 94CD83EA2D2D22C900041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD83EB2D2D22C900041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD83ED2D2D22C900041BBA /* array.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = array.cxx; sourceTree = ""; }; - 94CD83EE2D2D22C900041BBA /* binarystring.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = binarystring.cxx; sourceTree = ""; }; - 94CD83EF2D2D22C900041BBA /* blob.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = blob.cxx; sourceTree = ""; }; - 94CD83F02D2D22C900041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD83F12D2D22C900041BBA /* connection.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = connection.cxx; sourceTree = ""; }; - 94CD83F22D2D22C900041BBA /* cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = cursor.cxx; sourceTree = ""; }; - 94CD83F32D2D22C900041BBA /* encodings.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = encodings.cxx; sourceTree = ""; }; - 94CD83F42D2D22C900041BBA /* errorhandler.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = errorhandler.cxx; sourceTree = ""; }; - 94CD83F52D2D22C900041BBA /* except.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = except.cxx; sourceTree = ""; }; - 94CD83F62D2D22C900041BBA /* field.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = field.cxx; sourceTree = ""; }; - 94CD83F72D2D22C900041BBA /* largeobject.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = largeobject.cxx; sourceTree = ""; }; - 94CD83F82D2D22C900041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD83F92D2D22C900041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD83FA2D2D22C900041BBA /* notification.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = notification.cxx; sourceTree = ""; }; - 94CD83FB2D2D22C900041BBA /* params.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = params.cxx; sourceTree = ""; }; - 94CD83FC2D2D22C900041BBA /* pipeline.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pipeline.cxx; sourceTree = ""; }; - 94CD83FD2D2D22C900041BBA /* pqxx-source.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "pqxx-source.hxx"; sourceTree = ""; }; - 94CD83FE2D2D22C900041BBA /* result.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = result.cxx; sourceTree = ""; }; - 94CD83FF2D2D22C900041BBA /* robusttransaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = robusttransaction.cxx; sourceTree = ""; }; - 94CD84002D2D22C900041BBA /* row.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = row.cxx; sourceTree = ""; }; - 94CD84012D2D22C900041BBA /* sql_cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = sql_cursor.cxx; sourceTree = ""; }; - 94CD84022D2D22C900041BBA /* strconv.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = strconv.cxx; sourceTree = ""; }; - 94CD84032D2D22C900041BBA /* stream_from.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = stream_from.cxx; sourceTree = ""; }; - 94CD84042D2D22C900041BBA /* stream_to.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = stream_to.cxx; sourceTree = ""; }; - 94CD84052D2D22C900041BBA /* subtransaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = subtransaction.cxx; sourceTree = ""; }; - 94CD84062D2D22C900041BBA /* time.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = time.cxx; sourceTree = ""; }; - 94CD84072D2D22C900041BBA /* transaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = transaction.cxx; sourceTree = ""; }; - 94CD84082D2D22C900041BBA /* transaction_base.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = transaction_base.cxx; sourceTree = ""; }; - 94CD84092D2D22C900041BBA /* util.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = util.cxx; sourceTree = ""; }; - 94CD840A2D2D22C900041BBA /* version.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = version.cxx; sourceTree = ""; }; - 94CD840B2D2D22C900041BBA /* wait.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wait.cxx; sourceTree = ""; }; - 94CD840D2D2D22C900041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD840E2D2D22C900041BBA /* test_array.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_array.cxx; sourceTree = ""; }; - 94CD840F2D2D22C900041BBA /* test_binarystring.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_binarystring.cxx; sourceTree = ""; }; - 94CD84102D2D22C900041BBA /* test_blob.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_blob.cxx; sourceTree = ""; }; - 94CD84112D2D22C900041BBA /* test_cancel_query.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_cancel_query.cxx; sourceTree = ""; }; - 94CD84122D2D22C900041BBA /* test_column.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_column.cxx; sourceTree = ""; }; - 94CD84132D2D22C900041BBA /* test_composite.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_composite.cxx; sourceTree = ""; }; - 94CD84142D2D22C900041BBA /* test_connection.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_connection.cxx; sourceTree = ""; }; - 94CD84152D2D22C900041BBA /* test_cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_cursor.cxx; sourceTree = ""; }; - 94CD84162D2D22C900041BBA /* test_encodings.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_encodings.cxx; sourceTree = ""; }; - 94CD84172D2D22C900041BBA /* test_error_verbosity.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_error_verbosity.cxx; sourceTree = ""; }; - 94CD84182D2D22C900041BBA /* test_errorhandler.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_errorhandler.cxx; sourceTree = ""; }; - 94CD84192D2D22C900041BBA /* test_escape.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_escape.cxx; sourceTree = ""; }; - 94CD841A2D2D22C900041BBA /* test_exceptions.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_exceptions.cxx; sourceTree = ""; }; - 94CD841B2D2D22C900041BBA /* test_field.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_field.cxx; sourceTree = ""; }; - 94CD841C2D2D22C900041BBA /* test_float.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_float.cxx; sourceTree = ""; }; - 94CD841D2D2D22C900041BBA /* test_largeobject.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_largeobject.cxx; sourceTree = ""; }; - 94CD841E2D2D22C900041BBA /* test_nonblocking_connect.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_nonblocking_connect.cxx; sourceTree = ""; }; - 94CD841F2D2D22C900041BBA /* test_notice_handler.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_notice_handler.cxx; sourceTree = ""; }; - 94CD84202D2D22C900041BBA /* test_notification.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_notification.cxx; sourceTree = ""; }; - 94CD84212D2D22C900041BBA /* test_pipeline.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_pipeline.cxx; sourceTree = ""; }; - 94CD84222D2D22C900041BBA /* test_prepared_statement.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_prepared_statement.cxx; sourceTree = ""; }; - 94CD84232D2D22C900041BBA /* test_range.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_range.cxx; sourceTree = ""; }; - 94CD84242D2D22C900041BBA /* test_read_transaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_read_transaction.cxx; sourceTree = ""; }; - 94CD84252D2D22C900041BBA /* test_result_iteration.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_result_iteration.cxx; sourceTree = ""; }; - 94CD84262D2D22C900041BBA /* test_result_slicing.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_result_slicing.cxx; sourceTree = ""; }; - 94CD84272D2D22C900041BBA /* test_row.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_row.cxx; sourceTree = ""; }; - 94CD84282D2D22C900041BBA /* test_separated_list.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_separated_list.cxx; sourceTree = ""; }; - 94CD84292D2D22C900041BBA /* test_simultaneous_transactions.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_simultaneous_transactions.cxx; sourceTree = ""; }; - 94CD842A2D2D22C900041BBA /* test_sql_cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_sql_cursor.cxx; sourceTree = ""; }; - 94CD842B2D2D22C900041BBA /* test_stateless_cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_stateless_cursor.cxx; sourceTree = ""; }; - 94CD842C2D2D22C900041BBA /* test_strconv.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_strconv.cxx; sourceTree = ""; }; - 94CD842D2D2D22C900041BBA /* test_stream_from.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_stream_from.cxx; sourceTree = ""; }; - 94CD842E2D2D22C900041BBA /* test_stream_query.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_stream_query.cxx; sourceTree = ""; }; - 94CD842F2D2D22C900041BBA /* test_stream_to.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_stream_to.cxx; sourceTree = ""; }; - 94CD84302D2D22C900041BBA /* test_string_conversion.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_string_conversion.cxx; sourceTree = ""; }; - 94CD84312D2D22C900041BBA /* test_subtransaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_subtransaction.cxx; sourceTree = ""; }; - 94CD84322D2D22C900041BBA /* test_test_helpers.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_test_helpers.cxx; sourceTree = ""; }; - 94CD84332D2D22C900041BBA /* test_thread_safety_model.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_thread_safety_model.cxx; sourceTree = ""; }; - 94CD84342D2D22C900041BBA /* test_time.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_time.cxx; sourceTree = ""; }; - 94CD84352D2D22C900041BBA /* test_transaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_transaction.cxx; sourceTree = ""; }; - 94CD84362D2D22C900041BBA /* test_transaction_base.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_transaction_base.cxx; sourceTree = ""; }; - 94CD84372D2D22C900041BBA /* test_transaction_focus.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_transaction_focus.cxx; sourceTree = ""; }; - 94CD84382D2D22C900041BBA /* test_transactor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_transactor.cxx; sourceTree = ""; }; - 94CD84392D2D22C900041BBA /* test_type_name.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_type_name.cxx; sourceTree = ""; }; - 94CD843A2D2D22C900041BBA /* test_zview.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_zview.cxx; sourceTree = ""; }; - 94CD843C2D2D22C900041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD843D2D2D22C900041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD843E2D2D22C900041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD843F2D2D22C900041BBA /* Makefile.am.template */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am.template; sourceTree = ""; }; - 94CD84402D2D22C900041BBA /* runner.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = runner.cxx; sourceTree = ""; }; - 94CD84412D2D22C900041BBA /* test_helpers.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = test_helpers.hxx; sourceTree = ""; }; - 94CD84422D2D22C900041BBA /* test_types.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = test_types.hxx; sourceTree = ""; }; - 94CD84432D2D22C900041BBA /* test00.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test00.cxx; sourceTree = ""; }; - 94CD84442D2D22C900041BBA /* test01.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test01.cxx; sourceTree = ""; }; - 94CD84452D2D22C900041BBA /* test02.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test02.cxx; sourceTree = ""; }; - 94CD84462D2D22C900041BBA /* test04.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test04.cxx; sourceTree = ""; }; - 94CD84472D2D22C900041BBA /* test07.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test07.cxx; sourceTree = ""; }; - 94CD84482D2D22C900041BBA /* test10.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test10.cxx; sourceTree = ""; }; - 94CD84492D2D22C900041BBA /* test11.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test11.cxx; sourceTree = ""; }; - 94CD844A2D2D22C900041BBA /* test13.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test13.cxx; sourceTree = ""; }; - 94CD844B2D2D22C900041BBA /* test14.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test14.cxx; sourceTree = ""; }; - 94CD844C2D2D22C900041BBA /* test16.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test16.cxx; sourceTree = ""; }; - 94CD844D2D2D22C900041BBA /* test17.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test17.cxx; sourceTree = ""; }; - 94CD844E2D2D22C900041BBA /* test18.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test18.cxx; sourceTree = ""; }; - 94CD844F2D2D22C900041BBA /* test20.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test20.cxx; sourceTree = ""; }; - 94CD84502D2D22C900041BBA /* test21.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test21.cxx; sourceTree = ""; }; - 94CD84512D2D22C900041BBA /* test26.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test26.cxx; sourceTree = ""; }; - 94CD84522D2D22C900041BBA /* test29.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test29.cxx; sourceTree = ""; }; - 94CD84532D2D22C900041BBA /* test30.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test30.cxx; sourceTree = ""; }; - 94CD84542D2D22C900041BBA /* test32.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test32.cxx; sourceTree = ""; }; - 94CD84552D2D22C900041BBA /* test37.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test37.cxx; sourceTree = ""; }; - 94CD84562D2D22C900041BBA /* test39.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test39.cxx; sourceTree = ""; }; - 94CD84572D2D22C900041BBA /* test46.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test46.cxx; sourceTree = ""; }; - 94CD84582D2D22C900041BBA /* test56.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test56.cxx; sourceTree = ""; }; - 94CD84592D2D22C900041BBA /* test60.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test60.cxx; sourceTree = ""; }; - 94CD845A2D2D22C900041BBA /* test61.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test61.cxx; sourceTree = ""; }; - 94CD845B2D2D22C900041BBA /* test62.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test62.cxx; sourceTree = ""; }; - 94CD845C2D2D22C900041BBA /* test69.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test69.cxx; sourceTree = ""; }; - 94CD845D2D2D22C900041BBA /* test70.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test70.cxx; sourceTree = ""; }; - 94CD845E2D2D22C900041BBA /* test71.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test71.cxx; sourceTree = ""; }; - 94CD845F2D2D22C900041BBA /* test72.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test72.cxx; sourceTree = ""; }; - 94CD84602D2D22C900041BBA /* test74.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test74.cxx; sourceTree = ""; }; - 94CD84612D2D22C900041BBA /* test75.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test75.cxx; sourceTree = ""; }; - 94CD84622D2D22C900041BBA /* test76.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test76.cxx; sourceTree = ""; }; - 94CD84632D2D22C900041BBA /* test77.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test77.cxx; sourceTree = ""; }; - 94CD84642D2D22C900041BBA /* test78.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test78.cxx; sourceTree = ""; }; - 94CD84652D2D22C900041BBA /* test79.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test79.cxx; sourceTree = ""; }; - 94CD84662D2D22C900041BBA /* test82.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test82.cxx; sourceTree = ""; }; - 94CD84672D2D22C900041BBA /* test84.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test84.cxx; sourceTree = ""; }; - 94CD84682D2D22C900041BBA /* test87.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test87.cxx; sourceTree = ""; }; - 94CD84692D2D22C900041BBA /* test88.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test88.cxx; sourceTree = ""; }; - 94CD846A2D2D22C900041BBA /* test89.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test89.cxx; sourceTree = ""; }; - 94CD846B2D2D22C900041BBA /* test90.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test90.cxx; sourceTree = ""; }; - 94CD846D2D2D22C900041BBA /* deprecations */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = deprecations; sourceTree = ""; }; - 94CD846E2D2D22C900041BBA /* extract_version */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = extract_version; sourceTree = ""; }; - 94CD846F2D2D22C900041BBA /* format */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = format; sourceTree = ""; }; - 94CD84702D2D22C900041BBA /* generate_check_config.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = generate_check_config.py; sourceTree = ""; }; - 94CD84712D2D22C900041BBA /* generate_cxx_checks.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = generate_cxx_checks.py; sourceTree = ""; }; - 94CD84722D2D22C900041BBA /* lint */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = lint; sourceTree = ""; }; - 94CD84732D2D22C900041BBA /* m4esc.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = m4esc.py; sourceTree = ""; }; - 94CD84742D2D22C900041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD84752D2D22C900041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD84762D2D22C900041BBA /* pqxxthreadsafety.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pqxxthreadsafety.cxx; sourceTree = ""; }; - 94CD84772D2D22C900041BBA /* rmlo.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rmlo.cxx; sourceTree = ""; }; - 94CD84782D2D22C900041BBA /* splitconfig.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = splitconfig.py; sourceTree = ""; }; - 94CD84792D2D22C900041BBA /* template2mak.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = template2mak.py; sourceTree = ""; }; - 94CD847A2D2D22C900041BBA /* test_all.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = test_all.py; sourceTree = ""; }; - 94CD847B2D2D22C900041BBA /* todo */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = todo; sourceTree = ""; }; - 94CD847C2D2D22C900041BBA /* update-copyright */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "update-copyright"; sourceTree = ""; }; - 94CD847E2D2D22C900041BBA /* .clang-format */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".clang-format"; sourceTree = ""; }; - 94CD847F2D2D22C900041BBA /* .clang-tidy */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".clang-tidy"; sourceTree = ""; }; - 94CD84802D2D22C900041BBA /* .cmake-format */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".cmake-format"; sourceTree = ""; }; - 94CD84812D2D22C900041BBA /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = ""; }; - 94CD84822D2D22C900041BBA /* .lgtm.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .lgtm.yml; sourceTree = ""; }; - 94CD84832D2D22C900041BBA /* .mdl_style.rb */ = {isa = PBXFileReference; lastKnownFileType = text.script.ruby; path = .mdl_style.rb; sourceTree = ""; }; - 94CD84842D2D22C900041BBA /* .mdlrc */ = {isa = PBXFileReference; lastKnownFileType = text; path = .mdlrc; sourceTree = ""; }; - 94CD84852D2D22C900041BBA /* .readthedocs.yaml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .readthedocs.yaml; sourceTree = ""; }; - 94CD84862D2D22C900041BBA /* aclocal.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = aclocal.m4; sourceTree = ""; }; - 94CD84872D2D22C900041BBA /* appveyor.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = appveyor.yml; sourceTree = ""; }; - 94CD84882D2D22C900041BBA /* AUTHORS */ = {isa = PBXFileReference; lastKnownFileType = text; path = AUTHORS; sourceTree = ""; }; - 94CD84892D2D22C900041BBA /* autogen.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = autogen.sh; sourceTree = ""; }; - 94CD848A2D2D22C900041BBA /* BUILDING-cmake.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "BUILDING-cmake.md"; sourceTree = ""; }; - 94CD848B2D2D22C900041BBA /* BUILDING-configure.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "BUILDING-configure.md"; sourceTree = ""; }; - 94CD848C2D2D22C900041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD848D2D2D22C900041BBA /* compile_flags.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = compile_flags.in; sourceTree = ""; }; - 94CD848E2D2D22C900041BBA /* configitems */ = {isa = PBXFileReference; lastKnownFileType = text; path = configitems; sourceTree = ""; }; - 94CD848F2D2D22C900041BBA /* configure */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - 94CD84902D2D22C900041BBA /* configure.ac */ = {isa = PBXFileReference; lastKnownFileType = text; path = configure.ac; sourceTree = ""; }; - 94CD84912D2D22C900041BBA /* COPYING */ = {isa = PBXFileReference; lastKnownFileType = text; path = COPYING; sourceTree = ""; }; - 94CD84922D2D22C900041BBA /* cxx_features.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = cxx_features.txt; sourceTree = ""; }; - 94CD84932D2D22C900041BBA /* INSTALL */ = {isa = PBXFileReference; lastKnownFileType = text; path = INSTALL; sourceTree = ""; }; - 94CD84942D2D22C900041BBA /* libpqxx.pc.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = libpqxx.pc.in; sourceTree = ""; }; - 94CD84952D2D22C900041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD84962D2D22C900041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD84972D2D22C900041BBA /* NEWS */ = {isa = PBXFileReference; lastKnownFileType = text; path = NEWS; sourceTree = ""; }; - 94CD84982D2D22C900041BBA /* pqxx_cxx_feature_checks.ac */ = {isa = PBXFileReference; lastKnownFileType = text; path = pqxx_cxx_feature_checks.ac; sourceTree = ""; }; - 94CD84992D2D22C900041BBA /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - 94CD849A2D2D22C900041BBA /* README.rst */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.rst; sourceTree = ""; }; - 94CD849B2D2D22C900041BBA /* requirements.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = requirements.json; sourceTree = ""; }; - 94CD849C2D2D22C900041BBA /* VERSION */ = {isa = PBXFileReference; lastKnownFileType = text; path = VERSION; sourceTree = ""; }; - 94CD869F2D2D295900041BBA /* CMakeCXXCompilerId.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CMakeCXXCompilerId.cpp; sourceTree = ""; }; - 94CD86A02D2D295900041BBA /* CMakeCXXCompilerId.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = CMakeCXXCompilerId.o; sourceTree = ""; }; - 94CD86A22D2D295900041BBA /* CMakeCXXCompiler.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeCXXCompiler.cmake; sourceTree = ""; }; - 94CD86A32D2D295900041BBA /* CMakeDetermineCompilerABI_CXX.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = CMakeDetermineCompilerABI_CXX.bin; sourceTree = ""; }; - 94CD86A42D2D295900041BBA /* CMakeSystem.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeSystem.cmake; sourceTree = ""; }; - 94CD86A82D2D295900041BBA /* libpqxx-targets.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-targets.cmake"; sourceTree = ""; }; - 94CD86A92D2D295900041BBA /* libpqxx-targets-noconfig.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-targets-noconfig.cmake"; sourceTree = ""; }; - 94CD86AD2D2D295900041BBA /* cmake.check_cache */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake.check_cache; sourceTree = ""; }; - 94CD86AE2D2D295900041BBA /* CMakeConfigureLog.yaml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = CMakeConfigureLog.yaml; sourceTree = ""; }; - 94CD86AF2D2D295900041BBA /* CMakeDirectoryInformation.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeDirectoryInformation.cmake; sourceTree = ""; }; - 94CD86B02D2D295900041BBA /* Makefile.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.cmake; sourceTree = ""; }; - 94CD86B12D2D295900041BBA /* Makefile2 */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile2; sourceTree = ""; }; - 94CD86B22D2D295900041BBA /* progress.marks */ = {isa = PBXFileReference; lastKnownFileType = text; path = progress.marks; sourceTree = ""; }; - 94CD86B32D2D295900041BBA /* TargetDirectories.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TargetDirectories.txt; sourceTree = ""; }; - 94CD86B52D2D295900041BBA /* CMakeDirectoryInformation.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeDirectoryInformation.cmake; sourceTree = ""; }; - 94CD86B62D2D295900041BBA /* progress.marks */ = {isa = PBXFileReference; lastKnownFileType = text; path = progress.marks; sourceTree = ""; }; - 94CD86B82D2D295900041BBA /* config_cmake.h.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = config_cmake.h.in; sourceTree = ""; }; - 94CD86B92D2D295900041BBA /* config-internal-compiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-internal-compiler.h"; sourceTree = ""; }; - 94CD86BA2D2D295900041BBA /* config-internal-libpq.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-internal-libpq.h"; sourceTree = ""; }; - 94CD86BB2D2D295900041BBA /* config-public-compiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-public-compiler.h"; sourceTree = ""; }; - 94CD86BD2D2D295900041BBA /* cmake_install.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_install.cmake; sourceTree = ""; }; - 94CD86BE2D2D295900041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD86C02D2D295900041BBA /* build.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = build.make; sourceTree = ""; }; - 94CD86C12D2D295900041BBA /* cmake_clean.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_clean.cmake; sourceTree = ""; }; - 94CD86C22D2D295900041BBA /* cmake_clean_target.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_clean_target.cmake; sourceTree = ""; }; - 94CD86C32D2D295900041BBA /* compiler_depend.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = compiler_depend.make; sourceTree = ""; }; - 94CD86C42D2D295900041BBA /* compiler_depend.ts */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.typescript; path = compiler_depend.ts; sourceTree = ""; }; - 94CD86C52D2D295900041BBA /* depend.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = depend.make; sourceTree = ""; }; - 94CD86C62D2D295900041BBA /* DependInfo.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = DependInfo.cmake; sourceTree = ""; }; - 94CD86C72D2D295900041BBA /* flags.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = flags.make; sourceTree = ""; }; - 94CD86C82D2D295900041BBA /* link.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = link.txt; sourceTree = ""; }; - 94CD86C92D2D295900041BBA /* progress.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = progress.make; sourceTree = ""; }; - 94CD86CB2D2D295900041BBA /* CMakeDirectoryInformation.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeDirectoryInformation.cmake; sourceTree = ""; }; - 94CD86CC2D2D295900041BBA /* progress.marks */ = {isa = PBXFileReference; lastKnownFileType = text; path = progress.marks; sourceTree = ""; }; - 94CD86CE2D2D295900041BBA /* cmake_install.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_install.cmake; sourceTree = ""; }; - 94CD86CF2D2D295900041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD86D22D2D295900041BBA /* build.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = build.make; sourceTree = ""; }; - 94CD86D32D2D295900041BBA /* cmake_clean.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_clean.cmake; sourceTree = ""; }; - 94CD86D42D2D295900041BBA /* compiler_depend.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = compiler_depend.make; sourceTree = ""; }; - 94CD86D52D2D295900041BBA /* compiler_depend.ts */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.typescript; path = compiler_depend.ts; sourceTree = ""; }; - 94CD86D62D2D295900041BBA /* depend.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = depend.make; sourceTree = ""; }; - 94CD86D72D2D295900041BBA /* DependInfo.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = DependInfo.cmake; sourceTree = ""; }; - 94CD86D82D2D295900041BBA /* flags.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = flags.make; sourceTree = ""; }; - 94CD86D92D2D295900041BBA /* link.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = link.txt; sourceTree = ""; }; - 94CD86DA2D2D295900041BBA /* progress.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = progress.make; sourceTree = ""; }; - 94CD86DC2D2D295900041BBA /* CMakeDirectoryInformation.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeDirectoryInformation.cmake; sourceTree = ""; }; - 94CD86DD2D2D295900041BBA /* progress.marks */ = {isa = PBXFileReference; lastKnownFileType = text; path = progress.marks; sourceTree = ""; }; - 94CD86DF2D2D295900041BBA /* cmake_install.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_install.cmake; sourceTree = ""; }; - 94CD86E02D2D295900041BBA /* CTestTestfile.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CTestTestfile.cmake; sourceTree = ""; }; - 94CD86E12D2D295900041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD86E32D2D295900041BBA /* cmake_install.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_install.cmake; sourceTree = ""; }; - 94CD86E42D2D295900041BBA /* CMakeCache.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeCache.txt; sourceTree = ""; }; - 94CD86E52D2D295900041BBA /* CPackConfig.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CPackConfig.cmake; sourceTree = ""; }; - 94CD86E62D2D295900041BBA /* CPackSourceConfig.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CPackSourceConfig.cmake; sourceTree = ""; }; - 94CD86E72D2D295900041BBA /* libpqxx.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libpqxx.pc; sourceTree = ""; }; - 94CD86E82D2D295900041BBA /* libpqxx-config.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-config.cmake"; sourceTree = ""; }; - 94CD86E92D2D295900041BBA /* libpqxx-config-version.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-config-version.cmake"; sourceTree = ""; }; - 94CD86EA2D2D295900041BBA /* libpqxx-targets.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-targets.cmake"; sourceTree = ""; }; - 94CD86EB2D2D295900041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD87352D2D2EE100041BBA /* config.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = config.yml; sourceTree = ""; }; - 94CD87372D2D2EE100041BBA /* codeql.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = codeql.yml; sourceTree = ""; }; - 94CD87382D2D2EE100041BBA /* stale.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = stale.yml; sourceTree = ""; }; - 94CD873B2D2D2EE100041BBA /* ignoreFiles */ = {isa = PBXFileReference; lastKnownFileType = text; path = ignoreFiles; sourceTree = ""; }; - 94CD873E2D2D2EE100041BBA /* CMakeCXXCompilerId.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CMakeCXXCompilerId.cpp; sourceTree = ""; }; - 94CD873F2D2D2EE100041BBA /* CMakeCXXCompilerId.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = CMakeCXXCompilerId.o; sourceTree = ""; }; - 94CD87412D2D2EE100041BBA /* CMakeCXXCompiler.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeCXXCompiler.cmake; sourceTree = ""; }; - 94CD87422D2D2EE100041BBA /* CMakeDetermineCompilerABI_CXX.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = CMakeDetermineCompilerABI_CXX.bin; sourceTree = ""; }; - 94CD87432D2D2EE100041BBA /* CMakeSystem.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeSystem.cmake; sourceTree = ""; }; - 94CD87472D2D2EE100041BBA /* libpqxx-targets.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-targets.cmake"; sourceTree = ""; }; - 94CD87482D2D2EE100041BBA /* libpqxx-targets-noconfig.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-targets-noconfig.cmake"; sourceTree = ""; }; - 94CD874C2D2D2EE100041BBA /* cmake.check_cache */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake.check_cache; sourceTree = ""; }; - 94CD874D2D2D2EE100041BBA /* CMakeConfigureLog.yaml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = CMakeConfigureLog.yaml; sourceTree = ""; }; - 94CD874E2D2D2EE100041BBA /* CMakeDirectoryInformation.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeDirectoryInformation.cmake; sourceTree = ""; }; - 94CD874F2D2D2EE100041BBA /* Makefile.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.cmake; sourceTree = ""; }; - 94CD87502D2D2EE100041BBA /* Makefile2 */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile2; sourceTree = ""; }; - 94CD87512D2D2EE100041BBA /* progress.marks */ = {isa = PBXFileReference; lastKnownFileType = text; path = progress.marks; sourceTree = ""; }; - 94CD87522D2D2EE100041BBA /* TargetDirectories.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TargetDirectories.txt; sourceTree = ""; }; - 94CD87542D2D2EE100041BBA /* CMakeDirectoryInformation.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeDirectoryInformation.cmake; sourceTree = ""; }; - 94CD87552D2D2EE100041BBA /* progress.marks */ = {isa = PBXFileReference; lastKnownFileType = text; path = progress.marks; sourceTree = ""; }; - 94CD87572D2D2EE100041BBA /* config_cmake.h.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = config_cmake.h.in; sourceTree = ""; }; - 94CD87582D2D2EE100041BBA /* config-internal-compiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-internal-compiler.h"; sourceTree = ""; }; - 94CD87592D2D2EE100041BBA /* config-internal-libpq.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-internal-libpq.h"; sourceTree = ""; }; - 94CD875A2D2D2EE100041BBA /* config-public-compiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-public-compiler.h"; sourceTree = ""; }; - 94CD875C2D2D2EE100041BBA /* cmake_install.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_install.cmake; sourceTree = ""; }; - 94CD875D2D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD875F2D2D2EE100041BBA /* build.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = build.make; sourceTree = ""; }; - 94CD87602D2D2EE100041BBA /* cmake_clean.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_clean.cmake; sourceTree = ""; }; - 94CD87612D2D2EE100041BBA /* cmake_clean_target.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_clean_target.cmake; sourceTree = ""; }; - 94CD87622D2D2EE100041BBA /* compiler_depend.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = compiler_depend.make; sourceTree = ""; }; - 94CD87632D2D2EE100041BBA /* compiler_depend.ts */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.typescript; path = compiler_depend.ts; sourceTree = ""; }; - 94CD87642D2D2EE100041BBA /* depend.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = depend.make; sourceTree = ""; }; - 94CD87652D2D2EE100041BBA /* DependInfo.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = DependInfo.cmake; sourceTree = ""; }; - 94CD87662D2D2EE100041BBA /* flags.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = flags.make; sourceTree = ""; }; - 94CD87672D2D2EE100041BBA /* link.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = link.txt; sourceTree = ""; }; - 94CD87682D2D2EE100041BBA /* progress.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = progress.make; sourceTree = ""; }; - 94CD876A2D2D2EE100041BBA /* CMakeDirectoryInformation.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeDirectoryInformation.cmake; sourceTree = ""; }; - 94CD876B2D2D2EE100041BBA /* progress.marks */ = {isa = PBXFileReference; lastKnownFileType = text; path = progress.marks; sourceTree = ""; }; - 94CD876D2D2D2EE100041BBA /* cmake_install.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_install.cmake; sourceTree = ""; }; - 94CD876E2D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD87712D2D2EE100041BBA /* build.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = build.make; sourceTree = ""; }; - 94CD87722D2D2EE100041BBA /* cmake_clean.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_clean.cmake; sourceTree = ""; }; - 94CD87732D2D2EE100041BBA /* compiler_depend.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = compiler_depend.make; sourceTree = ""; }; - 94CD87742D2D2EE100041BBA /* compiler_depend.ts */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.typescript; path = compiler_depend.ts; sourceTree = ""; }; - 94CD87752D2D2EE100041BBA /* depend.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = depend.make; sourceTree = ""; }; - 94CD87762D2D2EE100041BBA /* DependInfo.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = DependInfo.cmake; sourceTree = ""; }; - 94CD87772D2D2EE100041BBA /* flags.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = flags.make; sourceTree = ""; }; - 94CD87782D2D2EE100041BBA /* link.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = link.txt; sourceTree = ""; }; - 94CD87792D2D2EE100041BBA /* progress.make */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = progress.make; sourceTree = ""; }; - 94CD877B2D2D2EE100041BBA /* CMakeDirectoryInformation.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeDirectoryInformation.cmake; sourceTree = ""; }; - 94CD877C2D2D2EE100041BBA /* progress.marks */ = {isa = PBXFileReference; lastKnownFileType = text; path = progress.marks; sourceTree = ""; }; - 94CD877E2D2D2EE100041BBA /* cmake_install.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_install.cmake; sourceTree = ""; }; - 94CD877F2D2D2EE100041BBA /* CTestTestfile.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CTestTestfile.cmake; sourceTree = ""; }; - 94CD87802D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD87822D2D2EE100041BBA /* cmake_install.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = cmake_install.cmake; sourceTree = ""; }; - 94CD87832D2D2EE100041BBA /* CMakeCache.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeCache.txt; sourceTree = ""; }; - 94CD87842D2D2EE100041BBA /* CPackConfig.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CPackConfig.cmake; sourceTree = ""; }; - 94CD87852D2D2EE100041BBA /* CPackSourceConfig.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = CPackSourceConfig.cmake; sourceTree = ""; }; - 94CD87862D2D2EE100041BBA /* libpqxx.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libpqxx.pc; sourceTree = ""; }; - 94CD87872D2D2EE100041BBA /* libpqxx-config.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-config.cmake"; sourceTree = ""; }; - 94CD87882D2D2EE100041BBA /* libpqxx-config-version.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-config-version.cmake"; sourceTree = ""; }; - 94CD87892D2D2EE100041BBA /* libpqxx-targets.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-targets.cmake"; sourceTree = ""; }; - 94CD878A2D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD878C2D2D2EE100041BBA /* config.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = config.cmake; sourceTree = ""; }; - 94CD878D2D2D2EE100041BBA /* libpqxx-config.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = "libpqxx-config.cmake"; sourceTree = ""; }; - 94CD878E2D2D2EE100041BBA /* pqxx_cxx_feature_checks.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = pqxx_cxx_feature_checks.cmake; sourceTree = ""; }; - 94CD87902D2D2EE100041BBA /* libtool.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = libtool.m4; sourceTree = ""; }; - 94CD87912D2D2EE100041BBA /* lt~obsolete.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = "lt~obsolete.m4"; sourceTree = ""; }; - 94CD87922D2D2EE100041BBA /* ltoptions.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ltoptions.m4; sourceTree = ""; }; - 94CD87932D2D2EE100041BBA /* ltsugar.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ltsugar.m4; sourceTree = ""; }; - 94CD87942D2D2EE100041BBA /* ltversion.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ltversion.m4; sourceTree = ""; }; - 94CD87952D2D2EE100041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD87972D2D2EE100041BBA /* compile */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = compile; sourceTree = ""; }; - 94CD87982D2D2EE100041BBA /* config.guess */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = config.guess; sourceTree = ""; }; - 94CD87992D2D2EE100041BBA /* config.sub */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = config.sub; sourceTree = ""; }; - 94CD879A2D2D2EE100041BBA /* depcomp */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = depcomp; sourceTree = ""; }; - 94CD879B2D2D2EE100041BBA /* install-sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = ""; }; - 94CD879C2D2D2EE100041BBA /* ltmain.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ltmain.sh; sourceTree = ""; }; - 94CD879D2D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD879E2D2D2EE100041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD879F2D2D2EE100041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD87A02D2D2EE100041BBA /* missing */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = missing; sourceTree = ""; }; - 94CD87A12D2D2EE100041BBA /* mkinstalldirs */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = mkinstalldirs; sourceTree = ""; }; - 94CD87A22D2D2EE100041BBA /* test-driver */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "test-driver"; sourceTree = ""; }; - 94CD87A42D2D2EE100041BBA /* no_need_fslib.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = no_need_fslib.cxx; sourceTree = ""; }; - 94CD87A52D2D2EE100041BBA /* PQXX_HAVE_ASSUME.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_ASSUME.cxx; sourceTree = ""; }; - 94CD87A62D2D2EE100041BBA /* PQXX_HAVE_CHARCONV_FLOAT.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CHARCONV_FLOAT.cxx; sourceTree = ""; }; - 94CD87A72D2D2EE100041BBA /* PQXX_HAVE_CHARCONV_INT.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CHARCONV_INT.cxx; sourceTree = ""; }; - 94CD87A82D2D2EE100041BBA /* PQXX_HAVE_CMP.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CMP.cxx; sourceTree = ""; }; - 94CD87A92D2D2EE100041BBA /* PQXX_HAVE_CONCEPTS.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CONCEPTS.cxx; sourceTree = ""; }; - 94CD87AA2D2D2EE100041BBA /* PQXX_HAVE_CXA_DEMANGLE.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_CXA_DEMANGLE.cxx; sourceTree = ""; }; - 94CD87AB2D2D2EE100041BBA /* PQXX_HAVE_GCC_PURE.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_GCC_PURE.cxx; sourceTree = ""; }; - 94CD87AC2D2D2EE100041BBA /* PQXX_HAVE_GCC_VISIBILITY.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_GCC_VISIBILITY.cxx; sourceTree = ""; }; - 94CD87AD2D2D2EE100041BBA /* PQXX_HAVE_LIKELY.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_LIKELY.cxx; sourceTree = ""; }; - 94CD87AE2D2D2EE100041BBA /* PQXX_HAVE_MULTIDIM.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_MULTIDIM.cxx; sourceTree = ""; }; - 94CD87AF2D2D2EE100041BBA /* PQXX_HAVE_PATH.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_PATH.cxx; sourceTree = ""; }; - 94CD87B02D2D2EE100041BBA /* PQXX_HAVE_POLL.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_POLL.cxx; sourceTree = ""; }; - 94CD87B12D2D2EE100041BBA /* PQXX_HAVE_SLEEP_FOR.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_SLEEP_FOR.cxx; sourceTree = ""; }; - 94CD87B22D2D2EE100041BBA /* PQXX_HAVE_SOURCE_LOCATION.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_SOURCE_LOCATION.cxx; sourceTree = ""; }; - 94CD87B32D2D2EE100041BBA /* PQXX_HAVE_SPAN.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_SPAN.cxx; sourceTree = ""; }; - 94CD87B42D2D2EE100041BBA /* PQXX_HAVE_SSIZE.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_SSIZE.cxx; sourceTree = ""; }; - 94CD87B52D2D2EE100041BBA /* PQXX_HAVE_STRERROR_R.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_STRERROR_R.cxx; sourceTree = ""; }; - 94CD87B62D2D2EE100041BBA /* PQXX_HAVE_STRERROR_S.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_STRERROR_S.cxx; sourceTree = ""; }; - 94CD87B72D2D2EE100041BBA /* PQXX_HAVE_THREAD_LOCAL.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_THREAD_LOCAL.cxx; sourceTree = ""; }; - 94CD87B82D2D2EE100041BBA /* PQXX_HAVE_YEAR_MONTH_DAY.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PQXX_HAVE_YEAR_MONTH_DAY.cxx; sourceTree = ""; }; - 94CD87B92D2D2EE100041BBA /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - 94CD87BB2D2D2EE100041BBA /* conf.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = conf.py; sourceTree = ""; }; - 94CD87BC2D2D2EE100041BBA /* index.rst */ = {isa = PBXFileReference; lastKnownFileType = text; path = index.rst; sourceTree = ""; }; - 94CD87BE2D2D2EE100041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD87BF2D2D2EE100041BBA /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Doxyfile; sourceTree = ""; }; - 94CD87C02D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD87C12D2D2EE100041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD87C22D2D2EE100041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD87C32D2D2EE100041BBA /* requirements.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = requirements.txt; sourceTree = ""; }; - 94CD87C52D2D2EE100041BBA /* accessing-results.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "accessing-results.md"; sourceTree = ""; }; - 94CD87C62D2D2EE100041BBA /* binary-data.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "binary-data.md"; sourceTree = ""; }; - 94CD87C72D2D2EE100041BBA /* datatypes.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = datatypes.md; sourceTree = ""; }; - 94CD87C82D2D2EE100041BBA /* escaping.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = escaping.md; sourceTree = ""; }; - 94CD87C92D2D2EE100041BBA /* getting-started.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "getting-started.md"; sourceTree = ""; }; - 94CD87CA2D2D2EE100041BBA /* mainpage.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = mainpage.md; sourceTree = ""; }; - 94CD87CB2D2D2EE100041BBA /* mainpage.md.template */ = {isa = PBXFileReference; lastKnownFileType = text; path = mainpage.md.template; sourceTree = ""; }; - 94CD87CC2D2D2EE100041BBA /* parameters.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = parameters.md; sourceTree = ""; }; - 94CD87CD2D2D2EE100041BBA /* performance.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = performance.md; sourceTree = ""; }; - 94CD87CE2D2D2EE100041BBA /* prepared-statement.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "prepared-statement.md"; sourceTree = ""; }; - 94CD87CF2D2D2EE100041BBA /* streams.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = streams.md; sourceTree = ""; }; - 94CD87D02D2D2EE100041BBA /* thread-safety.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "thread-safety.md"; sourceTree = ""; }; - 94CD87D22D2D2EE100041BBA /* connection-errorhandler.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-errorhandler.hxx"; sourceTree = ""; }; - 94CD87D32D2D2EE100041BBA /* connection-largeobject.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-largeobject.hxx"; sourceTree = ""; }; - 94CD87D42D2D2EE100041BBA /* connection-notification_receiver.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-notification_receiver.hxx"; sourceTree = ""; }; - 94CD87D52D2D2EE100041BBA /* connection-pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-pipeline.hxx"; sourceTree = ""; }; - 94CD87D62D2D2EE100041BBA /* connection-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-sql_cursor.hxx"; sourceTree = ""; }; - 94CD87D72D2D2EE100041BBA /* connection-stream_from.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-stream_from.hxx"; sourceTree = ""; }; - 94CD87D82D2D2EE100041BBA /* connection-stream_to.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-stream_to.hxx"; sourceTree = ""; }; - 94CD87D92D2D2EE100041BBA /* connection-transaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-transaction.hxx"; sourceTree = ""; }; - 94CD87DA2D2D2EE100041BBA /* errorhandler-connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "errorhandler-connection.hxx"; sourceTree = ""; }; - 94CD87DB2D2D2EE100041BBA /* icursor_iterator-icursorstream.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "icursor_iterator-icursorstream.hxx"; sourceTree = ""; }; - 94CD87DC2D2D2EE100041BBA /* icursorstream-icursor_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "icursorstream-icursor_iterator.hxx"; sourceTree = ""; }; - 94CD87DD2D2D2EE100041BBA /* result-connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-connection.hxx"; sourceTree = ""; }; - 94CD87DE2D2D2EE100041BBA /* result-creation.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-creation.hxx"; sourceTree = ""; }; - 94CD87DF2D2D2EE100041BBA /* result-pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-pipeline.hxx"; sourceTree = ""; }; - 94CD87E02D2D2EE100041BBA /* result-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-sql_cursor.hxx"; sourceTree = ""; }; - 94CD87E12D2D2EE100041BBA /* transaction-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "transaction-sql_cursor.hxx"; sourceTree = ""; }; - 94CD87E22D2D2EE100041BBA /* transaction-transaction_focus.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "transaction-transaction_focus.hxx"; sourceTree = ""; }; - 94CD87E42D2D2EE100041BBA /* array-composite.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "array-composite.hxx"; sourceTree = ""; }; - 94CD87E52D2D2EE100041BBA /* callgate.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = callgate.hxx; sourceTree = ""; }; - 94CD87E62D2D2EE100041BBA /* concat.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = concat.hxx; sourceTree = ""; }; - 94CD87E72D2D2EE100041BBA /* conversions.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = conversions.hxx; sourceTree = ""; }; - 94CD87E82D2D2EE100041BBA /* encoding_group.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = encoding_group.hxx; sourceTree = ""; }; - 94CD87E92D2D2EE100041BBA /* encodings.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = encodings.hxx; sourceTree = ""; }; - 94CD87EA2D2D2EE100041BBA /* header-post.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "header-post.hxx"; sourceTree = ""; }; - 94CD87EB2D2D2EE100041BBA /* header-pre.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "header-pre.hxx"; sourceTree = ""; }; - 94CD87EC2D2D2EE100041BBA /* ignore-deprecated-post.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "ignore-deprecated-post.hxx"; sourceTree = ""; }; - 94CD87ED2D2D2EE100041BBA /* ignore-deprecated-pre.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "ignore-deprecated-pre.hxx"; sourceTree = ""; }; - 94CD87EE2D2D2EE100041BBA /* libpq-forward.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "libpq-forward.hxx"; sourceTree = ""; }; - 94CD87EF2D2D2EE100041BBA /* result_iter.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = result_iter.hxx; sourceTree = ""; }; - 94CD87F02D2D2EE100041BBA /* result_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = result_iterator.hxx; sourceTree = ""; }; - 94CD87F12D2D2EE100041BBA /* sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = sql_cursor.hxx; sourceTree = ""; }; - 94CD87F22D2D2EE100041BBA /* statement_parameters.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = statement_parameters.hxx; sourceTree = ""; }; - 94CD87F32D2D2EE100041BBA /* stream_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_iterator.hxx; sourceTree = ""; }; - 94CD87F42D2D2EE100041BBA /* stream_query.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_query.hxx; sourceTree = ""; }; - 94CD87F52D2D2EE100041BBA /* stream_query_impl.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_query_impl.hxx; sourceTree = ""; }; - 94CD87F62D2D2EE100041BBA /* wait.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = wait.hxx; sourceTree = ""; }; - 94CD87F82D2D2EE100041BBA /* array.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = array.hxx; sourceTree = ""; }; - 94CD87F92D2D2EE100041BBA /* array */ = {isa = PBXFileReference; lastKnownFileType = text; path = array; sourceTree = ""; }; - 94CD87FA2D2D2EE100041BBA /* binarystring.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = binarystring.hxx; sourceTree = ""; }; - 94CD87FB2D2D2EE100041BBA /* binarystring */ = {isa = PBXFileReference; lastKnownFileType = text; path = binarystring; sourceTree = ""; }; - 94CD87FC2D2D2EE100041BBA /* blob.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = blob.hxx; sourceTree = ""; }; - 94CD87FD2D2D2EE100041BBA /* blob */ = {isa = PBXFileReference; lastKnownFileType = text; path = blob; sourceTree = ""; }; - 94CD87FE2D2D2EE100041BBA /* composite.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = composite.hxx; sourceTree = ""; }; - 94CD87FF2D2D2EE100041BBA /* composite */ = {isa = PBXFileReference; lastKnownFileType = text; path = composite; sourceTree = ""; }; - 94CD88002D2D2EE100041BBA /* config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; - 94CD88012D2D2EE100041BBA /* config-internal-autotools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-internal-autotools.h"; sourceTree = ""; }; - 94CD88022D2D2EE100041BBA /* config-internal-compiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-internal-compiler.h"; sourceTree = ""; }; - 94CD88032D2D2EE100041BBA /* config-public-autotools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-public-autotools.h"; sourceTree = ""; }; - 94CD88042D2D2EE100041BBA /* config-public-compiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "config-public-compiler.h"; sourceTree = ""; }; - 94CD88052D2D2EE100041BBA /* config.h.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = config.h.in; sourceTree = ""; }; - 94CD88062D2D2EE100041BBA /* connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = connection.hxx; sourceTree = ""; }; - 94CD88072D2D2EE100041BBA /* connection */ = {isa = PBXFileReference; lastKnownFileType = text; path = connection; sourceTree = ""; }; - 94CD88082D2D2EE100041BBA /* cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = cursor.hxx; sourceTree = ""; }; - 94CD88092D2D2EE100041BBA /* cursor */ = {isa = PBXFileReference; lastKnownFileType = text; path = cursor; sourceTree = ""; }; - 94CD880A2D2D2EE100041BBA /* dbtransaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = dbtransaction.hxx; sourceTree = ""; }; - 94CD880B2D2D2EE100041BBA /* dbtransaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = dbtransaction; sourceTree = ""; }; - 94CD880C2D2D2EE100041BBA /* errorhandler.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = errorhandler.hxx; sourceTree = ""; }; - 94CD880D2D2D2EE100041BBA /* errorhandler */ = {isa = PBXFileReference; lastKnownFileType = text; path = errorhandler; sourceTree = ""; }; - 94CD880E2D2D2EE100041BBA /* except.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = except.hxx; sourceTree = ""; }; - 94CD880F2D2D2EE100041BBA /* except */ = {isa = PBXFileReference; lastKnownFileType = text; path = except; sourceTree = ""; }; - 94CD88102D2D2EE100041BBA /* field.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = field.hxx; sourceTree = ""; }; - 94CD88112D2D2EE100041BBA /* field */ = {isa = PBXFileReference; lastKnownFileType = text; path = field; sourceTree = ""; }; - 94CD88122D2D2EE100041BBA /* isolation.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = isolation.hxx; sourceTree = ""; }; - 94CD88132D2D2EE100041BBA /* isolation */ = {isa = PBXFileReference; lastKnownFileType = text; path = isolation; sourceTree = ""; }; - 94CD88142D2D2EE100041BBA /* largeobject.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = largeobject.hxx; sourceTree = ""; }; - 94CD88152D2D2EE100041BBA /* largeobject */ = {isa = PBXFileReference; lastKnownFileType = text; path = largeobject; sourceTree = ""; }; - 94CD88162D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD88172D2D2EE100041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD88182D2D2EE100041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD88192D2D2EE100041BBA /* nontransaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = nontransaction.hxx; sourceTree = ""; }; - 94CD881A2D2D2EE100041BBA /* nontransaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = nontransaction; sourceTree = ""; }; - 94CD881B2D2D2EE100041BBA /* notification.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = notification.hxx; sourceTree = ""; }; - 94CD881C2D2D2EE100041BBA /* notification */ = {isa = PBXFileReference; lastKnownFileType = text; path = notification; sourceTree = ""; }; - 94CD881D2D2D2EE100041BBA /* params.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = params.hxx; sourceTree = ""; }; - 94CD881E2D2D2EE100041BBA /* params */ = {isa = PBXFileReference; lastKnownFileType = text; path = params; sourceTree = ""; }; - 94CD881F2D2D2EE100041BBA /* pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = pipeline.hxx; sourceTree = ""; }; - 94CD88202D2D2EE100041BBA /* pipeline */ = {isa = PBXFileReference; lastKnownFileType = text; path = pipeline; sourceTree = ""; }; - 94CD88212D2D2EE100041BBA /* pqxx */ = {isa = PBXFileReference; lastKnownFileType = text; path = pqxx; sourceTree = ""; }; - 94CD88222D2D2EE100041BBA /* prepared_statement.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = prepared_statement.hxx; sourceTree = ""; }; - 94CD88232D2D2EE100041BBA /* prepared_statement */ = {isa = PBXFileReference; lastKnownFileType = text; path = prepared_statement; sourceTree = ""; }; - 94CD88242D2D2EE100041BBA /* range.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = range.hxx; sourceTree = ""; }; - 94CD88252D2D2EE100041BBA /* range */ = {isa = PBXFileReference; lastKnownFileType = text; path = range; sourceTree = ""; }; - 94CD88262D2D2EE100041BBA /* result.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = result.hxx; sourceTree = ""; }; - 94CD88272D2D2EE100041BBA /* result */ = {isa = PBXFileReference; lastKnownFileType = text; path = result; sourceTree = ""; }; - 94CD88282D2D2EE100041BBA /* robusttransaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = robusttransaction.hxx; sourceTree = ""; }; - 94CD88292D2D2EE100041BBA /* robusttransaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = robusttransaction; sourceTree = ""; }; - 94CD882A2D2D2EE100041BBA /* row.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = row.hxx; sourceTree = ""; }; - 94CD882B2D2D2EE100041BBA /* row */ = {isa = PBXFileReference; lastKnownFileType = text; path = row; sourceTree = ""; }; - 94CD882C2D2D2EE100041BBA /* separated_list.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = separated_list.hxx; sourceTree = ""; }; - 94CD882D2D2D2EE100041BBA /* separated_list */ = {isa = PBXFileReference; lastKnownFileType = text; path = separated_list; sourceTree = ""; }; - 94CD882E2D2D2EE100041BBA /* stamp-h1 */ = {isa = PBXFileReference; lastKnownFileType = text; path = "stamp-h1"; sourceTree = ""; }; - 94CD882F2D2D2EE100041BBA /* strconv.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = strconv.hxx; sourceTree = ""; }; - 94CD88302D2D2EE100041BBA /* strconv */ = {isa = PBXFileReference; lastKnownFileType = text; path = strconv; sourceTree = ""; }; - 94CD88312D2D2EE100041BBA /* stream_from.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_from.hxx; sourceTree = ""; }; - 94CD88322D2D2EE100041BBA /* stream_from */ = {isa = PBXFileReference; lastKnownFileType = text; path = stream_from; sourceTree = ""; }; - 94CD88332D2D2EE100041BBA /* stream_to.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_to.hxx; sourceTree = ""; }; - 94CD88342D2D2EE100041BBA /* stream_to */ = {isa = PBXFileReference; lastKnownFileType = text; path = stream_to; sourceTree = ""; }; - 94CD88352D2D2EE100041BBA /* subtransaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = subtransaction.hxx; sourceTree = ""; }; - 94CD88362D2D2EE100041BBA /* subtransaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = subtransaction; sourceTree = ""; }; - 94CD88372D2D2EE100041BBA /* time.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = time.hxx; sourceTree = ""; }; - 94CD88382D2D2EE100041BBA /* time */ = {isa = PBXFileReference; lastKnownFileType = text; path = time; sourceTree = ""; }; - 94CD88392D2D2EE100041BBA /* transaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = transaction.hxx; sourceTree = ""; }; - 94CD883A2D2D2EE100041BBA /* transaction */ = {isa = PBXFileReference; lastKnownFileType = text; path = transaction; sourceTree = ""; }; - 94CD883B2D2D2EE100041BBA /* transaction_base.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = transaction_base.hxx; sourceTree = ""; }; - 94CD883C2D2D2EE100041BBA /* transaction_base */ = {isa = PBXFileReference; lastKnownFileType = text; path = transaction_base; sourceTree = ""; }; - 94CD883D2D2D2EE100041BBA /* transaction_focus.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = transaction_focus.hxx; sourceTree = ""; }; - 94CD883E2D2D2EE100041BBA /* transaction_focus */ = {isa = PBXFileReference; lastKnownFileType = text; path = transaction_focus; sourceTree = ""; }; - 94CD883F2D2D2EE100041BBA /* transactor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = transactor.hxx; sourceTree = ""; }; - 94CD88402D2D2EE100041BBA /* transactor */ = {isa = PBXFileReference; lastKnownFileType = text; path = transactor; sourceTree = ""; }; - 94CD88412D2D2EE100041BBA /* types.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = types.hxx; sourceTree = ""; }; - 94CD88422D2D2EE100041BBA /* types */ = {isa = PBXFileReference; lastKnownFileType = text; path = types; sourceTree = ""; }; - 94CD88432D2D2EE100041BBA /* util.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = util.hxx; sourceTree = ""; }; - 94CD88442D2D2EE100041BBA /* util */ = {isa = PBXFileReference; lastKnownFileType = text; path = util; sourceTree = ""; }; - 94CD88452D2D2EE100041BBA /* version.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = version.hxx; sourceTree = ""; }; - 94CD88462D2D2EE100041BBA /* version */ = {isa = PBXFileReference; lastKnownFileType = text; path = version; sourceTree = ""; }; - 94CD88472D2D2EE100041BBA /* version.hxx.template */ = {isa = PBXFileReference; lastKnownFileType = text; path = version.hxx.template; sourceTree = ""; }; - 94CD88482D2D2EE100041BBA /* zview.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = zview.hxx; sourceTree = ""; }; - 94CD88492D2D2EE100041BBA /* zview */ = {isa = PBXFileReference; lastKnownFileType = text; path = zview; sourceTree = ""; }; - 94CD884B2D2D2EE100041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD884C2D2D2EE100041BBA /* CMakeLists.txt.template */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt.template; sourceTree = ""; }; - 94CD884D2D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD884E2D2D2EE100041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD884F2D2D2EE100041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD88512D2D2EE100041BBA /* array.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = array.Plo; sourceTree = ""; }; - 94CD88522D2D2EE100041BBA /* binarystring.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = binarystring.Plo; sourceTree = ""; }; - 94CD88532D2D2EE100041BBA /* blob.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = blob.Plo; sourceTree = ""; }; - 94CD88542D2D2EE100041BBA /* connection.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = connection.Plo; sourceTree = ""; }; - 94CD88552D2D2EE100041BBA /* cursor.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = cursor.Plo; sourceTree = ""; }; - 94CD88562D2D2EE100041BBA /* encodings.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = encodings.Plo; sourceTree = ""; }; - 94CD88572D2D2EE100041BBA /* errorhandler.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = errorhandler.Plo; sourceTree = ""; }; - 94CD88582D2D2EE100041BBA /* except.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = except.Plo; sourceTree = ""; }; - 94CD88592D2D2EE100041BBA /* field.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = field.Plo; sourceTree = ""; }; - 94CD885A2D2D2EE100041BBA /* largeobject.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = largeobject.Plo; sourceTree = ""; }; - 94CD885B2D2D2EE100041BBA /* notification.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = notification.Plo; sourceTree = ""; }; - 94CD885C2D2D2EE100041BBA /* params.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = params.Plo; sourceTree = ""; }; - 94CD885D2D2D2EE100041BBA /* pipeline.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = pipeline.Plo; sourceTree = ""; }; - 94CD885E2D2D2EE100041BBA /* result.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = result.Plo; sourceTree = ""; }; - 94CD885F2D2D2EE100041BBA /* robusttransaction.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = robusttransaction.Plo; sourceTree = ""; }; - 94CD88602D2D2EE100041BBA /* row.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = row.Plo; sourceTree = ""; }; - 94CD88612D2D2EE100041BBA /* sql_cursor.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = sql_cursor.Plo; sourceTree = ""; }; - 94CD88622D2D2EE100041BBA /* strconv.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = strconv.Plo; sourceTree = ""; }; - 94CD88632D2D2EE100041BBA /* stream_from.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = stream_from.Plo; sourceTree = ""; }; - 94CD88642D2D2EE100041BBA /* stream_to.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = stream_to.Plo; sourceTree = ""; }; - 94CD88652D2D2EE100041BBA /* subtransaction.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = subtransaction.Plo; sourceTree = ""; }; - 94CD88662D2D2EE100041BBA /* time.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = time.Plo; sourceTree = ""; }; - 94CD88672D2D2EE100041BBA /* transaction.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = transaction.Plo; sourceTree = ""; }; - 94CD88682D2D2EE100041BBA /* transaction_base.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = transaction_base.Plo; sourceTree = ""; }; - 94CD88692D2D2EE100041BBA /* util.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = util.Plo; sourceTree = ""; }; - 94CD886A2D2D2EE100041BBA /* version.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = version.Plo; sourceTree = ""; }; - 94CD886B2D2D2EE100041BBA /* wait.Plo */ = {isa = PBXFileReference; lastKnownFileType = text; path = wait.Plo; sourceTree = ""; }; - 94CD886D2D2D2EE100041BBA /* array.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = array.cxx; sourceTree = ""; }; - 94CD886E2D2D2EE100041BBA /* binarystring.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = binarystring.cxx; sourceTree = ""; }; - 94CD886F2D2D2EE100041BBA /* blob.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = blob.cxx; sourceTree = ""; }; - 94CD88702D2D2EE100041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD88712D2D2EE100041BBA /* connection.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = connection.cxx; sourceTree = ""; }; - 94CD88722D2D2EE100041BBA /* cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = cursor.cxx; sourceTree = ""; }; - 94CD88732D2D2EE100041BBA /* encodings.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = encodings.cxx; sourceTree = ""; }; - 94CD88742D2D2EE100041BBA /* errorhandler.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = errorhandler.cxx; sourceTree = ""; }; - 94CD88752D2D2EE100041BBA /* except.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = except.cxx; sourceTree = ""; }; - 94CD88762D2D2EE100041BBA /* field.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = field.cxx; sourceTree = ""; }; - 94CD88772D2D2EE100041BBA /* largeobject.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = largeobject.cxx; sourceTree = ""; }; - 94CD88782D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD88792D2D2EE100041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD887A2D2D2EE100041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD887B2D2D2EE100041BBA /* notification.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = notification.cxx; sourceTree = ""; }; - 94CD887C2D2D2EE100041BBA /* params.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = params.cxx; sourceTree = ""; }; - 94CD887D2D2D2EE100041BBA /* pipeline.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pipeline.cxx; sourceTree = ""; }; - 94CD887E2D2D2EE100041BBA /* pqxx-source.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "pqxx-source.hxx"; sourceTree = ""; }; - 94CD887F2D2D2EE100041BBA /* result.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = result.cxx; sourceTree = ""; }; - 94CD88802D2D2EE100041BBA /* robusttransaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = robusttransaction.cxx; sourceTree = ""; }; - 94CD88812D2D2EE100041BBA /* row.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = row.cxx; sourceTree = ""; }; - 94CD88822D2D2EE100041BBA /* sql_cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = sql_cursor.cxx; sourceTree = ""; }; - 94CD88832D2D2EE100041BBA /* strconv.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = strconv.cxx; sourceTree = ""; }; - 94CD88842D2D2EE100041BBA /* stream_from.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = stream_from.cxx; sourceTree = ""; }; - 94CD88852D2D2EE100041BBA /* stream_to.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = stream_to.cxx; sourceTree = ""; }; - 94CD88862D2D2EE100041BBA /* subtransaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = subtransaction.cxx; sourceTree = ""; }; - 94CD88872D2D2EE100041BBA /* time.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = time.cxx; sourceTree = ""; }; - 94CD88882D2D2EE100041BBA /* transaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = transaction.cxx; sourceTree = ""; }; - 94CD88892D2D2EE100041BBA /* transaction_base.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = transaction_base.cxx; sourceTree = ""; }; - 94CD888A2D2D2EE100041BBA /* util.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = util.cxx; sourceTree = ""; }; - 94CD888B2D2D2EE100041BBA /* version.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = version.cxx; sourceTree = ""; }; - 94CD888C2D2D2EE100041BBA /* wait.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wait.cxx; sourceTree = ""; }; - 94CD888E2D2D2EE100041BBA /* runner.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = runner.Po; sourceTree = ""; }; - 94CD888F2D2D2EE100041BBA /* test00.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test00.Po; sourceTree = ""; }; - 94CD88902D2D2EE100041BBA /* test01.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test01.Po; sourceTree = ""; }; - 94CD88912D2D2EE100041BBA /* test02.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test02.Po; sourceTree = ""; }; - 94CD88922D2D2EE100041BBA /* test04.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test04.Po; sourceTree = ""; }; - 94CD88932D2D2EE100041BBA /* test07.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test07.Po; sourceTree = ""; }; - 94CD88942D2D2EE100041BBA /* test10.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test10.Po; sourceTree = ""; }; - 94CD88952D2D2EE100041BBA /* test11.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test11.Po; sourceTree = ""; }; - 94CD88962D2D2EE100041BBA /* test13.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test13.Po; sourceTree = ""; }; - 94CD88972D2D2EE100041BBA /* test14.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test14.Po; sourceTree = ""; }; - 94CD88982D2D2EE100041BBA /* test16.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test16.Po; sourceTree = ""; }; - 94CD88992D2D2EE100041BBA /* test17.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test17.Po; sourceTree = ""; }; - 94CD889A2D2D2EE100041BBA /* test18.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test18.Po; sourceTree = ""; }; - 94CD889B2D2D2EE100041BBA /* test20.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test20.Po; sourceTree = ""; }; - 94CD889C2D2D2EE100041BBA /* test21.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test21.Po; sourceTree = ""; }; - 94CD889D2D2D2EE100041BBA /* test26.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test26.Po; sourceTree = ""; }; - 94CD889E2D2D2EE100041BBA /* test29.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test29.Po; sourceTree = ""; }; - 94CD889F2D2D2EE100041BBA /* test30.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test30.Po; sourceTree = ""; }; - 94CD88A02D2D2EE100041BBA /* test32.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test32.Po; sourceTree = ""; }; - 94CD88A12D2D2EE100041BBA /* test37.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test37.Po; sourceTree = ""; }; - 94CD88A22D2D2EE100041BBA /* test39.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test39.Po; sourceTree = ""; }; - 94CD88A32D2D2EE100041BBA /* test46.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test46.Po; sourceTree = ""; }; - 94CD88A42D2D2EE100041BBA /* test56.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test56.Po; sourceTree = ""; }; - 94CD88A52D2D2EE100041BBA /* test60.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test60.Po; sourceTree = ""; }; - 94CD88A62D2D2EE100041BBA /* test61.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test61.Po; sourceTree = ""; }; - 94CD88A72D2D2EE100041BBA /* test62.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test62.Po; sourceTree = ""; }; - 94CD88A82D2D2EE100041BBA /* test69.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test69.Po; sourceTree = ""; }; - 94CD88A92D2D2EE100041BBA /* test70.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test70.Po; sourceTree = ""; }; - 94CD88AA2D2D2EE100041BBA /* test71.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test71.Po; sourceTree = ""; }; - 94CD88AB2D2D2EE100041BBA /* test72.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test72.Po; sourceTree = ""; }; - 94CD88AC2D2D2EE100041BBA /* test74.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test74.Po; sourceTree = ""; }; - 94CD88AD2D2D2EE100041BBA /* test75.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test75.Po; sourceTree = ""; }; - 94CD88AE2D2D2EE100041BBA /* test76.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test76.Po; sourceTree = ""; }; - 94CD88AF2D2D2EE100041BBA /* test77.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test77.Po; sourceTree = ""; }; - 94CD88B02D2D2EE100041BBA /* test78.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test78.Po; sourceTree = ""; }; - 94CD88B12D2D2EE100041BBA /* test79.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test79.Po; sourceTree = ""; }; - 94CD88B22D2D2EE100041BBA /* test82.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test82.Po; sourceTree = ""; }; - 94CD88B32D2D2EE100041BBA /* test84.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test84.Po; sourceTree = ""; }; - 94CD88B42D2D2EE100041BBA /* test87.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test87.Po; sourceTree = ""; }; - 94CD88B52D2D2EE100041BBA /* test88.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test88.Po; sourceTree = ""; }; - 94CD88B62D2D2EE100041BBA /* test89.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test89.Po; sourceTree = ""; }; - 94CD88B72D2D2EE100041BBA /* test90.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test90.Po; sourceTree = ""; }; - 94CD88B92D2D2EE100041BBA /* test_array.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_array.Po; sourceTree = ""; }; - 94CD88BA2D2D2EE100041BBA /* test_binarystring.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_binarystring.Po; sourceTree = ""; }; - 94CD88BB2D2D2EE100041BBA /* test_blob.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_blob.Po; sourceTree = ""; }; - 94CD88BC2D2D2EE100041BBA /* test_cancel_query.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_cancel_query.Po; sourceTree = ""; }; - 94CD88BD2D2D2EE100041BBA /* test_column.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_column.Po; sourceTree = ""; }; - 94CD88BE2D2D2EE100041BBA /* test_composite.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_composite.Po; sourceTree = ""; }; - 94CD88BF2D2D2EE100041BBA /* test_connection.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_connection.Po; sourceTree = ""; }; - 94CD88C02D2D2EE100041BBA /* test_cursor.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_cursor.Po; sourceTree = ""; }; - 94CD88C12D2D2EE100041BBA /* test_encodings.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_encodings.Po; sourceTree = ""; }; - 94CD88C22D2D2EE100041BBA /* test_error_verbosity.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_error_verbosity.Po; sourceTree = ""; }; - 94CD88C32D2D2EE100041BBA /* test_errorhandler.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_errorhandler.Po; sourceTree = ""; }; - 94CD88C42D2D2EE100041BBA /* test_escape.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_escape.Po; sourceTree = ""; }; - 94CD88C52D2D2EE100041BBA /* test_exceptions.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_exceptions.Po; sourceTree = ""; }; - 94CD88C62D2D2EE100041BBA /* test_field.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_field.Po; sourceTree = ""; }; - 94CD88C72D2D2EE100041BBA /* test_float.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_float.Po; sourceTree = ""; }; - 94CD88C82D2D2EE100041BBA /* test_largeobject.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_largeobject.Po; sourceTree = ""; }; - 94CD88C92D2D2EE100041BBA /* test_nonblocking_connect.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_nonblocking_connect.Po; sourceTree = ""; }; - 94CD88CA2D2D2EE100041BBA /* test_notice_handler.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_notice_handler.Po; sourceTree = ""; }; - 94CD88CB2D2D2EE100041BBA /* test_notification.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_notification.Po; sourceTree = ""; }; - 94CD88CC2D2D2EE100041BBA /* test_pipeline.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_pipeline.Po; sourceTree = ""; }; - 94CD88CD2D2D2EE100041BBA /* test_prepared_statement.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_prepared_statement.Po; sourceTree = ""; }; - 94CD88CE2D2D2EE100041BBA /* test_range.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_range.Po; sourceTree = ""; }; - 94CD88CF2D2D2EE100041BBA /* test_read_transaction.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_read_transaction.Po; sourceTree = ""; }; - 94CD88D02D2D2EE100041BBA /* test_result_iteration.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_result_iteration.Po; sourceTree = ""; }; - 94CD88D12D2D2EE100041BBA /* test_result_slicing.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_result_slicing.Po; sourceTree = ""; }; - 94CD88D22D2D2EE100041BBA /* test_row.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_row.Po; sourceTree = ""; }; - 94CD88D32D2D2EE100041BBA /* test_separated_list.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_separated_list.Po; sourceTree = ""; }; - 94CD88D42D2D2EE100041BBA /* test_simultaneous_transactions.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_simultaneous_transactions.Po; sourceTree = ""; }; - 94CD88D52D2D2EE100041BBA /* test_sql_cursor.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_sql_cursor.Po; sourceTree = ""; }; - 94CD88D62D2D2EE100041BBA /* test_stateless_cursor.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_stateless_cursor.Po; sourceTree = ""; }; - 94CD88D72D2D2EE100041BBA /* test_strconv.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_strconv.Po; sourceTree = ""; }; - 94CD88D82D2D2EE100041BBA /* test_stream_from.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_stream_from.Po; sourceTree = ""; }; - 94CD88D92D2D2EE100041BBA /* test_stream_query.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_stream_query.Po; sourceTree = ""; }; - 94CD88DA2D2D2EE100041BBA /* test_stream_to.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_stream_to.Po; sourceTree = ""; }; - 94CD88DB2D2D2EE100041BBA /* test_string_conversion.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_string_conversion.Po; sourceTree = ""; }; - 94CD88DC2D2D2EE100041BBA /* test_subtransaction.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_subtransaction.Po; sourceTree = ""; }; - 94CD88DD2D2D2EE100041BBA /* test_test_helpers.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_test_helpers.Po; sourceTree = ""; }; - 94CD88DE2D2D2EE100041BBA /* test_thread_safety_model.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_thread_safety_model.Po; sourceTree = ""; }; - 94CD88DF2D2D2EE100041BBA /* test_time.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_time.Po; sourceTree = ""; }; - 94CD88E02D2D2EE100041BBA /* test_transaction.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_transaction.Po; sourceTree = ""; }; - 94CD88E12D2D2EE100041BBA /* test_transaction_base.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_transaction_base.Po; sourceTree = ""; }; - 94CD88E22D2D2EE100041BBA /* test_transaction_focus.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_transaction_focus.Po; sourceTree = ""; }; - 94CD88E32D2D2EE100041BBA /* test_transactor.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_transactor.Po; sourceTree = ""; }; - 94CD88E42D2D2EE100041BBA /* test_type_name.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_type_name.Po; sourceTree = ""; }; - 94CD88E52D2D2EE100041BBA /* test_zview.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_zview.Po; sourceTree = ""; }; - 94CD88E72D2D2EE100041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD88E82D2D2EE100041BBA /* test_array.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_array.cxx; sourceTree = ""; }; - 94CD88E92D2D2EE100041BBA /* test_binarystring.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_binarystring.cxx; sourceTree = ""; }; - 94CD88EA2D2D2EE100041BBA /* test_blob.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_blob.cxx; sourceTree = ""; }; - 94CD88EB2D2D2EE100041BBA /* test_cancel_query.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_cancel_query.cxx; sourceTree = ""; }; - 94CD88EC2D2D2EE100041BBA /* test_column.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_column.cxx; sourceTree = ""; }; - 94CD88ED2D2D2EE100041BBA /* test_composite.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_composite.cxx; sourceTree = ""; }; - 94CD88EE2D2D2EE100041BBA /* test_connection.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_connection.cxx; sourceTree = ""; }; - 94CD88EF2D2D2EE100041BBA /* test_cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_cursor.cxx; sourceTree = ""; }; - 94CD88F02D2D2EE100041BBA /* test_encodings.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_encodings.cxx; sourceTree = ""; }; - 94CD88F12D2D2EE100041BBA /* test_error_verbosity.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_error_verbosity.cxx; sourceTree = ""; }; - 94CD88F22D2D2EE100041BBA /* test_errorhandler.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_errorhandler.cxx; sourceTree = ""; }; - 94CD88F32D2D2EE100041BBA /* test_escape.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_escape.cxx; sourceTree = ""; }; - 94CD88F42D2D2EE100041BBA /* test_exceptions.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_exceptions.cxx; sourceTree = ""; }; - 94CD88F52D2D2EE100041BBA /* test_field.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_field.cxx; sourceTree = ""; }; - 94CD88F62D2D2EE100041BBA /* test_float.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_float.cxx; sourceTree = ""; }; - 94CD88F72D2D2EE100041BBA /* test_largeobject.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_largeobject.cxx; sourceTree = ""; }; - 94CD88F82D2D2EE100041BBA /* test_nonblocking_connect.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_nonblocking_connect.cxx; sourceTree = ""; }; - 94CD88F92D2D2EE100041BBA /* test_notice_handler.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_notice_handler.cxx; sourceTree = ""; }; - 94CD88FA2D2D2EE100041BBA /* test_notification.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_notification.cxx; sourceTree = ""; }; - 94CD88FB2D2D2EE100041BBA /* test_pipeline.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_pipeline.cxx; sourceTree = ""; }; - 94CD88FC2D2D2EE100041BBA /* test_prepared_statement.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_prepared_statement.cxx; sourceTree = ""; }; - 94CD88FD2D2D2EE100041BBA /* test_range.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_range.cxx; sourceTree = ""; }; - 94CD88FE2D2D2EE100041BBA /* test_read_transaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_read_transaction.cxx; sourceTree = ""; }; - 94CD88FF2D2D2EE100041BBA /* test_result_iteration.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_result_iteration.cxx; sourceTree = ""; }; - 94CD89002D2D2EE100041BBA /* test_result_slicing.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_result_slicing.cxx; sourceTree = ""; }; - 94CD89012D2D2EE100041BBA /* test_row.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_row.cxx; sourceTree = ""; }; - 94CD89022D2D2EE100041BBA /* test_separated_list.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_separated_list.cxx; sourceTree = ""; }; - 94CD89032D2D2EE100041BBA /* test_simultaneous_transactions.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_simultaneous_transactions.cxx; sourceTree = ""; }; - 94CD89042D2D2EE100041BBA /* test_sql_cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_sql_cursor.cxx; sourceTree = ""; }; - 94CD89052D2D2EE100041BBA /* test_stateless_cursor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_stateless_cursor.cxx; sourceTree = ""; }; - 94CD89062D2D2EE100041BBA /* test_strconv.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_strconv.cxx; sourceTree = ""; }; - 94CD89072D2D2EE100041BBA /* test_stream_from.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_stream_from.cxx; sourceTree = ""; }; - 94CD89082D2D2EE100041BBA /* test_stream_query.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_stream_query.cxx; sourceTree = ""; }; - 94CD89092D2D2EE100041BBA /* test_stream_to.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_stream_to.cxx; sourceTree = ""; }; - 94CD890A2D2D2EE100041BBA /* test_string_conversion.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_string_conversion.cxx; sourceTree = ""; }; - 94CD890B2D2D2EE100041BBA /* test_subtransaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_subtransaction.cxx; sourceTree = ""; }; - 94CD890C2D2D2EE100041BBA /* test_test_helpers.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_test_helpers.cxx; sourceTree = ""; }; - 94CD890D2D2D2EE100041BBA /* test_thread_safety_model.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_thread_safety_model.cxx; sourceTree = ""; }; - 94CD890E2D2D2EE100041BBA /* test_time.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_time.cxx; sourceTree = ""; }; - 94CD890F2D2D2EE100041BBA /* test_transaction.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_transaction.cxx; sourceTree = ""; }; - 94CD89102D2D2EE100041BBA /* test_transaction_base.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_transaction_base.cxx; sourceTree = ""; }; - 94CD89112D2D2EE100041BBA /* test_transaction_focus.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_transaction_focus.cxx; sourceTree = ""; }; - 94CD89122D2D2EE100041BBA /* test_transactor.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_transactor.cxx; sourceTree = ""; }; - 94CD89132D2D2EE100041BBA /* test_type_name.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_type_name.cxx; sourceTree = ""; }; - 94CD89142D2D2EE100041BBA /* test_zview.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_zview.cxx; sourceTree = ""; }; - 94CD89162D2D2EE100041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD89172D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD89182D2D2EE100041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD89192D2D2EE100041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD891A2D2D2EE100041BBA /* Makefile.am.template */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am.template; sourceTree = ""; }; - 94CD891B2D2D2EE100041BBA /* runner.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = runner.cxx; sourceTree = ""; }; - 94CD891C2D2D2EE100041BBA /* test_helpers.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = test_helpers.hxx; sourceTree = ""; }; - 94CD891D2D2D2EE100041BBA /* test_types.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = test_types.hxx; sourceTree = ""; }; - 94CD891E2D2D2EE100041BBA /* test00.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test00.cxx; sourceTree = ""; }; - 94CD891F2D2D2EE100041BBA /* test01.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test01.cxx; sourceTree = ""; }; - 94CD89202D2D2EE100041BBA /* test02.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test02.cxx; sourceTree = ""; }; - 94CD89212D2D2EE100041BBA /* test04.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test04.cxx; sourceTree = ""; }; - 94CD89222D2D2EE100041BBA /* test07.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test07.cxx; sourceTree = ""; }; - 94CD89232D2D2EE100041BBA /* test10.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test10.cxx; sourceTree = ""; }; - 94CD89242D2D2EE100041BBA /* test11.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test11.cxx; sourceTree = ""; }; - 94CD89252D2D2EE100041BBA /* test13.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test13.cxx; sourceTree = ""; }; - 94CD89262D2D2EE100041BBA /* test14.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test14.cxx; sourceTree = ""; }; - 94CD89272D2D2EE100041BBA /* test16.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test16.cxx; sourceTree = ""; }; - 94CD89282D2D2EE100041BBA /* test17.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test17.cxx; sourceTree = ""; }; - 94CD89292D2D2EE100041BBA /* test18.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test18.cxx; sourceTree = ""; }; - 94CD892A2D2D2EE100041BBA /* test20.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test20.cxx; sourceTree = ""; }; - 94CD892B2D2D2EE100041BBA /* test21.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test21.cxx; sourceTree = ""; }; - 94CD892C2D2D2EE100041BBA /* test26.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test26.cxx; sourceTree = ""; }; - 94CD892D2D2D2EE100041BBA /* test29.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test29.cxx; sourceTree = ""; }; - 94CD892E2D2D2EE100041BBA /* test30.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test30.cxx; sourceTree = ""; }; - 94CD892F2D2D2EE100041BBA /* test32.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test32.cxx; sourceTree = ""; }; - 94CD89302D2D2EE100041BBA /* test37.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test37.cxx; sourceTree = ""; }; - 94CD89312D2D2EE100041BBA /* test39.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test39.cxx; sourceTree = ""; }; - 94CD89322D2D2EE100041BBA /* test46.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test46.cxx; sourceTree = ""; }; - 94CD89332D2D2EE100041BBA /* test56.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test56.cxx; sourceTree = ""; }; - 94CD89342D2D2EE100041BBA /* test60.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test60.cxx; sourceTree = ""; }; - 94CD89352D2D2EE100041BBA /* test61.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test61.cxx; sourceTree = ""; }; - 94CD89362D2D2EE100041BBA /* test62.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test62.cxx; sourceTree = ""; }; - 94CD89372D2D2EE100041BBA /* test69.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test69.cxx; sourceTree = ""; }; - 94CD89382D2D2EE100041BBA /* test70.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test70.cxx; sourceTree = ""; }; - 94CD89392D2D2EE100041BBA /* test71.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test71.cxx; sourceTree = ""; }; - 94CD893A2D2D2EE100041BBA /* test72.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test72.cxx; sourceTree = ""; }; - 94CD893B2D2D2EE100041BBA /* test74.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test74.cxx; sourceTree = ""; }; - 94CD893C2D2D2EE100041BBA /* test75.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test75.cxx; sourceTree = ""; }; - 94CD893D2D2D2EE100041BBA /* test76.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test76.cxx; sourceTree = ""; }; - 94CD893E2D2D2EE100041BBA /* test77.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test77.cxx; sourceTree = ""; }; - 94CD893F2D2D2EE100041BBA /* test78.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test78.cxx; sourceTree = ""; }; - 94CD89402D2D2EE100041BBA /* test79.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test79.cxx; sourceTree = ""; }; - 94CD89412D2D2EE100041BBA /* test82.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test82.cxx; sourceTree = ""; }; - 94CD89422D2D2EE100041BBA /* test84.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test84.cxx; sourceTree = ""; }; - 94CD89432D2D2EE100041BBA /* test87.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test87.cxx; sourceTree = ""; }; - 94CD89442D2D2EE100041BBA /* test88.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test88.cxx; sourceTree = ""; }; - 94CD89452D2D2EE100041BBA /* test89.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test89.cxx; sourceTree = ""; }; - 94CD89462D2D2EE100041BBA /* test90.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test90.cxx; sourceTree = ""; }; - 94CD89482D2D2EE100041BBA /* pqxxthreadsafety.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = pqxxthreadsafety.Po; sourceTree = ""; }; - 94CD89492D2D2EE100041BBA /* rmlo.Po */ = {isa = PBXFileReference; lastKnownFileType = text; path = rmlo.Po; sourceTree = ""; }; - 94CD894B2D2D2EE100041BBA /* deprecations */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = deprecations; sourceTree = ""; }; - 94CD894C2D2D2EE100041BBA /* extract_version */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = extract_version; sourceTree = ""; }; - 94CD894D2D2D2EE100041BBA /* format */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = format; sourceTree = ""; }; - 94CD894E2D2D2EE100041BBA /* generate_check_config.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = generate_check_config.py; sourceTree = ""; }; - 94CD894F2D2D2EE100041BBA /* generate_cxx_checks.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = generate_cxx_checks.py; sourceTree = ""; }; - 94CD89502D2D2EE100041BBA /* lint */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = lint; sourceTree = ""; }; - 94CD89512D2D2EE100041BBA /* m4esc.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = m4esc.py; sourceTree = ""; }; - 94CD89522D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD89532D2D2EE100041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD89542D2D2EE100041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD89552D2D2EE100041BBA /* pqxxthreadsafety.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pqxxthreadsafety.cxx; sourceTree = ""; }; - 94CD89562D2D2EE100041BBA /* rmlo.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rmlo.cxx; sourceTree = ""; }; - 94CD89572D2D2EE100041BBA /* splitconfig.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = splitconfig.py; sourceTree = ""; }; - 94CD89582D2D2EE100041BBA /* template2mak.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = template2mak.py; sourceTree = ""; }; - 94CD89592D2D2EE100041BBA /* test_all.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = test_all.py; sourceTree = ""; }; - 94CD895A2D2D2EE100041BBA /* todo */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = todo; sourceTree = ""; }; - 94CD895B2D2D2EE100041BBA /* update-copyright */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "update-copyright"; sourceTree = ""; }; - 94CD895D2D2D2EE100041BBA /* .clang-format */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".clang-format"; sourceTree = ""; }; - 94CD895E2D2D2EE100041BBA /* .clang-tidy */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".clang-tidy"; sourceTree = ""; }; - 94CD895F2D2D2EE100041BBA /* .cmake-format */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".cmake-format"; sourceTree = ""; }; - 94CD89602D2D2EE100041BBA /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = ""; }; - 94CD89612D2D2EE100041BBA /* .lgtm.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .lgtm.yml; sourceTree = ""; }; - 94CD89622D2D2EE100041BBA /* .mdl_style.rb */ = {isa = PBXFileReference; lastKnownFileType = text.script.ruby; path = .mdl_style.rb; sourceTree = ""; }; - 94CD89632D2D2EE100041BBA /* .mdlrc */ = {isa = PBXFileReference; lastKnownFileType = text; path = .mdlrc; sourceTree = ""; }; - 94CD89642D2D2EE100041BBA /* .readthedocs.yaml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .readthedocs.yaml; sourceTree = ""; }; - 94CD89652D2D2EE100041BBA /* aclocal.m4 */ = {isa = PBXFileReference; lastKnownFileType = text; path = aclocal.m4; sourceTree = ""; }; - 94CD89662D2D2EE100041BBA /* appveyor.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = appveyor.yml; sourceTree = ""; }; - 94CD89672D2D2EE100041BBA /* AUTHORS */ = {isa = PBXFileReference; lastKnownFileType = text; path = AUTHORS; sourceTree = ""; }; - 94CD89682D2D2EE100041BBA /* autogen.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = autogen.sh; sourceTree = ""; }; - 94CD89692D2D2EE100041BBA /* BUILDING-cmake.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "BUILDING-cmake.md"; sourceTree = ""; }; - 94CD896A2D2D2EE100041BBA /* BUILDING-configure.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "BUILDING-configure.md"; sourceTree = ""; }; - 94CD896B2D2D2EE100041BBA /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - 94CD896C2D2D2EE100041BBA /* compile_flags */ = {isa = PBXFileReference; lastKnownFileType = text; path = compile_flags; sourceTree = ""; }; - 94CD896D2D2D2EE100041BBA /* compile_flags.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = compile_flags.in; sourceTree = ""; }; - 94CD896E2D2D2EE100041BBA /* config.log */ = {isa = PBXFileReference; lastKnownFileType = text; path = config.log; sourceTree = ""; }; - 94CD896F2D2D2EE100041BBA /* config.status */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = config.status; sourceTree = ""; }; - 94CD89702D2D2EE100041BBA /* configitems */ = {isa = PBXFileReference; lastKnownFileType = text; path = configitems; sourceTree = ""; }; - 94CD89712D2D2EE100041BBA /* configure */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; - 94CD89722D2D2EE100041BBA /* configure.ac */ = {isa = PBXFileReference; lastKnownFileType = text; path = configure.ac; sourceTree = ""; }; - 94CD89732D2D2EE100041BBA /* COPYING */ = {isa = PBXFileReference; lastKnownFileType = text; path = COPYING; sourceTree = ""; }; - 94CD89742D2D2EE100041BBA /* cxx_features.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = cxx_features.txt; sourceTree = ""; }; - 94CD89752D2D2EE100041BBA /* INSTALL */ = {isa = PBXFileReference; lastKnownFileType = text; path = INSTALL; sourceTree = ""; }; - 94CD89762D2D2EE100041BBA /* libpqxx.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libpqxx.pc; sourceTree = ""; }; - 94CD89772D2D2EE100041BBA /* libpqxx.pc.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = libpqxx.pc.in; sourceTree = ""; }; - 94CD89782D2D2EE100041BBA /* libtool */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = libtool; sourceTree = ""; }; - 94CD89792D2D2EE100041BBA /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 94CD897A2D2D2EE100041BBA /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = ""; }; - 94CD897B2D2D2EE100041BBA /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - 94CD897C2D2D2EE100041BBA /* NEWS */ = {isa = PBXFileReference; lastKnownFileType = text; path = NEWS; sourceTree = ""; }; - 94CD897D2D2D2EE100041BBA /* pqxx_cxx_feature_checks.ac */ = {isa = PBXFileReference; lastKnownFileType = text; path = pqxx_cxx_feature_checks.ac; sourceTree = ""; }; - 94CD897E2D2D2EE100041BBA /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - 94CD897F2D2D2EE100041BBA /* README.rst */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.rst; sourceTree = ""; }; - 94CD89802D2D2EE100041BBA /* requirements.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = requirements.json; sourceTree = ""; }; - 94CD89812D2D2EE100041BBA /* VERSION */ = {isa = PBXFileReference; lastKnownFileType = text; path = VERSION; sourceTree = ""; }; - 94CD89D52D2D2FAC00041BBA /* connection-errorhandler.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-errorhandler.hxx"; sourceTree = ""; }; - 94CD89D62D2D2FAC00041BBA /* connection-largeobject.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-largeobject.hxx"; sourceTree = ""; }; - 94CD89D72D2D2FAC00041BBA /* connection-notification_receiver.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-notification_receiver.hxx"; sourceTree = ""; }; - 94CD89D82D2D2FAC00041BBA /* connection-pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-pipeline.hxx"; sourceTree = ""; }; - 94CD89D92D2D2FAC00041BBA /* connection-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-sql_cursor.hxx"; sourceTree = ""; }; - 94CD89DA2D2D2FAC00041BBA /* connection-stream_from.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-stream_from.hxx"; sourceTree = ""; }; - 94CD89DB2D2D2FAC00041BBA /* connection-stream_to.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-stream_to.hxx"; sourceTree = ""; }; - 94CD89DC2D2D2FAC00041BBA /* connection-transaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-transaction.hxx"; sourceTree = ""; }; - 94CD89DD2D2D2FAC00041BBA /* errorhandler-connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "errorhandler-connection.hxx"; sourceTree = ""; }; - 94CD89DE2D2D2FAC00041BBA /* icursor_iterator-icursorstream.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "icursor_iterator-icursorstream.hxx"; sourceTree = ""; }; - 94CD89DF2D2D2FAC00041BBA /* icursorstream-icursor_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "icursorstream-icursor_iterator.hxx"; sourceTree = ""; }; - 94CD89E02D2D2FAC00041BBA /* result-connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-connection.hxx"; sourceTree = ""; }; - 94CD89E12D2D2FAC00041BBA /* result-creation.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-creation.hxx"; sourceTree = ""; }; - 94CD89E22D2D2FAC00041BBA /* result-pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-pipeline.hxx"; sourceTree = ""; }; - 94CD89E32D2D2FAC00041BBA /* result-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-sql_cursor.hxx"; sourceTree = ""; }; - 94CD89E42D2D2FAC00041BBA /* transaction-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "transaction-sql_cursor.hxx"; sourceTree = ""; }; - 94CD89E52D2D2FAC00041BBA /* transaction-transaction_focus.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "transaction-transaction_focus.hxx"; sourceTree = ""; }; - 94CD89E72D2D2FAC00041BBA /* array-composite.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "array-composite.hxx"; sourceTree = ""; }; - 94CD89E82D2D2FAC00041BBA /* callgate.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = callgate.hxx; sourceTree = ""; }; - 94CD89E92D2D2FAC00041BBA /* concat.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = concat.hxx; sourceTree = ""; }; - 94CD89EA2D2D2FAC00041BBA /* conversions.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = conversions.hxx; sourceTree = ""; }; - 94CD89EB2D2D2FAC00041BBA /* encoding_group.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = encoding_group.hxx; sourceTree = ""; }; - 94CD89EC2D2D2FAC00041BBA /* encodings.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = encodings.hxx; sourceTree = ""; }; - 94CD89ED2D2D2FAC00041BBA /* header-post.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "header-post.hxx"; sourceTree = ""; }; - 94CD89EE2D2D2FAC00041BBA /* header-pre.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "header-pre.hxx"; sourceTree = ""; }; - 94CD89EF2D2D2FAC00041BBA /* ignore-deprecated-post.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "ignore-deprecated-post.hxx"; sourceTree = ""; }; - 94CD89F02D2D2FAC00041BBA /* ignore-deprecated-pre.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "ignore-deprecated-pre.hxx"; sourceTree = ""; }; - 94CD89F12D2D2FAC00041BBA /* libpq-forward.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "libpq-forward.hxx"; sourceTree = ""; }; - 94CD89F22D2D2FAC00041BBA /* result_iter.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = result_iter.hxx; sourceTree = ""; }; - 94CD89F32D2D2FAC00041BBA /* result_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = result_iterator.hxx; sourceTree = ""; }; - 94CD89F42D2D2FAC00041BBA /* sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = sql_cursor.hxx; sourceTree = ""; }; - 94CD89F52D2D2FAC00041BBA /* statement_parameters.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = statement_parameters.hxx; sourceTree = ""; }; - 94CD89F62D2D2FAC00041BBA /* stream_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_iterator.hxx; sourceTree = ""; }; - 94CD89F72D2D2FAC00041BBA /* stream_query.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_query.hxx; sourceTree = ""; }; - 94CD89F82D2D2FAC00041BBA /* stream_query_impl.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = stream_query_impl.hxx; sourceTree = ""; }; - 94CD89F92D2D2FAC00041BBA /* wait.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = wait.hxx; sourceTree = ""; }; - 94CD89FB2D2D2FAC00041BBA /* accessing-results.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "accessing-results.md"; sourceTree = ""; }; - 94CD89FC2D2D2FAC00041BBA /* binary-data.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "binary-data.md"; sourceTree = ""; }; - 94CD89FD2D2D2FAC00041BBA /* datatypes.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = datatypes.md; sourceTree = ""; }; - 94CD89FE2D2D2FAC00041BBA /* escaping.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = escaping.md; sourceTree = ""; }; - 94CD89FF2D2D2FAC00041BBA /* getting-started.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "getting-started.md"; sourceTree = ""; }; - 94CD8A002D2D2FAC00041BBA /* mainpage.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = mainpage.md; sourceTree = ""; }; - 94CD8A012D2D2FAC00041BBA /* mainpage.md.template */ = {isa = PBXFileReference; lastKnownFileType = text; path = mainpage.md.template; sourceTree = ""; }; - 94CD8A022D2D2FAC00041BBA /* parameters.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = parameters.md; sourceTree = ""; }; - 94CD8A032D2D2FAC00041BBA /* performance.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = performance.md; sourceTree = ""; }; - 94CD8A042D2D2FAC00041BBA /* prepared-statement.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "prepared-statement.md"; sourceTree = ""; }; - 94CD8A052D2D2FAC00041BBA /* streams.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = streams.md; sourceTree = ""; }; - 94CD8A062D2D2FAC00041BBA /* thread-safety.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "thread-safety.md"; sourceTree = ""; }; - 94CD8A1B2D2D2FC200041BBA /* connection-errorhandler.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-errorhandler.hxx"; sourceTree = ""; }; - 94CD8A1C2D2D2FC200041BBA /* connection-largeobject.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-largeobject.hxx"; sourceTree = ""; }; - 94CD8A1D2D2D2FC200041BBA /* connection-notification_receiver.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-notification_receiver.hxx"; sourceTree = ""; }; - 94CD8A1E2D2D2FC200041BBA /* connection-pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-pipeline.hxx"; sourceTree = ""; }; - 94CD8A1F2D2D2FC200041BBA /* connection-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-sql_cursor.hxx"; sourceTree = ""; }; - 94CD8A202D2D2FC200041BBA /* connection-stream_from.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-stream_from.hxx"; sourceTree = ""; }; - 94CD8A212D2D2FC200041BBA /* connection-stream_to.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-stream_to.hxx"; sourceTree = ""; }; - 94CD8A222D2D2FC200041BBA /* connection-transaction.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "connection-transaction.hxx"; sourceTree = ""; }; - 94CD8A232D2D2FC200041BBA /* errorhandler-connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "errorhandler-connection.hxx"; sourceTree = ""; }; - 94CD8A242D2D2FC200041BBA /* icursor_iterator-icursorstream.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "icursor_iterator-icursorstream.hxx"; sourceTree = ""; }; - 94CD8A252D2D2FC200041BBA /* icursorstream-icursor_iterator.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "icursorstream-icursor_iterator.hxx"; sourceTree = ""; }; - 94CD8A262D2D2FC200041BBA /* result-connection.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-connection.hxx"; sourceTree = ""; }; - 94CD8A272D2D2FC200041BBA /* result-creation.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-creation.hxx"; sourceTree = ""; }; - 94CD8A282D2D2FC200041BBA /* result-pipeline.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-pipeline.hxx"; sourceTree = ""; }; - 94CD8A292D2D2FC200041BBA /* result-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "result-sql_cursor.hxx"; sourceTree = ""; }; - 94CD8A2A2D2D2FC200041BBA /* transaction-sql_cursor.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "transaction-sql_cursor.hxx"; sourceTree = ""; }; - 94CD8A2B2D2D2FC200041BBA /* transaction-transaction_focus.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "transaction-transaction_focus.hxx"; sourceTree = ""; }; - 94CD8A8B2D2D33E200041BBA /* libpkgconf.5.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpkgconf.5.dylib; path = ../../../../../opt/homebrew/Cellar/pkgconf/2.3.0_1/lib/libpkgconf.5.dylib; sourceTree = ""; }; - 94CD8A8C2D2D33E200041BBA /* libpkgconf.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpkgconf.a; path = ../../../../../opt/homebrew/Cellar/pkgconf/2.3.0_1/lib/libpkgconf.a; sourceTree = ""; }; - 94CD8A8F2D2D33FC00041BBA /* libpkgconf.pc */ = {isa = PBXFileReference; lastKnownFileType = text; name = libpkgconf.pc; path = ../../../../../opt/homebrew/Cellar/pkgconf/2.3.0_1/lib/pkgconfig/libpkgconf.pc; sourceTree = ""; }; - 94CD8A912D2D34A100041BBA /* utf8_and_euc2004.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_euc2004.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_euc2004.so"; sourceTree = ""; }; - 94CD8A922D2D34A100041BBA /* pg_freespacemap.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pg_freespacemap.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pg_freespacemap.so"; sourceTree = ""; }; - 94CD8A932D2D34A100041BBA /* plpgsql.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = plpgsql.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/plpgsql.so"; sourceTree = ""; }; - 94CD8A942D2D34A100041BBA /* insert_username.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = insert_username.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/insert_username.so"; sourceTree = ""; }; - 94CD8A952D2D34A100041BBA /* auth_delay.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = auth_delay.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/auth_delay.so"; sourceTree = ""; }; - 94CD8A962D2D34A100041BBA /* passwordcheck.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = passwordcheck.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/passwordcheck.so"; sourceTree = ""; }; - 94CD8A972D2D34A100041BBA /* libpq.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpq.a; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpq.a"; sourceTree = ""; }; - 94CD8A982D2D34A100041BBA /* pg_trgm.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pg_trgm.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pg_trgm.so"; sourceTree = ""; }; - 94CD8A992D2D34A100041BBA /* pgcrypto.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pgcrypto.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pgcrypto.so"; sourceTree = ""; }; - 94CD8A9A2D2D34A200041BBA /* pageinspect.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pageinspect.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pageinspect.so"; sourceTree = ""; }; - 94CD8A9B2D2D34A200041BBA /* pgoutput.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pgoutput.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pgoutput.so"; sourceTree = ""; }; - 94CD8A9C2D2D34A200041BBA /* hstore_plperl.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = hstore_plperl.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/hstore_plperl.so"; sourceTree = ""; }; - 94CD8A9D2D2D34A200041BBA /* utf8_and_gbk.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_gbk.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_gbk.so"; sourceTree = ""; }; - 94CD8A9E2D2D34A200041BBA /* utf8_and_win.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_win.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_win.so"; sourceTree = ""; }; - 94CD8A9F2D2D34A200041BBA /* libecpg.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libecpg.pc; sourceTree = ""; }; - 94CD8AA02D2D34A200041BBA /* libecpg_compat.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libecpg_compat.pc; sourceTree = ""; }; - 94CD8AA12D2D34A200041BBA /* libpgtypes.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libpgtypes.pc; sourceTree = ""; }; - 94CD8AA22D2D34A200041BBA /* libpq.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libpq.pc; sourceTree = ""; }; - 94CD8AA42D2D34A200041BBA /* utf8_and_euc_tw.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_euc_tw.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_euc_tw.so"; sourceTree = ""; }; - 94CD8AA52D2D34A200041BBA /* lo.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = lo.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/lo.so"; sourceTree = ""; }; - 94CD8AA62D2D34A200041BBA /* dblink.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = dblink.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/dblink.so"; sourceTree = ""; }; - 94CD8AA72D2D34A200041BBA /* autoinc.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = autoinc.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/autoinc.so"; sourceTree = ""; }; - 94CD8AA82D2D34A200041BBA /* tsm_system_time.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = tsm_system_time.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/tsm_system_time.so"; sourceTree = ""; }; - 94CD8AA92D2D34A200041BBA /* moddatetime.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = moddatetime.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/moddatetime.so"; sourceTree = ""; }; - 94CD8AAA2D2D34A200041BBA /* latin_and_mic.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = latin_and_mic.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/latin_and_mic.so"; sourceTree = ""; }; - 94CD8AAB2D2D34A200041BBA /* pgrowlocks.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pgrowlocks.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pgrowlocks.so"; sourceTree = ""; }; - 94CD8AAC2D2D34A200041BBA /* libpgfeutils.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpgfeutils.a; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpgfeutils.a"; sourceTree = ""; }; - 94CD8AAD2D2D34A200041BBA /* dict_int.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = dict_int.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/dict_int.so"; sourceTree = ""; }; - 94CD8AAE2D2D34A200041BBA /* utf8_and_euc_cn.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_euc_cn.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_euc_cn.so"; sourceTree = ""; }; - 94CD8AAF2D2D34A200041BBA /* libpgtypes.3.14.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpgtypes.3.14.dylib; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpgtypes.3.14.dylib"; sourceTree = ""; }; - 94CD8AB02D2D34A200041BBA /* pltcl.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pltcl.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pltcl.so"; sourceTree = ""; }; - 94CD8AB12D2D34A200041BBA /* dict_snowball.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = dict_snowball.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/dict_snowball.so"; sourceTree = ""; }; - 94CD8AB22D2D34A200041BBA /* btree_gin.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = btree_gin.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/btree_gin.so"; sourceTree = ""; }; - 94CD8AB32D2D34A300041BBA /* utf8_and_big5.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_big5.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_big5.so"; sourceTree = ""; }; - 94CD8AB42D2D34A300041BBA /* libpgcommon_shlib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpgcommon_shlib.a; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpgcommon_shlib.a"; sourceTree = ""; }; - 94CD8AB52D2D34A300041BBA /* utf8_and_iso8859.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_iso8859.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_iso8859.so"; sourceTree = ""; }; - 94CD8AB62D2D34A300041BBA /* utf8_and_johab.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_johab.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_johab.so"; sourceTree = ""; }; - 94CD8AB72D2D34A300041BBA /* utf8_and_uhc.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_uhc.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_uhc.so"; sourceTree = ""; }; - 94CD8AB82D2D34A300041BBA /* libpgport_shlib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpgport_shlib.a; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpgport_shlib.a"; sourceTree = ""; }; - 94CD8AB92D2D34A300041BBA /* _int.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = _int.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/_int.so"; sourceTree = ""; }; - 94CD8ABA2D2D34A300041BBA /* tsm_system_rows.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = tsm_system_rows.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/tsm_system_rows.so"; sourceTree = ""; }; - 94CD8ABB2D2D34A300041BBA /* isn.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = isn.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/isn.so"; sourceTree = ""; }; - 94CD8ABC2D2D34A300041BBA /* euc2004_sjis2004.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = euc2004_sjis2004.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/euc2004_sjis2004.so"; sourceTree = ""; }; - 94CD8ABD2D2D34A300041BBA /* btree_gist.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = btree_gist.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/btree_gist.so"; sourceTree = ""; }; - 94CD8ABE2D2D34A300041BBA /* refint.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = refint.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/refint.so"; sourceTree = ""; }; - 94CD8ABF2D2D34A300041BBA /* pg_visibility.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pg_visibility.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pg_visibility.so"; sourceTree = ""; }; - 94CD8AC02D2D34A300041BBA /* cyrillic_and_mic.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = cyrillic_and_mic.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/cyrillic_and_mic.so"; sourceTree = ""; }; - 94CD8AC12D2D34A300041BBA /* utf8_and_sjis.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_sjis.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_sjis.so"; sourceTree = ""; }; - 94CD8AC22D2D34A300041BBA /* latin2_and_win1250.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = latin2_and_win1250.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/latin2_and_win1250.so"; sourceTree = ""; }; - 94CD8AC32D2D34A300041BBA /* postgres_fdw.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = postgres_fdw.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/postgres_fdw.so"; sourceTree = ""; }; - 94CD8AC42D2D34A300041BBA /* ltree.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = ltree.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/ltree.so"; sourceTree = ""; }; - 94CD8AC52D2D34A400041BBA /* pgstattuple.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pgstattuple.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pgstattuple.so"; sourceTree = ""; }; - 94CD8AC62D2D34A400041BBA /* utf8_and_gb18030.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_gb18030.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_gb18030.so"; sourceTree = ""; }; - 94CD8AC72D2D34A400041BBA /* euc_jp_and_sjis.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = euc_jp_and_sjis.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/euc_jp_and_sjis.so"; sourceTree = ""; }; - 94CD8AC82D2D34A400041BBA /* libecpg.6.14.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libecpg.6.14.dylib; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libecpg.6.14.dylib"; sourceTree = ""; }; - 94CD8AC92D2D34A400041BBA /* adminpack.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = adminpack.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/adminpack.so"; sourceTree = ""; }; - 94CD8ACA2D2D34A400041BBA /* citext.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = citext.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/citext.so"; sourceTree = ""; }; - 94CD8ACB2D2D34A400041BBA /* pg_surgery.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pg_surgery.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pg_surgery.so"; sourceTree = ""; }; - 94CD8ACC2D2D34A400041BBA /* plperl.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = plperl.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/plperl.so"; sourceTree = ""; }; - 94CD8ACD2D2D34A400041BBA /* fuzzystrmatch.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = fuzzystrmatch.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/fuzzystrmatch.so"; sourceTree = ""; }; - 94CD8ACE2D2D34A400041BBA /* earthdistance.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = earthdistance.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/earthdistance.so"; sourceTree = ""; }; - 94CD8ACF2D2D34A400041BBA /* libpgtypes.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpgtypes.a; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpgtypes.a"; sourceTree = ""; }; - 94CD8AD02D2D34A400041BBA /* libpq.5.14.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpq.5.14.dylib; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpq.5.14.dylib"; sourceTree = ""; }; - 94CD8AD12D2D34A400041BBA /* auto_explain.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = auto_explain.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/auto_explain.so"; sourceTree = ""; }; - 94CD8AD22D2D34A400041BBA /* libpgcommon.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpgcommon.a; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpgcommon.a"; sourceTree = ""; }; - 94CD8AD32D2D34A400041BBA /* uuid-ossp.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = "uuid-ossp.so"; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/uuid-ossp.so"; sourceTree = ""; }; - 94CD8AD42D2D34A500041BBA /* hstore.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = hstore.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/hstore.so"; sourceTree = ""; }; - 94CD8AD52D2D34A500041BBA /* unaccent.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = unaccent.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/unaccent.so"; sourceTree = ""; }; - 94CD8AD62D2D34A500041BBA /* seg.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = seg.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/seg.so"; sourceTree = ""; }; - 94CD8AD72D2D34A500041BBA /* file_fdw.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = file_fdw.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/file_fdw.so"; sourceTree = ""; }; - 94CD8AD82D2D34A500041BBA /* jsonb_plperl.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = jsonb_plperl.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/jsonb_plperl.so"; sourceTree = ""; }; - 94CD8AD92D2D34A500041BBA /* test_decoding.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = test_decoding.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/test_decoding.so"; sourceTree = ""; }; - 94CD8ADA2D2D34A500041BBA /* euc_kr_and_mic.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = euc_kr_and_mic.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/euc_kr_and_mic.so"; sourceTree = ""; }; - 94CD8ADB2D2D34A500041BBA /* utf8_and_euc_jp.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_euc_jp.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_euc_jp.so"; sourceTree = ""; }; - 94CD8ADC2D2D34A500041BBA /* utf8_and_cyrillic.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_cyrillic.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_cyrillic.so"; sourceTree = ""; }; - 94CD8ADD2D2D34A500041BBA /* euc_tw_and_big5.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = euc_tw_and_big5.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/euc_tw_and_big5.so"; sourceTree = ""; }; - 94CD8ADE2D2D34A500041BBA /* libpgport.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpgport.a; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpgport.a"; sourceTree = ""; }; - 94CD8ADF2D2D34A500041BBA /* libecpg_compat.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libecpg_compat.a; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libecpg_compat.a"; sourceTree = ""; }; - 94CD8AE02D2D34A500041BBA /* install-sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = ""; }; - 94CD8AE12D2D34A500041BBA /* missing */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = missing; sourceTree = ""; }; - 94CD8AE32D2D34A500041BBA /* pgxs.mk */ = {isa = PBXFileReference; lastKnownFileType = text; path = pgxs.mk; sourceTree = ""; }; - 94CD8AE52D2D34A500041BBA /* isolationtester */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = isolationtester; sourceTree = ""; }; - 94CD8AE62D2D34A500041BBA /* pg_isolation_regress */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = pg_isolation_regress; sourceTree = ""; }; - 94CD8AE82D2D34A500041BBA /* pg_regress */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = pg_regress; sourceTree = ""; }; - 94CD8AEB2D2D34A500041BBA /* Makefile.global */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.global; sourceTree = ""; }; - 94CD8AEC2D2D34A500041BBA /* Makefile.port */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.port; sourceTree = ""; }; - 94CD8AED2D2D34A500041BBA /* Makefile.shlib */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.shlib; sourceTree = ""; }; - 94CD8AEE2D2D34A500041BBA /* nls-global.mk */ = {isa = PBXFileReference; lastKnownFileType = text; path = "nls-global.mk"; sourceTree = ""; }; - 94CD8AF12D2D34A500041BBA /* libecpg_compat.3.14.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libecpg_compat.3.14.dylib; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libecpg_compat.3.14.dylib"; sourceTree = ""; }; - 94CD8AF22D2D34A500041BBA /* euc_cn_and_mic.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = euc_cn_and_mic.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/euc_cn_and_mic.so"; sourceTree = ""; }; - 94CD8AF32D2D34A600041BBA /* pg_stat_statements.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pg_stat_statements.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pg_stat_statements.so"; sourceTree = ""; }; - 94CD8AF42D2D34A700041BBA /* cube.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = cube.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/cube.so"; sourceTree = ""; }; - 94CD8AF52D2D34A700041BBA /* old_snapshot.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = old_snapshot.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/old_snapshot.so"; sourceTree = ""; }; - 94CD8AF62D2D34A700041BBA /* tablefunc.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = tablefunc.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/tablefunc.so"; sourceTree = ""; }; - 94CD8AF72D2D34A700041BBA /* utf8_and_sjis2004.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_sjis2004.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_sjis2004.so"; sourceTree = ""; }; - 94CD8AF82D2D34A700041BBA /* amcheck.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = amcheck.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/amcheck.so"; sourceTree = ""; }; - 94CD8AF92D2D34A800041BBA /* libecpg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libecpg.a; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libecpg.a"; sourceTree = ""; }; - 94CD8AFA2D2D34A800041BBA /* pg_prewarm.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pg_prewarm.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pg_prewarm.so"; sourceTree = ""; }; - 94CD8AFB2D2D34A800041BBA /* dict_xsyn.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = dict_xsyn.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/dict_xsyn.so"; sourceTree = ""; }; - 94CD8AFC2D2D34A800041BBA /* sslinfo.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = sslinfo.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/sslinfo.so"; sourceTree = ""; }; - 94CD8AFD2D2D34A800041BBA /* utf8_and_iso8859_1.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_iso8859_1.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_iso8859_1.so"; sourceTree = ""; }; - 94CD8AFE2D2D34A800041BBA /* utf8_and_euc_kr.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = utf8_and_euc_kr.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/utf8_and_euc_kr.so"; sourceTree = ""; }; - 94CD8AFF2D2D34A800041BBA /* bool_plperl.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = bool_plperl.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/bool_plperl.so"; sourceTree = ""; }; - 94CD8B002D2D34A800041BBA /* pgxml.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pgxml.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pgxml.so"; sourceTree = ""; }; - 94CD8B012D2D34A800041BBA /* libpqwalreceiver.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = libpqwalreceiver.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/libpqwalreceiver.so"; sourceTree = ""; }; - 94CD8B022D2D34A800041BBA /* bloom.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = bloom.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/bloom.so"; sourceTree = ""; }; - 94CD8B032D2D34A800041BBA /* pg_buffercache.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = pg_buffercache.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pg_buffercache.so"; sourceTree = ""; }; - 94CD8B042D2D34A800041BBA /* tcn.so */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; name = tcn.so; path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/tcn.so"; sourceTree = ""; }; - 94CD8B6F2D2D34C800041BBA /* install-sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = ""; }; - 94CD8B702D2D34C800041BBA /* missing */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = missing; sourceTree = ""; }; - 94CD8B722D2D34C800041BBA /* libecpg.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libecpg.pc; sourceTree = ""; }; - 94CD8B732D2D34C800041BBA /* libecpg_compat.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libecpg_compat.pc; sourceTree = ""; }; - 94CD8B742D2D34C800041BBA /* libpgtypes.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libpgtypes.pc; sourceTree = ""; }; - 94CD8B752D2D34C800041BBA /* libpq.pc */ = {isa = PBXFileReference; lastKnownFileType = text; path = libpq.pc; sourceTree = ""; }; - 94CD8B772D2D34C800041BBA /* pgxs.mk */ = {isa = PBXFileReference; lastKnownFileType = text; path = pgxs.mk; sourceTree = ""; }; - 94CD8B792D2D34C800041BBA /* isolationtester */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = isolationtester; sourceTree = ""; }; - 94CD8B7A2D2D34C800041BBA /* pg_isolation_regress */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = pg_isolation_regress; sourceTree = ""; }; - 94CD8B7C2D2D34C800041BBA /* pg_regress */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = pg_regress; sourceTree = ""; }; - 94CD8B7F2D2D34C800041BBA /* Makefile.global */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.global; sourceTree = ""; }; - 94CD8B802D2D34C800041BBA /* Makefile.port */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.port; sourceTree = ""; }; - 94CD8B812D2D34C800041BBA /* Makefile.shlib */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.shlib; sourceTree = ""; }; - 94CD8B822D2D34C800041BBA /* nls-global.mk */ = {isa = PBXFileReference; lastKnownFileType = text; path = "nls-global.mk"; sourceTree = ""; }; - 94CD8B842D2D34C800041BBA /* install-sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = ""; }; - 94CD8B852D2D34C800041BBA /* missing */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = missing; sourceTree = ""; }; - 94CD8B872D2D34C800041BBA /* pgxs.mk */ = {isa = PBXFileReference; lastKnownFileType = text; path = pgxs.mk; sourceTree = ""; }; - 94CD8B892D2D34C800041BBA /* isolationtester */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = isolationtester; sourceTree = ""; }; - 94CD8B8A2D2D34C800041BBA /* pg_isolation_regress */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = pg_isolation_regress; sourceTree = ""; }; - 94CD8B8C2D2D34C800041BBA /* pg_regress */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = pg_regress; sourceTree = ""; }; - 94CD8B8F2D2D34C800041BBA /* Makefile.global */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.global; sourceTree = ""; }; - 94CD8B902D2D34C800041BBA /* Makefile.port */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.port; sourceTree = ""; }; - 94CD8B912D2D34C800041BBA /* Makefile.shlib */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.shlib; sourceTree = ""; }; - 94CD8B922D2D34C800041BBA /* nls-global.mk */ = {isa = PBXFileReference; lastKnownFileType = text; path = "nls-global.mk"; sourceTree = ""; }; - 94CD8B982D2DCDD800041BBA /* libpqxx-7.10.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpqxx-7.10.a"; path = "external/libpqxx/build/src/libpqxx-7.10.a"; sourceTree = ""; }; - 94CD8B9A2D2DCF6E00041BBA /* libpqxx-7.10.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libpqxx-7.10.a"; path = "build/external/libpqxx/src/libpqxx-7.10.a"; sourceTree = ""; }; - 94CD8B9E2D2E8CE500041BBA /* databaseConnection.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = databaseConnection.hpp; sourceTree = ""; }; - 94CD8B9F2D2E8CE500041BBA /* databaseConnection.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = databaseConnection.cpp; sourceTree = ""; }; - 94D3A7222FC1B3A600EBEA32 /* loadCommand.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = loadCommand.hpp; sourceTree = ""; }; - 94D3A7242FC1B3AD00EBEA32 /* loadCommand.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = loadCommand.cpp; sourceTree = ""; }; - 94D3A7282FC1B41500EBEA32 /* runCommand.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = runCommand.cpp; sourceTree = ""; }; - 94D3A72B2FC1B41D00EBEA32 /* runCommand.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = runCommand.hpp; sourceTree = ""; }; - 94D6010E2FA9CD700066F51A /* randomStrategy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = randomStrategy.cpp; sourceTree = ""; }; - 94D601122FA9CD890066F51A /* randomStrategy.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = randomStrategy.hpp; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 9470B59E2C8C5AD0007D9CC6 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 942FDDE62FC5C9DB0096F318 /* libcurl.4.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9470B5A92C8C5B99007D9CC6 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 942FDDE52FC5C9D30096F318 /* libcurl.4.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 940F6E4E2FD9477E00B0364A /* sweep */ = { - isa = PBXGroup; - children = ( - 940F6E4C2FD9477E00B0364A /* randomStrategySweep.hpp */, - 940F6E4D2FD9477E00B0364A /* runConfigurationBuilder.hpp */, - ); - path = sweep; - sourceTree = ""; - }; - 940F6E522FD9479800B0364A /* sweep */ = { - isa = PBXGroup; - children = ( - 940F6E502FD9479800B0364A /* randomStrategySweep.cpp */, - 940F6E512FD9479800B0364A /* runConfigurationBuilder.cpp */, - ); - path = sweep; - sourceTree = ""; - }; - 941B548F2D3BBA3B00E3BF64 /* trading_definitions */ = { - isa = PBXGroup; - children = ( - 945F475D2FD5614600D19164 /* run_configuration.hpp */, - 941B54972D3BBAA200E3BF64 /* configuration.hpp */, - 941B54942D3BBA8300E3BF64 /* strategy.hpp */, - 941B54932D3BBA7300E3BF64 /* strategy_variables.hpp */, - 941B54922D3BBA6500E3BF64 /* trading_variables.hpp */, - 941B54912D3BBA5600E3BF64 /* ohlc_rsi_variables.hpp */, - 941B54902D3BBA4900E3BF64 /* ohlc_variables.hpp */, - ); - path = trading_definitions; - sourceTree = ""; - }; - 941B54982D3BBAD800E3BF64 /* trading_definitions */ = { - isa = PBXGroup; - children = ( - 941B54992D3BBADD00E3BF64 /* trading_definitions_json.cpp */, - ); - path = trading_definitions; - sourceTree = ""; - }; - 94280BA72D2FC29F00F1CF56 /* utilities */ = { - isa = PBXGroup; - children = ( - 940F6E572FD947A900B0364A /* decimalConvert.cpp */, - 94829FC42FCC1D1A00710E6E /* env.cpp */, - 942EC5612FBEF94700CCBB5D /* redisConnection.cpp */, - 94280BA22D2FC00200F1CF56 /* base64.cpp */, - 943398232D57E53400287A2D /* jsonParser.cpp */, - ); - path = utilities; - sourceTree = ""; - }; - 942966D72D48E84100532862 /* models */ = { - isa = PBXGroup; - children = ( - 9464E5EF2FA7466900D82BAD /* symbolScale.hpp */, - 94674B822D533B1D00973137 /* trade.hpp */, - 942966D82D48E84A00532862 /* priceData.hpp */, - ); - path = models; - sourceTree = ""; - }; - 9437703E2FD42FC000317424 /* reporting */ = { - isa = PBXGroup; - children = ( - 9437703D2FD42FC000317424 /* elasticClient.cpp */, - ); - path = reporting; - sourceTree = ""; - }; - 943770422FD42FDD00317424 /* reporting */ = { - isa = PBXGroup; - children = ( - 943770412FD42FDD00317424 /* elasticClient.hpp */, - ); - path = reporting; - sourceTree = ""; - }; - 944D0DB52C8C36C0004DD0FC = { - isa = PBXGroup; - children = ( - 94CD849E2D2D22C900041BBA /* external */, - 944D0DCE2C8C3704004DD0FC /* scripts */, - 94DE4F772C8C3E7C00FE48FF /* include */, - 9470B5A22C8C5AD0007D9CC6 /* source */, - 9470B5AD2C8C5B99007D9CC6 /* tests */, - 944D0DD32C8C3704004DD0FC /* CMakeLists.txt */, - 944D0DC82C8C3704004DD0FC /* LICENSE.MD */, - 944D0DD02C8C3704004DD0FC /* README.md */, - 948A9CCD2C906A5600E23669 /* CONVENTIONS.md */, - 94CD87342D2D2EE100041BBA /* Frameworks */, - 944D0DBF2C8C36C0004DD0FC /* Products */, - ); - sourceTree = ""; - }; - 944D0DBF2C8C36C0004DD0FC /* Products */ = { - isa = PBXGroup; - children = ( - 9470B5A12C8C5AD0007D9CC6 /* source */, - 9470B5AC2C8C5B99007D9CC6 /* tests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 944D0DCE2C8C3704004DD0FC /* scripts */ = { - isa = PBXGroup; - children = ( - 94BBA4502D2EA2570010E04D /* arguments */, - 944D0DC92C8C3704004DD0FC /* build.sh */, - 944D0DCA2C8C3704004DD0FC /* clean.sh */, - 944D0DCC2C8C3704004DD0FC /* run.sh */, - 944D0DCD2C8C3704004DD0FC /* test.sh */, - ); - path = scripts; - sourceTree = ""; - }; - 94674B842D533B2F00973137 /* trading */ = { - isa = PBXGroup; - children = ( - 94B1A5992FD735F100CB7C9F /* runLoop.hpp */, - 946EFF802FB9F457008D9647 /* reporting.hpp */, - 94674B832D533B2F00973137 /* tradeManager.hpp */, - 94674BA02D533B2F00973137 /* exitRules.hpp */, - 94674BA12F8B92C10029B940 /* reviewStopAndLimit.hpp */, - ); - path = trading; - sourceTree = ""; - }; - 94674B862D533B4000973137 /* trading */ = { - isa = PBXGroup; - children = ( - 946EFF7D2FB9F44E008D9647 /* reporting.cpp */, - 94674B852D533B4000973137 /* tradeManager.cpp */, - ); - path = trading; - sourceTree = ""; - }; - 94674B8C2D533E7800973137 /* models */ = { - isa = PBXGroup; - children = ( - ); - path = models; - sourceTree = ""; - }; - 94685CCF2D384A8B00863D04 /* nlohmann */ = { - isa = PBXGroup; - children = ( - 94685CCE2D384A8B00863D04 /* json.hpp */, - ); - path = nlohmann; - sourceTree = ""; - }; - 9470B5A22C8C5AD0007D9CC6 /* source */ = { - isa = PBXGroup; - children = ( - 940F6E522FD9479800B0364A /* sweep */, - 9437703E2FD42FC000317424 /* reporting */, - 941B54982D3BBAD800E3BF64 /* trading_definitions */, - 94674B862D533B4000973137 /* trading */, - 94674B8C2D533E7800973137 /* models */, - 94D6010F2FA9CD700066F51A /* strategies */, - 94D3A7252FC1B3AD00EBEA32 /* commands */, - 94280BA72D2FC29F00F1CF56 /* utilities */, - 942EC5642FBEF95000CCBB5D /* backtestRunner.cpp */, - 943770442FD4396F00317424 /* boostRedisImpl.cpp */, - 942EC5652FBEF95000CCBB5D /* redisLoader.cpp */, - 942FDDDF2FC5C8B20096F318 /* tradingResults.cpp */, - 942EC5662FBEF95000CCBB5D /* redisRunner.cpp */, - 9470B5A32C8C5AD0007D9CC6 /* main.cpp */, - 94CD8B9F2D2E8CE500041BBA /* databaseConnection.cpp */, - 941408AD2D59F93F000ED1F9 /* sqlManager.cpp */, - 94724A822F8B92C10029B940 /* operations.cpp */, - ); - path = source; - sourceTree = ""; - }; - 9470B5AD2C8C5B99007D9CC6 /* tests */ = { - isa = PBXGroup; - children = ( - 940F6E5A2FD947B800B0364A /* sweep.mm */, - 9464E5F02FA7467200D82BAD /* symbolScale.mm */, - 943398262D57E54000287A2D /* jsonParser.mm */, - 94674B892D533BDA00973137 /* tradeManager.mm */, - 94364CB52D416D8000F35B55 /* db.mm */, - ); - path = tests; - sourceTree = ""; - }; - 94B8C7932D3D770800E17EB6 /* utilities */ = { - isa = PBXGroup; - children = ( - 940F6E4F2FD9478800B0364A /* decimalConvert.hpp */, - 94B4F02A2FD618B300B08FB4 /* backtestLog.hpp */, - 94B4F02B2FD618B300B08FB4 /* threadPool.hpp */, - 945F475C2FD5607E00D19164 /* queueKeys.hpp */, - 943770432FD4351100317424 /* parameterSweep.hpp */, - 94829FC32FCC1D1200710E6E /* env.hpp */, - 942EC55D2FBEF92F00CCBB5D /* redisConnection.hpp */, - 94C331A02FA899A8006BD690 /* decimal_json.hpp */, - 94280BA12D2FC00200F1CF56 /* base64.hpp */, - ); - path = utilities; - sourceTree = ""; - }; - 94BBA4502D2EA2570010E04D /* arguments */ = { - isa = PBXGroup; - children = ( - 94BBA4512D2EA2640010E04D /* build.sh */, - ); - path = arguments; - sourceTree = ""; - }; - 94CD832B2D2D22C900041BBA /* .circleci */ = { - isa = PBXGroup; - children = ( - 94CD832A2D2D22C900041BBA /* config.yml */, - ); - path = .circleci; - sourceTree = ""; - }; - 94CD832E2D2D22C900041BBA /* workflows */ = { - isa = PBXGroup; - children = ( - 94CD832C2D2D22C900041BBA /* codeql.yml */, - 94CD832D2D2D22C900041BBA /* stale.yml */, - ); - path = workflows; - sourceTree = ""; - }; - 94CD832F2D2D22C900041BBA /* .github */ = { - isa = PBXGroup; - children = ( - 94CD832E2D2D22C900041BBA /* workflows */, - ); - path = .github; - sourceTree = ""; - }; - 94CD83312D2D22C900041BBA /* .lift */ = { - isa = PBXGroup; - children = ( - 94CD83302D2D22C900041BBA /* ignoreFiles */, - ); - path = .lift; - sourceTree = ""; - }; - 94CD83352D2D22C900041BBA /* cmake */ = { - isa = PBXGroup; - children = ( - 94CD83322D2D22C900041BBA /* config.cmake */, - 94CD83332D2D22C900041BBA /* libpqxx-config.cmake */, - 94CD83342D2D22C900041BBA /* pqxx_cxx_feature_checks.cmake */, - ); - path = cmake; - sourceTree = ""; - }; - 94CD833C2D2D22C900041BBA /* m4 */ = { - isa = PBXGroup; - children = ( - 94CD83362D2D22C900041BBA /* libtool.m4 */, - 94CD83372D2D22C900041BBA /* lt~obsolete.m4 */, - 94CD83382D2D22C900041BBA /* ltoptions.m4 */, - 94CD83392D2D22C900041BBA /* ltsugar.m4 */, - 94CD833A2D2D22C900041BBA /* ltversion.m4 */, - 94CD833B2D2D22C900041BBA /* Makefile.am */, - ); - path = m4; - sourceTree = ""; - }; - 94CD83482D2D22C900041BBA /* config */ = { - isa = PBXGroup; - children = ( - 94CD833C2D2D22C900041BBA /* m4 */, - 94CD833D2D2D22C900041BBA /* compile */, - 94CD833E2D2D22C900041BBA /* config.guess */, - 94CD833F2D2D22C900041BBA /* config.sub */, - 94CD83402D2D22C900041BBA /* depcomp */, - 94CD83412D2D22C900041BBA /* install-sh */, - 94CD83422D2D22C900041BBA /* ltmain.sh */, - 94CD83432D2D22C900041BBA /* Makefile.am */, - 94CD83442D2D22C900041BBA /* Makefile.in */, - 94CD83452D2D22C900041BBA /* missing */, - 94CD83462D2D22C900041BBA /* mkinstalldirs */, - 94CD83472D2D22C900041BBA /* test-driver */, - ); - path = config; - sourceTree = ""; - }; - 94CD835F2D2D22C900041BBA /* config-tests */ = { - isa = PBXGroup; - children = ( - 94CD83492D2D22C900041BBA /* no_need_fslib.cxx */, - 94CD834A2D2D22C900041BBA /* PQXX_HAVE_ASSUME.cxx */, - 94CD834B2D2D22C900041BBA /* PQXX_HAVE_CHARCONV_FLOAT.cxx */, - 94CD834C2D2D22C900041BBA /* PQXX_HAVE_CHARCONV_INT.cxx */, - 94CD834D2D2D22C900041BBA /* PQXX_HAVE_CMP.cxx */, - 94CD834E2D2D22C900041BBA /* PQXX_HAVE_CONCEPTS.cxx */, - 94CD834F2D2D22C900041BBA /* PQXX_HAVE_CXA_DEMANGLE.cxx */, - 94CD83502D2D22C900041BBA /* PQXX_HAVE_GCC_PURE.cxx */, - 94CD83512D2D22C900041BBA /* PQXX_HAVE_GCC_VISIBILITY.cxx */, - 94CD83522D2D22C900041BBA /* PQXX_HAVE_LIKELY.cxx */, - 94CD83532D2D22C900041BBA /* PQXX_HAVE_MULTIDIM.cxx */, - 94CD83542D2D22C900041BBA /* PQXX_HAVE_PATH.cxx */, - 94CD83552D2D22C900041BBA /* PQXX_HAVE_POLL.cxx */, - 94CD83562D2D22C900041BBA /* PQXX_HAVE_SLEEP_FOR.cxx */, - 94CD83572D2D22C900041BBA /* PQXX_HAVE_SOURCE_LOCATION.cxx */, - 94CD83582D2D22C900041BBA /* PQXX_HAVE_SPAN.cxx */, - 94CD83592D2D22C900041BBA /* PQXX_HAVE_SSIZE.cxx */, - 94CD835A2D2D22C900041BBA /* PQXX_HAVE_STRERROR_R.cxx */, - 94CD835B2D2D22C900041BBA /* PQXX_HAVE_STRERROR_S.cxx */, - 94CD835C2D2D22C900041BBA /* PQXX_HAVE_THREAD_LOCAL.cxx */, - 94CD835D2D2D22C900041BBA /* PQXX_HAVE_YEAR_MONTH_DAY.cxx */, - 94CD835E2D2D22C900041BBA /* README.md */, - ); - path = "config-tests"; - sourceTree = ""; - }; - 94CD83622D2D22C900041BBA /* source */ = { - isa = PBXGroup; - children = ( - 94CD83602D2D22C900041BBA /* conf.py */, - 94CD83612D2D22C900041BBA /* index.rst */, - ); - path = source; - sourceTree = ""; - }; - 94CD83682D2D22C900041BBA /* doc */ = { - isa = PBXGroup; - children = ( - 94CD83622D2D22C900041BBA /* source */, - 94CD83632D2D22C900041BBA /* CMakeLists.txt */, - 94CD83642D2D22C900041BBA /* Doxyfile */, - 94CD83652D2D22C900041BBA /* Makefile.am */, - 94CD83662D2D22C900041BBA /* Makefile.in */, - 94CD83672D2D22C900041BBA /* requirements.txt */, - ); - path = doc; - sourceTree = ""; - }; - 94CD83752D2D22C900041BBA /* doc */ = { - isa = PBXGroup; - children = ( - 94CD83692D2D22C900041BBA /* accessing-results.md */, - 94CD836A2D2D22C900041BBA /* binary-data.md */, - 94CD836B2D2D22C900041BBA /* datatypes.md */, - 94CD836C2D2D22C900041BBA /* escaping.md */, - 94CD836D2D2D22C900041BBA /* getting-started.md */, - 94CD836E2D2D22C900041BBA /* mainpage.md */, - 94CD836F2D2D22C900041BBA /* mainpage.md.template */, - 94CD83702D2D22C900041BBA /* parameters.md */, - 94CD83712D2D22C900041BBA /* performance.md */, - 94CD83722D2D22C900041BBA /* prepared-statement.md */, - 94CD83732D2D22C900041BBA /* streams.md */, - 94CD83742D2D22C900041BBA /* thread-safety.md */, - ); - path = doc; - sourceTree = ""; - }; - 94CD83872D2D22C900041BBA /* gates */ = { - isa = PBXGroup; - children = ( - 94CD83762D2D22C900041BBA /* connection-errorhandler.hxx */, - 94CD83772D2D22C900041BBA /* connection-largeobject.hxx */, - 94CD83782D2D22C900041BBA /* connection-notification_receiver.hxx */, - 94CD83792D2D22C900041BBA /* connection-pipeline.hxx */, - 94CD837A2D2D22C900041BBA /* connection-sql_cursor.hxx */, - 94CD837B2D2D22C900041BBA /* connection-stream_from.hxx */, - 94CD837C2D2D22C900041BBA /* connection-stream_to.hxx */, - 94CD837D2D2D22C900041BBA /* connection-transaction.hxx */, - 94CD837E2D2D22C900041BBA /* errorhandler-connection.hxx */, - 94CD837F2D2D22C900041BBA /* icursor_iterator-icursorstream.hxx */, - 94CD83802D2D22C900041BBA /* icursorstream-icursor_iterator.hxx */, - 94CD83812D2D22C900041BBA /* result-connection.hxx */, - 94CD83822D2D22C900041BBA /* result-creation.hxx */, - 94CD83832D2D22C900041BBA /* result-pipeline.hxx */, - 94CD83842D2D22C900041BBA /* result-sql_cursor.hxx */, - 94CD83852D2D22C900041BBA /* transaction-sql_cursor.hxx */, - 94CD83862D2D22C900041BBA /* transaction-transaction_focus.hxx */, - ); - path = gates; - sourceTree = ""; - }; - 94CD839B2D2D22C900041BBA /* internal */ = { - isa = PBXGroup; - children = ( - 94CD83872D2D22C900041BBA /* gates */, - 94CD83882D2D22C900041BBA /* array-composite.hxx */, - 94CD83892D2D22C900041BBA /* callgate.hxx */, - 94CD838A2D2D22C900041BBA /* concat.hxx */, - 94CD838B2D2D22C900041BBA /* conversions.hxx */, - 94CD838C2D2D22C900041BBA /* encoding_group.hxx */, - 94CD838D2D2D22C900041BBA /* encodings.hxx */, - 94CD838E2D2D22C900041BBA /* header-post.hxx */, - 94CD838F2D2D22C900041BBA /* header-pre.hxx */, - 94CD83902D2D22C900041BBA /* ignore-deprecated-post.hxx */, - 94CD83912D2D22C900041BBA /* ignore-deprecated-pre.hxx */, - 94CD83922D2D22C900041BBA /* libpq-forward.hxx */, - 94CD83932D2D22C900041BBA /* result_iter.hxx */, - 94CD83942D2D22C900041BBA /* result_iterator.hxx */, - 94CD83952D2D22C900041BBA /* sql_cursor.hxx */, - 94CD83962D2D22C900041BBA /* statement_parameters.hxx */, - 94CD83972D2D22C900041BBA /* stream_iterator.hxx */, - 94CD83982D2D22C900041BBA /* stream_query.hxx */, - 94CD83992D2D22C900041BBA /* stream_query_impl.hxx */, - 94CD839A2D2D22C900041BBA /* wait.hxx */, - ); - path = internal; - sourceTree = ""; - }; - 94CD83E72D2D22C900041BBA /* pqxx */ = { - isa = PBXGroup; - children = ( - 94CD83752D2D22C900041BBA /* doc */, - 94CD839B2D2D22C900041BBA /* internal */, - 94CD839C2D2D22C900041BBA /* array.hxx */, - 94CD839D2D2D22C900041BBA /* array */, - 94CD839E2D2D22C900041BBA /* binarystring.hxx */, - 94CD839F2D2D22C900041BBA /* binarystring */, - 94CD83A02D2D22C900041BBA /* blob.hxx */, - 94CD83A12D2D22C900041BBA /* blob */, - 94CD83A22D2D22C900041BBA /* composite.hxx */, - 94CD83A32D2D22C900041BBA /* composite */, - 94CD83A42D2D22C900041BBA /* config.h.in */, - 94CD83A52D2D22C900041BBA /* connection.hxx */, - 94CD83A62D2D22C900041BBA /* connection */, - 94CD83A72D2D22C900041BBA /* cursor.hxx */, - 94CD83A82D2D22C900041BBA /* cursor */, - 94CD83A92D2D22C900041BBA /* dbtransaction.hxx */, - 94CD83AA2D2D22C900041BBA /* dbtransaction */, - 94CD83AB2D2D22C900041BBA /* errorhandler.hxx */, - 94CD83AC2D2D22C900041BBA /* errorhandler */, - 94CD83AD2D2D22C900041BBA /* except.hxx */, - 94CD83AE2D2D22C900041BBA /* except */, - 94CD83AF2D2D22C900041BBA /* field.hxx */, - 94CD83B02D2D22C900041BBA /* field */, - 94CD83B12D2D22C900041BBA /* isolation.hxx */, - 94CD83B22D2D22C900041BBA /* isolation */, - 94CD83B32D2D22C900041BBA /* largeobject.hxx */, - 94CD83B42D2D22C900041BBA /* largeobject */, - 94CD83B52D2D22C900041BBA /* Makefile.am */, - 94CD83B62D2D22C900041BBA /* Makefile.in */, - 94CD83B72D2D22C900041BBA /* nontransaction.hxx */, - 94CD83B82D2D22C900041BBA /* nontransaction */, - 94CD83B92D2D22C900041BBA /* notification.hxx */, - 94CD83BA2D2D22C900041BBA /* notification */, - 94CD83BB2D2D22C900041BBA /* params.hxx */, - 94CD83BC2D2D22C900041BBA /* params */, - 94CD83BD2D2D22C900041BBA /* pipeline.hxx */, - 94CD83BE2D2D22C900041BBA /* pipeline */, - 94CD83BF2D2D22C900041BBA /* pqxx */, - 94CD83C02D2D22C900041BBA /* prepared_statement.hxx */, - 94CD83C12D2D22C900041BBA /* prepared_statement */, - 94CD83C22D2D22C900041BBA /* range.hxx */, - 94CD83C32D2D22C900041BBA /* range */, - 94CD83C42D2D22C900041BBA /* result.hxx */, - 94CD83C52D2D22C900041BBA /* result */, - 94CD83C62D2D22C900041BBA /* robusttransaction.hxx */, - 94CD83C72D2D22C900041BBA /* robusttransaction */, - 94CD83C82D2D22C900041BBA /* row.hxx */, - 94CD83C92D2D22C900041BBA /* row */, - 94CD83CA2D2D22C900041BBA /* separated_list.hxx */, - 94CD83CB2D2D22C900041BBA /* separated_list */, - 94CD83CC2D2D22C900041BBA /* strconv.hxx */, - 94CD83CD2D2D22C900041BBA /* strconv */, - 94CD83CE2D2D22C900041BBA /* stream_from.hxx */, - 94CD83CF2D2D22C900041BBA /* stream_from */, - 94CD83D02D2D22C900041BBA /* stream_to.hxx */, - 94CD83D12D2D22C900041BBA /* stream_to */, - 94CD83D22D2D22C900041BBA /* subtransaction.hxx */, - 94CD83D32D2D22C900041BBA /* subtransaction */, - 94CD83D42D2D22C900041BBA /* time.hxx */, - 94CD83D52D2D22C900041BBA /* time */, - 94CD83D62D2D22C900041BBA /* transaction.hxx */, - 94CD83D72D2D22C900041BBA /* transaction */, - 94CD83D82D2D22C900041BBA /* transaction_base.hxx */, - 94CD83D92D2D22C900041BBA /* transaction_base */, - 94CD83DA2D2D22C900041BBA /* transaction_focus.hxx */, - 94CD83DB2D2D22C900041BBA /* transaction_focus */, - 94CD83DC2D2D22C900041BBA /* transactor.hxx */, - 94CD83DD2D2D22C900041BBA /* transactor */, - 94CD83DE2D2D22C900041BBA /* types.hxx */, - 94CD83DF2D2D22C900041BBA /* types */, - 94CD83E02D2D22C900041BBA /* util.hxx */, - 94CD83E12D2D22C900041BBA /* util */, - 94CD83E22D2D22C900041BBA /* version.hxx */, - 94CD83E32D2D22C900041BBA /* version */, - 94CD83E42D2D22C900041BBA /* version.hxx.template */, - 94CD83E52D2D22C900041BBA /* zview.hxx */, - 94CD83E62D2D22C900041BBA /* zview */, - ); - path = pqxx; - sourceTree = ""; - }; - 94CD83EC2D2D22C900041BBA /* include */ = { - isa = PBXGroup; - children = ( - 94CD83E72D2D22C900041BBA /* pqxx */, - 94CD83E82D2D22C900041BBA /* CMakeLists.txt */, - 94CD83E92D2D22C900041BBA /* CMakeLists.txt.template */, - 94CD83EA2D2D22C900041BBA /* Makefile.am */, - 94CD83EB2D2D22C900041BBA /* Makefile.in */, - ); - path = include; - sourceTree = ""; - }; - 94CD840C2D2D22C900041BBA /* src */ = { - isa = PBXGroup; - children = ( - 94CD83ED2D2D22C900041BBA /* array.cxx */, - 94CD83EE2D2D22C900041BBA /* binarystring.cxx */, - 94CD83EF2D2D22C900041BBA /* blob.cxx */, - 94CD83F02D2D22C900041BBA /* CMakeLists.txt */, - 94CD83F12D2D22C900041BBA /* connection.cxx */, - 94CD83F22D2D22C900041BBA /* cursor.cxx */, - 94CD83F32D2D22C900041BBA /* encodings.cxx */, - 94CD83F42D2D22C900041BBA /* errorhandler.cxx */, - 94CD83F52D2D22C900041BBA /* except.cxx */, - 94CD83F62D2D22C900041BBA /* field.cxx */, - 94CD83F72D2D22C900041BBA /* largeobject.cxx */, - 94CD83F82D2D22C900041BBA /* Makefile.am */, - 94CD83F92D2D22C900041BBA /* Makefile.in */, - 94CD83FA2D2D22C900041BBA /* notification.cxx */, - 94CD83FB2D2D22C900041BBA /* params.cxx */, - 94CD83FC2D2D22C900041BBA /* pipeline.cxx */, - 94CD83FD2D2D22C900041BBA /* pqxx-source.hxx */, - 94CD83FE2D2D22C900041BBA /* result.cxx */, - 94CD83FF2D2D22C900041BBA /* robusttransaction.cxx */, - 94CD84002D2D22C900041BBA /* row.cxx */, - 94CD84012D2D22C900041BBA /* sql_cursor.cxx */, - 94CD84022D2D22C900041BBA /* strconv.cxx */, - 94CD84032D2D22C900041BBA /* stream_from.cxx */, - 94CD84042D2D22C900041BBA /* stream_to.cxx */, - 94CD84052D2D22C900041BBA /* subtransaction.cxx */, - 94CD84062D2D22C900041BBA /* time.cxx */, - 94CD84072D2D22C900041BBA /* transaction.cxx */, - 94CD84082D2D22C900041BBA /* transaction_base.cxx */, - 94CD84092D2D22C900041BBA /* util.cxx */, - 94CD840A2D2D22C900041BBA /* version.cxx */, - 94CD840B2D2D22C900041BBA /* wait.cxx */, - ); - path = src; - sourceTree = ""; - }; - 94CD843B2D2D22C900041BBA /* unit */ = { - isa = PBXGroup; - children = ( - 94CD840D2D2D22C900041BBA /* CMakeLists.txt */, - 94CD840E2D2D22C900041BBA /* test_array.cxx */, - 94CD840F2D2D22C900041BBA /* test_binarystring.cxx */, - 94CD84102D2D22C900041BBA /* test_blob.cxx */, - 94CD84112D2D22C900041BBA /* test_cancel_query.cxx */, - 94CD84122D2D22C900041BBA /* test_column.cxx */, - 94CD84132D2D22C900041BBA /* test_composite.cxx */, - 94CD84142D2D22C900041BBA /* test_connection.cxx */, - 94CD84152D2D22C900041BBA /* test_cursor.cxx */, - 94CD84162D2D22C900041BBA /* test_encodings.cxx */, - 94CD84172D2D22C900041BBA /* test_error_verbosity.cxx */, - 94CD84182D2D22C900041BBA /* test_errorhandler.cxx */, - 94CD84192D2D22C900041BBA /* test_escape.cxx */, - 94CD841A2D2D22C900041BBA /* test_exceptions.cxx */, - 94CD841B2D2D22C900041BBA /* test_field.cxx */, - 94CD841C2D2D22C900041BBA /* test_float.cxx */, - 94CD841D2D2D22C900041BBA /* test_largeobject.cxx */, - 94CD841E2D2D22C900041BBA /* test_nonblocking_connect.cxx */, - 94CD841F2D2D22C900041BBA /* test_notice_handler.cxx */, - 94CD84202D2D22C900041BBA /* test_notification.cxx */, - 94CD84212D2D22C900041BBA /* test_pipeline.cxx */, - 94CD84222D2D22C900041BBA /* test_prepared_statement.cxx */, - 94CD84232D2D22C900041BBA /* test_range.cxx */, - 94CD84242D2D22C900041BBA /* test_read_transaction.cxx */, - 94CD84252D2D22C900041BBA /* test_result_iteration.cxx */, - 94CD84262D2D22C900041BBA /* test_result_slicing.cxx */, - 94CD84272D2D22C900041BBA /* test_row.cxx */, - 94CD84282D2D22C900041BBA /* test_separated_list.cxx */, - 94CD84292D2D22C900041BBA /* test_simultaneous_transactions.cxx */, - 94CD842A2D2D22C900041BBA /* test_sql_cursor.cxx */, - 94CD842B2D2D22C900041BBA /* test_stateless_cursor.cxx */, - 94CD842C2D2D22C900041BBA /* test_strconv.cxx */, - 94CD842D2D2D22C900041BBA /* test_stream_from.cxx */, - 94CD842E2D2D22C900041BBA /* test_stream_query.cxx */, - 94CD842F2D2D22C900041BBA /* test_stream_to.cxx */, - 94CD84302D2D22C900041BBA /* test_string_conversion.cxx */, - 94CD84312D2D22C900041BBA /* test_subtransaction.cxx */, - 94CD84322D2D22C900041BBA /* test_test_helpers.cxx */, - 94CD84332D2D22C900041BBA /* test_thread_safety_model.cxx */, - 94CD84342D2D22C900041BBA /* test_time.cxx */, - 94CD84352D2D22C900041BBA /* test_transaction.cxx */, - 94CD84362D2D22C900041BBA /* test_transaction_base.cxx */, - 94CD84372D2D22C900041BBA /* test_transaction_focus.cxx */, - 94CD84382D2D22C900041BBA /* test_transactor.cxx */, - 94CD84392D2D22C900041BBA /* test_type_name.cxx */, - 94CD843A2D2D22C900041BBA /* test_zview.cxx */, - ); - path = unit; - sourceTree = ""; - }; - 94CD846C2D2D22C900041BBA /* test */ = { - isa = PBXGroup; - children = ( - 94CD843B2D2D22C900041BBA /* unit */, - 94CD843C2D2D22C900041BBA /* CMakeLists.txt */, - 94CD843D2D2D22C900041BBA /* Makefile.am */, - 94CD843E2D2D22C900041BBA /* Makefile.in */, - 94CD843F2D2D22C900041BBA /* Makefile.am.template */, - 94CD84402D2D22C900041BBA /* runner.cxx */, - 94CD84412D2D22C900041BBA /* test_helpers.hxx */, - 94CD84422D2D22C900041BBA /* test_types.hxx */, - 94CD84432D2D22C900041BBA /* test00.cxx */, - 94CD84442D2D22C900041BBA /* test01.cxx */, - 94CD84452D2D22C900041BBA /* test02.cxx */, - 94CD84462D2D22C900041BBA /* test04.cxx */, - 94CD84472D2D22C900041BBA /* test07.cxx */, - 94CD84482D2D22C900041BBA /* test10.cxx */, - 94CD84492D2D22C900041BBA /* test11.cxx */, - 94CD844A2D2D22C900041BBA /* test13.cxx */, - 94CD844B2D2D22C900041BBA /* test14.cxx */, - 94CD844C2D2D22C900041BBA /* test16.cxx */, - 94CD844D2D2D22C900041BBA /* test17.cxx */, - 94CD844E2D2D22C900041BBA /* test18.cxx */, - 94CD844F2D2D22C900041BBA /* test20.cxx */, - 94CD84502D2D22C900041BBA /* test21.cxx */, - 94CD84512D2D22C900041BBA /* test26.cxx */, - 94CD84522D2D22C900041BBA /* test29.cxx */, - 94CD84532D2D22C900041BBA /* test30.cxx */, - 94CD84542D2D22C900041BBA /* test32.cxx */, - 94CD84552D2D22C900041BBA /* test37.cxx */, - 94CD84562D2D22C900041BBA /* test39.cxx */, - 94CD84572D2D22C900041BBA /* test46.cxx */, - 94CD84582D2D22C900041BBA /* test56.cxx */, - 94CD84592D2D22C900041BBA /* test60.cxx */, - 94CD845A2D2D22C900041BBA /* test61.cxx */, - 94CD845B2D2D22C900041BBA /* test62.cxx */, - 94CD845C2D2D22C900041BBA /* test69.cxx */, - 94CD845D2D2D22C900041BBA /* test70.cxx */, - 94CD845E2D2D22C900041BBA /* test71.cxx */, - 94CD845F2D2D22C900041BBA /* test72.cxx */, - 94CD84602D2D22C900041BBA /* test74.cxx */, - 94CD84612D2D22C900041BBA /* test75.cxx */, - 94CD84622D2D22C900041BBA /* test76.cxx */, - 94CD84632D2D22C900041BBA /* test77.cxx */, - 94CD84642D2D22C900041BBA /* test78.cxx */, - 94CD84652D2D22C900041BBA /* test79.cxx */, - 94CD84662D2D22C900041BBA /* test82.cxx */, - 94CD84672D2D22C900041BBA /* test84.cxx */, - 94CD84682D2D22C900041BBA /* test87.cxx */, - 94CD84692D2D22C900041BBA /* test88.cxx */, - 94CD846A2D2D22C900041BBA /* test89.cxx */, - 94CD846B2D2D22C900041BBA /* test90.cxx */, - ); - path = test; - sourceTree = ""; - }; - 94CD847D2D2D22C900041BBA /* tools */ = { - isa = PBXGroup; - children = ( - 94CD846D2D2D22C900041BBA /* deprecations */, - 94CD846E2D2D22C900041BBA /* extract_version */, - 94CD846F2D2D22C900041BBA /* format */, - 94CD84702D2D22C900041BBA /* generate_check_config.py */, - 94CD84712D2D22C900041BBA /* generate_cxx_checks.py */, - 94CD84722D2D22C900041BBA /* lint */, - 94CD84732D2D22C900041BBA /* m4esc.py */, - 94CD84742D2D22C900041BBA /* Makefile.am */, - 94CD84752D2D22C900041BBA /* Makefile.in */, - 94CD84762D2D22C900041BBA /* pqxxthreadsafety.cxx */, - 94CD84772D2D22C900041BBA /* rmlo.cxx */, - 94CD84782D2D22C900041BBA /* splitconfig.py */, - 94CD84792D2D22C900041BBA /* template2mak.py */, - 94CD847A2D2D22C900041BBA /* test_all.py */, - 94CD847B2D2D22C900041BBA /* todo */, - 94CD847C2D2D22C900041BBA /* update-copyright */, - ); - path = tools; - sourceTree = ""; - }; - 94CD849D2D2D22C900041BBA /* libpqxx */ = { - isa = PBXGroup; - children = ( - 94CD86EC2D2D295900041BBA /* build */, - 94CD832B2D2D22C900041BBA /* .circleci */, - 94CD832F2D2D22C900041BBA /* .github */, - 94CD83312D2D22C900041BBA /* .lift */, - 94CD83352D2D22C900041BBA /* cmake */, - 94CD83482D2D22C900041BBA /* config */, - 94CD835F2D2D22C900041BBA /* config-tests */, - 94CD83682D2D22C900041BBA /* doc */, - 94CD83EC2D2D22C900041BBA /* include */, - 94CD840C2D2D22C900041BBA /* src */, - 94CD846C2D2D22C900041BBA /* test */, - 94CD847D2D2D22C900041BBA /* tools */, - 94CD847E2D2D22C900041BBA /* .clang-format */, - 94CD847F2D2D22C900041BBA /* .clang-tidy */, - 94CD84802D2D22C900041BBA /* .cmake-format */, - 94CD84812D2D22C900041BBA /* .gitignore */, - 94CD84822D2D22C900041BBA /* .lgtm.yml */, - 94CD84832D2D22C900041BBA /* .mdl_style.rb */, - 94CD84842D2D22C900041BBA /* .mdlrc */, - 94CD84852D2D22C900041BBA /* .readthedocs.yaml */, - 94CD84862D2D22C900041BBA /* aclocal.m4 */, - 94CD84872D2D22C900041BBA /* appveyor.yml */, - 94CD84882D2D22C900041BBA /* AUTHORS */, - 94CD84892D2D22C900041BBA /* autogen.sh */, - 94CD848A2D2D22C900041BBA /* BUILDING-cmake.md */, - 94CD848B2D2D22C900041BBA /* BUILDING-configure.md */, - 94CD848C2D2D22C900041BBA /* CMakeLists.txt */, - 94CD848D2D2D22C900041BBA /* compile_flags.in */, - 94CD848E2D2D22C900041BBA /* configitems */, - 94CD848F2D2D22C900041BBA /* configure */, - 94CD84902D2D22C900041BBA /* configure.ac */, - 94CD84912D2D22C900041BBA /* COPYING */, - 94CD84922D2D22C900041BBA /* cxx_features.txt */, - 94CD84932D2D22C900041BBA /* INSTALL */, - 94CD84942D2D22C900041BBA /* libpqxx.pc.in */, - 94CD84952D2D22C900041BBA /* Makefile.am */, - 94CD84962D2D22C900041BBA /* Makefile.in */, - 94CD84972D2D22C900041BBA /* NEWS */, - 94CD84982D2D22C900041BBA /* pqxx_cxx_feature_checks.ac */, - 94CD84992D2D22C900041BBA /* README.md */, - 94CD849A2D2D22C900041BBA /* README.rst */, - 94CD849B2D2D22C900041BBA /* requirements.json */, - 94CD849C2D2D22C900041BBA /* VERSION */, - ); - path = libpqxx; - sourceTree = ""; - }; - 94CD849E2D2D22C900041BBA /* external */ = { - isa = PBXGroup; - children = ( - 94685CCF2D384A8B00863D04 /* nlohmann */, - 94CD849D2D2D22C900041BBA /* libpqxx */, - ); - path = external; - sourceTree = ""; - }; - 94CD869E2D2D295900041BBA /* tmp */ = { - isa = PBXGroup; - children = ( - ); - path = tmp; - sourceTree = ""; - }; - 94CD86A12D2D295900041BBA /* CompilerIdCXX */ = { - isa = PBXGroup; - children = ( - 94CD869E2D2D295900041BBA /* tmp */, - 94CD869F2D2D295900041BBA /* CMakeCXXCompilerId.cpp */, - 94CD86A02D2D295900041BBA /* CMakeCXXCompilerId.o */, - ); - path = CompilerIdCXX; - sourceTree = ""; - }; - 94CD86A52D2D295900041BBA /* 3.30.3 */ = { - isa = PBXGroup; - children = ( - 94CD86A12D2D295900041BBA /* CompilerIdCXX */, - 94CD86A22D2D295900041BBA /* CMakeCXXCompiler.cmake */, - 94CD86A32D2D295900041BBA /* CMakeDetermineCompilerABI_CXX.bin */, - 94CD86A42D2D295900041BBA /* CMakeSystem.cmake */, - ); - path = 3.30.3; - sourceTree = ""; - }; - 94CD86A62D2D295900041BBA /* CMakeScratch */ = { - isa = PBXGroup; - children = ( - ); - path = CMakeScratch; - sourceTree = ""; - }; - 94CD86A72D2D295900041BBA /* CMakeTmp */ = { - isa = PBXGroup; - children = ( - ); - path = CMakeTmp; - sourceTree = ""; - }; - 94CD86AA2D2D295900041BBA /* d6b66e93f8212dd1f00debf9f6654819 */ = { - isa = PBXGroup; - children = ( - 94CD86A82D2D295900041BBA /* libpqxx-targets.cmake */, - 94CD86A92D2D295900041BBA /* libpqxx-targets-noconfig.cmake */, - ); - path = d6b66e93f8212dd1f00debf9f6654819; - sourceTree = ""; - }; - 94CD86AB2D2D295900041BBA /* Export */ = { - isa = PBXGroup; - children = ( - 94CD86AA2D2D295900041BBA /* d6b66e93f8212dd1f00debf9f6654819 */, - ); - path = Export; - sourceTree = ""; - }; - 94CD86AC2D2D295900041BBA /* pkgRedirects */ = { - isa = PBXGroup; - children = ( - ); - path = pkgRedirects; - sourceTree = ""; - }; - 94CD86B42D2D295900041BBA /* CMakeFiles */ = { - isa = PBXGroup; - children = ( - 94CD86A52D2D295900041BBA /* 3.30.3 */, - 94CD86A62D2D295900041BBA /* CMakeScratch */, - 94CD86A72D2D295900041BBA /* CMakeTmp */, - 94CD86AB2D2D295900041BBA /* Export */, - 94CD86AC2D2D295900041BBA /* pkgRedirects */, - 94CD86AD2D2D295900041BBA /* cmake.check_cache */, - 94CD86AE2D2D295900041BBA /* CMakeConfigureLog.yaml */, - 94CD86AF2D2D295900041BBA /* CMakeDirectoryInformation.cmake */, - 94CD86B02D2D295900041BBA /* Makefile.cmake */, - 94CD86B12D2D295900041BBA /* Makefile2 */, - 94CD86B22D2D295900041BBA /* progress.marks */, - 94CD86B32D2D295900041BBA /* TargetDirectories.txt */, - ); - path = CMakeFiles; - sourceTree = ""; - }; - 94CD86B72D2D295900041BBA /* CMakeFiles */ = { - isa = PBXGroup; - children = ( - 94CD86B52D2D295900041BBA /* CMakeDirectoryInformation.cmake */, - 94CD86B62D2D295900041BBA /* progress.marks */, - ); - path = CMakeFiles; - sourceTree = ""; - }; - 94CD86BC2D2D295900041BBA /* pqxx */ = { - isa = PBXGroup; - children = ( - 94CD86B82D2D295900041BBA /* config_cmake.h.in */, - 94CD86B92D2D295900041BBA /* config-internal-compiler.h */, - 94CD86BA2D2D295900041BBA /* config-internal-libpq.h */, - 94CD86BB2D2D295900041BBA /* config-public-compiler.h */, - ); - path = pqxx; - sourceTree = ""; - }; - 94CD86BF2D2D295900041BBA /* include */ = { - isa = PBXGroup; - children = ( - 94CD86B72D2D295900041BBA /* CMakeFiles */, - 94CD86BC2D2D295900041BBA /* pqxx */, - 94CD86BD2D2D295900041BBA /* cmake_install.cmake */, - 94CD86BE2D2D295900041BBA /* Makefile */, - ); - path = include; - sourceTree = ""; - }; - 94CD86CA2D2D295900041BBA /* pqxx.dir */ = { - isa = PBXGroup; - children = ( - 94CD86C02D2D295900041BBA /* build.make */, - 94CD86C12D2D295900041BBA /* cmake_clean.cmake */, - 94CD86C22D2D295900041BBA /* cmake_clean_target.cmake */, - 94CD86C32D2D295900041BBA /* compiler_depend.make */, - 94CD86C42D2D295900041BBA /* compiler_depend.ts */, - 94CD86C52D2D295900041BBA /* depend.make */, - 94CD86C62D2D295900041BBA /* DependInfo.cmake */, - 94CD86C72D2D295900041BBA /* flags.make */, - 94CD86C82D2D295900041BBA /* link.txt */, - 94CD86C92D2D295900041BBA /* progress.make */, - ); - path = pqxx.dir; - sourceTree = ""; - }; - 94CD86CD2D2D295900041BBA /* CMakeFiles */ = { - isa = PBXGroup; - children = ( - 94CD86CA2D2D295900041BBA /* pqxx.dir */, - 94CD86CB2D2D295900041BBA /* CMakeDirectoryInformation.cmake */, - 94CD86CC2D2D295900041BBA /* progress.marks */, - ); - path = CMakeFiles; - sourceTree = ""; - }; - 94CD86D02D2D295900041BBA /* src */ = { - isa = PBXGroup; - children = ( - 94CD86CD2D2D295900041BBA /* CMakeFiles */, - 94CD86CE2D2D295900041BBA /* cmake_install.cmake */, - 94CD86CF2D2D295900041BBA /* Makefile */, - ); - path = src; - sourceTree = ""; - }; - 94CD86D12D2D295900041BBA /* unit */ = { - isa = PBXGroup; - children = ( - ); - path = unit; - sourceTree = ""; - }; - 94CD86DB2D2D295900041BBA /* runner.dir */ = { - isa = PBXGroup; - children = ( - 94CD86D12D2D295900041BBA /* unit */, - 94CD86D22D2D295900041BBA /* build.make */, - 94CD86D32D2D295900041BBA /* cmake_clean.cmake */, - 94CD86D42D2D295900041BBA /* compiler_depend.make */, - 94CD86D52D2D295900041BBA /* compiler_depend.ts */, - 94CD86D62D2D295900041BBA /* depend.make */, - 94CD86D72D2D295900041BBA /* DependInfo.cmake */, - 94CD86D82D2D295900041BBA /* flags.make */, - 94CD86D92D2D295900041BBA /* link.txt */, - 94CD86DA2D2D295900041BBA /* progress.make */, - ); - path = runner.dir; - sourceTree = ""; - }; - 94CD86DE2D2D295900041BBA /* CMakeFiles */ = { - isa = PBXGroup; - children = ( - 94CD86DB2D2D295900041BBA /* runner.dir */, - 94CD86DC2D2D295900041BBA /* CMakeDirectoryInformation.cmake */, - 94CD86DD2D2D295900041BBA /* progress.marks */, - ); - path = CMakeFiles; - sourceTree = ""; - }; - 94CD86E22D2D295900041BBA /* test */ = { - isa = PBXGroup; - children = ( - 94CD86DE2D2D295900041BBA /* CMakeFiles */, - 94CD86DF2D2D295900041BBA /* cmake_install.cmake */, - 94CD86E02D2D295900041BBA /* CTestTestfile.cmake */, - 94CD86E12D2D295900041BBA /* Makefile */, - ); - path = test; - sourceTree = ""; - }; - 94CD86EC2D2D295900041BBA /* build */ = { - isa = PBXGroup; - children = ( - 94CD86B42D2D295900041BBA /* CMakeFiles */, - 94CD86BF2D2D295900041BBA /* include */, - 94CD86D02D2D295900041BBA /* src */, - 94CD86E22D2D295900041BBA /* test */, - 94CD86E32D2D295900041BBA /* cmake_install.cmake */, - 94CD86E42D2D295900041BBA /* CMakeCache.txt */, - 94CD86E52D2D295900041BBA /* CPackConfig.cmake */, - 94CD86E62D2D295900041BBA /* CPackSourceConfig.cmake */, - 94CD86E72D2D295900041BBA /* libpqxx.pc */, - 94CD86E82D2D295900041BBA /* libpqxx-config.cmake */, - 94CD86E92D2D295900041BBA /* libpqxx-config-version.cmake */, - 94CD86EA2D2D295900041BBA /* libpqxx-targets.cmake */, - 94CD86EB2D2D295900041BBA /* Makefile */, - ); - path = build; - sourceTree = ""; - }; - 94CD87342D2D2EE100041BBA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 942FDDE42FC5C9D30096F318 /* libcurl.4.tbd */, - 94CD8B982D2DCDD800041BBA /* libpqxx-7.10.a */, - 94CD8B9A2D2DCF6E00041BBA /* libpqxx-7.10.a */, - 94CD8B712D2D34C800041BBA /* config */, - 94CD8B942D2D34C800041BBA /* pgxs */, - 94CD8B762D2D34C800041BBA /* pkgconfig */, - 94CD8B832D2D34C800041BBA /* src */, - 94CD8AB92D2D34A300041BBA /* _int.so */, - 94CD8AC92D2D34A400041BBA /* adminpack.so */, - 94CD8AF82D2D34A700041BBA /* amcheck.so */, - 94CD8A952D2D34A100041BBA /* auth_delay.so */, - 94CD8AD12D2D34A400041BBA /* auto_explain.so */, - 94CD8AA72D2D34A200041BBA /* autoinc.so */, - 94CD8B022D2D34A800041BBA /* bloom.so */, - 94CD8AFF2D2D34A800041BBA /* bool_plperl.so */, - 94CD8AB22D2D34A200041BBA /* btree_gin.so */, - 94CD8ABD2D2D34A300041BBA /* btree_gist.so */, - 94CD8ACA2D2D34A400041BBA /* citext.so */, - 94CD8AF42D2D34A700041BBA /* cube.so */, - 94CD8AC02D2D34A300041BBA /* cyrillic_and_mic.so */, - 94CD8AA62D2D34A200041BBA /* dblink.so */, - 94CD8AAD2D2D34A200041BBA /* dict_int.so */, - 94CD8AB12D2D34A200041BBA /* dict_snowball.so */, - 94CD8AFB2D2D34A800041BBA /* dict_xsyn.so */, - 94CD8ACE2D2D34A400041BBA /* earthdistance.so */, - 94CD8AF22D2D34A500041BBA /* euc_cn_and_mic.so */, - 94CD8AC72D2D34A400041BBA /* euc_jp_and_sjis.so */, - 94CD8ADA2D2D34A500041BBA /* euc_kr_and_mic.so */, - 94CD8ADD2D2D34A500041BBA /* euc_tw_and_big5.so */, - 94CD8ABC2D2D34A300041BBA /* euc2004_sjis2004.so */, - 94CD8AD72D2D34A500041BBA /* file_fdw.so */, - 94CD8ACD2D2D34A400041BBA /* fuzzystrmatch.so */, - 94CD8AD42D2D34A500041BBA /* hstore.so */, - 94CD8A9C2D2D34A200041BBA /* hstore_plperl.so */, - 94CD8A942D2D34A100041BBA /* insert_username.so */, - 94CD8ABB2D2D34A300041BBA /* isn.so */, - 94CD8AD82D2D34A500041BBA /* jsonb_plperl.so */, - 94CD8AAA2D2D34A200041BBA /* latin_and_mic.so */, - 94CD8AC22D2D34A300041BBA /* latin2_and_win1250.so */, - 94CD8AF92D2D34A800041BBA /* libecpg.a */, - 94CD8ADF2D2D34A500041BBA /* libecpg_compat.a */, - 94CD8AF12D2D34A500041BBA /* libecpg_compat.3.14.dylib */, - 94CD8AC82D2D34A400041BBA /* libecpg.6.14.dylib */, - 94CD8AD22D2D34A400041BBA /* libpgcommon.a */, - 94CD8AB42D2D34A300041BBA /* libpgcommon_shlib.a */, - 94CD8AAC2D2D34A200041BBA /* libpgfeutils.a */, - 94CD8ADE2D2D34A500041BBA /* libpgport.a */, - 94CD8AB82D2D34A300041BBA /* libpgport_shlib.a */, - 94CD8ACF2D2D34A400041BBA /* libpgtypes.a */, - 94CD8AAF2D2D34A200041BBA /* libpgtypes.3.14.dylib */, - 94CD8A972D2D34A100041BBA /* libpq.a */, - 94CD8AD02D2D34A400041BBA /* libpq.5.14.dylib */, - 94CD8B012D2D34A800041BBA /* libpqwalreceiver.so */, - 94CD8AA52D2D34A200041BBA /* lo.so */, - 94CD8AC42D2D34A300041BBA /* ltree.so */, - 94CD8AA92D2D34A200041BBA /* moddatetime.so */, - 94CD8AF52D2D34A700041BBA /* old_snapshot.so */, - 94CD8A9A2D2D34A200041BBA /* pageinspect.so */, - 94CD8A962D2D34A100041BBA /* passwordcheck.so */, - 94CD8B032D2D34A800041BBA /* pg_buffercache.so */, - 94CD8A922D2D34A100041BBA /* pg_freespacemap.so */, - 94CD8AFA2D2D34A800041BBA /* pg_prewarm.so */, - 94CD8AF32D2D34A600041BBA /* pg_stat_statements.so */, - 94CD8ACB2D2D34A400041BBA /* pg_surgery.so */, - 94CD8A982D2D34A100041BBA /* pg_trgm.so */, - 94CD8ABF2D2D34A300041BBA /* pg_visibility.so */, - 94CD8A992D2D34A100041BBA /* pgcrypto.so */, - 94CD8A9B2D2D34A200041BBA /* pgoutput.so */, - 94CD8AAB2D2D34A200041BBA /* pgrowlocks.so */, - 94CD8AC52D2D34A400041BBA /* pgstattuple.so */, - 94CD8B002D2D34A800041BBA /* pgxml.so */, - 94CD8AF02D2D34A500041BBA /* pgxs */, - 94CD8AA32D2D34A200041BBA /* pkgconfig */, - 94CD8ACC2D2D34A400041BBA /* plperl.so */, - 94CD8A932D2D34A100041BBA /* plpgsql.so */, - 94CD8AB02D2D34A200041BBA /* pltcl.so */, - 94CD8AC32D2D34A300041BBA /* postgres_fdw.so */, - 94CD8ABE2D2D34A300041BBA /* refint.so */, - 94CD8AD62D2D34A500041BBA /* seg.so */, - 94CD8AFC2D2D34A800041BBA /* sslinfo.so */, - 94CD8AF62D2D34A700041BBA /* tablefunc.so */, - 94CD8B042D2D34A800041BBA /* tcn.so */, - 94CD8AD92D2D34A500041BBA /* test_decoding.so */, - 94CD8ABA2D2D34A300041BBA /* tsm_system_rows.so */, - 94CD8AA82D2D34A200041BBA /* tsm_system_time.so */, - 94CD8AD52D2D34A500041BBA /* unaccent.so */, - 94CD8AB32D2D34A300041BBA /* utf8_and_big5.so */, - 94CD8ADC2D2D34A500041BBA /* utf8_and_cyrillic.so */, - 94CD8AAE2D2D34A200041BBA /* utf8_and_euc_cn.so */, - 94CD8ADB2D2D34A500041BBA /* utf8_and_euc_jp.so */, - 94CD8AFE2D2D34A800041BBA /* utf8_and_euc_kr.so */, - 94CD8AA42D2D34A200041BBA /* utf8_and_euc_tw.so */, - 94CD8A912D2D34A100041BBA /* utf8_and_euc2004.so */, - 94CD8AC62D2D34A400041BBA /* utf8_and_gb18030.so */, - 94CD8A9D2D2D34A200041BBA /* utf8_and_gbk.so */, - 94CD8AB52D2D34A300041BBA /* utf8_and_iso8859.so */, - 94CD8AFD2D2D34A800041BBA /* utf8_and_iso8859_1.so */, - 94CD8AB62D2D34A300041BBA /* utf8_and_johab.so */, - 94CD8AC12D2D34A300041BBA /* utf8_and_sjis.so */, - 94CD8AF72D2D34A700041BBA /* utf8_and_sjis2004.so */, - 94CD8AB72D2D34A300041BBA /* utf8_and_uhc.so */, - 94CD8A9E2D2D34A200041BBA /* utf8_and_win.so */, - 94CD8AD32D2D34A400041BBA /* uuid-ossp.so */, - 94CD8A8F2D2D33FC00041BBA /* libpkgconf.pc */, - 94CD8A8C2D2D33E200041BBA /* libpkgconf.a */, - 94CD8A8B2D2D33E200041BBA /* libpkgconf.5.dylib */, - 94CD8A2C2D2D2FC200041BBA /* gates */, - 94CD8A072D2D2FAC00041BBA /* doc */, - 94CD89FA2D2D2FAC00041BBA /* internal */, - 94CD89822D2D2EE100041BBA /* libpqxx */, - ); - name = Frameworks; - sourceTree = ""; - }; - 94CD87362D2D2EE100041BBA /* .circleci */ = { - isa = PBXGroup; - children = ( - 94CD87352D2D2EE100041BBA /* config.yml */, - ); - path = .circleci; - sourceTree = ""; - }; - 94CD87392D2D2EE100041BBA /* workflows */ = { - isa = PBXGroup; - children = ( - 94CD87372D2D2EE100041BBA /* codeql.yml */, - 94CD87382D2D2EE100041BBA /* stale.yml */, - ); - path = workflows; - sourceTree = ""; - }; - 94CD873A2D2D2EE100041BBA /* .github */ = { - isa = PBXGroup; - children = ( - 94CD87392D2D2EE100041BBA /* workflows */, - ); - path = .github; - sourceTree = ""; - }; - 94CD873C2D2D2EE100041BBA /* .lift */ = { - isa = PBXGroup; - children = ( - 94CD873B2D2D2EE100041BBA /* ignoreFiles */, - ); - path = .lift; - sourceTree = ""; - }; - 94CD873D2D2D2EE100041BBA /* tmp */ = { - isa = PBXGroup; - children = ( - ); - path = tmp; - sourceTree = ""; - }; - 94CD87402D2D2EE100041BBA /* CompilerIdCXX */ = { - isa = PBXGroup; - children = ( - 94CD873D2D2D2EE100041BBA /* tmp */, - 94CD873E2D2D2EE100041BBA /* CMakeCXXCompilerId.cpp */, - 94CD873F2D2D2EE100041BBA /* CMakeCXXCompilerId.o */, - ); - path = CompilerIdCXX; - sourceTree = ""; - }; - 94CD87442D2D2EE100041BBA /* 3.30.3 */ = { - isa = PBXGroup; - children = ( - 94CD87402D2D2EE100041BBA /* CompilerIdCXX */, - 94CD87412D2D2EE100041BBA /* CMakeCXXCompiler.cmake */, - 94CD87422D2D2EE100041BBA /* CMakeDetermineCompilerABI_CXX.bin */, - 94CD87432D2D2EE100041BBA /* CMakeSystem.cmake */, - ); - path = 3.30.3; - sourceTree = ""; - }; - 94CD87452D2D2EE100041BBA /* CMakeScratch */ = { - isa = PBXGroup; - children = ( - ); - path = CMakeScratch; - sourceTree = ""; - }; - 94CD87462D2D2EE100041BBA /* CMakeTmp */ = { - isa = PBXGroup; - children = ( - ); - path = CMakeTmp; - sourceTree = ""; - }; - 94CD87492D2D2EE100041BBA /* d6b66e93f8212dd1f00debf9f6654819 */ = { - isa = PBXGroup; - children = ( - 94CD87472D2D2EE100041BBA /* libpqxx-targets.cmake */, - 94CD87482D2D2EE100041BBA /* libpqxx-targets-noconfig.cmake */, - ); - path = d6b66e93f8212dd1f00debf9f6654819; - sourceTree = ""; - }; - 94CD874A2D2D2EE100041BBA /* Export */ = { - isa = PBXGroup; - children = ( - 94CD87492D2D2EE100041BBA /* d6b66e93f8212dd1f00debf9f6654819 */, - ); - path = Export; - sourceTree = ""; - }; - 94CD874B2D2D2EE100041BBA /* pkgRedirects */ = { - isa = PBXGroup; - children = ( - ); - path = pkgRedirects; - sourceTree = ""; - }; - 94CD87532D2D2EE100041BBA /* CMakeFiles */ = { - isa = PBXGroup; - children = ( - 94CD87442D2D2EE100041BBA /* 3.30.3 */, - 94CD87452D2D2EE100041BBA /* CMakeScratch */, - 94CD87462D2D2EE100041BBA /* CMakeTmp */, - 94CD874A2D2D2EE100041BBA /* Export */, - 94CD874B2D2D2EE100041BBA /* pkgRedirects */, - 94CD874C2D2D2EE100041BBA /* cmake.check_cache */, - 94CD874D2D2D2EE100041BBA /* CMakeConfigureLog.yaml */, - 94CD874E2D2D2EE100041BBA /* CMakeDirectoryInformation.cmake */, - 94CD874F2D2D2EE100041BBA /* Makefile.cmake */, - 94CD87502D2D2EE100041BBA /* Makefile2 */, - 94CD87512D2D2EE100041BBA /* progress.marks */, - 94CD87522D2D2EE100041BBA /* TargetDirectories.txt */, - ); - path = CMakeFiles; - sourceTree = ""; - }; - 94CD87562D2D2EE100041BBA /* CMakeFiles */ = { - isa = PBXGroup; - children = ( - 94CD87542D2D2EE100041BBA /* CMakeDirectoryInformation.cmake */, - 94CD87552D2D2EE100041BBA /* progress.marks */, - ); - path = CMakeFiles; - sourceTree = ""; - }; - 94CD875B2D2D2EE100041BBA /* pqxx */ = { - isa = PBXGroup; - children = ( - 94CD87572D2D2EE100041BBA /* config_cmake.h.in */, - 94CD87582D2D2EE100041BBA /* config-internal-compiler.h */, - 94CD87592D2D2EE100041BBA /* config-internal-libpq.h */, - 94CD875A2D2D2EE100041BBA /* config-public-compiler.h */, - ); - path = pqxx; - sourceTree = ""; - }; - 94CD875E2D2D2EE100041BBA /* include */ = { - isa = PBXGroup; - children = ( - 94CD87562D2D2EE100041BBA /* CMakeFiles */, - 94CD875B2D2D2EE100041BBA /* pqxx */, - 94CD875C2D2D2EE100041BBA /* cmake_install.cmake */, - 94CD875D2D2D2EE100041BBA /* Makefile */, - ); - path = include; - sourceTree = ""; - }; - 94CD87692D2D2EE100041BBA /* pqxx.dir */ = { - isa = PBXGroup; - children = ( - 94CD875F2D2D2EE100041BBA /* build.make */, - 94CD87602D2D2EE100041BBA /* cmake_clean.cmake */, - 94CD87612D2D2EE100041BBA /* cmake_clean_target.cmake */, - 94CD87622D2D2EE100041BBA /* compiler_depend.make */, - 94CD87632D2D2EE100041BBA /* compiler_depend.ts */, - 94CD87642D2D2EE100041BBA /* depend.make */, - 94CD87652D2D2EE100041BBA /* DependInfo.cmake */, - 94CD87662D2D2EE100041BBA /* flags.make */, - 94CD87672D2D2EE100041BBA /* link.txt */, - 94CD87682D2D2EE100041BBA /* progress.make */, - ); - path = pqxx.dir; - sourceTree = ""; - }; - 94CD876C2D2D2EE100041BBA /* CMakeFiles */ = { - isa = PBXGroup; - children = ( - 94CD87692D2D2EE100041BBA /* pqxx.dir */, - 94CD876A2D2D2EE100041BBA /* CMakeDirectoryInformation.cmake */, - 94CD876B2D2D2EE100041BBA /* progress.marks */, - ); - path = CMakeFiles; - sourceTree = ""; - }; - 94CD876F2D2D2EE100041BBA /* src */ = { - isa = PBXGroup; - children = ( - 94CD876C2D2D2EE100041BBA /* CMakeFiles */, - 94CD876D2D2D2EE100041BBA /* cmake_install.cmake */, - 94CD876E2D2D2EE100041BBA /* Makefile */, - ); - path = src; - sourceTree = ""; - }; - 94CD87702D2D2EE100041BBA /* unit */ = { - isa = PBXGroup; - children = ( - ); - path = unit; - sourceTree = ""; - }; - 94CD877A2D2D2EE100041BBA /* runner.dir */ = { - isa = PBXGroup; - children = ( - 94CD87702D2D2EE100041BBA /* unit */, - 94CD87712D2D2EE100041BBA /* build.make */, - 94CD87722D2D2EE100041BBA /* cmake_clean.cmake */, - 94CD87732D2D2EE100041BBA /* compiler_depend.make */, - 94CD87742D2D2EE100041BBA /* compiler_depend.ts */, - 94CD87752D2D2EE100041BBA /* depend.make */, - 94CD87762D2D2EE100041BBA /* DependInfo.cmake */, - 94CD87772D2D2EE100041BBA /* flags.make */, - 94CD87782D2D2EE100041BBA /* link.txt */, - 94CD87792D2D2EE100041BBA /* progress.make */, - ); - path = runner.dir; - sourceTree = ""; - }; - 94CD877D2D2D2EE100041BBA /* CMakeFiles */ = { - isa = PBXGroup; - children = ( - 94CD877A2D2D2EE100041BBA /* runner.dir */, - 94CD877B2D2D2EE100041BBA /* CMakeDirectoryInformation.cmake */, - 94CD877C2D2D2EE100041BBA /* progress.marks */, - ); - path = CMakeFiles; - sourceTree = ""; - }; - 94CD87812D2D2EE100041BBA /* test */ = { - isa = PBXGroup; - children = ( - 94CD877D2D2D2EE100041BBA /* CMakeFiles */, - 94CD877E2D2D2EE100041BBA /* cmake_install.cmake */, - 94CD877F2D2D2EE100041BBA /* CTestTestfile.cmake */, - 94CD87802D2D2EE100041BBA /* Makefile */, - ); - path = test; - sourceTree = ""; - }; - 94CD878B2D2D2EE100041BBA /* build */ = { - isa = PBXGroup; - children = ( - 94CD87532D2D2EE100041BBA /* CMakeFiles */, - 94CD875E2D2D2EE100041BBA /* include */, - 94CD876F2D2D2EE100041BBA /* src */, - 94CD87812D2D2EE100041BBA /* test */, - 94CD87822D2D2EE100041BBA /* cmake_install.cmake */, - 94CD87832D2D2EE100041BBA /* CMakeCache.txt */, - 94CD87842D2D2EE100041BBA /* CPackConfig.cmake */, - 94CD87852D2D2EE100041BBA /* CPackSourceConfig.cmake */, - 94CD87862D2D2EE100041BBA /* libpqxx.pc */, - 94CD87872D2D2EE100041BBA /* libpqxx-config.cmake */, - 94CD87882D2D2EE100041BBA /* libpqxx-config-version.cmake */, - 94CD87892D2D2EE100041BBA /* libpqxx-targets.cmake */, - 94CD878A2D2D2EE100041BBA /* Makefile */, - ); - path = build; - sourceTree = ""; - }; - 94CD878F2D2D2EE100041BBA /* cmake */ = { - isa = PBXGroup; - children = ( - 94CD878C2D2D2EE100041BBA /* config.cmake */, - 94CD878D2D2D2EE100041BBA /* libpqxx-config.cmake */, - 94CD878E2D2D2EE100041BBA /* pqxx_cxx_feature_checks.cmake */, - ); - path = cmake; - sourceTree = ""; - }; - 94CD87962D2D2EE100041BBA /* m4 */ = { - isa = PBXGroup; - children = ( - 94CD87902D2D2EE100041BBA /* libtool.m4 */, - 94CD87912D2D2EE100041BBA /* lt~obsolete.m4 */, - 94CD87922D2D2EE100041BBA /* ltoptions.m4 */, - 94CD87932D2D2EE100041BBA /* ltsugar.m4 */, - 94CD87942D2D2EE100041BBA /* ltversion.m4 */, - 94CD87952D2D2EE100041BBA /* Makefile.am */, - ); - path = m4; - sourceTree = ""; - }; - 94CD87A32D2D2EE100041BBA /* config */ = { - isa = PBXGroup; - children = ( - 94CD87962D2D2EE100041BBA /* m4 */, - 94CD87972D2D2EE100041BBA /* compile */, - 94CD87982D2D2EE100041BBA /* config.guess */, - 94CD87992D2D2EE100041BBA /* config.sub */, - 94CD879A2D2D2EE100041BBA /* depcomp */, - 94CD879B2D2D2EE100041BBA /* install-sh */, - 94CD879C2D2D2EE100041BBA /* ltmain.sh */, - 94CD879D2D2D2EE100041BBA /* Makefile */, - 94CD879E2D2D2EE100041BBA /* Makefile.am */, - 94CD879F2D2D2EE100041BBA /* Makefile.in */, - 94CD87A02D2D2EE100041BBA /* missing */, - 94CD87A12D2D2EE100041BBA /* mkinstalldirs */, - 94CD87A22D2D2EE100041BBA /* test-driver */, - ); - path = config; - sourceTree = ""; - }; - 94CD87BA2D2D2EE100041BBA /* config-tests */ = { - isa = PBXGroup; - children = ( - 94CD87A42D2D2EE100041BBA /* no_need_fslib.cxx */, - 94CD87A52D2D2EE100041BBA /* PQXX_HAVE_ASSUME.cxx */, - 94CD87A62D2D2EE100041BBA /* PQXX_HAVE_CHARCONV_FLOAT.cxx */, - 94CD87A72D2D2EE100041BBA /* PQXX_HAVE_CHARCONV_INT.cxx */, - 94CD87A82D2D2EE100041BBA /* PQXX_HAVE_CMP.cxx */, - 94CD87A92D2D2EE100041BBA /* PQXX_HAVE_CONCEPTS.cxx */, - 94CD87AA2D2D2EE100041BBA /* PQXX_HAVE_CXA_DEMANGLE.cxx */, - 94CD87AB2D2D2EE100041BBA /* PQXX_HAVE_GCC_PURE.cxx */, - 94CD87AC2D2D2EE100041BBA /* PQXX_HAVE_GCC_VISIBILITY.cxx */, - 94CD87AD2D2D2EE100041BBA /* PQXX_HAVE_LIKELY.cxx */, - 94CD87AE2D2D2EE100041BBA /* PQXX_HAVE_MULTIDIM.cxx */, - 94CD87AF2D2D2EE100041BBA /* PQXX_HAVE_PATH.cxx */, - 94CD87B02D2D2EE100041BBA /* PQXX_HAVE_POLL.cxx */, - 94CD87B12D2D2EE100041BBA /* PQXX_HAVE_SLEEP_FOR.cxx */, - 94CD87B22D2D2EE100041BBA /* PQXX_HAVE_SOURCE_LOCATION.cxx */, - 94CD87B32D2D2EE100041BBA /* PQXX_HAVE_SPAN.cxx */, - 94CD87B42D2D2EE100041BBA /* PQXX_HAVE_SSIZE.cxx */, - 94CD87B52D2D2EE100041BBA /* PQXX_HAVE_STRERROR_R.cxx */, - 94CD87B62D2D2EE100041BBA /* PQXX_HAVE_STRERROR_S.cxx */, - 94CD87B72D2D2EE100041BBA /* PQXX_HAVE_THREAD_LOCAL.cxx */, - 94CD87B82D2D2EE100041BBA /* PQXX_HAVE_YEAR_MONTH_DAY.cxx */, - 94CD87B92D2D2EE100041BBA /* README.md */, - ); - path = "config-tests"; - sourceTree = ""; - }; - 94CD87BD2D2D2EE100041BBA /* source */ = { - isa = PBXGroup; - children = ( - 94CD87BB2D2D2EE100041BBA /* conf.py */, - 94CD87BC2D2D2EE100041BBA /* index.rst */, - ); - path = source; - sourceTree = ""; - }; - 94CD87C42D2D2EE100041BBA /* doc */ = { - isa = PBXGroup; - children = ( - 94CD87BD2D2D2EE100041BBA /* source */, - 94CD87BE2D2D2EE100041BBA /* CMakeLists.txt */, - 94CD87BF2D2D2EE100041BBA /* Doxyfile */, - 94CD87C02D2D2EE100041BBA /* Makefile */, - 94CD87C12D2D2EE100041BBA /* Makefile.am */, - 94CD87C22D2D2EE100041BBA /* Makefile.in */, - 94CD87C32D2D2EE100041BBA /* requirements.txt */, - ); - path = doc; - sourceTree = ""; - }; - 94CD87D12D2D2EE100041BBA /* doc */ = { - isa = PBXGroup; - children = ( - 94CD87C52D2D2EE100041BBA /* accessing-results.md */, - 94CD87C62D2D2EE100041BBA /* binary-data.md */, - 94CD87C72D2D2EE100041BBA /* datatypes.md */, - 94CD87C82D2D2EE100041BBA /* escaping.md */, - 94CD87C92D2D2EE100041BBA /* getting-started.md */, - 94CD87CA2D2D2EE100041BBA /* mainpage.md */, - 94CD87CB2D2D2EE100041BBA /* mainpage.md.template */, - 94CD87CC2D2D2EE100041BBA /* parameters.md */, - 94CD87CD2D2D2EE100041BBA /* performance.md */, - 94CD87CE2D2D2EE100041BBA /* prepared-statement.md */, - 94CD87CF2D2D2EE100041BBA /* streams.md */, - 94CD87D02D2D2EE100041BBA /* thread-safety.md */, - ); - path = doc; - sourceTree = ""; - }; - 94CD87E32D2D2EE100041BBA /* gates */ = { - isa = PBXGroup; - children = ( - 94CD87D22D2D2EE100041BBA /* connection-errorhandler.hxx */, - 94CD87D32D2D2EE100041BBA /* connection-largeobject.hxx */, - 94CD87D42D2D2EE100041BBA /* connection-notification_receiver.hxx */, - 94CD87D52D2D2EE100041BBA /* connection-pipeline.hxx */, - 94CD87D62D2D2EE100041BBA /* connection-sql_cursor.hxx */, - 94CD87D72D2D2EE100041BBA /* connection-stream_from.hxx */, - 94CD87D82D2D2EE100041BBA /* connection-stream_to.hxx */, - 94CD87D92D2D2EE100041BBA /* connection-transaction.hxx */, - 94CD87DA2D2D2EE100041BBA /* errorhandler-connection.hxx */, - 94CD87DB2D2D2EE100041BBA /* icursor_iterator-icursorstream.hxx */, - 94CD87DC2D2D2EE100041BBA /* icursorstream-icursor_iterator.hxx */, - 94CD87DD2D2D2EE100041BBA /* result-connection.hxx */, - 94CD87DE2D2D2EE100041BBA /* result-creation.hxx */, - 94CD87DF2D2D2EE100041BBA /* result-pipeline.hxx */, - 94CD87E02D2D2EE100041BBA /* result-sql_cursor.hxx */, - 94CD87E12D2D2EE100041BBA /* transaction-sql_cursor.hxx */, - 94CD87E22D2D2EE100041BBA /* transaction-transaction_focus.hxx */, - ); - path = gates; - sourceTree = ""; - }; - 94CD87F72D2D2EE100041BBA /* internal */ = { - isa = PBXGroup; - children = ( - 94CD87E32D2D2EE100041BBA /* gates */, - 94CD87E42D2D2EE100041BBA /* array-composite.hxx */, - 94CD87E52D2D2EE100041BBA /* callgate.hxx */, - 94CD87E62D2D2EE100041BBA /* concat.hxx */, - 94CD87E72D2D2EE100041BBA /* conversions.hxx */, - 94CD87E82D2D2EE100041BBA /* encoding_group.hxx */, - 94CD87E92D2D2EE100041BBA /* encodings.hxx */, - 94CD87EA2D2D2EE100041BBA /* header-post.hxx */, - 94CD87EB2D2D2EE100041BBA /* header-pre.hxx */, - 94CD87EC2D2D2EE100041BBA /* ignore-deprecated-post.hxx */, - 94CD87ED2D2D2EE100041BBA /* ignore-deprecated-pre.hxx */, - 94CD87EE2D2D2EE100041BBA /* libpq-forward.hxx */, - 94CD87EF2D2D2EE100041BBA /* result_iter.hxx */, - 94CD87F02D2D2EE100041BBA /* result_iterator.hxx */, - 94CD87F12D2D2EE100041BBA /* sql_cursor.hxx */, - 94CD87F22D2D2EE100041BBA /* statement_parameters.hxx */, - 94CD87F32D2D2EE100041BBA /* stream_iterator.hxx */, - 94CD87F42D2D2EE100041BBA /* stream_query.hxx */, - 94CD87F52D2D2EE100041BBA /* stream_query_impl.hxx */, - 94CD87F62D2D2EE100041BBA /* wait.hxx */, - ); - path = internal; - sourceTree = ""; - }; - 94CD884A2D2D2EE100041BBA /* pqxx */ = { - isa = PBXGroup; - children = ( - 94CD87D12D2D2EE100041BBA /* doc */, - 94CD87F72D2D2EE100041BBA /* internal */, - 94CD87F82D2D2EE100041BBA /* array.hxx */, - 94CD87F92D2D2EE100041BBA /* array */, - 94CD87FA2D2D2EE100041BBA /* binarystring.hxx */, - 94CD87FB2D2D2EE100041BBA /* binarystring */, - 94CD87FC2D2D2EE100041BBA /* blob.hxx */, - 94CD87FD2D2D2EE100041BBA /* blob */, - 94CD87FE2D2D2EE100041BBA /* composite.hxx */, - 94CD87FF2D2D2EE100041BBA /* composite */, - 94CD88002D2D2EE100041BBA /* config.h */, - 94CD88012D2D2EE100041BBA /* config-internal-autotools.h */, - 94CD88022D2D2EE100041BBA /* config-internal-compiler.h */, - 94CD88032D2D2EE100041BBA /* config-public-autotools.h */, - 94CD88042D2D2EE100041BBA /* config-public-compiler.h */, - 94CD88052D2D2EE100041BBA /* config.h.in */, - 94CD88062D2D2EE100041BBA /* connection.hxx */, - 94CD88072D2D2EE100041BBA /* connection */, - 94CD88082D2D2EE100041BBA /* cursor.hxx */, - 94CD88092D2D2EE100041BBA /* cursor */, - 94CD880A2D2D2EE100041BBA /* dbtransaction.hxx */, - 94CD880B2D2D2EE100041BBA /* dbtransaction */, - 94CD880C2D2D2EE100041BBA /* errorhandler.hxx */, - 94CD880D2D2D2EE100041BBA /* errorhandler */, - 94CD880E2D2D2EE100041BBA /* except.hxx */, - 94CD880F2D2D2EE100041BBA /* except */, - 94CD88102D2D2EE100041BBA /* field.hxx */, - 94CD88112D2D2EE100041BBA /* field */, - 94CD88122D2D2EE100041BBA /* isolation.hxx */, - 94CD88132D2D2EE100041BBA /* isolation */, - 94CD88142D2D2EE100041BBA /* largeobject.hxx */, - 94CD88152D2D2EE100041BBA /* largeobject */, - 94CD88162D2D2EE100041BBA /* Makefile */, - 94CD88172D2D2EE100041BBA /* Makefile.am */, - 94CD88182D2D2EE100041BBA /* Makefile.in */, - 94CD88192D2D2EE100041BBA /* nontransaction.hxx */, - 94CD881A2D2D2EE100041BBA /* nontransaction */, - 94CD881B2D2D2EE100041BBA /* notification.hxx */, - 94CD881C2D2D2EE100041BBA /* notification */, - 94CD881D2D2D2EE100041BBA /* params.hxx */, - 94CD881E2D2D2EE100041BBA /* params */, - 94CD881F2D2D2EE100041BBA /* pipeline.hxx */, - 94CD88202D2D2EE100041BBA /* pipeline */, - 94CD88212D2D2EE100041BBA /* pqxx */, - 94CD88222D2D2EE100041BBA /* prepared_statement.hxx */, - 94CD88232D2D2EE100041BBA /* prepared_statement */, - 94CD88242D2D2EE100041BBA /* range.hxx */, - 94CD88252D2D2EE100041BBA /* range */, - 94CD88262D2D2EE100041BBA /* result.hxx */, - 94CD88272D2D2EE100041BBA /* result */, - 94CD88282D2D2EE100041BBA /* robusttransaction.hxx */, - 94CD88292D2D2EE100041BBA /* robusttransaction */, - 94CD882A2D2D2EE100041BBA /* row.hxx */, - 94CD882B2D2D2EE100041BBA /* row */, - 94CD882C2D2D2EE100041BBA /* separated_list.hxx */, - 94CD882D2D2D2EE100041BBA /* separated_list */, - 94CD882E2D2D2EE100041BBA /* stamp-h1 */, - 94CD882F2D2D2EE100041BBA /* strconv.hxx */, - 94CD88302D2D2EE100041BBA /* strconv */, - 94CD88312D2D2EE100041BBA /* stream_from.hxx */, - 94CD88322D2D2EE100041BBA /* stream_from */, - 94CD88332D2D2EE100041BBA /* stream_to.hxx */, - 94CD88342D2D2EE100041BBA /* stream_to */, - 94CD88352D2D2EE100041BBA /* subtransaction.hxx */, - 94CD88362D2D2EE100041BBA /* subtransaction */, - 94CD88372D2D2EE100041BBA /* time.hxx */, - 94CD88382D2D2EE100041BBA /* time */, - 94CD88392D2D2EE100041BBA /* transaction.hxx */, - 94CD883A2D2D2EE100041BBA /* transaction */, - 94CD883B2D2D2EE100041BBA /* transaction_base.hxx */, - 94CD883C2D2D2EE100041BBA /* transaction_base */, - 94CD883D2D2D2EE100041BBA /* transaction_focus.hxx */, - 94CD883E2D2D2EE100041BBA /* transaction_focus */, - 94CD883F2D2D2EE100041BBA /* transactor.hxx */, - 94CD88402D2D2EE100041BBA /* transactor */, - 94CD88412D2D2EE100041BBA /* types.hxx */, - 94CD88422D2D2EE100041BBA /* types */, - 94CD88432D2D2EE100041BBA /* util.hxx */, - 94CD88442D2D2EE100041BBA /* util */, - 94CD88452D2D2EE100041BBA /* version.hxx */, - 94CD88462D2D2EE100041BBA /* version */, - 94CD88472D2D2EE100041BBA /* version.hxx.template */, - 94CD88482D2D2EE100041BBA /* zview.hxx */, - 94CD88492D2D2EE100041BBA /* zview */, - ); - path = pqxx; - sourceTree = ""; - }; - 94CD88502D2D2EE100041BBA /* include */ = { - isa = PBXGroup; - children = ( - 94CD884A2D2D2EE100041BBA /* pqxx */, - 94CD884B2D2D2EE100041BBA /* CMakeLists.txt */, - 94CD884C2D2D2EE100041BBA /* CMakeLists.txt.template */, - 94CD884D2D2D2EE100041BBA /* Makefile */, - 94CD884E2D2D2EE100041BBA /* Makefile.am */, - 94CD884F2D2D2EE100041BBA /* Makefile.in */, - ); - path = include; - sourceTree = ""; - }; - 94CD886C2D2D2EE100041BBA /* .deps */ = { - isa = PBXGroup; - children = ( - 94CD88512D2D2EE100041BBA /* array.Plo */, - 94CD88522D2D2EE100041BBA /* binarystring.Plo */, - 94CD88532D2D2EE100041BBA /* blob.Plo */, - 94CD88542D2D2EE100041BBA /* connection.Plo */, - 94CD88552D2D2EE100041BBA /* cursor.Plo */, - 94CD88562D2D2EE100041BBA /* encodings.Plo */, - 94CD88572D2D2EE100041BBA /* errorhandler.Plo */, - 94CD88582D2D2EE100041BBA /* except.Plo */, - 94CD88592D2D2EE100041BBA /* field.Plo */, - 94CD885A2D2D2EE100041BBA /* largeobject.Plo */, - 94CD885B2D2D2EE100041BBA /* notification.Plo */, - 94CD885C2D2D2EE100041BBA /* params.Plo */, - 94CD885D2D2D2EE100041BBA /* pipeline.Plo */, - 94CD885E2D2D2EE100041BBA /* result.Plo */, - 94CD885F2D2D2EE100041BBA /* robusttransaction.Plo */, - 94CD88602D2D2EE100041BBA /* row.Plo */, - 94CD88612D2D2EE100041BBA /* sql_cursor.Plo */, - 94CD88622D2D2EE100041BBA /* strconv.Plo */, - 94CD88632D2D2EE100041BBA /* stream_from.Plo */, - 94CD88642D2D2EE100041BBA /* stream_to.Plo */, - 94CD88652D2D2EE100041BBA /* subtransaction.Plo */, - 94CD88662D2D2EE100041BBA /* time.Plo */, - 94CD88672D2D2EE100041BBA /* transaction.Plo */, - 94CD88682D2D2EE100041BBA /* transaction_base.Plo */, - 94CD88692D2D2EE100041BBA /* util.Plo */, - 94CD886A2D2D2EE100041BBA /* version.Plo */, - 94CD886B2D2D2EE100041BBA /* wait.Plo */, - ); - path = .deps; - sourceTree = ""; - }; - 94CD888D2D2D2EE100041BBA /* src */ = { - isa = PBXGroup; - children = ( - 94CD886C2D2D2EE100041BBA /* .deps */, - 94CD886D2D2D2EE100041BBA /* array.cxx */, - 94CD886E2D2D2EE100041BBA /* binarystring.cxx */, - 94CD886F2D2D2EE100041BBA /* blob.cxx */, - 94CD88702D2D2EE100041BBA /* CMakeLists.txt */, - 94CD88712D2D2EE100041BBA /* connection.cxx */, - 94CD88722D2D2EE100041BBA /* cursor.cxx */, - 94CD88732D2D2EE100041BBA /* encodings.cxx */, - 94CD88742D2D2EE100041BBA /* errorhandler.cxx */, - 94CD88752D2D2EE100041BBA /* except.cxx */, - 94CD88762D2D2EE100041BBA /* field.cxx */, - 94CD88772D2D2EE100041BBA /* largeobject.cxx */, - 94CD88782D2D2EE100041BBA /* Makefile */, - 94CD88792D2D2EE100041BBA /* Makefile.am */, - 94CD887A2D2D2EE100041BBA /* Makefile.in */, - 94CD887B2D2D2EE100041BBA /* notification.cxx */, - 94CD887C2D2D2EE100041BBA /* params.cxx */, - 94CD887D2D2D2EE100041BBA /* pipeline.cxx */, - 94CD887E2D2D2EE100041BBA /* pqxx-source.hxx */, - 94CD887F2D2D2EE100041BBA /* result.cxx */, - 94CD88802D2D2EE100041BBA /* robusttransaction.cxx */, - 94CD88812D2D2EE100041BBA /* row.cxx */, - 94CD88822D2D2EE100041BBA /* sql_cursor.cxx */, - 94CD88832D2D2EE100041BBA /* strconv.cxx */, - 94CD88842D2D2EE100041BBA /* stream_from.cxx */, - 94CD88852D2D2EE100041BBA /* stream_to.cxx */, - 94CD88862D2D2EE100041BBA /* subtransaction.cxx */, - 94CD88872D2D2EE100041BBA /* time.cxx */, - 94CD88882D2D2EE100041BBA /* transaction.cxx */, - 94CD88892D2D2EE100041BBA /* transaction_base.cxx */, - 94CD888A2D2D2EE100041BBA /* util.cxx */, - 94CD888B2D2D2EE100041BBA /* version.cxx */, - 94CD888C2D2D2EE100041BBA /* wait.cxx */, - ); - path = src; - sourceTree = ""; - }; - 94CD88B82D2D2EE100041BBA /* .deps */ = { - isa = PBXGroup; - children = ( - 94CD888E2D2D2EE100041BBA /* runner.Po */, - 94CD888F2D2D2EE100041BBA /* test00.Po */, - 94CD88902D2D2EE100041BBA /* test01.Po */, - 94CD88912D2D2EE100041BBA /* test02.Po */, - 94CD88922D2D2EE100041BBA /* test04.Po */, - 94CD88932D2D2EE100041BBA /* test07.Po */, - 94CD88942D2D2EE100041BBA /* test10.Po */, - 94CD88952D2D2EE100041BBA /* test11.Po */, - 94CD88962D2D2EE100041BBA /* test13.Po */, - 94CD88972D2D2EE100041BBA /* test14.Po */, - 94CD88982D2D2EE100041BBA /* test16.Po */, - 94CD88992D2D2EE100041BBA /* test17.Po */, - 94CD889A2D2D2EE100041BBA /* test18.Po */, - 94CD889B2D2D2EE100041BBA /* test20.Po */, - 94CD889C2D2D2EE100041BBA /* test21.Po */, - 94CD889D2D2D2EE100041BBA /* test26.Po */, - 94CD889E2D2D2EE100041BBA /* test29.Po */, - 94CD889F2D2D2EE100041BBA /* test30.Po */, - 94CD88A02D2D2EE100041BBA /* test32.Po */, - 94CD88A12D2D2EE100041BBA /* test37.Po */, - 94CD88A22D2D2EE100041BBA /* test39.Po */, - 94CD88A32D2D2EE100041BBA /* test46.Po */, - 94CD88A42D2D2EE100041BBA /* test56.Po */, - 94CD88A52D2D2EE100041BBA /* test60.Po */, - 94CD88A62D2D2EE100041BBA /* test61.Po */, - 94CD88A72D2D2EE100041BBA /* test62.Po */, - 94CD88A82D2D2EE100041BBA /* test69.Po */, - 94CD88A92D2D2EE100041BBA /* test70.Po */, - 94CD88AA2D2D2EE100041BBA /* test71.Po */, - 94CD88AB2D2D2EE100041BBA /* test72.Po */, - 94CD88AC2D2D2EE100041BBA /* test74.Po */, - 94CD88AD2D2D2EE100041BBA /* test75.Po */, - 94CD88AE2D2D2EE100041BBA /* test76.Po */, - 94CD88AF2D2D2EE100041BBA /* test77.Po */, - 94CD88B02D2D2EE100041BBA /* test78.Po */, - 94CD88B12D2D2EE100041BBA /* test79.Po */, - 94CD88B22D2D2EE100041BBA /* test82.Po */, - 94CD88B32D2D2EE100041BBA /* test84.Po */, - 94CD88B42D2D2EE100041BBA /* test87.Po */, - 94CD88B52D2D2EE100041BBA /* test88.Po */, - 94CD88B62D2D2EE100041BBA /* test89.Po */, - 94CD88B72D2D2EE100041BBA /* test90.Po */, - ); - path = .deps; - sourceTree = ""; - }; - 94CD88E62D2D2EE100041BBA /* .deps */ = { - isa = PBXGroup; - children = ( - 94CD88B92D2D2EE100041BBA /* test_array.Po */, - 94CD88BA2D2D2EE100041BBA /* test_binarystring.Po */, - 94CD88BB2D2D2EE100041BBA /* test_blob.Po */, - 94CD88BC2D2D2EE100041BBA /* test_cancel_query.Po */, - 94CD88BD2D2D2EE100041BBA /* test_column.Po */, - 94CD88BE2D2D2EE100041BBA /* test_composite.Po */, - 94CD88BF2D2D2EE100041BBA /* test_connection.Po */, - 94CD88C02D2D2EE100041BBA /* test_cursor.Po */, - 94CD88C12D2D2EE100041BBA /* test_encodings.Po */, - 94CD88C22D2D2EE100041BBA /* test_error_verbosity.Po */, - 94CD88C32D2D2EE100041BBA /* test_errorhandler.Po */, - 94CD88C42D2D2EE100041BBA /* test_escape.Po */, - 94CD88C52D2D2EE100041BBA /* test_exceptions.Po */, - 94CD88C62D2D2EE100041BBA /* test_field.Po */, - 94CD88C72D2D2EE100041BBA /* test_float.Po */, - 94CD88C82D2D2EE100041BBA /* test_largeobject.Po */, - 94CD88C92D2D2EE100041BBA /* test_nonblocking_connect.Po */, - 94CD88CA2D2D2EE100041BBA /* test_notice_handler.Po */, - 94CD88CB2D2D2EE100041BBA /* test_notification.Po */, - 94CD88CC2D2D2EE100041BBA /* test_pipeline.Po */, - 94CD88CD2D2D2EE100041BBA /* test_prepared_statement.Po */, - 94CD88CE2D2D2EE100041BBA /* test_range.Po */, - 94CD88CF2D2D2EE100041BBA /* test_read_transaction.Po */, - 94CD88D02D2D2EE100041BBA /* test_result_iteration.Po */, - 94CD88D12D2D2EE100041BBA /* test_result_slicing.Po */, - 94CD88D22D2D2EE100041BBA /* test_row.Po */, - 94CD88D32D2D2EE100041BBA /* test_separated_list.Po */, - 94CD88D42D2D2EE100041BBA /* test_simultaneous_transactions.Po */, - 94CD88D52D2D2EE100041BBA /* test_sql_cursor.Po */, - 94CD88D62D2D2EE100041BBA /* test_stateless_cursor.Po */, - 94CD88D72D2D2EE100041BBA /* test_strconv.Po */, - 94CD88D82D2D2EE100041BBA /* test_stream_from.Po */, - 94CD88D92D2D2EE100041BBA /* test_stream_query.Po */, - 94CD88DA2D2D2EE100041BBA /* test_stream_to.Po */, - 94CD88DB2D2D2EE100041BBA /* test_string_conversion.Po */, - 94CD88DC2D2D2EE100041BBA /* test_subtransaction.Po */, - 94CD88DD2D2D2EE100041BBA /* test_test_helpers.Po */, - 94CD88DE2D2D2EE100041BBA /* test_thread_safety_model.Po */, - 94CD88DF2D2D2EE100041BBA /* test_time.Po */, - 94CD88E02D2D2EE100041BBA /* test_transaction.Po */, - 94CD88E12D2D2EE100041BBA /* test_transaction_base.Po */, - 94CD88E22D2D2EE100041BBA /* test_transaction_focus.Po */, - 94CD88E32D2D2EE100041BBA /* test_transactor.Po */, - 94CD88E42D2D2EE100041BBA /* test_type_name.Po */, - 94CD88E52D2D2EE100041BBA /* test_zview.Po */, - ); - path = .deps; - sourceTree = ""; - }; - 94CD89152D2D2EE100041BBA /* unit */ = { - isa = PBXGroup; - children = ( - 94CD88E62D2D2EE100041BBA /* .deps */, - 94CD88E72D2D2EE100041BBA /* CMakeLists.txt */, - 94CD88E82D2D2EE100041BBA /* test_array.cxx */, - 94CD88E92D2D2EE100041BBA /* test_binarystring.cxx */, - 94CD88EA2D2D2EE100041BBA /* test_blob.cxx */, - 94CD88EB2D2D2EE100041BBA /* test_cancel_query.cxx */, - 94CD88EC2D2D2EE100041BBA /* test_column.cxx */, - 94CD88ED2D2D2EE100041BBA /* test_composite.cxx */, - 94CD88EE2D2D2EE100041BBA /* test_connection.cxx */, - 94CD88EF2D2D2EE100041BBA /* test_cursor.cxx */, - 94CD88F02D2D2EE100041BBA /* test_encodings.cxx */, - 94CD88F12D2D2EE100041BBA /* test_error_verbosity.cxx */, - 94CD88F22D2D2EE100041BBA /* test_errorhandler.cxx */, - 94CD88F32D2D2EE100041BBA /* test_escape.cxx */, - 94CD88F42D2D2EE100041BBA /* test_exceptions.cxx */, - 94CD88F52D2D2EE100041BBA /* test_field.cxx */, - 94CD88F62D2D2EE100041BBA /* test_float.cxx */, - 94CD88F72D2D2EE100041BBA /* test_largeobject.cxx */, - 94CD88F82D2D2EE100041BBA /* test_nonblocking_connect.cxx */, - 94CD88F92D2D2EE100041BBA /* test_notice_handler.cxx */, - 94CD88FA2D2D2EE100041BBA /* test_notification.cxx */, - 94CD88FB2D2D2EE100041BBA /* test_pipeline.cxx */, - 94CD88FC2D2D2EE100041BBA /* test_prepared_statement.cxx */, - 94CD88FD2D2D2EE100041BBA /* test_range.cxx */, - 94CD88FE2D2D2EE100041BBA /* test_read_transaction.cxx */, - 94CD88FF2D2D2EE100041BBA /* test_result_iteration.cxx */, - 94CD89002D2D2EE100041BBA /* test_result_slicing.cxx */, - 94CD89012D2D2EE100041BBA /* test_row.cxx */, - 94CD89022D2D2EE100041BBA /* test_separated_list.cxx */, - 94CD89032D2D2EE100041BBA /* test_simultaneous_transactions.cxx */, - 94CD89042D2D2EE100041BBA /* test_sql_cursor.cxx */, - 94CD89052D2D2EE100041BBA /* test_stateless_cursor.cxx */, - 94CD89062D2D2EE100041BBA /* test_strconv.cxx */, - 94CD89072D2D2EE100041BBA /* test_stream_from.cxx */, - 94CD89082D2D2EE100041BBA /* test_stream_query.cxx */, - 94CD89092D2D2EE100041BBA /* test_stream_to.cxx */, - 94CD890A2D2D2EE100041BBA /* test_string_conversion.cxx */, - 94CD890B2D2D2EE100041BBA /* test_subtransaction.cxx */, - 94CD890C2D2D2EE100041BBA /* test_test_helpers.cxx */, - 94CD890D2D2D2EE100041BBA /* test_thread_safety_model.cxx */, - 94CD890E2D2D2EE100041BBA /* test_time.cxx */, - 94CD890F2D2D2EE100041BBA /* test_transaction.cxx */, - 94CD89102D2D2EE100041BBA /* test_transaction_base.cxx */, - 94CD89112D2D2EE100041BBA /* test_transaction_focus.cxx */, - 94CD89122D2D2EE100041BBA /* test_transactor.cxx */, - 94CD89132D2D2EE100041BBA /* test_type_name.cxx */, - 94CD89142D2D2EE100041BBA /* test_zview.cxx */, - ); - path = unit; - sourceTree = ""; - }; - 94CD89472D2D2EE100041BBA /* test */ = { - isa = PBXGroup; - children = ( - 94CD88B82D2D2EE100041BBA /* .deps */, - 94CD89152D2D2EE100041BBA /* unit */, - 94CD89162D2D2EE100041BBA /* CMakeLists.txt */, - 94CD89172D2D2EE100041BBA /* Makefile */, - 94CD89182D2D2EE100041BBA /* Makefile.am */, - 94CD89192D2D2EE100041BBA /* Makefile.in */, - 94CD891A2D2D2EE100041BBA /* Makefile.am.template */, - 94CD891B2D2D2EE100041BBA /* runner.cxx */, - 94CD891C2D2D2EE100041BBA /* test_helpers.hxx */, - 94CD891D2D2D2EE100041BBA /* test_types.hxx */, - 94CD891E2D2D2EE100041BBA /* test00.cxx */, - 94CD891F2D2D2EE100041BBA /* test01.cxx */, - 94CD89202D2D2EE100041BBA /* test02.cxx */, - 94CD89212D2D2EE100041BBA /* test04.cxx */, - 94CD89222D2D2EE100041BBA /* test07.cxx */, - 94CD89232D2D2EE100041BBA /* test10.cxx */, - 94CD89242D2D2EE100041BBA /* test11.cxx */, - 94CD89252D2D2EE100041BBA /* test13.cxx */, - 94CD89262D2D2EE100041BBA /* test14.cxx */, - 94CD89272D2D2EE100041BBA /* test16.cxx */, - 94CD89282D2D2EE100041BBA /* test17.cxx */, - 94CD89292D2D2EE100041BBA /* test18.cxx */, - 94CD892A2D2D2EE100041BBA /* test20.cxx */, - 94CD892B2D2D2EE100041BBA /* test21.cxx */, - 94CD892C2D2D2EE100041BBA /* test26.cxx */, - 94CD892D2D2D2EE100041BBA /* test29.cxx */, - 94CD892E2D2D2EE100041BBA /* test30.cxx */, - 94CD892F2D2D2EE100041BBA /* test32.cxx */, - 94CD89302D2D2EE100041BBA /* test37.cxx */, - 94CD89312D2D2EE100041BBA /* test39.cxx */, - 94CD89322D2D2EE100041BBA /* test46.cxx */, - 94CD89332D2D2EE100041BBA /* test56.cxx */, - 94CD89342D2D2EE100041BBA /* test60.cxx */, - 94CD89352D2D2EE100041BBA /* test61.cxx */, - 94CD89362D2D2EE100041BBA /* test62.cxx */, - 94CD89372D2D2EE100041BBA /* test69.cxx */, - 94CD89382D2D2EE100041BBA /* test70.cxx */, - 94CD89392D2D2EE100041BBA /* test71.cxx */, - 94CD893A2D2D2EE100041BBA /* test72.cxx */, - 94CD893B2D2D2EE100041BBA /* test74.cxx */, - 94CD893C2D2D2EE100041BBA /* test75.cxx */, - 94CD893D2D2D2EE100041BBA /* test76.cxx */, - 94CD893E2D2D2EE100041BBA /* test77.cxx */, - 94CD893F2D2D2EE100041BBA /* test78.cxx */, - 94CD89402D2D2EE100041BBA /* test79.cxx */, - 94CD89412D2D2EE100041BBA /* test82.cxx */, - 94CD89422D2D2EE100041BBA /* test84.cxx */, - 94CD89432D2D2EE100041BBA /* test87.cxx */, - 94CD89442D2D2EE100041BBA /* test88.cxx */, - 94CD89452D2D2EE100041BBA /* test89.cxx */, - 94CD89462D2D2EE100041BBA /* test90.cxx */, - ); - path = test; - sourceTree = ""; - }; - 94CD894A2D2D2EE100041BBA /* .deps */ = { - isa = PBXGroup; - children = ( - 94CD89482D2D2EE100041BBA /* pqxxthreadsafety.Po */, - 94CD89492D2D2EE100041BBA /* rmlo.Po */, - ); - path = .deps; - sourceTree = ""; - }; - 94CD895C2D2D2EE100041BBA /* tools */ = { - isa = PBXGroup; - children = ( - 94CD894A2D2D2EE100041BBA /* .deps */, - 94CD894B2D2D2EE100041BBA /* deprecations */, - 94CD894C2D2D2EE100041BBA /* extract_version */, - 94CD894D2D2D2EE100041BBA /* format */, - 94CD894E2D2D2EE100041BBA /* generate_check_config.py */, - 94CD894F2D2D2EE100041BBA /* generate_cxx_checks.py */, - 94CD89502D2D2EE100041BBA /* lint */, - 94CD89512D2D2EE100041BBA /* m4esc.py */, - 94CD89522D2D2EE100041BBA /* Makefile */, - 94CD89532D2D2EE100041BBA /* Makefile.am */, - 94CD89542D2D2EE100041BBA /* Makefile.in */, - 94CD89552D2D2EE100041BBA /* pqxxthreadsafety.cxx */, - 94CD89562D2D2EE100041BBA /* rmlo.cxx */, - 94CD89572D2D2EE100041BBA /* splitconfig.py */, - 94CD89582D2D2EE100041BBA /* template2mak.py */, - 94CD89592D2D2EE100041BBA /* test_all.py */, - 94CD895A2D2D2EE100041BBA /* todo */, - 94CD895B2D2D2EE100041BBA /* update-copyright */, - ); - path = tools; - sourceTree = ""; - }; - 94CD89822D2D2EE100041BBA /* libpqxx */ = { - isa = PBXGroup; - children = ( - 94CD87362D2D2EE100041BBA /* .circleci */, - 94CD873A2D2D2EE100041BBA /* .github */, - 94CD873C2D2D2EE100041BBA /* .lift */, - 94CD878B2D2D2EE100041BBA /* build */, - 94CD878F2D2D2EE100041BBA /* cmake */, - 94CD87A32D2D2EE100041BBA /* config */, - 94CD87BA2D2D2EE100041BBA /* config-tests */, - 94CD87C42D2D2EE100041BBA /* doc */, - 94CD88502D2D2EE100041BBA /* include */, - 94CD888D2D2D2EE100041BBA /* src */, - 94CD89472D2D2EE100041BBA /* test */, - 94CD895C2D2D2EE100041BBA /* tools */, - 94CD895D2D2D2EE100041BBA /* .clang-format */, - 94CD895E2D2D2EE100041BBA /* .clang-tidy */, - 94CD895F2D2D2EE100041BBA /* .cmake-format */, - 94CD89602D2D2EE100041BBA /* .gitignore */, - 94CD89612D2D2EE100041BBA /* .lgtm.yml */, - 94CD89622D2D2EE100041BBA /* .mdl_style.rb */, - 94CD89632D2D2EE100041BBA /* .mdlrc */, - 94CD89642D2D2EE100041BBA /* .readthedocs.yaml */, - 94CD89652D2D2EE100041BBA /* aclocal.m4 */, - 94CD89662D2D2EE100041BBA /* appveyor.yml */, - 94CD89672D2D2EE100041BBA /* AUTHORS */, - 94CD89682D2D2EE100041BBA /* autogen.sh */, - 94CD89692D2D2EE100041BBA /* BUILDING-cmake.md */, - 94CD896A2D2D2EE100041BBA /* BUILDING-configure.md */, - 94CD896B2D2D2EE100041BBA /* CMakeLists.txt */, - 94CD896C2D2D2EE100041BBA /* compile_flags */, - 94CD896D2D2D2EE100041BBA /* compile_flags.in */, - 94CD896E2D2D2EE100041BBA /* config.log */, - 94CD896F2D2D2EE100041BBA /* config.status */, - 94CD89702D2D2EE100041BBA /* configitems */, - 94CD89712D2D2EE100041BBA /* configure */, - 94CD89722D2D2EE100041BBA /* configure.ac */, - 94CD89732D2D2EE100041BBA /* COPYING */, - 94CD89742D2D2EE100041BBA /* cxx_features.txt */, - 94CD89752D2D2EE100041BBA /* INSTALL */, - 94CD89762D2D2EE100041BBA /* libpqxx.pc */, - 94CD89772D2D2EE100041BBA /* libpqxx.pc.in */, - 94CD89782D2D2EE100041BBA /* libtool */, - 94CD89792D2D2EE100041BBA /* Makefile */, - 94CD897A2D2D2EE100041BBA /* Makefile.am */, - 94CD897B2D2D2EE100041BBA /* Makefile.in */, - 94CD897C2D2D2EE100041BBA /* NEWS */, - 94CD897D2D2D2EE100041BBA /* pqxx_cxx_feature_checks.ac */, - 94CD897E2D2D2EE100041BBA /* README.md */, - 94CD897F2D2D2EE100041BBA /* README.rst */, - 94CD89802D2D2EE100041BBA /* requirements.json */, - 94CD89812D2D2EE100041BBA /* VERSION */, - ); - name = libpqxx; - path = external/libpqxx; - sourceTree = ""; - }; - 94CD89E62D2D2FAC00041BBA /* gates */ = { - isa = PBXGroup; - children = ( - 94CD89D52D2D2FAC00041BBA /* connection-errorhandler.hxx */, - 94CD89D62D2D2FAC00041BBA /* connection-largeobject.hxx */, - 94CD89D72D2D2FAC00041BBA /* connection-notification_receiver.hxx */, - 94CD89D82D2D2FAC00041BBA /* connection-pipeline.hxx */, - 94CD89D92D2D2FAC00041BBA /* connection-sql_cursor.hxx */, - 94CD89DA2D2D2FAC00041BBA /* connection-stream_from.hxx */, - 94CD89DB2D2D2FAC00041BBA /* connection-stream_to.hxx */, - 94CD89DC2D2D2FAC00041BBA /* connection-transaction.hxx */, - 94CD89DD2D2D2FAC00041BBA /* errorhandler-connection.hxx */, - 94CD89DE2D2D2FAC00041BBA /* icursor_iterator-icursorstream.hxx */, - 94CD89DF2D2D2FAC00041BBA /* icursorstream-icursor_iterator.hxx */, - 94CD89E02D2D2FAC00041BBA /* result-connection.hxx */, - 94CD89E12D2D2FAC00041BBA /* result-creation.hxx */, - 94CD89E22D2D2FAC00041BBA /* result-pipeline.hxx */, - 94CD89E32D2D2FAC00041BBA /* result-sql_cursor.hxx */, - 94CD89E42D2D2FAC00041BBA /* transaction-sql_cursor.hxx */, - 94CD89E52D2D2FAC00041BBA /* transaction-transaction_focus.hxx */, - ); - path = gates; - sourceTree = ""; - }; - 94CD89FA2D2D2FAC00041BBA /* internal */ = { - isa = PBXGroup; - children = ( - 94CD89E62D2D2FAC00041BBA /* gates */, - 94CD89E72D2D2FAC00041BBA /* array-composite.hxx */, - 94CD89E82D2D2FAC00041BBA /* callgate.hxx */, - 94CD89E92D2D2FAC00041BBA /* concat.hxx */, - 94CD89EA2D2D2FAC00041BBA /* conversions.hxx */, - 94CD89EB2D2D2FAC00041BBA /* encoding_group.hxx */, - 94CD89EC2D2D2FAC00041BBA /* encodings.hxx */, - 94CD89ED2D2D2FAC00041BBA /* header-post.hxx */, - 94CD89EE2D2D2FAC00041BBA /* header-pre.hxx */, - 94CD89EF2D2D2FAC00041BBA /* ignore-deprecated-post.hxx */, - 94CD89F02D2D2FAC00041BBA /* ignore-deprecated-pre.hxx */, - 94CD89F12D2D2FAC00041BBA /* libpq-forward.hxx */, - 94CD89F22D2D2FAC00041BBA /* result_iter.hxx */, - 94CD89F32D2D2FAC00041BBA /* result_iterator.hxx */, - 94CD89F42D2D2FAC00041BBA /* sql_cursor.hxx */, - 94CD89F52D2D2FAC00041BBA /* statement_parameters.hxx */, - 94CD89F62D2D2FAC00041BBA /* stream_iterator.hxx */, - 94CD89F72D2D2FAC00041BBA /* stream_query.hxx */, - 94CD89F82D2D2FAC00041BBA /* stream_query_impl.hxx */, - 94CD89F92D2D2FAC00041BBA /* wait.hxx */, - ); - name = internal; - path = external/libpqxx/include/pqxx/internal; - sourceTree = ""; - }; - 94CD8A072D2D2FAC00041BBA /* doc */ = { - isa = PBXGroup; - children = ( - 94CD89FB2D2D2FAC00041BBA /* accessing-results.md */, - 94CD89FC2D2D2FAC00041BBA /* binary-data.md */, - 94CD89FD2D2D2FAC00041BBA /* datatypes.md */, - 94CD89FE2D2D2FAC00041BBA /* escaping.md */, - 94CD89FF2D2D2FAC00041BBA /* getting-started.md */, - 94CD8A002D2D2FAC00041BBA /* mainpage.md */, - 94CD8A012D2D2FAC00041BBA /* mainpage.md.template */, - 94CD8A022D2D2FAC00041BBA /* parameters.md */, - 94CD8A032D2D2FAC00041BBA /* performance.md */, - 94CD8A042D2D2FAC00041BBA /* prepared-statement.md */, - 94CD8A052D2D2FAC00041BBA /* streams.md */, - 94CD8A062D2D2FAC00041BBA /* thread-safety.md */, - ); - name = doc; - path = external/libpqxx/include/pqxx/doc; - sourceTree = ""; - }; - 94CD8A2C2D2D2FC200041BBA /* gates */ = { - isa = PBXGroup; - children = ( - 94CD8A1B2D2D2FC200041BBA /* connection-errorhandler.hxx */, - 94CD8A1C2D2D2FC200041BBA /* connection-largeobject.hxx */, - 94CD8A1D2D2D2FC200041BBA /* connection-notification_receiver.hxx */, - 94CD8A1E2D2D2FC200041BBA /* connection-pipeline.hxx */, - 94CD8A1F2D2D2FC200041BBA /* connection-sql_cursor.hxx */, - 94CD8A202D2D2FC200041BBA /* connection-stream_from.hxx */, - 94CD8A212D2D2FC200041BBA /* connection-stream_to.hxx */, - 94CD8A222D2D2FC200041BBA /* connection-transaction.hxx */, - 94CD8A232D2D2FC200041BBA /* errorhandler-connection.hxx */, - 94CD8A242D2D2FC200041BBA /* icursor_iterator-icursorstream.hxx */, - 94CD8A252D2D2FC200041BBA /* icursorstream-icursor_iterator.hxx */, - 94CD8A262D2D2FC200041BBA /* result-connection.hxx */, - 94CD8A272D2D2FC200041BBA /* result-creation.hxx */, - 94CD8A282D2D2FC200041BBA /* result-pipeline.hxx */, - 94CD8A292D2D2FC200041BBA /* result-sql_cursor.hxx */, - 94CD8A2A2D2D2FC200041BBA /* transaction-sql_cursor.hxx */, - 94CD8A2B2D2D2FC200041BBA /* transaction-transaction_focus.hxx */, - ); - name = gates; - path = external/libpqxx/include/pqxx/internal/gates; - sourceTree = ""; - }; - 94CD8AA32D2D34A200041BBA /* pkgconfig */ = { - isa = PBXGroup; - children = ( - 94CD8A9F2D2D34A200041BBA /* libecpg.pc */, - 94CD8AA02D2D34A200041BBA /* libecpg_compat.pc */, - 94CD8AA12D2D34A200041BBA /* libpgtypes.pc */, - 94CD8AA22D2D34A200041BBA /* libpq.pc */, - ); - name = pkgconfig; - path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pkgconfig"; - sourceTree = ""; - }; - 94CD8AE22D2D34A500041BBA /* config */ = { - isa = PBXGroup; - children = ( - 94CD8AE02D2D34A500041BBA /* install-sh */, - 94CD8AE12D2D34A500041BBA /* missing */, - ); - path = config; - sourceTree = ""; - }; - 94CD8AE42D2D34A500041BBA /* makefiles */ = { - isa = PBXGroup; - children = ( - 94CD8AE32D2D34A500041BBA /* pgxs.mk */, - ); - path = makefiles; - sourceTree = ""; - }; - 94CD8AE72D2D34A500041BBA /* isolation */ = { - isa = PBXGroup; - children = ( - 94CD8AE52D2D34A500041BBA /* isolationtester */, - 94CD8AE62D2D34A500041BBA /* pg_isolation_regress */, - ); - path = isolation; - sourceTree = ""; - }; - 94CD8AE92D2D34A500041BBA /* regress */ = { - isa = PBXGroup; - children = ( - 94CD8AE82D2D34A500041BBA /* pg_regress */, - ); - path = regress; - sourceTree = ""; - }; - 94CD8AEA2D2D34A500041BBA /* test */ = { - isa = PBXGroup; - children = ( - 94CD8AE72D2D34A500041BBA /* isolation */, - 94CD8AE92D2D34A500041BBA /* regress */, - ); - path = test; - sourceTree = ""; - }; - 94CD8AEF2D2D34A500041BBA /* src */ = { - isa = PBXGroup; - children = ( - 94CD8AE42D2D34A500041BBA /* makefiles */, - 94CD8AEA2D2D34A500041BBA /* test */, - 94CD8AEB2D2D34A500041BBA /* Makefile.global */, - 94CD8AEC2D2D34A500041BBA /* Makefile.port */, - 94CD8AED2D2D34A500041BBA /* Makefile.shlib */, - 94CD8AEE2D2D34A500041BBA /* nls-global.mk */, - ); - path = src; - sourceTree = ""; - }; - 94CD8AF02D2D34A500041BBA /* pgxs */ = { - isa = PBXGroup; - children = ( - 94CD8AE22D2D34A500041BBA /* config */, - 94CD8AEF2D2D34A500041BBA /* src */, - ); - name = pgxs; - path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pgxs"; - sourceTree = ""; - }; - 94CD8B712D2D34C800041BBA /* config */ = { - isa = PBXGroup; - children = ( - 94CD8B6F2D2D34C800041BBA /* install-sh */, - 94CD8B702D2D34C800041BBA /* missing */, - ); - name = config; - path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pgxs/config"; - sourceTree = ""; - }; - 94CD8B762D2D34C800041BBA /* pkgconfig */ = { - isa = PBXGroup; - children = ( - 94CD8B722D2D34C800041BBA /* libecpg.pc */, - 94CD8B732D2D34C800041BBA /* libecpg_compat.pc */, - 94CD8B742D2D34C800041BBA /* libpgtypes.pc */, - 94CD8B752D2D34C800041BBA /* libpq.pc */, - ); - name = pkgconfig; - path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pkgconfig"; - sourceTree = ""; - }; - 94CD8B782D2D34C800041BBA /* makefiles */ = { - isa = PBXGroup; - children = ( - 94CD8B772D2D34C800041BBA /* pgxs.mk */, - ); - path = makefiles; - sourceTree = ""; - }; - 94CD8B7B2D2D34C800041BBA /* isolation */ = { - isa = PBXGroup; - children = ( - 94CD8B792D2D34C800041BBA /* isolationtester */, - 94CD8B7A2D2D34C800041BBA /* pg_isolation_regress */, - ); - path = isolation; - sourceTree = ""; - }; - 94CD8B7D2D2D34C800041BBA /* regress */ = { - isa = PBXGroup; - children = ( - 94CD8B7C2D2D34C800041BBA /* pg_regress */, - ); - path = regress; - sourceTree = ""; - }; - 94CD8B7E2D2D34C800041BBA /* test */ = { - isa = PBXGroup; - children = ( - 94CD8B7B2D2D34C800041BBA /* isolation */, - 94CD8B7D2D2D34C800041BBA /* regress */, - ); - path = test; - sourceTree = ""; - }; - 94CD8B832D2D34C800041BBA /* src */ = { - isa = PBXGroup; - children = ( - 94CD8B782D2D34C800041BBA /* makefiles */, - 94CD8B7E2D2D34C800041BBA /* test */, - 94CD8B7F2D2D34C800041BBA /* Makefile.global */, - 94CD8B802D2D34C800041BBA /* Makefile.port */, - 94CD8B812D2D34C800041BBA /* Makefile.shlib */, - 94CD8B822D2D34C800041BBA /* nls-global.mk */, - ); - name = src; - path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pgxs/src"; - sourceTree = ""; - }; - 94CD8B862D2D34C800041BBA /* config */ = { - isa = PBXGroup; - children = ( - 94CD8B842D2D34C800041BBA /* install-sh */, - 94CD8B852D2D34C800041BBA /* missing */, - ); - path = config; - sourceTree = ""; - }; - 94CD8B882D2D34C800041BBA /* makefiles */ = { - isa = PBXGroup; - children = ( - 94CD8B872D2D34C800041BBA /* pgxs.mk */, - ); - path = makefiles; - sourceTree = ""; - }; - 94CD8B8B2D2D34C800041BBA /* isolation */ = { - isa = PBXGroup; - children = ( - 94CD8B892D2D34C800041BBA /* isolationtester */, - 94CD8B8A2D2D34C800041BBA /* pg_isolation_regress */, - ); - path = isolation; - sourceTree = ""; - }; - 94CD8B8D2D2D34C800041BBA /* regress */ = { - isa = PBXGroup; - children = ( - 94CD8B8C2D2D34C800041BBA /* pg_regress */, - ); - path = regress; - sourceTree = ""; - }; - 94CD8B8E2D2D34C800041BBA /* test */ = { - isa = PBXGroup; - children = ( - 94CD8B8B2D2D34C800041BBA /* isolation */, - 94CD8B8D2D2D34C800041BBA /* regress */, - ); - path = test; - sourceTree = ""; - }; - 94CD8B932D2D34C800041BBA /* src */ = { - isa = PBXGroup; - children = ( - 94CD8B882D2D34C800041BBA /* makefiles */, - 94CD8B8E2D2D34C800041BBA /* test */, - 94CD8B8F2D2D34C800041BBA /* Makefile.global */, - 94CD8B902D2D34C800041BBA /* Makefile.port */, - 94CD8B912D2D34C800041BBA /* Makefile.shlib */, - 94CD8B922D2D34C800041BBA /* nls-global.mk */, - ); - path = src; - sourceTree = ""; - }; - 94CD8B942D2D34C800041BBA /* pgxs */ = { - isa = PBXGroup; - children = ( - 94CD8B862D2D34C800041BBA /* config */, - 94CD8B932D2D34C800041BBA /* src */, - ); - name = pgxs; - path = "../../../../../opt/homebrew/Cellar/postgresql@14/14.15/lib/postgresql@14/pgxs"; - sourceTree = ""; - }; - 94D3A7232FC1B3A600EBEA32 /* commands */ = { - isa = PBXGroup; - children = ( - 94D3A72B2FC1B41D00EBEA32 /* runCommand.hpp */, - 94D3A7222FC1B3A600EBEA32 /* loadCommand.hpp */, - ); - path = commands; - sourceTree = ""; - }; - 94D3A7252FC1B3AD00EBEA32 /* commands */ = { - isa = PBXGroup; - children = ( - 94D3A7282FC1B41500EBEA32 /* runCommand.cpp */, - 94D3A7242FC1B3AD00EBEA32 /* loadCommand.cpp */, - ); - path = commands; - sourceTree = ""; - }; - 94D6010F2FA9CD700066F51A /* strategies */ = { - isa = PBXGroup; - children = ( - 94D6010E2FA9CD700066F51A /* randomStrategy.cpp */, - ); - path = strategies; - sourceTree = ""; - }; - 94D601132FA9CD890066F51A /* strategies */ = { - isa = PBXGroup; - children = ( - 9409A61B2FAA6411002C30FF /* strategy.hpp */, - 94D601122FA9CD890066F51A /* randomStrategy.hpp */, - ); - path = strategies; - sourceTree = ""; - }; - 94DE4F772C8C3E7C00FE48FF /* include */ = { - isa = PBXGroup; - children = ( - 940F6E4E2FD9477E00B0364A /* sweep */, - 943770422FD42FDD00317424 /* reporting */, - 94D3A7232FC1B3A600EBEA32 /* commands */, - 942966D72D48E84100532862 /* models */, - 94674B842D533B2F00973137 /* trading */, - 94D601132FA9CD890066F51A /* strategies */, - 94B8C7932D3D770800E17EB6 /* utilities */, - 941B548F2D3BBA3B00E3BF64 /* trading_definitions */, - 941B549C2D3BBFB900E3BF64 /* trading_definitions.hpp */, - 942EC55E2FBEF93A00CCBB5D /* backtestRunner.hpp */, - 942EC55F2FBEF93A00CCBB5D /* redisLoader.hpp */, - 942EC5602FBEF93A00CCBB5D /* redisRunner.hpp */, - 943398222D57E52900287A2D /* jsonParser.hpp */, - 942FDDDD2FC5C8A30096F318 /* tradingResults.hpp */, - 941408B02D59F954000ED1F9 /* sqlManager.hpp */, - 94724A852F8B92E30029B940 /* operations.hpp */, - 94CD8B9E2D2E8CE500041BBA /* databaseConnection.hpp */, - ); - path = include; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 9470B5A02C8C5AD0007D9CC6 /* source */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9470B5A52C8C5AD0007D9CC6 /* Build configuration list for PBXNativeTarget "source" */; - buildPhases = ( - 9470B59D2C8C5AD0007D9CC6 /* Sources */, - 9470B59E2C8C5AD0007D9CC6 /* Frameworks */, - 9470B59F2C8C5AD0007D9CC6 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = source; - productName = source; - productReference = 9470B5A12C8C5AD0007D9CC6 /* source */; - productType = "com.apple.product-type.tool"; - }; - 9470B5AB2C8C5B99007D9CC6 /* tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9470B5B02C8C5B99007D9CC6 /* Build configuration list for PBXNativeTarget "tests" */; - buildPhases = ( - 9470B5A82C8C5B99007D9CC6 /* Sources */, - 9470B5A92C8C5B99007D9CC6 /* Frameworks */, - 9470B5AA2C8C5B99007D9CC6 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = tests; - productName = tests; - productReference = 9470B5AC2C8C5B99007D9CC6 /* tests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 944D0DB62C8C36C0004DD0FC /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - KnownAssetTags = ( - New, - ); - LastUpgradeCheck = 1540; - TargetAttributes = { - 9470B5A02C8C5AD0007D9CC6 = { - CreatedOnToolsVersion = 15.4; - }; - 9470B5AB2C8C5B99007D9CC6 = { - CreatedOnToolsVersion = 15.4; - }; - }; - }; - buildConfigurationList = 944D0DB92C8C36C0004DD0FC /* Build configuration list for PBXProject "backtesting-engine-cpp" */; - compatibilityVersion = "Xcode 14.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 944D0DB52C8C36C0004DD0FC; - packageReferences = ( - ); - productRefGroup = 944D0DBF2C8C36C0004DD0FC /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 9470B5A02C8C5AD0007D9CC6 /* source */, - 9470B5AB2C8C5B99007D9CC6 /* tests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 9470B5AA2C8C5B99007D9CC6 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 9470B59D2C8C5AD0007D9CC6 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 941408AE2D59F93F000ED1F9 /* sqlManager.cpp in Sources */, - 94D3A7272FC1B3AD00EBEA32 /* loadCommand.cpp in Sources */, - 9470B5A42C8C5AD0007D9CC6 /* main.cpp in Sources */, - 943398252D57E53400287A2D /* jsonParser.cpp in Sources */, - 942FDDE02FC5C8B20096F318 /* tradingResults.cpp in Sources */, - 94D3A72A2FC1B41500EBEA32 /* runCommand.cpp in Sources */, - 943770452FD4396F00317424 /* boostRedisImpl.cpp in Sources */, - 942EC56A2FBEF95000CCBB5D /* backtestRunner.cpp in Sources */, - 942EC56B2FBEF95000CCBB5D /* redisLoader.cpp in Sources */, - 94829FC52FCC1D1A00710E6E /* env.cpp in Sources */, - 942EC56C2FBEF95000CCBB5D /* redisRunner.cpp in Sources */, - 940F6E592FD947A900B0364A /* decimalConvert.cpp in Sources */, - 94280BA32D2FC00200F1CF56 /* base64.cpp in Sources */, - 943770402FD42FC000317424 /* elasticClient.cpp in Sources */, - 941B549B2D3BBADE00E3BF64 /* trading_definitions_json.cpp in Sources */, - 940F6E532FD9479800B0364A /* randomStrategySweep.cpp in Sources */, - 940F6E542FD9479800B0364A /* runConfigurationBuilder.cpp in Sources */, - 946EFF7E2FB9F44E008D9647 /* reporting.cpp in Sources */, - 94674B872D533B4000973137 /* tradeManager.cpp in Sources */, - 94CD8BA02D2E8CE500041BBA /* databaseConnection.cpp in Sources */, - 942EC5622FBEF94700CCBB5D /* redisConnection.cpp in Sources */, - 94724A842F8B92C10029B940 /* operations.cpp in Sources */, - 94D601112FA9CD700066F51A /* randomStrategy.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9470B5A82C8C5B99007D9CC6 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 94CD8BA12D2E8CE500041BBA /* databaseConnection.cpp in Sources */, - 941408AF2D59F93F000ED1F9 /* sqlManager.cpp in Sources */, - 9464E5F12FA7467200D82BAD /* symbolScale.mm in Sources */, - 942EC5632FBEF94700CCBB5D /* redisConnection.cpp in Sources */, - 943398242D57E53400287A2D /* jsonParser.cpp in Sources */, - 942EC5672FBEF95000CCBB5D /* backtestRunner.cpp in Sources */, - 942EC5682FBEF95000CCBB5D /* redisLoader.cpp in Sources */, - 94D3A7262FC1B3AD00EBEA32 /* loadCommand.cpp in Sources */, - 942EC5692FBEF95000CCBB5D /* redisRunner.cpp in Sources */, - 94280BA42D2FC00200F1CF56 /* base64.cpp in Sources */, - 943770462FD4396F00317424 /* boostRedisImpl.cpp in Sources */, - 941B549A2D3BBADE00E3BF64 /* trading_definitions_json.cpp in Sources */, - 94D3A7292FC1B41500EBEA32 /* runCommand.cpp in Sources */, - 94D601102FA9CD700066F51A /* randomStrategy.cpp in Sources */, - 94674B8A2D533BDA00973137 /* tradeManager.mm in Sources */, - 94829FC62FCC1D1A00710E6E /* env.cpp in Sources */, - 94724A832F8B92C10029B940 /* operations.cpp in Sources */, - 94674B882D533B4000973137 /* tradeManager.cpp in Sources */, - 946EFF7F2FB9F44E008D9647 /* reporting.cpp in Sources */, - 943398272D57E54000287A2D /* jsonParser.mm in Sources */, - 942FDDE22FC5C8B20096F318 /* tradingResults.cpp in Sources */, - 9437703F2FD42FC000317424 /* elasticClient.cpp in Sources */, - 9470B5B62C8C5BFD007D9CC6 /* main.cpp in Sources */, - 940F6E552FD9479800B0364A /* randomStrategySweep.cpp in Sources */, - 940F6E5B2FD947C000B0364A /* sweep.mm in Sources */, - 940F6E562FD9479800B0364A /* runConfigurationBuilder.cpp in Sources */, - 940F6E582FD947A900B0364A /* decimalConvert.cpp in Sources */, - 94364CB62D416D8D00F35B55 /* db.mm in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 944D0DC32C8C36C0004DD0FC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++23"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 14.5; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - 944D0DC42C8C36C0004DD0FC /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++23"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 14.5; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = macosx; - }; - name = Release; - }; - 9470B5A62C8C5AD0007D9CC6 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - FRAMEWORK_SEARCH_PATHS = ""; - HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/include\"", - "\"$(SRCROOT)/external/libpqxx/include\"", - "\"$(SRCROOT)/external/libpqxx/include/pqxx/internal\"", - "\"$(SRCROOT)/external/libpqxx/build/include\"", - "\"$(SRCROOT)/external/\"", - "\"$(SRCROOT)/external/boost-decimal/include\"", - /opt/homebrew/include, - /opt/homebrew/opt/openssl/include, - ); - INCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = ""; - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/external/libpqxx/build/src\"", - "/opt/homebrew/opt/postgresql@18/lib/postgresql", - /opt/homebrew/opt/openssl/lib, - ); - MACOSX_DEPLOYMENT_TARGET = 26.0; - OTHER_LDFLAGS = ( - "-lpq", - "-lpqxx", - "-lssl", - "-lcrypto", - "-pthread", - ); - OTHER_LIBTOOLFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - SECTORDER_FLAGS = ""; - }; - name = Debug; - }; - 9470B5A72C8C5AD0007D9CC6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - FRAMEWORK_SEARCH_PATHS = ""; - HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/include\"", - "\"$(SRCROOT)/external/libpqxx/include\"", - "\"$(SRCROOT)/external/libpqxx/include/pqxx/internal\"", - "\"$(SRCROOT)/external/libpqxx/build/include\"", - "\"$(SRCROOT)/external/\"", - "\"$(SRCROOT)/external/boost-decimal/include\"", - /opt/homebrew/include, - /opt/homebrew/opt/openssl/include, - ); - INCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = ""; - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/external/libpqxx/build/src\"", - "/opt/homebrew/opt/postgresql@18/lib/postgresql", - /opt/homebrew/opt/openssl/lib, - ); - MACOSX_DEPLOYMENT_TARGET = 26.0; - OTHER_LDFLAGS = ( - "-lpq", - "-lpqxx", - "-lssl", - "-lcrypto", - "-pthread", - ); - OTHER_LIBTOOLFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - SECTORDER_FLAGS = ""; - }; - name = Release; - }; - 9470B5B12C8C5B99007D9CC6 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/include\"", - "\"$(SRCROOT)/external/\"", - "\"$(SRCROOT)/external/libpqxx/include\"", - "\"$(SRCROOT)/external/libpqxx/include/pqxx/internal\"", - "\"$(SRCROOT)/external/libpqxx/build/include\"", - "\"$(SRCROOT)/external/boost-decimal/include\"", - /opt/homebrew/include, - /opt/homebrew/opt/openssl/include, - ); - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/external/libpqxx/build/src\"", - "/opt/homebrew/opt/postgresql@18/lib/postgresql", - /opt/homebrew/opt/openssl/lib, - ); - MACOSX_DEPLOYMENT_TARGET = 26.0; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-lpq", - "-lpqxx", - "-lssl", - "-lcrypto", - "-pthread", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.mccaffers.tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - }; - name = Debug; - }; - 9470B5B22C8C5B99007D9CC6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/include\"", - "\"$(SRCROOT)/external/\"", - "\"$(SRCROOT)/external/libpqxx/include\"", - "\"$(SRCROOT)/external/libpqxx/include/pqxx/internal\"", - "\"$(SRCROOT)/external/libpqxx/build/include\"", - "\"$(SRCROOT)/external/boost-decimal/include\"", - /opt/homebrew/include, - /opt/homebrew/opt/openssl/include, - ); - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/external/libpqxx/build/src\"", - "/opt/homebrew/opt/postgresql@18/lib/postgresql", - /opt/homebrew/opt/openssl/lib, - ); - MACOSX_DEPLOYMENT_TARGET = 26.0; - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "-lpq", - "-lpqxx", - "-lssl", - "-lcrypto", - "-pthread", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.mccaffers.tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 944D0DB92C8C36C0004DD0FC /* Build configuration list for PBXProject "backtesting-engine-cpp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 944D0DC32C8C36C0004DD0FC /* Debug */, - 944D0DC42C8C36C0004DD0FC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9470B5A52C8C5AD0007D9CC6 /* Build configuration list for PBXNativeTarget "source" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9470B5A62C8C5AD0007D9CC6 /* Debug */, - 9470B5A72C8C5AD0007D9CC6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9470B5B02C8C5B99007D9CC6 /* Build configuration list for PBXNativeTarget "tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9470B5B12C8C5B99007D9CC6 /* Debug */, - 9470B5B22C8C5B99007D9CC6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 944D0DB62C8C36C0004DD0FC /* Project object */; -} diff --git a/backtesting-engine-cpp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/backtesting-engine-cpp.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/backtesting-engine-cpp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/backtesting-engine-cpp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/backtesting-engine-cpp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/backtesting-engine-cpp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/backtesting-engine-cpp.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/backtesting-engine-cpp.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index 0c67376..0000000 --- a/backtesting-engine-cpp.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/backtesting-engine-cpp.xcodeproj/xcshareddata/xcschemes/source.xcscheme b/backtesting-engine-cpp.xcodeproj/xcshareddata/xcschemes/source.xcscheme deleted file mode 100644 index 4b7e568..0000000 --- a/backtesting-engine-cpp.xcodeproj/xcshareddata/xcschemes/source.xcscheme +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/backtesting-engine-cpp.xcodeproj/xcshareddata/xcschemes/tests.xcscheme b/backtesting-engine-cpp.xcodeproj/xcshareddata/xcschemes/tests.xcscheme deleted file mode 100644 index d8cadc1..0000000 --- a/backtesting-engine-cpp.xcodeproj/xcshareddata/xcschemes/tests.xcscheme +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/backtesting-engine-cpp.xcodeproj/xcuserdata/ryan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/backtesting-engine-cpp.xcodeproj/xcuserdata/ryan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist deleted file mode 100644 index 8391224..0000000 --- a/backtesting-engine-cpp.xcodeproj/xcuserdata/ryan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/backtesting-engine-cpp.xcodeproj/xcuserdata/ryan.xcuserdatad/xcschemes/xcschememanagement.plist b/backtesting-engine-cpp.xcodeproj/xcuserdata/ryan.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 2f27c30..0000000 --- a/backtesting-engine-cpp.xcodeproj/xcuserdata/ryan.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,42 +0,0 @@ - - - - - SchemeUserState - - source.xcscheme_^#shared#^_ - - orderHint - 0 - - tests.xcscheme_^#shared#^_ - - orderHint - 1 - - - SuppressBuildableAutocreation - - 944D0DBD2C8C36C0004DD0FC - - primary - - - 9470B58A2C8C5988007D9CC6 - - primary - - - 9470B5A02C8C5AD0007D9CC6 - - primary - - - 9470B5AB2C8C5B99007D9CC6 - - primary - - - - - diff --git a/external/Catch2 b/external/Catch2 new file mode 160000 index 0000000..bcfb10e --- /dev/null +++ b/external/Catch2 @@ -0,0 +1 @@ +Subproject commit bcfb10e498df3e2ed8f814b3e4b689b9a85608ab diff --git a/include/backtestRunner.hpp b/include/backtestRunner.hpp deleted file mode 100644 index dc72244..0000000 --- a/include/backtestRunner.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once -#include -#include -#include "models/priceData.hpp" -#include "trading_definitions/configuration.hpp" - -// Pulls all tick data for the run's symbols/window out of QuestDB. Expensive — -// call once per run and reuse the result across that run's strategies. -std::vector loadTicks(const std::string& questdbHost, - const std::string& symbolsCsv, - int lastMonths); - -// Runs one backtest against already-loaded ticks (no QuestDB access). -void runBacktestOnTicks(const std::vector& ticks, - const trading_definitions::Configuration& config); - -// Convenience for the direct path: loads ticks then runs a single backtest. -int runBacktest(const std::string& questdbHost, - const trading_definitions::Configuration& config); diff --git a/include/commands/loadCommand.hpp b/include/commands/loadCommand.hpp deleted file mode 100644 index 8b952a1..0000000 --- a/include/commands/loadCommand.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once - -// Backs the `load` subcommand: for one RUN_ID, LPUSHes every swept strategy onto -// BACKTESTING_QUEUE_STRATEGY:, then LPUSHes the run descriptor onto -// BACKTESTING_QUEUE_RUN (see source/commands/loadCommand.cpp). -class LoadCommand { -public: - static int run(); -}; diff --git a/include/commands/runCommand.hpp b/include/commands/runCommand.hpp deleted file mode 100644 index 75ade68..0000000 --- a/include/commands/runCommand.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once - -// Backs the `run` subcommand: drains BACKTESTING_QUEUE_RUN (loading each run's -// QuestDB ticks once, then running its strategies), or runs a single Base64 -// Configuration supplied directly on the command line. -class RunCommand { -public: - static int run(int argc, const char* argv[]); -}; diff --git a/include/databaseConnection.hpp b/include/databaseConnection.hpp deleted file mode 100644 index 2a84567..0000000 --- a/include/databaseConnection.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2025 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- -#pragma once -#include -#include "models/priceData.hpp" - -class DatabaseConnection { -private: - std::string connection_string; - -public: - DatabaseConnection(const std::string& endpoint = "localhost", - int port = 8812, - const std::string& dbname = "qdb", - const std::string& user = "admin", - const std::string& password = ""); - - std::vector executeQuery(const std::string& query) const; - - const std::string& getConnectionString() const { - return connection_string; - } - -}; diff --git a/include/jsonParser.hpp b/include/jsonParser.hpp deleted file mode 100644 index 821fc9a..0000000 --- a/include/jsonParser.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2025 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once - -#include -#include -#include "trading_definitions.hpp" - -class JsonParser { -public: - static trading_definitions::Configuration parseConfigurationFromBase64(const std::string& input); - static trading_definitions::RunConfiguration parseRunConfigurationFromBase64(const std::string& input); - static trading_definitions::Strategy parseStrategyFromBase64(const std::string& input); -}; diff --git a/include/models/priceData.hpp b/include/models/priceData.hpp deleted file mode 100644 index 38589c8..0000000 --- a/include/models/priceData.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- -#pragma once -#include -#include -#include - -// decimal64_t: 16 significant base-10 digits, no binary floating-point drift on -// values like 1.23456. Closest C# analogue is System.Decimal (though decimal64_t -// is 64-bit IEEE 754-2008 vs C#'s 128-bit type). -struct PriceData { - boost::decimal::decimal64_t ask; - boost::decimal::decimal64_t bid; - std::chrono::system_clock::time_point timestamp; - std::string symbol; - - PriceData(boost::decimal::decimal64_t ask, boost::decimal::decimal64_t bid, - const std::chrono::system_clock::time_point& ts, const std::string& symbol) - : ask(ask), bid(bid), timestamp(ts), symbol(symbol) {} - - PriceData() : ask(0), bid(0), timestamp{}, symbol("") {} -}; diff --git a/include/operations.hpp b/include/operations.hpp deleted file mode 100644 index 0a65f1d..0000000 --- a/include/operations.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once -#include -#include "models/priceData.hpp" -#include "trading_definitions/configuration.hpp" - -class Operations { - -public: - static void run(const std::vector& priceData, - const trading_definitions::Configuration& config); -}; diff --git a/include/reporting/elasticClient.hpp b/include/reporting/elasticClient.hpp deleted file mode 100644 index 8f9a4c9..0000000 --- a/include/reporting/elasticClient.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once - -#include "tradingResults.hpp" - -// Minimal Elasticsearch HTTP client — PUT-only, for indexing run outcomes. -// Host is read from $ELASTIC_HOST (default http://localhost:9200) with optional -// HTTP basic auth from $ELASTIC_USER / $ELASTIC_USER_PASSWORD. Completed runs -// land in index "trading_results"; runs cut off early (loss limit) land in -// "trading_failures". Each doc gets a freshly generated UUID. -class ElasticClient { -public: - static int putTradingResults(const TradingResults& results); - static int putTradingFailure(const TradingFailure& failure); -}; diff --git a/include/sqlManager.hpp b/include/sqlManager.hpp deleted file mode 100644 index 592b007..0000000 --- a/include/sqlManager.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- -#pragma once -#include -#include -#include "models/priceData.hpp" -#include "databaseConnection.hpp" - -class SqlManager { -public: - static std::vector loadPriceData(const DatabaseConnection& db, const std::vector& symbols, int LAST_MONTHS = 1); -}; diff --git a/include/sweep/randomStrategySweep.hpp b/include/sweep/randomStrategySweep.hpp deleted file mode 100644 index f49dbd2..0000000 --- a/include/sweep/randomStrategySweep.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once - -#include "parameterSweep.hpp" - -namespace sweep { - -// Declares which parameters to sweep for the RandomStrategy. Keeping the ranges -// in one place means a new strategy (or extra swept parameter) is a localised -// edit: register it here, then read it back in makeStrategy(). -ParameterGenerator buildRandomStrategySweep(); - -} // namespace sweep diff --git a/include/sweep/runConfigurationBuilder.hpp b/include/sweep/runConfigurationBuilder.hpp deleted file mode 100644 index 0132ee3..0000000 --- a/include/sweep/runConfigurationBuilder.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once - -#include - -#include "run_configuration.hpp" - -namespace sweep { - -// The run-level descriptor: what tick data to pull from QuestDB, plus the risk -// limits every strategy in the sweep runs under. Shared by every strategy in -// this sweep and linked to them by RUN_ID. -trading_definitions::RunConfiguration makeRunConfiguration(const std::string& runId); - -} // namespace sweep diff --git a/include/trading/exitRules.hpp b/include/trading/exitRules.hpp deleted file mode 100644 index c7bc293..0000000 --- a/include/trading/exitRules.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once -#include -#include -#include "models/trade.hpp" -#include "models/priceData.hpp" - -namespace trading::exit_rules { - -// Decide whether the current tick has hit a trade's stop-loss or -// take-profit boundary. Returns the price at which the position would -// close (bid for LONG exits, ask for SHORT exits); `std::nullopt` -// means "no exit on this tick". -// -// SL/TP distances are anchored on the close-side of the entry spread -// (`trade.exitReferencePrice`: the entry-tick bid for LONG, entry-tick -// ask for SHORT) — the price the trade would actually exit at — not -// from the execution price. So a 1-pip stop on a LONG means "exit when -// bid drops 1 pip below the entry bid", which prevents the spread -// itself from triggering an exit on the opening tick. -// -// Pip → price conversion uses the symbol's scaling factor: a 1.5-pip -// distance on EURUSD (scale 10000) is 0.00015; on USDJPY (scale 100) -// it's 0.015. Trades on unknown symbols (scale 0) are skipped — there -// is no sensible pip distance to apply. -inline std::optional -checkExit(const Trade& trade, const PriceData& tick) { - if (trade.scalingFactor == 0) return std::nullopt; - if (trade.stopDistancePips == 0 && - trade.limitDistancePips == 0) { - return std::nullopt; - } - - const auto stopOffset = trade.stopDistancePips / trade.scalingFactor; - const auto limitOffset = trade.limitDistancePips / trade.scalingFactor; - - if (trade.direction == Direction::LONG) { - const auto stopPrice = trade.exitReferencePrice - stopOffset; - const auto limitPrice = trade.exitReferencePrice + limitOffset; - // Exit a long at the bid (the price the broker pays us). - if (trade.stopDistancePips != 0 && tick.bid <= stopPrice) return tick.bid; - if (trade.limitDistancePips != 0 && tick.bid >= limitPrice) return tick.bid; - } else { - const auto stopPrice = trade.exitReferencePrice + stopOffset; - const auto limitPrice = trade.exitReferencePrice - limitOffset; - // Exit a short at the ask (the price we pay to buy back). - if (trade.stopDistancePips != 0 && tick.ask >= stopPrice) return tick.ask; - if (trade.limitDistancePips != 0 && tick.ask <= limitPrice) return tick.ask; - } - return std::nullopt; -} - -} // namespace trading::exit_rules diff --git a/include/trading/reporting.hpp b/include/trading/reporting.hpp deleted file mode 100644 index 3bafcfe..0000000 --- a/include/trading/reporting.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once -#include "tradeManager.hpp" -#include "tradingResults.hpp" - -class Reporting { - -public: - static TradingResultsStats collect(const TradeManager& tradeManager); - static void summarise(const TradeManager& tradeManager); -}; diff --git a/include/trading/tradeManager.hpp b/include/trading/tradeManager.hpp deleted file mode 100644 index 7576b74..0000000 --- a/include/trading/tradeManager.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2025 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once -#include -#include -#include -#include -#include -#include "trade.hpp" -#include "priceData.hpp" - -class TradeManager { -private: - std::unordered_map activeTrades; - std::vector closedTrades; - // Running sums maintained by openTrade/markToMarket/closeTrade so the - // per-tick loss-limit check in runTicks stays O(1): realized PnL across - // closed trades, and floating (mark-to-market) PnL across open ones. - boost::decimal::decimal64_t closedPnl{0}; - boost::decimal::decimal64_t openPnl{0}; - -public: - TradeManager() = default; - std::string openTrade(const PriceData& tick, - boost::decimal::decimal64_t size, - Direction direction, - boost::decimal::decimal64_t stopDistancePips = boost::decimal::decimal64_t{0}, - boost::decimal::decimal64_t limitDistancePips = boost::decimal::decimal64_t{0}); - size_t reviewAccount() const; - bool hasActiveTradeForSymbol(std::string_view symbol) const; - // `liquidated` marks the close as forced by the account loss limit - // rather than earned via SL/TP or strategy logic. - bool closeTrade(const std::string& tradeId, - boost::decimal::decimal64_t closePrice, - const PriceData& tick, - bool liquidated = false); - const std::unordered_map& getActiveTrades() const; - const std::vector& getClosedTrades() const; - // Realized PnL across all closed trades. O(1): returns the running sum. - boost::decimal::decimal64_t calculatePnl() const; - // Floating (mark-to-market) PnL across all open trades, as of each - // trade's last marked price. O(1): returns the running sum. - boost::decimal::decimal64_t unrealizedPnl() const; - // Revalue open trades for this tick's symbol at its close-side price - // (bid for LONG, ask for SHORT), updating their floating PnL. - void markToMarket(const PriceData& tick); - // Liquidate every open trade at its last marked price (timestamped with - // `tick`), realizing the floating PnL — used when a run is cut off. - void closeAllTrades(const PriceData& tick); -}; diff --git a/include/trading_definitions.hpp b/include/trading_definitions.hpp deleted file mode 100644 index b454130..0000000 --- a/include/trading_definitions.hpp +++ /dev/null @@ -1,14 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2025 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- -#pragma once - -#include "trading_definitions/ohlc_variables.hpp" -#include "trading_definitions/ohlc_rsi_variables.hpp" -#include "trading_definitions/trading_variables.hpp" -#include "trading_definitions/strategy_variables.hpp" -#include "trading_definitions/strategy.hpp" -#include "trading_definitions/configuration.hpp" -#include "trading_definitions/run_configuration.hpp" diff --git a/include/trading_definitions/trading_variables.hpp b/include/trading_definitions/trading_variables.hpp deleted file mode 100644 index 5a9fa8c..0000000 --- a/include/trading_definitions/trading_variables.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2025 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once -#include -#include -#include -#include "utilities/decimal_json.hpp" - -namespace trading_definitions { -struct TradingVariables { - std::string STRATEGY; - boost::decimal::decimal64_t STOP_DISTANCE_IN_PIPS; - boost::decimal::decimal64_t LIMIT_DISTANCE_IN_PIPS; - boost::decimal::decimal64_t TRADING_SIZE; -}; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(TradingVariables, - STRATEGY, - STOP_DISTANCE_IN_PIPS, - LIMIT_DISTANCE_IN_PIPS, - TRADING_SIZE -); -} diff --git a/include/utilities/decimalConvert.hpp b/include/utilities/decimalConvert.hpp deleted file mode 100644 index b01f6cb..0000000 --- a/include/utilities/decimalConvert.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#pragma once - -#include - -namespace decimal_convert { - -// Converts a double into a decimal64_t via its shortest round-trip decimal -// string. Routing through text (rather than constructing from the binary double) -// stops clean decimals like 1.5 / 2.0 from snapping to an IEEE-754 neighbour, -// consistent with how decimal_json.hpp moves values through JSON. Feed it -// binary-exact values (halves, quarters) or explicit lists to keep this exact. -boost::decimal::decimal64_t toDecimal(double value); - -} // namespace decimal_convert diff --git a/scripts/build.sh b/scripts/build.sh index 0bb830f..6c67e3a 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -18,18 +18,44 @@ fi # Step 2: Navigate to the build directory cd "$BUILD_DIR" || exit -# Expose paths so CMake finds libpq +# Expose paths so CMake finds libpq, and select the Homebrew LLVM toolchain. +# The project uses C++23 modules + `import std;`, which needs the Ninja +# generator and a Clang whose libc++ ships a `std` module (Apple Clang does +# not). COMPILER_PATH points Clang at that libc++ so CMake can locate +# libc++.modules.json. +TOOLCHAIN_ARGS=() if command -v brew &>/dev/null; then export PATH="$(brew --prefix libpq)/bin:$PATH" - export PKG_CONFIG_PATH="$(brew --prefix libpq)/lib/pkgconfig:$PKG_CONFIG_PATH" + export PKG_CONFIG_PATH="$(brew --prefix libpq)/lib/pkgconfig:${PKG_CONFIG_PATH:-}" export PostgreSQL_ROOT="$(brew --prefix libpq)" + + LLVM_PREFIX="$(brew --prefix llvm)" + export COMPILER_PATH="$LLVM_PREFIX/lib/c++" + TOOLCHAIN_ARGS+=( + -DCMAKE_C_COMPILER="$LLVM_PREFIX/bin/clang" + -DCMAKE_CXX_COMPILER="$LLVM_PREFIX/bin/clang++" + ) +else + # Off Homebrew (Linux/CI): use Clang + libc++ so `import std` works, matching + # the macOS toolchain. CMakeLists adds -stdlib=libc++ and locates the libc++ + # `std` module manifest. Honour $CC/$CXX if the caller pinned a version + # (e.g. clang-19), otherwise fall back to the unversioned names. + TOOLCHAIN_ARGS+=( + -DCMAKE_C_COMPILER="${CC:-clang}" + -DCMAKE_CXX_COMPILER="${CXX:-clang++}" + ) fi -# 1. Generate build files (Passing your CXX flags directly to CMake instead of configure) -cmake .. \ +# 1. Generate build files. -G Ninja is required for `import std`; -Wno-dev +# silences the (expected) "import std support is experimental" developer note. +# ENABLE_COVERAGE=ON (default OFF) instruments the build for Clang source-based +# coverage — CI sets it on the macOS leg to produce the SonarCloud report. +cmake .. -G Ninja -Wno-dev \ + "${TOOLCHAIN_ARGS[@]}" \ -DCMAKE_CXX_STANDARD=23 \ -DCMAKE_BUILD_TYPE=Release \ -DSKIP_BUILD_TEST=ON \ + -DENABLE_COVERAGE="${ENABLE_COVERAGE:-OFF}" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON # Step 4: Compile the project diff --git a/scripts/generate_clangd.sh b/scripts/generate_clangd.sh deleted file mode 100755 index 1616808..0000000 --- a/scripts/generate_clangd.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash -# Generates the .clangd IntelliSense config at the repo root. -# -# .clangd needs absolute, machine-specific paths (clangd resolves relative -I -# flags against the inferred command's working directory, not the repo root), -# so the file is gitignored and each user regenerates it locally with this -# script. Re-run it after adding a new include/ subdirectory — and add the new -# directory to the list below, mirroring CMakeLists.txt. - -# Fail fast: -e exits on any error, -u errors on undefined vars, -# pipefail propagates failures through pipes. -set -euo pipefail - -# Resolve paths relative to this script, not the caller's working directory, -# so the script works no matter where it's invoked from. -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Homebrew lives at /opt/homebrew on Apple Silicon and /usr/local on Intel; -# `brew --prefix` resolves the right one. The keg-only formulas (libomp, -# libpq) are addressed via their own prefixes rather than /opt/... so -# the script also works if they were installed elsewhere. -BREW_PREFIX="$(brew --prefix)" -LIBOMP_PREFIX="$(brew --prefix libomp)" -LIBPQ_PREFIX="$(brew --prefix libpq)" - -# Where the XCTest framework lives for the active Xcode installation. -XCODE_FRAMEWORKS="$(xcode-select -p)/Platforms/MacOSX.platform/Developer/Library/Frameworks" - -OUTPUT="$REPO_ROOT/.clangd" - -cat > "$OUTPUT" < sonarqube-generic-coverage.xml \ No newline at end of file +rm -f sonarqube-generic-coverage.xml + +# Instrument the build (-DENABLE_COVERAGE=ON via the env passthrough in build.sh). +ENABLE_COVERAGE=ON bash ./scripts/build.sh + +# Runs the tests, merges the profile, and converts llvm-cov output to Sonar +# generic XML. +bash ./.github/workflows/scripts/llvmcov-to-sonarqube-generic.sh build \ + > sonarqube-generic-coverage.xml + +echo "Wrote sonarqube-generic-coverage.xml" diff --git a/scripts/test.sh b/scripts/test.sh index 1480ccf..3b62a99 100644 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -1,21 +1,19 @@ #!/bin/bash +# Build and run the Catch2 unit tests via CMake/Ninja + ctest. The test suite +# moved off Xcode/XCTest onto Catch2 (see tests/*.cpp); scripts/build.sh selects +# the Clang/libc++ toolchain and builds the unit_tests target as part of `all`. +# +# Pass CLEAN=1 to force a clean reconfigure: CLEAN=1 ./scripts/test.sh +set -euo pipefail -if [[ "$(uname)" != "Darwin" ]]; then - echo "Testing is done via Xcode build — C++ methods are wrapped in Objective-C for inline debugging and testing in Xcode." - exit 0 -fi +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR/.." -# Pass CLEAN=1 to force a clean build: CLEAN=1 ./scripts/test.sh -CLEAN_ACTION="" if [[ "${CLEAN:-0}" == "1" ]]; then - CLEAN_ACTION="clean" + rm -rf build fi -xcodebuild \ - -project backtesting-engine-cpp.xcodeproj \ - -scheme tests \ - -parallelizeTargets \ - -jobs "$(sysctl -n hw.logicalcpu)" \ - CODE_SIGN_IDENTITY="-" \ - ENABLE_TESTABILITY=YES \ - ${CLEAN_ACTION} build test 2>&1 | xcpretty \ No newline at end of file +# Configures the toolchain and builds the library, executable, and unit_tests. +bash ./scripts/build.sh + +ctest --test-dir build --output-on-failure diff --git a/source/backtestRunner.cpp b/source/backtestRunner.cpp deleted file mode 100644 index c2935ba..0000000 --- a/source/backtestRunner.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#include "backtestRunner.hpp" - -#include -#include -#include -#include - -#include "databaseConnection.hpp" -#include "operations.hpp" -#include "sqlManager.hpp" - -std::vector loadTicks(const std::string& questdbHost, - const std::string& symbolsCsv, - int lastMonths) { - - DatabaseConnection db(questdbHost, 8812, "qdb", "admin", "quest"); - - // Get a list of symbols - std::vector symbols; - std::istringstream ss(symbolsCsv); - for (std::string token; std::getline(ss, token, ',');) { - symbols.push_back(token); - } - - // Get all the tick data out of QuestDB for these symbols - std::vector ticks = - SqlManager::loadPriceData(db, symbols, lastMonths); - - printf("Total ticks streamed: %zu\n", ticks.size()); - - return ticks; -} - -void runBacktestOnTicks(const std::vector& ticks, - const trading_definitions::Configuration& config) { - Operations::run(ticks, config); -} - -int runBacktest(const std::string& questdbHost, - const trading_definitions::Configuration& config) { - const std::vector ticks = - loadTicks(questdbHost, config.SYMBOLS, config.LAST_MONTHS); - runBacktestOnTicks(ticks, config); - return 0; -} diff --git a/source/commands/runCommand.cpp b/source/commands/runCommand.cpp deleted file mode 100644 index e306433..0000000 --- a/source/commands/runCommand.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#include "runCommand.hpp" - -#include -#include - -#include "backtestRunner.hpp" -#include "env.hpp" -#include "jsonParser.hpp" -#include "redisRunner.hpp" - -int RunCommand::run(int argc, const char* argv[]) { - - if (argc < 3) { - std::println(stderr, "Usage: BacktestingEngine run \n" - " BacktestingEngine run "); - return 1; - } - - if (argc == 3) { - return RedisRunner::run(argv[2], env::getOr("REDIS_HOST", "127.0.0.1")); - } - - // Else we'll just parse one base64 blob - auto config = JsonParser::parseConfigurationFromBase64(argv[3]); - return runBacktest(argv[2], config); -} \ No newline at end of file diff --git a/source/commands/loadCommand.cpp b/source/load/loadCommand.cppm similarity index 65% rename from source/commands/loadCommand.cpp rename to source/load/loadCommand.cppm index 77f58a4..01cf17e 100644 --- a/source/commands/loadCommand.cpp +++ b/source/load/loadCommand.cppm @@ -4,38 +4,35 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "loadCommand.hpp" +module; -#include -#include -#include -#include - -#include -#include #include #include #include -#include "decimalConvert.hpp" -#include "env.hpp" -#include "parameterSweep.hpp" -#include "queueKeys.hpp" -#include "randomStrategySweep.hpp" -#include "redisLoader.hpp" -#include "runConfigurationBuilder.hpp" -#include "trading_definitions/strategy.hpp" +#include "shared/utilities/env.hpp" +#include "shared/utilities/parameterSweep.hpp" +#include "shared/utilities/queueKeys.hpp" +#include "shared/redis/redisLoader.hpp" +#include "shared/tradingDefinitions/runConfiguration.hpp" // RunConfiguration (json conversion) +#include "shared/tradingDefinitions/strategy.hpp" + +export module loadCommand; -namespace { +import std; // replaces , , , +import randomStrategySweep; // buildRandomStrategySweep +import runConfigurationBuilder; // makeRunConfiguration -using trading_definitions::Strategy; +export class LoadCommand { +public: + static int run(); +}; + +using tradingDefinitions::Strategy; -// Maps one point in the parameter grid onto a Strategy. Fields not being swept -// keep their fixed defaults; swept fields are pulled from `combo`. Strategy makeStrategy(const sweep::Combination& combo) { - using namespace boost::decimal::literals; - using namespace trading_definitions; + using namespace tradingDefinitions; return Strategy{ // Each parameter combination gets its own UUID so a single backtest @@ -43,11 +40,9 @@ Strategy makeStrategy(const sweep::Combination& combo) { .UUID = boost::uuids::to_string(boost::uuids::random_generator()()), .TRADING_VARIABLES = TradingVariables{ .STRATEGY = "RandomStrategy", - .STOP_DISTANCE_IN_PIPS = - decimal_convert::toDecimal(combo.get("STOP_DISTANCE_IN_PIPS")), - .LIMIT_DISTANCE_IN_PIPS = - decimal_convert::toDecimal(combo.get("LIMIT_DISTANCE_IN_PIPS")), - .TRADING_SIZE = 1_DD, + .STOP_DISTANCE_IN_PIPS = combo.getInt("STOP_DISTANCE_IN_PIPS"), + .LIMIT_DISTANCE_IN_PIPS = combo.getInt("LIMIT_DISTANCE_IN_PIPS"), + .TRADING_SIZE = 1, }, .OHLC_VARIABLES = { OHLCVariables{ @@ -63,46 +58,47 @@ Strategy makeStrategy(const sweep::Combination& combo) { }; } -} // namespace - int LoadCommand::run() { + // One RUN_ID identifies the whole sweep; each combination becomes its own // queue entry, distinguished by its parameter values. const auto runId = boost::uuids::to_string(boost::uuids::random_generator()()); - const auto redisHost = env::getOr("REDIS_HOST", "127.0.0.1"); // Build random here + // TODO Configurable? maybe in the future ENV variable? const auto generator = sweep::buildRandomStrategySweep(); const auto combinations = generator.generateAllCombinations(); - std::println("LoadCommand: sweeping {} parameter combination(s) for RUN_ID={}", - combinations.size(), runId); + std::println("LoadCommand: sweeping {} parameter combination(s) for RUN_ID={}", combinations.size(), runId); // Serialise every swept strategy first. combinations is a sized range, so // std::ranges::to reserves up front (no manual reserve needed). The json type // is pinned explicitly because makeStrategy returns a Strategy and relies on // the implicit conversion for .dump(). - const auto strategyPayloads = - combinations | std::views::transform([](const sweep::Combination& combo) { + const auto strategyPayloads = combinations + | std::views::transform([](const sweep::Combination& combo) { + // Pin to JSON explicitly to trigger implicit Strategy conversion const nlohmann::json j = makeStrategy(combo); return j.dump(); - }) | std::ranges::to>(); + }) + | std::ranges::to(); // Push all strategies BEFORE the run descriptor. A worker that sees the run // immediately drains the strategy list and retires the run when empty, so the // full set must already be present the moment the run becomes visible. const auto strategyKey = queue_keys::strategyKey(runId); - const auto strategyStatus = RedisLoader::loadPayloadBatch( - redisHost, 6379, strategyKey, strategyPayloads); - if (strategyStatus != 0) { + + const auto redisHost = env::getOr("REDIS_HOST", "127.0.0.1"); + if (const auto strategyStatus = RedisLoader::loadPayloadBatch(redisHost, 6379, strategyKey, strategyPayloads); + strategyStatus != 0) + { return strategyStatus; } // Now advertise the run so workers can pick it up. runJson is pinned to - // nlohmann::json (not auto) because makeRunConfiguration returns a + // nlohmann::JSON (not auto) because makeRunConfiguration returns a // RunConfiguration and relies on the implicit conversion for .dump(). const nlohmann::json runJson = sweep::makeRunConfiguration(runId); - return RedisLoader::loadPayload(redisHost, 6379, queue_keys::RUN, - runJson.dump()); + return RedisLoader::loadPayload(redisHost, 6379, queue_keys::RUN, runJson.dump()); } diff --git a/source/sweep/randomStrategySweep.cpp b/source/load/sweep/randomStrategySweep.cppm similarity index 50% rename from source/sweep/randomStrategySweep.cpp rename to source/load/sweep/randomStrategySweep.cppm index d8e59c2..565c4e0 100644 --- a/source/sweep/randomStrategySweep.cpp +++ b/source/load/sweep/randomStrategySweep.cppm @@ -4,16 +4,23 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "randomStrategySweep.hpp" +module; -namespace sweep { +#include "shared/utilities/parameterSweep.hpp" +export module randomStrategySweep; + +export namespace sweep { + +// Declares which parameters to sweep for the RandomStrategy. Keeping the ranges +// in one place means a new strategy (or extra swept parameter) is a localised +// edit: register it here, then read it back in makeStrategy(). ParameterGenerator buildRandomStrategySweep() { ParameterGenerator generator; // generator.addRange("OHLC_COUNT", 80, 20, 140); // 80, 100, 120, 140 // generator.addList("OHLC_MINUTES", {1, 3, 5, 8}); - generator.addList("STOP_DISTANCE_IN_PIPS", {1.0, 1.5, 10.0}); - generator.addList("LIMIT_DISTANCE_IN_PIPS", {1.0, 1.5, 10.0}); + generator.addRange("LIMIT_DISTANCE_IN_PIPS", 1, 1, 100); + generator.addRange("STOP_DISTANCE_IN_PIPS", 1, 1, 100); return generator; } diff --git a/source/sweep/runConfigurationBuilder.cpp b/source/load/sweep/runConfigurationBuilder.cppm similarity index 61% rename from source/sweep/runConfigurationBuilder.cpp rename to source/load/sweep/runConfigurationBuilder.cppm index 8fdc6fd..4e9b326 100644 --- a/source/sweep/runConfigurationBuilder.cpp +++ b/source/load/sweep/runConfigurationBuilder.cppm @@ -4,27 +4,36 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "runConfigurationBuilder.hpp" +module; #include #include -namespace sweep { +#include "shared/tradingDefinitions/runConfiguration.hpp" -trading_definitions::RunConfiguration makeRunConfiguration(const std::string& runId) { +export module runConfigurationBuilder; + +import std; // replaces + +export namespace sweep { + +// The run-level descriptor: what tick data to pull from QuestDB, plus the risk +// limits every strategy in the sweep runs under. Shared by every strategy in +// this sweep and linked to them by RUN_ID. +tradingDefinitions::RunConfiguration makeRunConfiguration(const std::string& runId) { using namespace boost::decimal::literals; - return trading_definitions::RunConfiguration{ + return tradingDefinitions::RunConfiguration{ .RUN_ID = runId, .SYMBOLS = "EURUSD", .LAST_MONTHS = 6, - .STARTING_BALANCE = trading_definitions::DEFAULT_STARTING_BALANCE, + .STARTING_BALANCE = tradingDefinitions::DEFAULT_STARTING_BALANCE, // Cut a run off once it has lost 5% of the account (fail fast); // set <= 0 to run without any loss cutoff. .MAX_LOSS_PERCENT = 5_DD, // Cap on simultaneously open positions per run (<= 0 = unlimited). // The per-symbol gate already limits to one trade per symbol, so this // only bites on multi-symbol runs. - .MAX_OPEN_TRADES = 10, + .MAX_OPEN_TRADES = 1, // Flip to false to silence liquidated runs from Elasticsearch once // sweeps scale up and loss-limit cutoffs are expected noise. .REPORT_FAILURES = true, diff --git a/source/main.cpp b/source/main.cpp index 968ff32..ec8e420 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -4,16 +4,14 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -// std headers -#include -#include +import std; // replaces , // backtesting engine headers -#include "loadCommand.hpp" -#include "runCommand.hpp" +import loadCommand; +import runCommand; // Entry point -int main(int argc, const char* argv[]) { +int main(const int argc, const char* argv[]) { if (argc < 2) { std::cerr << "BacktestingEngine: missing a subcommand. See README.md for usage" diff --git a/source/operations.cpp b/source/run/operations.cppm similarity index 71% rename from source/operations.cpp rename to source/run/operations.cppm index 763282e..a37f809 100644 --- a/source/operations.cpp +++ b/source/run/operations.cppm @@ -4,29 +4,37 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "operations.hpp" -#include -#include -#include -#include -#include -#include -#include -#include "backtestLog.hpp" -#include "tradeManager.hpp" -#include "runLoop.hpp" -#include "reporting.hpp" -#include "tradingResults.hpp" -#include "reporting/elasticClient.hpp" -#include "strategies/strategy.hpp" -#include "strategies/randomStrategy.hpp" -#include "strategies/strategyErrors.hpp" +module; + +#include "shared/utilities/backtestLog.hpp" +#include "shared/tradingDefinitions/configuration.hpp" +#include "run/reporting/tradingResults.hpp" + +export module operations; + +import std; // replaces , , , , , + // , +import priceData; // PriceData +import tradeManager; // TradeManager +import runLoop; // trading::runTicks, RiskLimits, RunStatus +import resultsSummary; // ResultsSummary +import symbolScale; // symbol_scale::get +import strategy; // IStrategy +import randomStrategy; // RandomStrategy +import strategyErrors; // UnknownStrategyError +import elasticClient; // ElasticClient + +export class Operations { +public: + static void run(const std::vector& ticks, + const tradingDefinitions::Configuration& config); +}; namespace { // Adding a new strategy means adding one branch here; nothing else in // Operations needs to know about the concrete type. -std::unique_ptr selectStrategy(const trading_definitions::Configuration& config) { +std::unique_ptr selectStrategy(const tradingDefinitions::Configuration& config) { const auto& name = config.STRATEGY.TRADING_VARIABLES.STRATEGY; if (name == "RandomStrategy") { return std::make_unique(config.STRATEGY); @@ -37,7 +45,7 @@ std::unique_ptr selectStrategy(const trading_definitions::Configurati } // namespace void Operations::run(const std::vector& ticks, - const trading_definitions::Configuration& config) { + const tradingDefinitions::Configuration& config) { // Function-local (stack) start time: each worker thread times only its own // run. steady_clock is monotonic, the correct clock for elapsed durations. @@ -54,16 +62,21 @@ void Operations::run(const std::vector& ticks, // in trading::runTicks so it can be driven with a deterministic strategy and // an inspectable TradeManager under test. The run-level risk limits make a // breaching run stop early (fail fast) instead of burning ticks. + // The loss floor is pip-denominated; scale it to points using the run's + // primary (first) symbol. Single-symbol/single-asset-class runs are exact. + const std::string primarySymbol = + config.SYMBOLS.substr(0, config.SYMBOLS.find(',')); const trading::RiskLimits riskLimits{ .startingBalance = config.STARTING_BALANCE, .maxLossPercent = config.MAX_LOSS_PERCENT, .maxOpenTrades = config.MAX_OPEN_TRADES, + .pointsPerPip = symbol_scale::get(primarySymbol), }; const trading::RunStatus status = trading::runTicks(tradeManager, *strategy, ticks, config.STRATEGY.TRADING_VARIABLES, riskLimits); - Reporting::summarise(tradeManager); + ResultsSummary::summarise(tradeManager); // Elapsed backtest time for this run, measured from the top of run(). The // Elasticsearch PUT below is deliberately excluded so the duration reflects @@ -74,7 +87,7 @@ void Operations::run(const std::vector& ticks, // Per-run completion line, suppressed under concurrent (quiet) sweeps to // match the other per-run logs. - if (!backtest_log::quiet) { + if (!backtest_log::is_quiet()) { if (status == trading::RunStatus::LossLimitBreached) { std::println("Operations: run RUN_ID={} stopped after {:.3f}s — account loss limit reached", config.RUN_ID, durationSeconds); @@ -101,9 +114,12 @@ void Operations::run(const std::vector& ticks, } // Open trades were liquidated at their last marked prices on the // breach, so calculatePnl() is the true account PnL at cutoff. + // PnL is int64 points-per-lot; report it in pips. + const double pnlPips = riskLimits.pointsPerPip != 0 + ? static_cast(tradeManager.calculatePnl()) / riskLimits.pointsPerPip + : 0.0; std::ostringstream reason; - reason << "account loss limit reached: PnL " - << tradeManager.calculatePnl() << " breached " + reason << "account loss limit reached: PnL " << pnlPips << " pips breached " << config.MAX_LOSS_PERCENT << "% of starting balance " << config.STARTING_BALANCE << " (open trades liquidated)"; const TradingFailure failure{ @@ -112,7 +128,7 @@ void Operations::run(const std::vector& ticks, durationSeconds, reason.str(), config, - Reporting::collect(tradeManager), + ResultsSummary::collect(tradeManager), }; ElasticClient::putTradingFailure(failure); } else { @@ -121,7 +137,7 @@ void Operations::run(const std::vector& ticks, TradingResults::nowIsoUtc(), durationSeconds, config, - Reporting::collect(tradeManager), + ResultsSummary::collect(tradeManager), }; ElasticClient::putTradingResults(results); } diff --git a/source/reporting/elasticClient.cpp b/source/run/reporting/elasticClient.cppm similarity index 81% rename from source/reporting/elasticClient.cpp rename to source/run/reporting/elasticClient.cppm index 0f3d3a7..a4eb51b 100644 --- a/source/reporting/elasticClient.cpp +++ b/source/run/reporting/elasticClient.cppm @@ -4,18 +4,31 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "reporting/elasticClient.hpp" - -#include -#include +module; #include #include #include #include -#include "backtestLog.hpp" -#include "env.hpp" +#include "shared/utilities/backtestLog.hpp" +#include "shared/utilities/env.hpp" +#include "run/reporting/tradingResults.hpp" + +export module elasticClient; + +import std; // replaces , + +// Minimal Elasticsearch HTTP client — PUT-only, for indexing run outcomes. +// Host is read from $ELASTIC_HOST (default http://localhost:9200) with optional +// HTTP basic auth from $ELASTIC_USER / $ELASTIC_USER_PASSWORD. Completed runs +// land in index "trading_results"; runs cut off early (loss limit) land in +// "trading_failures". Each doc gets a freshly generated UUID. +export class ElasticClient { +public: + static int putTradingResults(const TradingResults& results); + static int putTradingFailure(const TradingFailure& failure); +}; namespace { @@ -34,7 +47,8 @@ std::string generateUuid() { // Swallow the response body so curl does not dump it to stdout (its default // behaviour when no write callback is configured). -size_t discardResponse(char* /*ptr*/, size_t size, size_t nmemb, void* /*userdata*/) { +std::size_t discardResponse(char* /*ptr*/, std::size_t size, std::size_t nmemb, + void* /*userdata*/) { return size * nmemb; } @@ -104,7 +118,7 @@ int putDocument(const std::string& index, const std::string& body) { return 3; } // Per-strategy success line is skipped under concurrent backtests (quiet). - if (!backtest_log::quiet) { + if (!backtest_log::is_quiet()) { std::cout << "ElasticClient: PUT " << url << " (HTTP " << httpStatus << ")" << std::endl; } diff --git a/source/trading/reporting.cpp b/source/run/reporting/resultsSummary.cppm similarity index 72% rename from source/trading/reporting.cpp rename to source/run/reporting/resultsSummary.cppm index ce98534..595741e 100644 --- a/source/trading/reporting.cpp +++ b/source/run/reporting/resultsSummary.cppm @@ -4,16 +4,26 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "reporting.hpp" -#include -#include -#include +module; + #include -#include "backtestLog.hpp" -#include "trade.hpp" -#include "tradingResults.hpp" -TradingResultsStats Reporting::collect(const TradeManager& tradeManager) { +#include "shared/utilities/backtestLog.hpp" +#include "run/reporting/tradingResults.hpp" + +export module resultsSummary; + +import std; // replaces , , +import tradeManager; // TradeManager +import trade; // Trade, Direction + +export class ResultsSummary { +public: + static TradingResultsStats collect(const TradeManager& tradeManager); + static void summarise(const TradeManager& tradeManager); +}; + +TradingResultsStats ResultsSummary::collect(const TradeManager& tradeManager) { const auto& activeTrades = tradeManager.getActiveTrades(); const auto& closedTrades = tradeManager.getClosedTrades(); @@ -33,16 +43,19 @@ TradingResultsStats Reporting::collect(const TradeManager& tradeManager) { std::size_t losers = 0; std::size_t breakeven = 0; std::size_t liquidated = 0; - boost::decimal::decimal64_t pnlSum{0}; - const boost::decimal::decimal64_t zero{0}; + boost::decimal::decimal64_t pnlSum{0}; // accumulated in pips for (const auto& trade : closedTrades) { if (trade.direction == Direction::LONG) ++closedLong; else ++closedShort; - if (trade.pnl > zero) ++winners; - else if (trade.pnl < zero) ++losers; + if (trade.pnl > 0) ++winners; + else if (trade.pnl < 0) ++losers; else ++breakeven; if (trade.liquidated) ++liquidated; - pnlSum += trade.pnl; + // trade.pnl is int64 points-per-lot; convert to pips using the trade's + // own points-per-pip so mixed-symbol runs sum correctly. + if (trade.scalingFactor != 0) { + pnlSum += boost::decimal::decimal64_t{trade.pnl} / trade.scalingFactor; + } } openedLong += closedLong; openedShort += closedShort; @@ -67,9 +80,9 @@ TradingResultsStats Reporting::collect(const TradeManager& tradeManager) { return stats; } -void Reporting::summarise(const TradeManager& tradeManager) { +void ResultsSummary::summarise(const TradeManager& tradeManager) { // Per-strategy summary is skipped under concurrent backtests (quiet). - if (backtest_log::quiet) { + if (backtest_log::is_quiet()) { return; } diff --git a/source/tradingResults.cpp b/source/run/reporting/tradingResults.cpp similarity index 97% rename from source/tradingResults.cpp rename to source/run/reporting/tradingResults.cpp index 2f4fa9f..00d57a1 100644 --- a/source/tradingResults.cpp +++ b/source/run/reporting/tradingResults.cpp @@ -4,7 +4,7 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "tradingResults.hpp" +#include "run/reporting/tradingResults.hpp" #include #include diff --git a/include/tradingResults.hpp b/source/run/reporting/tradingResults.hpp similarity index 73% rename from include/tradingResults.hpp rename to source/run/reporting/tradingResults.hpp index e186e61..c4c729b 100644 --- a/include/tradingResults.hpp +++ b/source/run/reporting/tradingResults.hpp @@ -13,24 +13,24 @@ #include #include -#include "utilities/decimal_json.hpp" -#include "trading_definitions.hpp" +#include "shared/utilities/decimalJson.hpp" +#include "shared/tradingDefinitions.hpp" -// Per-run summary mirroring what Reporting::summarise prints today. +// Per-run summary mirroring what ResultsSummary::summarise prints today. struct TradingResultsStats { boost::decimal::decimal64_t finalPnl; - std::size_t tradesOpened; - std::size_t tradesClosed; - std::size_t openedLong; - std::size_t openedShort; - std::size_t closedLong; - std::size_t closedShort; - std::size_t winners; - std::size_t losers; - std::size_t breakeven; + std::size_t tradesOpened = 0; + std::size_t tradesClosed = 0; + std::size_t openedLong = 0; + std::size_t openedShort = 0; + std::size_t closedLong = 0; + std::size_t closedShort = 0; + std::size_t winners = 0; + std::size_t losers = 0; + std::size_t breakeven = 0; // Closes forced by the account loss limit, so winners/losers/avgPnl can // be read net of liquidation noise. - std::size_t liquidated; + std::size_t liquidated = 0; std::optional avgPnl; }; @@ -40,7 +40,7 @@ struct TradingResults { std::string RUN_ID; std::string timestamp; double durationSeconds; // wall-clock seconds for this run's backtest - trading_definitions::Configuration config; + tradingDefinitions::Configuration config; TradingResultsStats results; static std::string nowIsoUtc(); @@ -54,7 +54,7 @@ struct TradingFailure { std::string timestamp; double durationSeconds; // wall-clock seconds until the cutoff std::string reason; - trading_definitions::Configuration config; + tradingDefinitions::Configuration config; TradingResultsStats results; }; diff --git a/source/run/runCommand.cppm b/source/run/runCommand.cppm new file mode 100644 index 0000000..b7a6355 --- /dev/null +++ b/source/run/runCommand.cppm @@ -0,0 +1,40 @@ +// Backtesting Engine in C++ +// +// (c) 2026 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +module; + +#include "shared/utilities/env.hpp" +#include "shared/utilities/jsonParser.hpp" +#include "shared/redis/redisRunner.hpp" + +export module runCommand; + +import std; // replaces , +import backtestRunner; // runBacktest + +// Backs the `run` subcommand: drains BACKTESTING_QUEUE_RUN (loading each run's +// QuestDB ticks once, then running its strategies), or runs a single Base64 +// Configuration supplied directly on the command line. +export class RunCommand { +public: + static int run(int argc, const char* argv[]); +}; + +int RunCommand::run(int argc, const char* argv[]) { + + if (argc < 3) { + std::println(stderr, "Usage: BacktestingEngine run \n" + " BacktestingEngine run "); + return 1; + } + + if (argc == 3) { + return RedisRunner::run(argv[2], env::getOr("REDIS_HOST", "127.0.0.1")); + } + + const auto config = JsonParser::parseConfigurationFromBase64(argv[3]); + return runBacktest(argv[2], config); +} diff --git a/source/run/trading/exitRules.cppm b/source/run/trading/exitRules.cppm new file mode 100644 index 0000000..a82f7b2 --- /dev/null +++ b/source/run/trading/exitRules.cppm @@ -0,0 +1,49 @@ +// Backtesting Engine in C++ +// +// (c) 2026 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +export module exitRules; + +import std; // replaces , +import trade; // Trade, Direction +import priceData; // PriceData + +export namespace trading::exit_rules { + +// Decide whether the current tick has hit a trade's stop-loss or +// take-profit boundary. Returns the price at which the position would +// close (bid for LONG exits, ask for SHORT exits); `std::nullopt` +// means "no exit on this tick". +// +// SL/TP distances are anchored on the close-side of the entry spread +// (`trade.exitReferencePrice`: the entry-tick bid for LONG, entry-tick +// ask for SHORT) — the price the trade would actually exit at — not +// from the execution price. So a 1-pip stop on a LONG means "exit when +// bid drops 1 pip below the entry bid", which prevents the spread +// itself from triggering an exit on the opening tick. +// +// Distances and the resulting trigger prices are scaled-integer price points +// (a value of 10 on EURUSD, scale 100000, is 10 points == 0.0001 == one classic +// pip). trade.stopPrice / trade.limitPrice are precomputed once in +// TradeManager::openTrade, so this hot-path check is pure integer comparison — +// no decimal arithmetic. Trades on unknown symbols (scale 0) are skipped, and a +// zero distance means that leg is disarmed. +inline std::optional +checkExit(const Trade& trade, const PriceData& tick) { + if (trade.scalingFactor == 0) return std::nullopt; + + if (trade.direction == Direction::LONG) { + // Exit a long at the bid (the price the broker pays us). + if (trade.stopDistancePips != 0 && tick.bid <= trade.stopPrice) return tick.bid; + if (trade.limitDistancePips != 0 && tick.bid >= trade.limitPrice) return tick.bid; + } else { + // Exit a short at the ask (the price we pay to buy back). + if (trade.stopDistancePips != 0 && tick.ask >= trade.stopPrice) return tick.ask; + if (trade.limitDistancePips != 0 && tick.ask <= trade.limitPrice) return tick.ask; + } + return std::nullopt; +} + +} // namespace trading::exit_rules diff --git a/include/trading/reviewStopAndLimit.hpp b/source/run/trading/reviewStopAndLimit.cppm similarity index 78% rename from include/trading/reviewStopAndLimit.hpp rename to source/run/trading/reviewStopAndLimit.cppm index 8afb610..7f2ac27 100644 --- a/include/trading/reviewStopAndLimit.hpp +++ b/source/run/trading/reviewStopAndLimit.cppm @@ -4,16 +4,14 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#pragma once -#include -#include -#include -#include -#include "tradeManager.hpp" -#include "exitRules.hpp" -#include "models/priceData.hpp" +export module reviewStopAndLimit; -namespace trading { +import std; // replaces , , , +import tradeManager; // TradeManager +import exitRules; // trading::exit_rules::checkExit +import priceData; // PriceData + +export namespace trading { // Walk every active trade, close any whose SL/TP has been hit on this // tick. Two-phase to avoid invalidating the map iterator while erasing. @@ -27,7 +25,7 @@ inline void reviewStopAndLimit(TradeManager& tradeManager, const PriceData& tick const auto& openTrades = tradeManager.getActiveTrades(); if (openTrades.empty()) return; - std::vector> toClose; + std::vector> toClose; toClose.reserve(openTrades.size()); for (const auto& [id, trade] : openTrades) { if (trade.symbol != tick.symbol) continue; diff --git a/include/trading/runLoop.hpp b/source/run/trading/runLoop.cppm similarity index 75% rename from include/trading/runLoop.hpp rename to source/run/trading/runLoop.cppm index 9842f09..33f2785 100644 --- a/include/trading/runLoop.hpp +++ b/source/run/trading/runLoop.cppm @@ -4,25 +4,36 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#pragma once -#include -#include "tradeManager.hpp" -#include "reviewStopAndLimit.hpp" -#include "models/priceData.hpp" -#include "strategies/strategy.hpp" // IStrategy -#include "trading_definitions/run_configuration.hpp" // DEFAULT_STARTING_BALANCE -#include "trading_definitions/trading_variables.hpp" +module; -namespace trading { +#include + +#include "shared/tradingDefinitions/runConfiguration.hpp" // DEFAULT_STARTING_BALANCE +#include "shared/tradingDefinitions/tradingVariables.hpp" + +export module runLoop; + +import std; // replaces , +import tradeManager; // TradeManager +import reviewStopAndLimit; // trading::reviewStopAndLimit +import priceData; // PriceData +import strategy; // IStrategy + +export namespace trading { // Run-level risk limits, shared by every strategy in a sweep (they come from // RunConfiguration). <= 0 disables the respective check, so unconstrained // experiments need no extra flag. struct RiskLimits { boost::decimal::decimal64_t startingBalance{ - trading_definitions::DEFAULT_STARTING_BALANCE}; + tradingDefinitions::DEFAULT_STARTING_BALANCE}; boost::decimal::decimal64_t maxLossPercent{0}; int maxOpenTrades{0}; + // Points-per-pip of the run's symbol — converts the pip-denominated loss + // floor into the integer points the PnL is tracked in. Defaults to 1 (floor + // stays in raw points) for callers/tests that don't set it. Set by + // Operations::run from the run's symbol; exact for single-asset-class runs. + int pointsPerPip{1}; }; // How a run ended: ran out of ticks, or was cut off because realized losses @@ -52,16 +63,19 @@ enum class RunStatus { inline RunStatus runTicks(TradeManager& tradeManager, IStrategy& strategy, const std::vector& ticks, - const trading_definitions::TradingVariables& vars, + const tradingDefinitions::TradingVariables& vars, const RiskLimits& limits = {}) { const boost::decimal::decimal64_t zero{0}; const bool lossLimitActive = limits.maxLossPercent > zero; - // Lowest equity PnL the run may reach, e.g. 10000 at 5% -> -500. - const auto pnlFloor = - -(limits.startingBalance * limits.maxLossPercent / 100); + // Lowest equity the run may reach, in int64 points. balance * loss% gives + // the floor in pips; scaling by points-per-pip puts it in the same integer + // points the PnL is tracked in, e.g. 10000 at 5% on EURUSD (10 pts/pip) -> + // -500 pips -> -5000 points. Computed once; the per-tick check is integer. + const std::int64_t pnlFloorPoints = -static_cast( + limits.startingBalance * limits.maxLossPercent / 100 * limits.pointsPerPip); const auto lossLimitBreached = [&] { return lossLimitActive && - tradeManager.calculatePnl() + tradeManager.unrealizedPnl() <= pnlFloor; + tradeManager.calculatePnl() + tradeManager.unrealizedPnl() <= pnlFloorPoints; }; for (const auto& tick : ticks) { diff --git a/source/run/trading/tradeManager.cppm b/source/run/trading/tradeManager.cppm new file mode 100644 index 0000000..2d7d4f9 --- /dev/null +++ b/source/run/trading/tradeManager.cppm @@ -0,0 +1,209 @@ +// Backtesting Engine in C++ +// +// (c) 2025 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +module; + +#include // POSIX gmtime_r (not exported by `import std`) + +#include "shared/utilities/backtestLog.hpp" + +export module tradeManager; + +import std; // replaces , , , , + // , , , , , , + // , +import trade; // Trade, Direction +import priceData; // PriceData + +export class TradeManager { +private: + std::unordered_map activeTrades; + std::vector closedTrades; + // Running sums (int64 points-per-lot) maintained by openTrade/markToMarket/ + // closeTrade so the per-tick loss-limit check in runTicks stays O(1): + // realized PnL across closed trades, and floating (mark-to-market) PnL + // across open ones. + std::int64_t closedPnl{0}; + std::int64_t openPnl{0}; + +public: + TradeManager() = default; + std::string openTrade(const PriceData& tick, + std::int32_t size, + Direction direction, + std::int32_t stopDistancePips = 0, + std::int32_t limitDistancePips = 0); + std::size_t reviewAccount() const; + bool hasActiveTradeForSymbol(std::string_view symbol) const; + // `liquidated` marks the close as forced by the account loss limit + // rather than earned via SL/TP or strategy logic. + bool closeTrade(const std::string& tradeId, + std::int32_t closePrice, + const PriceData& tick, + bool liquidated = false); + const std::unordered_map& getActiveTrades() const; + const std::vector& getClosedTrades() const; + // Realized PnL (int64 points-per-lot) across all closed trades. O(1). + std::int64_t calculatePnl() const; + // Floating (mark-to-market) PnL (int64 points-per-lot) across all open + // trades, as of each trade's last marked price. O(1). + std::int64_t unrealizedPnl() const; + // Revalue open trades for this tick's symbol at its close-side price + // (bid for LONG, ask for SHORT), updating their floating PnL. + void markToMarket(const PriceData& tick); + // Liquidate every open trade at its last marked price (timestamped with + // `tick`), realizing the floating PnL — used when a run is cut off. + void closeAllTrades(const PriceData& tick); +}; + +namespace { +std::string nextTradeId() { + static std::atomic counter{0}; + return std::format("T{}", counter.fetch_add(1)); +} + +// Floating PnL (int64 points-per-lot) of an open trade valued at `mark` — the +// same formula closeTrade uses for realized PnL, so liquidating at the last +// mark realizes exactly the floating amount. Pure integer: no decimal on the +// per-tick path. Divide by scalingFactor for pips at the reporting boundary. +std::int64_t floatingPnlAt(const Trade& trade, std::int32_t mark) { + std::int32_t diff = mark - trade.entryPrice; + if (trade.direction == Direction::SHORT) diff = -diff; + return static_cast(diff) * trade.size; +} +} + +std::string TradeManager::openTrade(const PriceData& tick, + std::int32_t size, + Direction direction, + std::int32_t stopDistancePips, + std::int32_t limitDistancePips) { + auto price = (direction == Direction::LONG) ? tick.ask : tick.bid; + Trade trade(price, size, direction, tick.symbol); + trade.entryBid = tick.bid; + trade.entryAsk = tick.ask; + trade.id = nextTradeId(); + trade.stopDistancePips = stopDistancePips; + trade.limitDistancePips = limitDistancePips; + trade.exitReferencePrice = (direction == Direction::LONG) ? tick.bid : tick.ask; + // Precompute the SL/TP trigger prices once, so the per-tick exit check is a + // pure integer comparison. Distances are in pips; convert to stored points + // here (pips * points-per-pip) and anchor on exitReferencePrice (the + // close-side of the entry spread). + const std::int32_t stopOffset = stopDistancePips * trade.scalingFactor; + const std::int32_t limitOffset = limitDistancePips * trade.scalingFactor; + if (direction == Direction::LONG) { + trade.stopPrice = trade.exitReferencePrice - stopOffset; + trade.limitPrice = trade.exitReferencePrice + limitOffset; + } else { + trade.stopPrice = trade.exitReferencePrice + stopOffset; + trade.limitPrice = trade.exitReferencePrice - limitOffset; + } + // Mark the trade at its entry tick: the close side of the spread. The + // initial floating PnL is therefore the spread cost — true mark-to-market + // equity dips by the spread the moment a trade opens. + trade.lastMarkPrice = trade.exitReferencePrice; + trade.floatingPnl = floatingPnlAt(trade, trade.lastMarkPrice); + openPnl += trade.floatingPnl; + activeTrades[trade.id] = trade; + return trade.id; +} + +void TradeManager::markToMarket(const PriceData& tick) { + for (auto& [id, trade] : activeTrades) { + if (trade.symbol != tick.symbol) continue; + const auto mark = (trade.direction == Direction::LONG) ? tick.bid : tick.ask; + const auto updated = floatingPnlAt(trade, mark); + openPnl += updated - trade.floatingPnl; + trade.floatingPnl = updated; + trade.lastMarkPrice = mark; + } +} + +void TradeManager::closeAllTrades(const PriceData& tick) { + // Snapshot ids/prices first: closeTrade mutates activeTrades. + std::vector> toClose; + toClose.reserve(activeTrades.size()); + for (const auto& [id, trade] : activeTrades) { + toClose.emplace_back(id, trade.lastMarkPrice); + } + for (const auto& [id, price] : toClose) { + closeTrade(id, price, tick, /*liquidated=*/true); + } +} + +std::size_t TradeManager::reviewAccount() const { + return activeTrades.size(); +} + +bool TradeManager::hasActiveTradeForSymbol(std::string_view symbol) const { + return std::any_of(activeTrades.begin(), activeTrades.end(), + [symbol](const auto& pair) { + return pair.second.symbol == symbol; + }); +} + +bool TradeManager::closeTrade(const std::string& tradeId, + std::int32_t closePrice, + const PriceData& tick, + bool liquidated) { + auto it = activeTrades.find(tradeId); + if (it != activeTrades.end()) { + Trade closed = it->second; + closed.closePrice = closePrice; + closed.closeTime = tick.timestamp; + closed.liquidated = liquidated; + std::int32_t diff = closePrice - closed.entryPrice; + if (closed.direction == Direction::SHORT) diff = -diff; + // Realized PnL in int64 points-per-lot (converted to pips at reporting). + closed.pnl = static_cast(diff) * closed.size; + closedPnl += closed.pnl; + openPnl -= it->second.floatingPnl; // realized now, no longer floating + closed.floatingPnl = 0; + closedTrades.push_back(closed); + activeTrades.erase(it); + + // Per-trade chatter is skipped under concurrent backtests (quiet), + // which also avoids the formatting work below. + if (!backtest_log::is_quiet()) { + auto t = std::chrono::system_clock::to_time_t(tick.timestamp); + std::tm utc{}; + gmtime_r(&t, &utc); + std::ostringstream ts; + ts << std::put_time(&utc, "%Y-%m-%dT%H:%M:%SZ"); + + const char* side = (closed.direction == Direction::LONG) ? "BUY" : "SELL"; + // PnL is stored in points-per-lot; show it in pips for readability. + const double pnlPips = closed.scalingFactor != 0 + ? static_cast(closed.pnl) / closed.scalingFactor + : 0.0; + std::cout << ts.str() + << ", Trade Closed, " << closed.symbol + << ", " << side + << ", " << std::showpos << std::fixed << std::setprecision(2) << pnlPips + << std::noshowpos + << std::endl; + } + return true; + } + return false; +} + +const std::unordered_map& TradeManager::getActiveTrades() const { + return activeTrades; +} + +const std::vector& TradeManager::getClosedTrades() const { + return closedTrades; +} + +std::int64_t TradeManager::calculatePnl() const { + return closedPnl; +} + +std::int64_t TradeManager::unrealizedPnl() const { + return openPnl; +} diff --git a/source/shared/models/priceData.cppm b/source/shared/models/priceData.cppm new file mode 100644 index 0000000..4e1c081 --- /dev/null +++ b/source/shared/models/priceData.cppm @@ -0,0 +1,28 @@ +// Backtesting Engine in C++ +// +// (c) 2026 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +export module priceData; + +import std; // replaces , , + +// ask/bid are scaled fixed-point integers as stored in QuestDB: the real price +// multiplied by the symbol's fixed multiplier (FX majors x100000, JPY pairs & +// metals x1000, indices/commodities x100 — see the symbolScale module). e.g. +// EURUSD 1.10001 is stored as 110001. Integer prices keep the per-tick loop free +// of software-emulated decimal arithmetic; PnL/balance stay decimal64_t at the +// boundary. Largest scaled value (~4.5M for indices) fits comfortably in int32. +export struct PriceData { + std::int32_t ask; + std::int32_t bid; + std::chrono::system_clock::time_point timestamp; + std::string symbol; + + PriceData(std::int32_t ask, std::int32_t bid, + const std::chrono::system_clock::time_point& ts, const std::string& symbol) + : ask(ask), bid(bid), timestamp(ts), symbol(symbol) {} + + PriceData() : ask(0), bid(0), timestamp{}, symbol("") {} +}; diff --git a/include/models/trade.hpp b/source/shared/models/trade.cppm similarity index 56% rename from include/models/trade.hpp rename to source/shared/models/trade.cppm index 5ea1f97..0e0bf53 100644 --- a/include/models/trade.hpp +++ b/source/shared/models/trade.cppm @@ -4,49 +4,59 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#pragma once -#include -#include -#include -#include "symbolScale.hpp" -#include +export module trade; -enum class Direction { +import std; // replaces , , , +import symbolScale; // symbol_scale::get for the scaling factor + +export enum class Direction { LONG, SHORT }; -struct Trade { +export struct Trade { std::string id; - boost::decimal::decimal64_t entryPrice; - boost::decimal::decimal64_t entryBid; - boost::decimal::decimal64_t entryAsk; - boost::decimal::decimal64_t size; + // Everything is integer: prices/exit-prices are scaled INT32 points (see + // the priceData / symbolScale modules), distances are whole pips, size is + // whole lots, and PnL is int64 points-per-lot. Pips are derived only at the + // display/reporting boundary (points / scalingFactor). + std::int32_t entryPrice; + std::int32_t entryBid; + std::int32_t entryAsk; + std::int32_t size; std::chrono::system_clock::time_point openTime; Direction direction; std::string dealReference; std::string symbol; int scalingFactor; - boost::decimal::decimal64_t stopDistancePips; - boost::decimal::decimal64_t limitDistancePips; - boost::decimal::decimal64_t exitReferencePrice; + // SL/TP distances in integer price points (same scale as prices); a value + // of 0 means that leg is disarmed. + std::int32_t stopDistancePips; + std::int32_t limitDistancePips; + std::int32_t exitReferencePrice; + // Exit trigger prices, precomputed once in TradeManager::openTrade from + // exitReferencePrice +/- the distances, so the per-tick exit check is a pure + // integer comparison. Only meaningful when the matching distance is non-zero. + std::int32_t stopPrice; + std::int32_t limitPrice; std::string strategyId; std::string strategyName; - boost::decimal::decimal64_t closePrice; + std::int32_t closePrice = 0; std::chrono::system_clock::time_point closeTime; - // Realised profit/loss for this trade in pip-points, populated on close. - // Pip-PnL = price difference * scalingFactor * size (sign flipped for SHORT). - boost::decimal::decimal64_t pnl; + // Realised profit/loss in int64 points-per-lot, populated on close: + // PnL = (closePrice - entryPrice) * size (sign flipped for SHORT). Divide by + // scalingFactor (points-per-pip) at the reporting boundary to get pips. + std::int64_t pnl; // Mark-to-market state while the trade is open, maintained by // TradeManager: the most recent close-side price seen for this symbol and // the floating PnL at that price. Feeds the account loss limit, and // lastMarkPrice is the liquidation price if the run is cut off. // floatingPnl is zeroed on close — its value has been realized into pnl. - boost::decimal::decimal64_t lastMarkPrice; - boost::decimal::decimal64_t floatingPnl; + std::int32_t lastMarkPrice; + std::int64_t floatingPnl; // True when the close was forced by the account loss limit (liquidation // at the last marked price) rather than earned via SL/TP or strategy @@ -56,7 +66,7 @@ struct Trade { // Default constructor Trade() : entryPrice(0), entryBid(0), entryAsk(0), size(0), direction(Direction::LONG), scalingFactor(0), stopDistancePips(0), limitDistancePips(0), - exitReferencePrice(0), + exitReferencePrice(0), stopPrice(0), limitPrice(0), closePrice(0), pnl(0), lastMarkPrice(0), floatingPnl(0), openTime(std::chrono::system_clock::now()) {} @@ -67,7 +77,7 @@ struct Trade { // Member initializers run in declaration order, not the order written // here, so it's safe to derive `scalingFactor` from `tradeSymbol` // regardless of where these appear in the list. - Trade(boost::decimal::decimal64_t price, boost::decimal::decimal64_t quantity, Direction dir, std::string_view tradeSymbol) + Trade(std::int32_t price, std::int32_t quantity, Direction dir, std::string_view tradeSymbol) : entryPrice(price), entryBid(0), entryAsk(0), @@ -79,6 +89,8 @@ struct Trade { stopDistancePips(0), limitDistancePips(0), exitReferencePrice(0), + stopPrice(0), + limitPrice(0), pnl(0), lastMarkPrice(0), floatingPnl(0) { diff --git a/source/databaseConnection.cpp b/source/shared/questdb/databaseConnection.cppm similarity index 66% rename from source/databaseConnection.cpp rename to source/shared/questdb/databaseConnection.cppm index e6f6154..33b4239 100644 --- a/source/databaseConnection.cpp +++ b/source/shared/questdb/databaseConnection.cppm @@ -1,15 +1,39 @@ // Backtesting Engine in C++ // -// (c) 2026 Ryan McCaffery | https://mccaffers.com +// (c) 2025 Ryan McCaffery | https://mccaffers.com // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "databaseConnection.hpp" +module; + +#include // POSIX timegm (not exported by `import std`) + #include -#include -#include -#include -#include + +export module databaseConnection; + +import std; // replaces , , , , , + // , , , +import priceData; // PriceData + +export class DatabaseConnection { +private: + std::string connection_string; + +public: + DatabaseConnection(const std::string& endpoint = "localhost", + int port = 8812, + const std::string& dbname = "qdb", + const std::string& user = "admin", + const std::string& password = ""); + + std::vector executeQuery(const std::string& query) const; + + const std::string& getConnectionString() const { + return connection_string; + } + +}; class InvalidTimestampFormatError : public std::runtime_error { public: @@ -21,7 +45,7 @@ class InvalidTimestampFormatError : public std::runtime_error { // the parse stays safe if loading ever moves onto the ThreadPool. struct DateCache { std::string date; - time_t epoch = 0; + std::time_t epoch = 0; }; static std::chrono::system_clock::time_point fastParseTimestamp(const char* ts, DateCache& cache) { @@ -49,7 +73,7 @@ static std::chrono::system_clock::time_point fastParseTimestamp(const char* ts, cache.epoch = timegm(&tm); } - time_t t = cache.epoch + hour * 3600 + min * 60 + sec; + std::time_t t = cache.epoch + hour * 3600 + min * 60 + sec; return std::chrono::system_clock::from_time_t(t) + std::chrono::microseconds(usec); } @@ -72,15 +96,16 @@ std::vector DatabaseConnection::executeQuery(const std::string& query for (std::size_t i = 0; i < result.size(); ++i) { const auto& row = result[static_cast(i)]; - boost::decimal::decimal64_t ask; - boost::decimal::decimal64_t bid; + std::int32_t ask = 0; + std::int32_t bid = 0; auto symbol = row[0].view(); auto sv1 = row[1].view(); auto sv2 = row[2].view(); - // boost::decimal ships its own from_chars overload — std::from_chars - // doesn't know about decimal64_t. - const auto askResult = boost::decimal::from_chars(sv1.data(), sv1.data() + sv1.size(), ask); - const auto bidResult = boost::decimal::from_chars(sv2.data(), sv2.data() + sv2.size(), bid); + // ask/bid are INT32 scaled fixed-point in QuestDB now, so a plain + // integer parse replaces the decimal from_chars — no decimal arithmetic + // touches the load path. + const auto askResult = std::from_chars(sv1.data(), sv1.data() + sv1.size(), ask); + const auto bidResult = std::from_chars(sv2.data(), sv2.data() + sv2.size(), bid); if (askResult.ec != std::errc{} || bidResult.ec != std::errc{}) { throw std::runtime_error(std::format( "Failed to parse price for {}: ask='{}' bid='{}'", symbol, sv1, sv2)); diff --git a/source/sqlManager.cpp b/source/shared/questdb/sqlManager.cppm similarity index 70% rename from source/sqlManager.cpp rename to source/shared/questdb/sqlManager.cppm index 05391b8..79509ed 100644 --- a/source/sqlManager.cpp +++ b/source/shared/questdb/sqlManager.cppm @@ -3,13 +3,18 @@ // (c) 2026 Ryan McCaffery | https://mccaffers.com // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "sqlManager.hpp" -#include "models/symbolScale.hpp" -#include -#include -#include -#include -#include + +export module sqlManager; + +import std; // replaces , , , , +import priceData; // PriceData +import databaseConnection; // DatabaseConnection +import symbolScale; // symbol_scale::get / kUnknown + +export class SqlManager { +public: + static std::vector loadPriceData(const DatabaseConnection& db, const std::vector& symbols, int LAST_MONTHS = 1); +}; std::vector SqlManager::loadPriceData(const DatabaseConnection& db, const std::vector& symbols, int LAST_MONTHS) { if (symbols.empty()) { @@ -26,7 +31,7 @@ std::vector SqlManager::loadPriceData(const DatabaseConnection& db, c } std::ostringstream query; - for (size_t i = 0; i < symbols.size(); ++i) { + for (std::size_t i = 0; i < symbols.size(); ++i) { if (i > 0) { query << " UNION ALL "; } diff --git a/source/shared/redis/backtestRunner.cppm b/source/shared/redis/backtestRunner.cppm new file mode 100644 index 0000000..b798d9d --- /dev/null +++ b/source/shared/redis/backtestRunner.cppm @@ -0,0 +1,61 @@ +// Backtesting Engine in C++ +// +// (c) 2026 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +module; + +#include "shared/utilities/env.hpp" +#include "shared/tradingDefinitions/configuration.hpp" + +export module backtestRunner; + +import std; // replaces , , , +import priceData; // PriceData +import operations; // Operations +import sqlManager; // SqlManager +import databaseConnection; // DatabaseConnection + +// Pulls all tick data for the run's symbols/window out of QuestDB. Expensive — +// call once per run and reuse the result across that run's strategies. +export std::vector loadTicks(const std::string& questdbHost, + const std::string& symbolsCsv, + int lastMonths) { + + // QuestDB pg-wire port: defaults to 8812 but is overridable via QUESTDB_PORT + // so a non-default instance (e.g. a converted dataset) can be targeted + // without a rebuild. + const int questdbPort = std::stoi(env::getOr("QUESTDB_PORT", "8812")); + DatabaseConnection db(questdbHost, questdbPort, "qdb", "admin", "quest"); + + // Get a list of symbols + std::vector symbols; + std::istringstream ss(symbolsCsv); + for (std::string token; std::getline(ss, token, ',');) { + symbols.push_back(token); + } + + // Get all the tick data out of QuestDB for these symbols + std::vector ticks = + SqlManager::loadPriceData(db, symbols, lastMonths); + + std::printf("Total ticks streamed: %zu\n", ticks.size()); + + return ticks; +} + +// Runs one backtest against already-loaded ticks (no QuestDB access). +export void runBacktestOnTicks(const std::vector& ticks, + const tradingDefinitions::Configuration& config) { + Operations::run(ticks, config); +} + +// Convenience for the direct path: loads ticks then runs a single backtest. +export int runBacktest(const std::string& questdbHost, + const tradingDefinitions::Configuration& config) { + const std::vector ticks = + loadTicks(questdbHost, config.SYMBOLS, config.LAST_MONTHS); + runBacktestOnTicks(ticks, config); + return 0; +} diff --git a/source/boostRedisImpl.cpp b/source/shared/redis/boostRedisImpl.cpp similarity index 100% rename from source/boostRedisImpl.cpp rename to source/shared/redis/boostRedisImpl.cpp diff --git a/source/utilities/redisConnection.cpp b/source/shared/redis/redisConnection.cpp similarity index 96% rename from source/utilities/redisConnection.cpp rename to source/shared/redis/redisConnection.cpp index 3e75ac1..30e6053 100644 --- a/source/utilities/redisConnection.cpp +++ b/source/shared/redis/redisConnection.cpp @@ -4,7 +4,7 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "redisConnection.hpp" +#include "shared/redis/redisConnection.hpp" #include #include diff --git a/include/utilities/redisConnection.hpp b/source/shared/redis/redisConnection.hpp similarity index 100% rename from include/utilities/redisConnection.hpp rename to source/shared/redis/redisConnection.hpp diff --git a/source/redisLoader.cpp b/source/shared/redis/redisLoader.cpp similarity index 83% rename from source/redisLoader.cpp rename to source/shared/redis/redisLoader.cpp index 524f60a..5257847 100644 --- a/source/redisLoader.cpp +++ b/source/shared/redis/redisLoader.cpp @@ -4,7 +4,7 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "redisLoader.hpp" +#include "shared/redis/redisLoader.hpp" #include #include @@ -23,8 +23,8 @@ #include #include -#include "base64.hpp" -#include "redisConnection.hpp" +#include "shared/utilities/base64.hpp" +#include "shared/redis/redisConnection.hpp" namespace asio = boost::asio; namespace redis = boost::redis; @@ -69,10 +69,10 @@ int RedisLoader::loadPayload(const std::string& redisHost, int redisPort, const std::string& queueKey, const std::string& rawJson) { - const bool isBlank = std::all_of(rawJson.begin(), rawJson.end(), - [](unsigned char c) { - return std::isspace(c); - }); + const bool isBlank = std::ranges::all_of(rawJson, + [](unsigned char c) { + return std::isspace(c); + }); if (isBlank) { std::cerr << "RedisLoader: empty payload rejected" << std::endl; return 1; @@ -87,7 +87,7 @@ int RedisLoader::loadPayload(const std::string& redisHost, cfg.addr.host = redisHost; cfg.addr.port = std::to_string(redisPort); - conn->async_run(cfg, {}, asio::consign(asio::detached, conn)); + conn->async_run(cfg, asio::consign(asio::detached, conn)); std::exception_ptr pushError; @@ -115,7 +115,7 @@ int RedisLoader::loadPayload(const std::string& redisHost, } int RedisLoader::loadPayloadBatch(const std::string& redisHost, - int redisPort, + const int redisPort, const std::string& queueKey, const std::vector& rawJsonPayloads) { if (rawJsonPayloads.empty()) { @@ -125,10 +125,10 @@ int RedisLoader::loadPayloadBatch(const std::string& redisHost, std::vector encoded; encoded.reserve(rawJsonPayloads.size()); for (const std::string& rawJson : rawJsonPayloads) { - const bool isBlank = std::all_of(rawJson.begin(), rawJson.end(), - [](unsigned char c) { - return std::isspace(c); - }); + const bool isBlank = std::ranges::all_of(rawJson, + [](unsigned char c) { + return std::isspace(c); + }); if (isBlank) { std::cerr << "RedisLoader: empty payload rejected" << std::endl; return 1; @@ -144,7 +144,7 @@ int RedisLoader::loadPayloadBatch(const std::string& redisHost, asio::co_spawn( ioc, pushManyOnce(conn, queueKey, std::move(encoded)), - [&pushError](std::exception_ptr e) { + [&pushError](const std::exception_ptr& e) { if (e) { pushError = e; } diff --git a/include/redisLoader.hpp b/source/shared/redis/redisLoader.hpp similarity index 100% rename from include/redisLoader.hpp rename to source/shared/redis/redisLoader.hpp diff --git a/source/redisRunner.cpp b/source/shared/redis/redisRunner.cpp similarity index 91% rename from source/redisRunner.cpp rename to source/shared/redis/redisRunner.cpp index 4e86ff9..b71097a 100644 --- a/source/redisRunner.cpp +++ b/source/shared/redis/redisRunner.cpp @@ -4,7 +4,7 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "redisRunner.hpp" +#include "shared/redis/redisRunner.hpp" #include #include @@ -25,12 +25,12 @@ #include #include -#include "backtestLog.hpp" -#include "backtestRunner.hpp" -#include "jsonParser.hpp" -#include "queueKeys.hpp" -#include "redisConnection.hpp" -#include "threadPool.hpp" +#include "shared/utilities/backtestLog.hpp" +#include "shared/utilities/jsonParser.hpp" +#include "shared/utilities/queueKeys.hpp" +#include "shared/redis/redisConnection.hpp" +#include "shared/redis/runnerBridge.hpp" +#include "shared/utilities/threadPool.hpp" namespace asio = boost::asio; namespace redis = boost::redis; @@ -118,12 +118,15 @@ asio::awaitable drainRuns(std::shared_ptr conn, } waitingLogged = false; // got a run; re-arm the idle log for next time - const trading_definitions::RunConfiguration runCfg = JsonParser::parseRunConfigurationFromBase64(*descriptorB64); + const tradingDefinitions::RunConfiguration runCfg = JsonParser::parseRunConfigurationFromBase64(*descriptorB64); const std::string strategyKey = queue_keys::strategyKey(runCfg.RUN_ID); std::println("RedisRunner: picked up RUN_ID={} SYMBOLS={} LAST_MONTHS={}", runCfg.RUN_ID, runCfg.SYMBOLS, runCfg.LAST_MONTHS); // Pull this run's tick data once, then reuse across every strategy. - const std::vector ticks = loadTicks(questdbHost, runCfg.SYMBOLS, runCfg.LAST_MONTHS); + // `ticks` is an opaque shared handle (see runnerBridge.hpp) so this + // TU never names PriceData or imports a module. + const std::shared_ptr ticks = + bridgeLoadTicks(questdbHost, runCfg.SYMBOLS, runCfg.LAST_MONTHS); // Backtests run on the pool but every task reads this run's `ticks` // by reference (no copies). This guard joins all in-flight backtests @@ -148,7 +151,7 @@ asio::awaitable drainRuns(std::shared_ptr conn, // Reassemble the Configuration the rest of the pipeline expects. // Parsing stays on this thread; the worker only runs the backtest. - trading_definitions::Configuration config{ + tradingDefinitions::Configuration config{ .RUN_ID = runCfg.RUN_ID, .SYMBOLS = runCfg.SYMBOLS, .LAST_MONTHS = runCfg.LAST_MONTHS, @@ -159,7 +162,7 @@ asio::awaitable drainRuns(std::shared_ptr conn, .STRATEGY = JsonParser::parseStrategyFromBase64(*strategyB64), }; pool.submit([&ticks, cfg = std::move(config)]() { - runBacktestOnTicks(ticks, cfg); + bridgeRunOnTicks(*ticks, cfg); }); ++strategiesRun; } @@ -202,7 +205,7 @@ int RedisRunner::run(const std::string& questdbHost, int redisPort) { // Mute logs to prevent interleaved thread spam - backtest_log::quiet = true; + backtest_log::set_quiet(true); // Set up the async event loop asio::io_context ioc; diff --git a/include/redisRunner.hpp b/source/shared/redis/redisRunner.hpp similarity index 100% rename from include/redisRunner.hpp rename to source/shared/redis/redisRunner.hpp diff --git a/source/shared/redis/runnerBridge.cpp b/source/shared/redis/runnerBridge.cpp new file mode 100644 index 0000000..f7be6d1 --- /dev/null +++ b/source/shared/redis/runnerBridge.cpp @@ -0,0 +1,31 @@ +// Backtesting Engine in C++ +// +// (c) 2026 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +#include "shared/redis/runnerBridge.hpp" + +import std; +import priceData; // PriceData +import backtestRunner; // loadTicks, runBacktestOnTicks + +// The tick buffer the opaque handle wraps. Kept out of redisRunner.cpp so that +// TU never has to name PriceData (a module type) or import a module — see +// runnerBridge.hpp for why that matters. +struct LoadedTicks { + std::vector ticks; +}; + +std::shared_ptr bridgeLoadTicks(const std::string& questdbHost, + const std::string& symbolsCsv, + int lastMonths) { + auto loaded = std::make_shared(); + loaded->ticks = loadTicks(questdbHost, symbolsCsv, lastMonths); + return loaded; +} + +void bridgeRunOnTicks(const LoadedTicks& ticks, + const tradingDefinitions::Configuration& config) { + runBacktestOnTicks(ticks.ticks, config); +} diff --git a/source/shared/redis/runnerBridge.hpp b/source/shared/redis/runnerBridge.hpp new file mode 100644 index 0000000..49ed090 --- /dev/null +++ b/source/shared/redis/runnerBridge.hpp @@ -0,0 +1,30 @@ +// Backtesting Engine in C++ +// +// (c) 2026 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- +#pragma once +#include +#include +#include "shared/tradingDefinitions/configuration.hpp" + +// Opaque handle to a run's loaded tick data, defined in runnerBridge.cpp. +// +// runnerBridge.cpp is the import boundary to the backtestRunner module. +// redisRunner.cpp must stay a *purely textual* TU: its ThreadPool instantiates +// std::condition_variable_any::wait(lock, stop_token, pred), whose libc++ +// internal helper (__atomic_unique_lock::__set_locked_bit) the toolchain fails +// to emit when the same TU also imports a module. So redisRunner.cpp reaches +// the module only through these plain (global-module) functions, never naming +// PriceData or importing anything itself. +struct LoadedTicks; + +// Pulls a run's ticks out of QuestDB once; the handle is shared so tasks can +// hold it for the lifetime of their backtest. +std::shared_ptr bridgeLoadTicks(const std::string& questdbHost, + const std::string& symbolsCsv, + int lastMonths); + +// Runs a single backtest against already-loaded ticks (no QuestDB access). +void bridgeRunOnTicks(const LoadedTicks& ticks, + const tradingDefinitions::Configuration& config); diff --git a/source/shared/tradingDefinitions.hpp b/source/shared/tradingDefinitions.hpp new file mode 100644 index 0000000..3fef651 --- /dev/null +++ b/source/shared/tradingDefinitions.hpp @@ -0,0 +1,14 @@ +// Backtesting Engine in C++ +// +// (c) 2025 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- +#pragma once + +#include "shared/tradingDefinitions/ohlcVariables.hpp" +#include "shared/tradingDefinitions/ohlcRsiVariables.hpp" +#include "shared/tradingDefinitions/tradingVariables.hpp" +#include "shared/tradingDefinitions/strategyVariables.hpp" +#include "shared/tradingDefinitions/strategy.hpp" +#include "shared/tradingDefinitions/configuration.hpp" +#include "shared/tradingDefinitions/runConfiguration.hpp" diff --git a/include/trading_definitions/configuration.hpp b/source/shared/tradingDefinitions/configuration.hpp similarity index 75% rename from include/trading_definitions/configuration.hpp rename to source/shared/tradingDefinitions/configuration.hpp index 6d0350e..c7d24cc 100644 --- a/include/trading_definitions/configuration.hpp +++ b/source/shared/tradingDefinitions/configuration.hpp @@ -8,17 +8,22 @@ #include #include #include -#include "trading_definitions/run_configuration.hpp" -#include "trading_definitions/strategy.hpp" -#include "utilities/decimal_json.hpp" +#include "shared/tradingDefinitions/runConfiguration.hpp" +#include "shared/tradingDefinitions/strategy.hpp" +#include "shared/utilities/decimalJson.hpp" -namespace trading_definitions { +// Intentionally a plain header, NOT a .cppm module. Every JSON-serializable +// struct in this repo stays a GMF-includable header and is #include'd into the +// global module fragment of its consumers (next to ), because +// nlohmann's ADL-based to_json/from_json do not resolve reliably across a module +// import boundary. See source/.../*.cppm GMFs and the module-migration notes. +namespace tradingDefinitions { // The risk fields (STARTING_BALANCE, MAX_LOSS_PERCENT, MAX_OPEN_TRADES, // REPORT_FAILURES) mirror RunConfiguration — see the comments there. struct Configuration { std::string RUN_ID; std::string SYMBOLS; - int LAST_MONTHS; + int LAST_MONTHS = 0; boost::decimal::decimal64_t STARTING_BALANCE{DEFAULT_STARTING_BALANCE}; boost::decimal::decimal64_t MAX_LOSS_PERCENT{0}; int MAX_OPEN_TRADES{0}; diff --git a/include/trading_definitions/ohlc_rsi_variables.hpp b/source/shared/tradingDefinitions/ohlcRsiVariables.hpp similarity index 92% rename from include/trading_definitions/ohlc_rsi_variables.hpp rename to source/shared/tradingDefinitions/ohlcRsiVariables.hpp index fc3ab1c..1eeb238 100644 --- a/include/trading_definitions/ohlc_rsi_variables.hpp +++ b/source/shared/tradingDefinitions/ohlcRsiVariables.hpp @@ -7,7 +7,7 @@ #pragma once #include -namespace trading_definitions { +namespace tradingDefinitions { struct OHLCRSIVariables { int RSI_LONG; int RSI_SHORT; diff --git a/include/trading_definitions/ohlc_variables.hpp b/source/shared/tradingDefinitions/ohlcVariables.hpp similarity index 92% rename from include/trading_definitions/ohlc_variables.hpp rename to source/shared/tradingDefinitions/ohlcVariables.hpp index 21ac74a..2593035 100644 --- a/include/trading_definitions/ohlc_variables.hpp +++ b/source/shared/tradingDefinitions/ohlcVariables.hpp @@ -7,7 +7,7 @@ #pragma once #include -namespace trading_definitions { +namespace tradingDefinitions { struct OHLCVariables { int OHLC_COUNT; int OHLC_MINUTES; diff --git a/include/trading_definitions/run_configuration.hpp b/source/shared/tradingDefinitions/runConfiguration.hpp similarity index 91% rename from include/trading_definitions/run_configuration.hpp rename to source/shared/tradingDefinitions/runConfiguration.hpp index dc11a28..0610d4b 100644 --- a/include/trading_definitions/run_configuration.hpp +++ b/source/shared/tradingDefinitions/runConfiguration.hpp @@ -8,9 +8,11 @@ #include #include #include -#include "utilities/decimal_json.hpp" +#include "shared/utilities/decimalJson.hpp" -namespace trading_definitions { +// Intentionally a plain header, NOT a .cppm module — see configuration.hpp for +// why JSON-serializable structs stay GMF-includable headers in this repo. +namespace tradingDefinitions { // Single source of truth for the default account balance. Configuration and // trading::RiskLimits reference this rather than repeating the literal. @@ -33,7 +35,7 @@ inline constexpr boost::decimal::decimal64_t DEFAULT_STARTING_BALANCE{10000}; struct RunConfiguration { std::string RUN_ID; std::string SYMBOLS; - int LAST_MONTHS; + int LAST_MONTHS = 0; boost::decimal::decimal64_t STARTING_BALANCE{DEFAULT_STARTING_BALANCE}; boost::decimal::decimal64_t MAX_LOSS_PERCENT{0}; int MAX_OPEN_TRADES{0}; diff --git a/include/trading_definitions/strategy.hpp b/source/shared/tradingDefinitions/strategy.hpp similarity index 74% rename from include/trading_definitions/strategy.hpp rename to source/shared/tradingDefinitions/strategy.hpp index 725312a..c59088b 100644 --- a/include/trading_definitions/strategy.hpp +++ b/source/shared/tradingDefinitions/strategy.hpp @@ -8,11 +8,11 @@ #include #include #include -#include "trading_variables.hpp" -#include "ohlc_variables.hpp" -#include "strategy_variables.hpp" +#include "shared/tradingDefinitions/tradingVariables.hpp" +#include "shared/tradingDefinitions/ohlcVariables.hpp" +#include "shared/tradingDefinitions/strategyVariables.hpp" -namespace trading_definitions { +namespace tradingDefinitions { struct Strategy { std::string UUID; diff --git a/include/trading_definitions/strategy_variables.hpp b/source/shared/tradingDefinitions/strategyVariables.hpp similarity index 85% rename from include/trading_definitions/strategy_variables.hpp rename to source/shared/tradingDefinitions/strategyVariables.hpp index eb8828c..e815f57 100644 --- a/include/trading_definitions/strategy_variables.hpp +++ b/source/shared/tradingDefinitions/strategyVariables.hpp @@ -7,9 +7,9 @@ #pragma once #include #include -#include "ohlc_rsi_variables.hpp" +#include "shared/tradingDefinitions/ohlcRsiVariables.hpp" -namespace trading_definitions { +namespace tradingDefinitions { // Add in custom parameters struct StrategyVariables { diff --git a/source/trading_definitions/trading_definitions_json.cpp b/source/shared/tradingDefinitions/tradingDefinitionsJson.cpp similarity index 88% rename from source/trading_definitions/trading_definitions_json.cpp rename to source/shared/tradingDefinitions/tradingDefinitionsJson.cpp index aba5ffc..a180af5 100644 --- a/source/trading_definitions/trading_definitions_json.cpp +++ b/source/shared/tradingDefinitions/tradingDefinitionsJson.cpp @@ -3,9 +3,9 @@ // (c) 2025 Ryan McCaffery | https://mccaffers.com // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "strategy_variables.hpp" +#include "shared/tradingDefinitions/strategyVariables.hpp" -namespace trading_definitions { +namespace tradingDefinitions { void to_json(nlohmann::json& j, const StrategyVariables& s) { if (s.OHLC_RSI_VARIABLES) { diff --git a/source/shared/tradingDefinitions/tradingVariables.hpp b/source/shared/tradingDefinitions/tradingVariables.hpp new file mode 100644 index 0000000..7691dc5 --- /dev/null +++ b/source/shared/tradingDefinitions/tradingVariables.hpp @@ -0,0 +1,51 @@ +// Backtesting Engine in C++ +// +// (c) 2025 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +#pragma once +#include +#include +#include +#include + +namespace tradingDefinitions { +struct TradingVariables { + std::string STRATEGY; + // SL/TP distances in whole pips; TRADING_SIZE in whole lots. All integer — + // the engine converts pips->points and applies size inside its integer + // hot loop (see symbolScale.hpp / tradeManager). + int32_t STOP_DISTANCE_IN_PIPS = 0; + int32_t LIMIT_DISTANCE_IN_PIPS = 0; + int32_t TRADING_SIZE = 0; +}; + +// Read an integer field that may arrive as a JSON number or, per this codebase's +// string-encoded-numeric convention, as a string. lround matches +// sweep::Combination::getInt and tolerates any legacy decimal value. +inline int32_t readIntField(const nlohmann::json& j) { + const double value = + j.is_string() ? std::stod(j.get()) : j.get(); + return static_cast(std::lround(value)); +} + +// Custom (de)serialisation: the fields are int32_t in memory but travel on the +// wire as strings (matching the existing convention), and from_json accepts +// either a string or a number so existing payloads keep parsing. +inline void to_json(nlohmann::json& j, const TradingVariables& v) { + j = nlohmann::json{ + {"STRATEGY", v.STRATEGY}, + {"STOP_DISTANCE_IN_PIPS", std::to_string(v.STOP_DISTANCE_IN_PIPS)}, + {"LIMIT_DISTANCE_IN_PIPS", std::to_string(v.LIMIT_DISTANCE_IN_PIPS)}, + {"TRADING_SIZE", std::to_string(v.TRADING_SIZE)}, + }; +} + +inline void from_json(const nlohmann::json& j, TradingVariables& v) { + j.at("STRATEGY").get_to(v.STRATEGY); + v.STOP_DISTANCE_IN_PIPS = readIntField(j.at("STOP_DISTANCE_IN_PIPS")); + v.LIMIT_DISTANCE_IN_PIPS = readIntField(j.at("LIMIT_DISTANCE_IN_PIPS")); + v.TRADING_SIZE = readIntField(j.at("TRADING_SIZE")); +} +} diff --git a/include/utilities/backtestLog.hpp b/source/shared/utilities/backtestLog.hpp similarity index 65% rename from include/utilities/backtestLog.hpp rename to source/shared/utilities/backtestLog.hpp index 32bdb14..f1bb3b2 100644 --- a/include/utilities/backtestLog.hpp +++ b/source/shared/utilities/backtestLog.hpp @@ -16,12 +16,27 @@ // // When backtests run concurrently (see RedisRunner's thread pool) the chatty // per-strategy output would both interleave and race on the shared std::cout / -// std::cerr. RedisRunner sets `quiet` so those call sites skip their output +// std::cerr. RedisRunner calls set_quiet(true) so those call sites skip their output // entirely (no stream access -> no race), while error() serialises the rare // failure path behind a mutex so genuine problems still surface safely. namespace backtest_log { -inline std::atomic quiet{false}; +// Hide the actual state inside a private detail namespace. +namespace detail { +inline std::atomic& quiet_flag() { + static std::atomic q{false}; + return q; +} +} // namespace detail + +// Provide clean, explicit public getters and setters. +inline bool is_quiet() { + return detail::quiet_flag().load(std::memory_order_relaxed); +} + +inline void set_quiet(bool state) { + detail::quiet_flag().store(state, std::memory_order_relaxed); +} inline std::mutex& errorMutex() { static std::mutex m; diff --git a/source/utilities/base64.cpp b/source/shared/utilities/base64.cpp similarity index 98% rename from source/utilities/base64.cpp rename to source/shared/utilities/base64.cpp index ae1ee97..9d16c2d 100644 --- a/source/utilities/base64.cpp +++ b/source/shared/utilities/base64.cpp @@ -4,7 +4,7 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "base64.hpp" +#include "shared/utilities/base64.hpp" static const char* const B64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; diff --git a/include/utilities/base64.hpp b/source/shared/utilities/base64.hpp similarity index 100% rename from include/utilities/base64.hpp rename to source/shared/utilities/base64.hpp diff --git a/include/utilities/decimal_json.hpp b/source/shared/utilities/decimalJson.hpp similarity index 100% rename from include/utilities/decimal_json.hpp rename to source/shared/utilities/decimalJson.hpp diff --git a/source/utilities/env.cpp b/source/shared/utilities/env.cpp similarity index 92% rename from source/utilities/env.cpp rename to source/shared/utilities/env.cpp index f695fc6..b66eb4b 100644 --- a/source/utilities/env.cpp +++ b/source/shared/utilities/env.cpp @@ -4,7 +4,7 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#include "env.hpp" +#include "shared/utilities/env.hpp" #include #include diff --git a/include/utilities/env.hpp b/source/shared/utilities/env.hpp similarity index 100% rename from include/utilities/env.hpp rename to source/shared/utilities/env.hpp diff --git a/source/shared/utilities/jsonParser.cpp b/source/shared/utilities/jsonParser.cpp new file mode 100644 index 0000000..9d6c5c7 --- /dev/null +++ b/source/shared/utilities/jsonParser.cpp @@ -0,0 +1,26 @@ +// Backtesting Engine in C++ +// +// (c) 2026 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +#include "shared/utilities/jsonParser.hpp" +#include "shared/utilities/base64.hpp" + +using json = nlohmann::json; + +// Parse errors propagate to the caller — json::parse_error carries the byte +// offset, which is more useful than the downstream type_error a discarded +// json value would produce. + +tradingDefinitions::Configuration JsonParser::parseConfigurationFromBase64(const std::string& input) { + return json::parse(Base64::b64decode(input)).get(); +} + +tradingDefinitions::RunConfiguration JsonParser::parseRunConfigurationFromBase64(const std::string& input) { + return json::parse(Base64::b64decode(input)).get(); +} + +tradingDefinitions::Strategy JsonParser::parseStrategyFromBase64(const std::string& input) { + return json::parse(Base64::b64decode(input)).get(); +} diff --git a/source/shared/utilities/jsonParser.hpp b/source/shared/utilities/jsonParser.hpp new file mode 100644 index 0000000..ea2798e --- /dev/null +++ b/source/shared/utilities/jsonParser.hpp @@ -0,0 +1,18 @@ +// Backtesting Engine in C++ +// +// (c) 2025 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +#pragma once + +#include +#include +#include "shared/tradingDefinitions.hpp" + +class JsonParser { +public: + static tradingDefinitions::Configuration parseConfigurationFromBase64(const std::string& input); + static tradingDefinitions::RunConfiguration parseRunConfigurationFromBase64(const std::string& input); + static tradingDefinitions::Strategy parseStrategyFromBase64(const std::string& input); +}; diff --git a/include/utilities/parameterSweep.hpp b/source/shared/utilities/parameterSweep.hpp similarity index 100% rename from include/utilities/parameterSweep.hpp rename to source/shared/utilities/parameterSweep.hpp diff --git a/include/utilities/queueKeys.hpp b/source/shared/utilities/queueKeys.hpp similarity index 100% rename from include/utilities/queueKeys.hpp rename to source/shared/utilities/queueKeys.hpp diff --git a/include/models/symbolScale.hpp b/source/shared/utilities/symbolScale.cppm similarity index 68% rename from include/models/symbolScale.hpp rename to source/shared/utilities/symbolScale.cppm index 207dd2f..a3df2e9 100644 --- a/include/models/symbolScale.hpp +++ b/source/shared/utilities/symbolScale.cppm @@ -4,37 +4,39 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- // -// symbolScale.hpp — fast symbol -> pip-scale lookup. +// symbolScale — fast symbol -> points-per-pip lookup. // -// Given a symbol like "EURUSD" or "USDJPY", returns the integer scale -// used to convert price differences into pips (e.g. 10000 for most FX -// pairs, 100 for JPY pairs, 1 for indices/metals). +// Prices are stored as scaled INT32 "points" in QuestDB (EURUSD 1.10001 -> +// 110001). This returns how many of those integer points make up one pip for +// the symbol: 10 for FX majors and JPY pairs, 100 for indices/commodities, +// 1000 for metals. So a pip distance becomes points via `pips * pointsPerPip`, +// and a point PnL becomes pips via `points / pointsPerPip`. +// +// The engine keeps the per-tick loop entirely in integer points; this factor +// is applied only at the edges (pip distance -> points on trade open, and +// point PnL -> pips at display/reporting). It also doubles as the symbol +// validator: unknown symbols return 0 (kUnknown), which skips the exit check. // // Design goals (this is on the hot path of the backtester): // - No heap allocation, no hashing, no string parsing at runtime. // - The whole table is `constexpr`, so when the caller passes a string // literal the compiler can fold the lookup down to a single `mov`. -// - Header-only on purpose: every translation unit sees the body of -// `get()` and can inline it. +// - Exported `inline`/`constexpr` so every importer can inline `get()`. // // C# analogy: think of this as a `static readonly Dictionary`, // except the lookup is resolved at compile time when possible. -#pragma once -// — std::array is a fixed-size, stack-allocated array -// with an STL-style interface. Like a C# fixed-size buffer -// but type-safe and bounds-checkable. -// — std::string_view is a non-owning view over an existing -// string's characters: a (const char* + length) pair. It -// does NOT allocate or copy. Closest C# equivalent is -// ReadOnlySpan. Use it for parameters that read but -// don't store the string. -#include -#include +export module symbolScale; + +// std::array is a fixed-size, stack-allocated array with an STL-style +// interface; std::string_view is a non-owning (const char* + length) view that +// neither allocates nor copies (closest C# analogues: a fixed buffer and +// ReadOnlySpan). +import std; // replaces , // `namespace` is C++'s scoping construct. `symbol_scale::get(...)` is // the fully qualified name from outside this namespace. -namespace symbol_scale { +export namespace symbol_scale { // A plain "POD" (plain old data) record. No constructors needed — we use // brace-initialization below. `string_view` is safe to store here because @@ -47,9 +49,7 @@ struct Entry { // Three keywords doing three different jobs on this one declaration: // - `inline` : tells the linker "if you see this defined in multiple -// .cpp files (because it's in a header), that's fine — -// they're all the same thing." Required for variables -// defined in headers since C++17. +// TUs, that's fine — they're all the same thing." // - `constexpr` : the value is computable at compile time. The whole // table lives in read-only program memory and the // compiler can use it during constant evaluation. @@ -59,36 +59,38 @@ struct Entry { // // IMPORTANT: this table MUST stay sorted ascending by symbol. The // `static_assert` below enforces that at compile time. +// Values are integer price points per pip (see header comment). FX majors and +// JPY pairs are 10, indices/commodities 100, metals 1000. inline constexpr std::array kTable{{ - {"AUDNZD", 10000}, - {"AUDUSD", 10000}, - {"AUSIDXAUD", 1}, - {"BRENTCMDUSD", 1}, - {"COPPERCMDUSD", 1}, - {"DEUIDXEUR", 1}, - {"EURAUD", 10000}, - {"EURCHF", 10000}, - {"EURGBP", 10000}, - {"EURJPY", 100}, - {"EURNOK", 10000}, - {"EURUSD", 10000}, - {"FRAIDXEUR", 1}, - {"GBPJPY", 100}, - {"GBPUSD", 10000}, - {"GBRIDXGBP", 1}, - {"HKGIDXHKD", 1}, - {"JPNIDXJPY", 1}, - {"LIGHTCMDUSD", 1}, - {"NZDUSD", 10000}, - {"USA30IDXUSD", 1}, - {"USA500IDXUSD", 1}, - {"USATECHIDXUSD", 1}, - {"USDCAD", 10000}, - {"USDCHF", 10000}, - {"USDJPY", 100}, - {"USDSEK", 10000}, - {"XAGUSD", 1}, - {"XAUUSD", 1}, + {"AUDNZD", 10}, + {"AUDUSD", 10}, + {"AUSIDXAUD", 100}, + {"BRENTCMDUSD", 100}, + {"COPPERCMDUSD", 100}, + {"DEUIDXEUR", 100}, + {"EURAUD", 10}, + {"EURCHF", 10}, + {"EURGBP", 10}, + {"EURJPY", 10}, + {"EURNOK", 10}, + {"EURUSD", 10}, + {"FRAIDXEUR", 100}, + {"GBPJPY", 10}, + {"GBPUSD", 10}, + {"GBRIDXGBP", 100}, + {"HKGIDXHKD", 100}, + {"JPNIDXJPY", 100}, + {"LIGHTCMDUSD", 100}, + {"NZDUSD", 10}, + {"USA30IDXUSD", 100}, + {"USA500IDXUSD", 100}, + {"USATECHIDXUSD", 100}, + {"USDCAD", 10}, + {"USDCHF", 10}, + {"USDJPY", 10}, + {"USDSEK", 10}, + {"XAGUSD", 1000}, + {"XAUUSD", 1000}, }}; // Compile-time invariant check. The pattern is an IIFE — Immediately diff --git a/include/utilities/threadPool.hpp b/source/shared/utilities/threadPool.hpp similarity index 100% rename from include/utilities/threadPool.hpp rename to source/shared/utilities/threadPool.hpp diff --git a/source/strategies/randomStrategy.cpp b/source/strategies/randomStrategy.cpp deleted file mode 100644 index bdb5ad1..0000000 --- a/source/strategies/randomStrategy.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#include "strategies/randomStrategy.hpp" - -#include "tradeManager.hpp" - -// Member initialiser list (the bit after the `:`) runs in declaration -// order, not the order written here — same caveat called out in -// trade.hpp. The C# equivalent would be field initialisers plus a -// constructor body, but C++ prefers the initialiser list because it -// constructs members directly rather than default-then-assign. -RandomStrategy::RandomStrategy(const trading_definitions::Strategy& strategyConfig) - : config(strategyConfig), - rng(std::random_device{}()), // seed once from the OS entropy source - coin(0.5), - closeProb(0.0) {} // unused — exits are driven by SL/TP in Operations - -std::optional RandomStrategy::decide(const PriceData& /*tick*/) { - return coin(rng) ? Direction::LONG : Direction::SHORT; -} - -void RandomStrategy::during(const PriceData& /*price*/, - TradeManager& /*tradeManager*/) { - // Exits are handled centrally by Operations using each trade's - // stop-loss / take-profit pip distances. Strategies that want - // bespoke exit logic (trailing stops, partial closes, etc.) - // should override this hook. -} diff --git a/include/strategies/randomStrategy.hpp b/source/strategies/randomStrategy.cppm similarity index 63% rename from include/strategies/randomStrategy.hpp rename to source/strategies/randomStrategy.cppm index e10821f..983c074 100644 --- a/include/strategies/randomStrategy.hpp +++ b/source/strategies/randomStrategy.cppm @@ -4,16 +4,17 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#pragma once -#include -#include -#include -#include "models/priceData.hpp" -#include "models/trade.hpp" // for Direction enum -#include "strategies/strategy.hpp" // IStrategy base class -#include "trading_definitions/strategy.hpp" +module; -class TradeManager; // forward declared in strategy.hpp; redeclaring is harmless +#include "shared/tradingDefinitions/strategy.hpp" + +export module randomStrategy; + +import std; // replaces , , +import strategy; // IStrategy base class +import priceData; // PriceData +import trade; // Direction +import tradeManager; // TradeManager // A trivial strategy: on every tick it flips a fair coin and returns // LONG or SHORT. Exits are not the strategy's responsibility — they @@ -36,9 +37,9 @@ class TradeManager; // forward declared in strategy.hpp; redeclaring is harmles // `RandomStrategy` anywhere an `IStrategy` is expected. The C# // equivalent is `: IStrategy`; C# has no concept of private // inheritance, so the `public` keyword has no analogue there. -class RandomStrategy : public IStrategy { +export class RandomStrategy : public IStrategy { public: - explicit RandomStrategy(const trading_definitions::Strategy& strategyConfig); + explicit RandomStrategy(const tradingDefinitions::Strategy& strategyConfig); // Returns `std::nullopt` to mean "no signal — don't trade". The // random strategy always returns a direction, but the interface @@ -61,8 +62,31 @@ class RandomStrategy : public IStrategy { TradeManager& tradeManager) override; private: - trading_definitions::Strategy config; + tradingDefinitions::Strategy config; std::mt19937 rng; std::bernoulli_distribution coin; // fair coin flip for entry direction std::bernoulli_distribution closeProb; // per-tick probability of closing all trades }; + +// Member initialiser list (the bit after the `:`) runs in declaration +// order, not the order written here — same caveat called out in +// trade.hpp. The C# equivalent would be field initialisers plus a +// constructor body, but C++ prefers the initialiser list because it +// constructs members directly rather than default-then-assign. +RandomStrategy::RandomStrategy(const tradingDefinitions::Strategy& strategyConfig) + : config(strategyConfig), + rng(std::random_device{}()), // seed once from the OS entropy source + coin(0.5), + closeProb(0.0) {} // unused — exits are driven by SL/TP in Operations + +std::optional RandomStrategy::decide(const PriceData& /*tick*/) { + return coin(rng) ? Direction::LONG : Direction::SHORT; +} + +void RandomStrategy::during(const PriceData& /*price*/, + TradeManager& /*tradeManager*/) { + // Exits are handled centrally by Operations using each trade's + // stop-loss / take-profit pip distances. Strategies that want + // bespoke exit logic (trailing stops, partial closes, etc.) + // should override this hook. +} diff --git a/include/strategies/strategy.hpp b/source/strategies/strategy.cppm similarity index 78% rename from include/strategies/strategy.hpp rename to source/strategies/strategy.cppm index a514368..b11f761 100644 --- a/include/strategies/strategy.hpp +++ b/source/strategies/strategy.cppm @@ -4,20 +4,17 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#pragma once -#include -#include -#include "models/priceData.hpp" -#include "models/trade.hpp" +export module strategy; -// Forward declaration. We only refer to `TradeManager` by reference in -// this header, so the compiler doesn't need its full definition here, -// just to know "it's a class". Pulling in the full header would drag -// every TradeManager dependency into every strategy. C# doesn't really -// have an equivalent because it resolves types at the assembly level -// rather than per file, but in C++ this is a standard way to keep -// header dependencies (and compile times) under control. -class TradeManager; +import std; // replaces , +import priceData; // PriceData +import trade; // Direction +import tradeManager; // TradeManager + +// IStrategy's interface refers to TradeManager only by reference, but once +// TradeManager is module-attached it cannot be forward-declared in the global +// module (that would be a distinct, incompatible type and RandomStrategy's +// override would stop matching), so the strategy module imports it directly. // Abstract base class that every concrete strategy implements. // @@ -39,7 +36,7 @@ class TradeManager; // - Derived classes annotate their implementations with `override` // (see `RandomStrategy`). It's optional in C++ but catches // signature typos at compile time, exactly like C#'s `override`. -class IStrategy { +export class IStrategy { public: virtual ~IStrategy() = default; diff --git a/include/strategies/strategyErrors.hpp b/source/strategies/strategyErrors.cppm similarity index 84% rename from include/strategies/strategyErrors.hpp rename to source/strategies/strategyErrors.cppm index 8cdb663..bf31cd3 100644 --- a/include/strategies/strategyErrors.hpp +++ b/source/strategies/strategyErrors.cppm @@ -4,18 +4,16 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#pragma once +export module strategyErrors; -#include -#include -#include +import std; // replaces , , // Thrown by the strategy factory when the configured strategy name does not // match any known strategy. Derives from std::runtime_error so existing // catch(const std::runtime_error&) / catch(const std::exception&) sites still // match, while giving new callers a dedicated type to discriminate a // configuration / domain error from any other runtime failure. -class UnknownStrategyError : public std::runtime_error { +export class UnknownStrategyError : public std::runtime_error { public: explicit UnknownStrategyError(std::string name) : std::runtime_error("Unknown strategy: '" + name + "'"), diff --git a/source/trading/tradeManager.cpp b/source/trading/tradeManager.cpp deleted file mode 100644 index 48b1dc4..0000000 --- a/source/trading/tradeManager.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2025 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#include "tradeManager.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include "backtestLog.hpp" - -namespace { -std::string nextTradeId() { - static std::atomic counter{0}; - return std::format("T{}", counter.fetch_add(1)); -} - -// Floating PnL of an open trade valued at `mark` — the same formula -// closeTrade uses for realized PnL, so liquidating at the last mark realizes -// exactly the floating amount. -boost::decimal::decimal64_t floatingPnlAt(const Trade& trade, - boost::decimal::decimal64_t mark) { - auto diff = mark - trade.entryPrice; - if (trade.direction == Direction::SHORT) diff = -diff; - return diff * trade.scalingFactor * trade.size; -} -} - -std::string TradeManager::openTrade(const PriceData& tick, - boost::decimal::decimal64_t size, - Direction direction, - boost::decimal::decimal64_t stopDistancePips, - boost::decimal::decimal64_t limitDistancePips) { - auto price = (direction == Direction::LONG) ? tick.ask : tick.bid; - Trade trade(price, size, direction, tick.symbol); - trade.entryBid = tick.bid; - trade.entryAsk = tick.ask; - trade.id = nextTradeId(); - trade.stopDistancePips = stopDistancePips; - trade.limitDistancePips = limitDistancePips; - trade.exitReferencePrice = (direction == Direction::LONG) ? tick.bid : tick.ask; - // Mark the trade at its entry tick: the close side of the spread. The - // initial floating PnL is therefore the spread cost — true mark-to-market - // equity dips by the spread the moment a trade opens. - trade.lastMarkPrice = trade.exitReferencePrice; - trade.floatingPnl = floatingPnlAt(trade, trade.lastMarkPrice); - openPnl += trade.floatingPnl; - activeTrades[trade.id] = trade; - return trade.id; -} - -void TradeManager::markToMarket(const PriceData& tick) { - for (auto& [id, trade] : activeTrades) { - if (trade.symbol != tick.symbol) continue; - const auto mark = (trade.direction == Direction::LONG) ? tick.bid : tick.ask; - const auto updated = floatingPnlAt(trade, mark); - openPnl += updated - trade.floatingPnl; - trade.floatingPnl = updated; - trade.lastMarkPrice = mark; - } -} - -void TradeManager::closeAllTrades(const PriceData& tick) { - // Snapshot ids/prices first: closeTrade mutates activeTrades. - std::vector> toClose; - toClose.reserve(activeTrades.size()); - for (const auto& [id, trade] : activeTrades) { - toClose.emplace_back(id, trade.lastMarkPrice); - } - for (const auto& [id, price] : toClose) { - closeTrade(id, price, tick, /*liquidated=*/true); - } -} - -size_t TradeManager::reviewAccount() const { - return activeTrades.size(); -} - -bool TradeManager::hasActiveTradeForSymbol(std::string_view symbol) const { - return std::any_of(activeTrades.begin(), activeTrades.end(), - [symbol](const auto& pair) { - return pair.second.symbol == symbol; - }); -} - -bool TradeManager::closeTrade(const std::string& tradeId, - boost::decimal::decimal64_t closePrice, - const PriceData& tick, - bool liquidated) { - auto it = activeTrades.find(tradeId); - if (it != activeTrades.end()) { - Trade closed = it->second; - closed.closePrice = closePrice; - closed.closeTime = tick.timestamp; - closed.liquidated = liquidated; - auto diff = closePrice - closed.entryPrice; - if (closed.direction == Direction::SHORT) diff = -diff; - // scalingFactor stays an int — boost::decimal has overloads for builtin - // integer types, so no conversion is needed there. - closed.pnl = diff * closed.scalingFactor * closed.size; - closedPnl += closed.pnl; - openPnl -= it->second.floatingPnl; // realized now, no longer floating - closed.floatingPnl = boost::decimal::decimal64_t{0}; - closedTrades.push_back(closed); - activeTrades.erase(it); - - // Per-trade chatter is skipped under concurrent backtests (quiet), - // which also avoids the formatting work below. - if (!backtest_log::quiet) { - auto t = std::chrono::system_clock::to_time_t(tick.timestamp); - std::tm utc{}; - gmtime_r(&t, &utc); - std::ostringstream ts; - ts << std::put_time(&utc, "%Y-%m-%dT%H:%M:%SZ"); - - const char* side = (closed.direction == Direction::LONG) ? "BUY" : "SELL"; - std::cout << ts.str() - << ", Trade Closed, " << closed.symbol - << ", " << side - << ", " << std::showpos << std::fixed << std::setprecision(2) << closed.pnl - << std::noshowpos - << std::endl; - } - return true; - } - return false; -} - -const std::unordered_map& TradeManager::getActiveTrades() const { - return activeTrades; -} - -const std::vector& TradeManager::getClosedTrades() const { - return closedTrades; -} - -boost::decimal::decimal64_t TradeManager::calculatePnl() const { - return closedPnl; -} - -boost::decimal::decimal64_t TradeManager::unrealizedPnl() const { - return openPnl; -} - - diff --git a/source/utilities/decimalConvert.cpp b/source/utilities/decimalConvert.cpp deleted file mode 100644 index 20b2a92..0000000 --- a/source/utilities/decimalConvert.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#include "decimalConvert.hpp" - -#include -#include -#include -#include - -#include - -namespace decimal_convert { - -boost::decimal::decimal64_t toDecimal(double value) { - std::array buffer; - const auto [ptr, ec] = - std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); - if (ec != std::errc{}) { - throw std::runtime_error("decimalConvert: to_chars failed for double"); - } - boost::decimal::decimal64_t result; - const auto parsed = boost::decimal::from_chars(buffer.data(), ptr, result); - if (parsed.ec != std::errc{}) { - throw std::runtime_error("decimalConvert: from_chars failed for double"); - } - return result; -} - -} // namespace decimal_convert diff --git a/source/utilities/jsonParser.cpp b/source/utilities/jsonParser.cpp deleted file mode 100644 index 4868dfb..0000000 --- a/source/utilities/jsonParser.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#include "jsonParser.hpp" -#include "base64.hpp" - -using json = nlohmann::json; - -// Parse errors propagate to the caller — json::parse_error carries the byte -// offset, which is more useful than the downstream type_error a discarded -// json value would produce. - -trading_definitions::Configuration JsonParser::parseConfigurationFromBase64(const std::string& input) { - return json::parse(Base64::b64decode(input)).get(); -} - -trading_definitions::RunConfiguration JsonParser::parseRunConfigurationFromBase64(const std::string& input) { - return json::parse(Base64::b64decode(input)).get(); -} - -trading_definitions::Strategy JsonParser::parseStrategyFromBase64(const std::string& input) { - return json::parse(Base64::b64decode(input)).get(); -} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..82f6ba8 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,25 @@ +# Catch2 unit tests. Each ported file is one translation unit that links the +# project library (BacktestingEngineLib) and consumes its C++23 modules via +# `import`. The library's module FILE_SET and include directories are PUBLIC, so +# they propagate here through the link below. +add_executable(unit_tests + symbolScale.cpp + jsonParser.cpp + db.cpp + sweep.cpp + tradeManager.cpp +) + +target_link_libraries(unit_tests PRIVATE + BacktestingEngineLib + Catch2::Catch2WithMain) + +# Match the library's module configuration so this consumer can import the +# library's modules (which were built against `import std;`). Without these the +# imported BMIs are rejected as a config mismatch. +set_target_properties(unit_tests PROPERTIES CXX_MODULE_STD ON) +target_compile_features(unit_tests PRIVATE cxx_std_23) + +# Register every TEST_CASE with CTest so `ctest` lists/runs them individually. +include(${Catch2_SOURCE_DIR}/extras/Catch.cmake) +catch_discover_tests(unit_tests) diff --git a/tests/db.cpp b/tests/db.cpp new file mode 100644 index 0000000..2cc1cc0 --- /dev/null +++ b/tests/db.cpp @@ -0,0 +1,24 @@ +// Backtesting Engine in C++ +// +// (c) 2025 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +#include + +#include + +import databaseConnection; + +TEST_CASE("DatabaseConnection builds the QuestDB connection string", "[db]") { + DatabaseConnection db("test"); + std::string endpoint = "test"; + std::string connection_string = + "host=" + endpoint + " " + "port=8812 " + "dbname=qdb " + "user=admin " + "password= " + "connect_timeout=3"; + CHECK(connection_string == db.getConnectionString()); +} diff --git a/tests/db.mm b/tests/db.mm deleted file mode 100644 index e7dc927..0000000 --- a/tests/db.mm +++ /dev/null @@ -1,43 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2025 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#import -#import "databaseConnection.hpp" - -// Using the Objective-C Framework to build XCTestCases -// This code is a mix of Objective-C and C++, commonly referred to as Objective-C++. -// This is possible because .mm files in Apple's ecosystem allow Objective-C and C++ code to coexist. - -@interface dbtests : XCTestCase -@end - -@implementation dbtests - -- (void)setUp { - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. -} - -- (void)testExample { - - DatabaseConnection db("test"); - std::string endpoint = "test"; - std::string connection_string = - "host=" + endpoint + " " - "port=8812 " - "dbname=qdb " - "user=admin " - "password= " - "connect_timeout=3"; - XCTAssertEqual(connection_string, db.getConnectionString()); - - -} - -@end diff --git a/tests/jsonParser.mm b/tests/jsonParser.cpp similarity index 53% rename from tests/jsonParser.mm rename to tests/jsonParser.cpp index 74a3f2a..afb77f1 100644 --- a/tests/jsonParser.mm +++ b/tests/jsonParser.cpp @@ -4,25 +4,15 @@ // This code is licensed under MIT license (see LICENSE.txt for details) // --------------------------------------- -#import -#import "jsonParser.hpp" -#include "base64.hpp" +#include -@interface jsonParserTests : XCTestCase -@end +#include -@implementation jsonParserTests +#include "shared/utilities/jsonParser.hpp" +#include "shared/utilities/base64.hpp" -- (void)setUp { - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. -} - -- (void)testValidJsonParsing { - // Create a sample configuration JSON with all required fields +TEST_CASE("JsonParser parses a valid base64 configuration", "[jsonParser]") { + // A sample configuration JSON with all required fields. std::string validJson = R"({ "RUN_ID": "UNIQUE_IDENTIFER", "SYMBOLS": "EURUSD", @@ -49,14 +39,11 @@ - (void)testValidJsonParsing { } } })"; - - // Convert to base64 - std::string base64Input = Base64::b64encode(validJson); - - // Test parsing - trading_definitions::Configuration result = JsonParser::parseConfigurationFromBase64(base64Input); - XCTAssertFalse(result.RUN_ID.empty(), "Parsing should succeed with valid JSON"); -} + std::string base64Input = Base64::b64encode(validJson); -@end + tradingDefinitions::Configuration result = + JsonParser::parseConfigurationFromBase64(base64Input); + INFO("Parsing should succeed with valid JSON"); + CHECK_FALSE(result.RUN_ID.empty()); +} diff --git a/tests/sweep.cpp b/tests/sweep.cpp new file mode 100644 index 0000000..81871d5 --- /dev/null +++ b/tests/sweep.cpp @@ -0,0 +1,180 @@ +// Backtesting Engine in C++ +// +// (c) 2026 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "shared/utilities/parameterSweep.hpp" +#include "shared/tradingDefinitions/runConfiguration.hpp" +#include "shared/tradingDefinitions/strategy.hpp" + +import randomStrategySweep; // sweep::buildRandomStrategySweep +import runConfigurationBuilder; // sweep::makeRunConfiguration +import randomStrategy; // RandomStrategy +import tradeManager; // TradeManager +import priceData; // PriceData +import trade; // Direction + +// Pulls in the _dd user-defined literal so "5"_dd produces a decimal64_t +// directly — same convention as tradeManager.cpp. +using namespace boost::decimal::literals; + +TEST_CASE("buildRandomStrategySweep registers exactly STOP and LIMIT", "[sweep]") { + const auto generator = sweep::buildRandomStrategySweep(); + INFO("RandomStrategy sweeps exactly STOP and LIMIT pip distances"); + CHECK(generator.parameterCount() == 2); +} + +// Config-agnostic: whatever STOP/LIMIT ranges the builder registers, the output +// must be their full cartesian product, so its size equals (distinct stops) x +// (distinct limits). Derived from the combinations themselves, so this holds +// for any range the sweep is tuned to (1 combo or 10,000). +TEST_CASE("buildRandomStrategySweep generates the full cartesian product", "[sweep]") { + const auto combinations = + sweep::buildRandomStrategySweep().generateAllCombinations(); + + std::set stops, limits; + for (const auto& combo : combinations) { + stops.insert(combo.get("STOP_DISTANCE_IN_PIPS")); + limits.insert(combo.get("LIMIT_DISTANCE_IN_PIPS")); + } + CHECK(combinations.size() > 0); + CHECK(combinations.size() == stops.size() * limits.size()); + for (const auto& combo : combinations) { + CHECK(combo.has("STOP_DISTANCE_IN_PIPS")); + CHECK(combo.has("LIMIT_DISTANCE_IN_PIPS")); + // The OHLC ranges are commented out in the builder; loadCommand's + // makeStrategy relies on has() returning false so the fields default + // to 0 instead of throwing in get(). + CHECK_FALSE(combo.has("OHLC_COUNT")); + CHECK_FALSE(combo.has("OHLC_MINUTES")); + } +} + +TEST_CASE("buildRandomStrategySweep covers every stop/limit pair once", "[sweep]") { + const auto combinations = + sweep::buildRandomStrategySweep().generateAllCombinations(); + + std::set stops, limits; + std::set> pairs; + for (const auto& combo : combinations) { + const double s = combo.get("STOP_DISTANCE_IN_PIPS"); + const double l = combo.get("LIMIT_DISTANCE_IN_PIPS"); + stops.insert(s); + limits.insert(l); + pairs.emplace(s, l); + } + + // No duplicate combinations, and every (stop, limit) from the grid present. + CHECK(pairs.size() == combinations.size()); + CHECK(pairs.size() == stops.size() * limits.size()); + for (const double s : stops) { + for (const double l : limits) { + INFO("Missing stop=" << s << " / limit=" << l << " from the grid"); + CHECK(pairs.count({s, l}) == 1); + } + } +} + +// generateAllCombinations must be deterministic — its order feeds the RUN +// queue, so two expansions must be byte-for-byte identical. (Config-agnostic: +// holds for any range the sweep is tuned to.) +TEST_CASE("buildRandomStrategySweep expansion order is deterministic", "[sweep]") { + const auto a = sweep::buildRandomStrategySweep().generateAllCombinations(); + const auto b = sweep::buildRandomStrategySweep().generateAllCombinations(); + REQUIRE(a.size() == b.size()); + for (std::size_t i = 0; i < a.size() && i < b.size(); ++i) { + CHECK(a[i].get("STOP_DISTANCE_IN_PIPS") == b[i].get("STOP_DISTANCE_IN_PIPS")); + CHECK(a[i].get("LIMIT_DISTANCE_IN_PIPS") == b[i].get("LIMIT_DISTANCE_IN_PIPS")); + } +} + +TEST_CASE("makeRunConfiguration carries the run id", "[sweep]") { + const auto config = sweep::makeRunConfiguration("test-run-id"); + CHECK(config.RUN_ID == std::string("test-run-id")); +} + +TEST_CASE("makeRunConfiguration sets the run descriptor values", "[sweep]") { + const auto config = sweep::makeRunConfiguration("test-run-id"); + CHECK(config.SYMBOLS == std::string("EURUSD")); + CHECK(config.LAST_MONTHS == 6); + CHECK(config.STARTING_BALANCE == tradingDefinitions::DEFAULT_STARTING_BALANCE); + CHECK(config.MAX_LOSS_PERCENT == "5"_dd); + CHECK(config.MAX_OPEN_TRADES == 1); + CHECK(config.REPORT_FAILURES); +} + +// The descriptor travels through Redis as JSON (loadCommand dumps it, the +// runner parses it back), so the round-trip must preserve every field — +// including the decimal ones, which move as strings via decimal_json.hpp. +TEST_CASE("makeRunConfiguration survives a JSON round-trip", "[sweep]") { + const auto original = sweep::makeRunConfiguration("round-trip-id"); + + const nlohmann::json j = original; + const auto restored = j.get(); + + CHECK(restored.RUN_ID == original.RUN_ID); + CHECK(restored.SYMBOLS == original.SYMBOLS); + CHECK(restored.LAST_MONTHS == original.LAST_MONTHS); + CHECK(restored.STARTING_BALANCE == original.STARTING_BALANCE); + CHECK(restored.MAX_LOSS_PERCENT == original.MAX_LOSS_PERCENT); + CHECK(restored.MAX_OPEN_TRADES == original.MAX_OPEN_TRADES); + CHECK(restored.REPORT_FAILURES == original.REPORT_FAILURES); +} + +// RandomStrategy ignores everything in its config, so default-constructed +// Strategy is enough — selectStrategy only needs the name, and these tests +// construct the class directly. +TEST_CASE("RandomStrategy always returns a signal", "[sweep]") { + RandomStrategy strategy{tradingDefinitions::Strategy{}}; + PriceData tick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + + for (int i = 0; i < 100; ++i) { + const auto signal = strategy.decide(tick); + REQUIRE(signal.has_value()); + CHECK((*signal == Direction::LONG || *signal == Direction::SHORT)); + } +} + +// A fair coin over 1000 flips produces both directions with probability +// 1 - 2^-999 — a single-sided run means the distribution (or seeding) broke. +TEST_CASE("RandomStrategy produces both directions", "[sweep]") { + RandomStrategy strategy{tradingDefinitions::Strategy{}}; + PriceData tick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + + bool sawLong = false; + bool sawShort = false; + for (int i = 0; i < 1000 && !(sawLong && sawShort); ++i) { + const auto signal = strategy.decide(tick); + sawLong = sawLong || (signal == Direction::LONG); + sawShort = sawShort || (signal == Direction::SHORT); + } + CHECK(sawLong); + CHECK(sawShort); +} + +// Exits are owned by Operations via SL/TP — during() must not touch open +// positions, otherwise the sweep's stop/limit parameters stop being the only +// exit mechanism under test. +TEST_CASE("RandomStrategy::during leaves open trades alone", "[sweep]") { + RandomStrategy strategy{tradingDefinitions::Strategy{}}; + TradeManager manager; + PriceData tick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + manager.openTrade(tick, 1, Direction::LONG); + + strategy.during(tick, manager); + + CHECK(manager.getActiveTrades().size() == 1); + CHECK(manager.getClosedTrades().size() == 0); +} diff --git a/tests/sweep.mm b/tests/sweep.mm deleted file mode 100644 index 135b84c..0000000 --- a/tests/sweep.mm +++ /dev/null @@ -1,192 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#import -#import -#import -#import -#import -#import -#import -#import -#import "parameterSweep.hpp" -#import "randomStrategySweep.hpp" -#import "runConfigurationBuilder.hpp" -#import "tradeManager.hpp" -#import "run_configuration.hpp" -#import "strategies/randomStrategy.hpp" -#import "trading_definitions/strategy.hpp" - -// Pulls in the _dd user-defined literal so "5"_dd produces a decimal64_t -// directly — same convention as tradeManager.mm. -using namespace boost::decimal::literals; - -@interface SweepTests : XCTestCase -@end - -@implementation SweepTests - -#pragma mark - buildRandomStrategySweep - -- (void)testBuildRandomStrategySweep_RegistersTwoParameters { - const auto generator = sweep::buildRandomStrategySweep(); - XCTAssertEqual(generator.parameterCount(), 2, - "RandomStrategy sweeps exactly STOP and LIMIT pip distances"); -} - -- (void)testBuildRandomStrategySweep_GeneratesFullCartesianProduct { - const auto combinations = - sweep::buildRandomStrategySweep().generateAllCombinations(); - XCTAssertEqual(combinations.size(), 9, - "3 stop values x 3 limit values must expand to 9 combinations"); - for (const auto& combo : combinations) { - XCTAssertTrue(combo.has("STOP_DISTANCE_IN_PIPS"), - "Every combination must carry the stop distance"); - XCTAssertTrue(combo.has("LIMIT_DISTANCE_IN_PIPS"), - "Every combination must carry the limit distance"); - // The OHLC ranges are commented out in the builder; loadCommand's - // makeStrategy relies on has() returning false so the fields default - // to 0 instead of throwing in get(). - XCTAssertFalse(combo.has("OHLC_COUNT"), - "OHLC_COUNT is not currently swept"); - XCTAssertFalse(combo.has("OHLC_MINUTES"), - "OHLC_MINUTES is not currently swept"); - } -} - -- (void)testBuildRandomStrategySweep_CoversEveryStopLimitPair { - const auto combinations = - sweep::buildRandomStrategySweep().generateAllCombinations(); - - std::set> pairs; - for (const auto& combo : combinations) { - pairs.emplace(combo.get("STOP_DISTANCE_IN_PIPS"), - combo.get("LIMIT_DISTANCE_IN_PIPS")); - } - - XCTAssertEqual(pairs.size(), 9, "All 9 combinations must be distinct"); - for (const double stop : {1.0, 1.5, 10.0}) { - for (const double limit : {1.0, 1.5, 10.0}) { - XCTAssertTrue(pairs.count({stop, limit}) == 1, - "Missing stop=%.1f / limit=%.1f from the grid", stop, limit); - } - } -} - -// generateAllCombinations expands ranges in registration order with the -// last-registered parameter varying fastest. RUN output ordering feeds the -// queue, so pin it: the first three combinations hold STOP at 1.0 while -// LIMIT walks the list. -- (void)testBuildRandomStrategySweep_OrderIsDeterministic { - const auto combinations = - sweep::buildRandomStrategySweep().generateAllCombinations(); - XCTAssertEqual(combinations.size(), 9, "Pre-condition: full grid"); - - const double stops[] = {1.0, 1.0, 1.0, 1.5, 1.5, 1.5, 10.0, 10.0, 10.0}; - const double limits[] = {1.0, 1.5, 10.0, 1.0, 1.5, 10.0, 1.0, 1.5, 10.0}; - for (std::size_t i = 0; i < combinations.size(); ++i) { - XCTAssertEqual(combinations[i].get("STOP_DISTANCE_IN_PIPS"), stops[i], - "STOP order must be stable (slow axis)"); - XCTAssertEqual(combinations[i].get("LIMIT_DISTANCE_IN_PIPS"), limits[i], - "LIMIT order must be stable (fast axis)"); - } -} - -#pragma mark - makeRunConfiguration - -- (void)testMakeRunConfiguration_CarriesRunId { - const auto config = sweep::makeRunConfiguration("test-run-id"); - XCTAssertEqual(config.RUN_ID, std::string("test-run-id"), - "RUN_ID links the run descriptor to its swept strategies"); -} - -- (void)testMakeRunConfiguration_RunDescriptorValues { - const auto config = sweep::makeRunConfiguration("test-run-id"); - XCTAssertEqual(config.SYMBOLS, std::string("EURUSD"), "Tick data symbol"); - XCTAssertEqual(config.LAST_MONTHS, 6, "Tick data window in months"); - XCTAssertEqual(config.STARTING_BALANCE, trading_definitions::DEFAULT_STARTING_BALANCE, - "Runs start from the shared default balance"); - XCTAssertEqual(config.MAX_LOSS_PERCENT, "5"_dd, - "Runs cut off after losing 5%% of the account"); - XCTAssertEqual(config.MAX_OPEN_TRADES, 10, "Cap on simultaneous open positions"); - XCTAssertTrue(config.REPORT_FAILURES, "Liquidated runs currently still report"); -} - -// The descriptor travels through Redis as JSON (loadCommand dumps it, the -// runner parses it back), so the round-trip must preserve every field — -// including the decimal ones, which move as strings via decimal_json.hpp. -- (void)testMakeRunConfiguration_SurvivesJsonRoundTrip { - const auto original = sweep::makeRunConfiguration("round-trip-id"); - - const nlohmann::json j = original; - const auto restored = j.get(); - - XCTAssertEqual(restored.RUN_ID, original.RUN_ID, "RUN_ID must survive"); - XCTAssertEqual(restored.SYMBOLS, original.SYMBOLS, "SYMBOLS must survive"); - XCTAssertEqual(restored.LAST_MONTHS, original.LAST_MONTHS, "LAST_MONTHS must survive"); - XCTAssertEqual(restored.STARTING_BALANCE, original.STARTING_BALANCE, - "STARTING_BALANCE must survive exactly (decimal-as-string)"); - XCTAssertEqual(restored.MAX_LOSS_PERCENT, original.MAX_LOSS_PERCENT, - "MAX_LOSS_PERCENT must survive exactly (decimal-as-string)"); - XCTAssertEqual(restored.MAX_OPEN_TRADES, original.MAX_OPEN_TRADES, - "MAX_OPEN_TRADES must survive"); - XCTAssertEqual(restored.REPORT_FAILURES, original.REPORT_FAILURES, - "REPORT_FAILURES must survive"); -} - -#pragma mark - RandomStrategy (the strategy the sweep drives) - -// RandomStrategy ignores everything in its config, so default-constructed -// Strategy is enough — selectStrategy only needs the name, and these tests -// construct the class directly. -- (void)testRandomStrategy_AlwaysReturnsASignal { - RandomStrategy strategy{trading_definitions::Strategy{}}; - PriceData tick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - - for (int i = 0; i < 100; ++i) { - const auto signal = strategy.decide(tick); - XCTAssertTrue(signal.has_value(), - "The coin flip always lands — decide() must never return nullopt"); - XCTAssertTrue(*signal == Direction::LONG || *signal == Direction::SHORT, - "Signal must be one of the two directions"); - } -} - -// A fair coin over 1000 flips produces both directions with probability -// 1 - 2^-999 — a single-sided run means the distribution (or seeding) broke. -- (void)testRandomStrategy_ProducesBothDirections { - RandomStrategy strategy{trading_definitions::Strategy{}}; - PriceData tick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - - bool sawLong = false; - bool sawShort = false; - for (int i = 0; i < 1000 && !(sawLong && sawShort); ++i) { - const auto signal = strategy.decide(tick); - sawLong = sawLong || (signal == Direction::LONG); - sawShort = sawShort || (signal == Direction::SHORT); - } - XCTAssertTrue(sawLong, "1000 fair flips must produce at least one LONG"); - XCTAssertTrue(sawShort, "1000 fair flips must produce at least one SHORT"); -} - -// Exits are owned by Operations via SL/TP — during() must not touch open -// positions, otherwise the sweep's stop/limit parameters stop being the only -// exit mechanism under test. -- (void)testRandomStrategy_DuringLeavesOpenTradesAlone { - RandomStrategy strategy{trading_definitions::Strategy{}}; - TradeManager manager; - PriceData tick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - manager.openTrade(tick, "1.0"_dd, Direction::LONG); - - strategy.during(tick, manager); - - XCTAssertEqual(manager.getActiveTrades().size(), 1, - "during() is a no-op — the open trade must remain untouched"); - XCTAssertEqual(manager.getClosedTrades().size(), 0, - "during() must not close anything"); -} - -@end diff --git a/tests/symbolScale.cpp b/tests/symbolScale.cpp new file mode 100644 index 0000000..087ce14 --- /dev/null +++ b/tests/symbolScale.cpp @@ -0,0 +1,60 @@ +// Backtesting Engine in C++ +// +// (c) 2026 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +#include + +#include + +import symbolScale; + +// points-per-pip: FX majors & JPY pairs = 10, indices/commodities = 100, +// metals = 1000. +TEST_CASE("symbol_scale::get maps symbols to points-per-pip", "[symbolScale]") { + SECTION("FX majors") { + CHECK(symbol_scale::get("EURUSD") == 10); + CHECK(symbol_scale::get("AUDUSD") == 10); + CHECK(symbol_scale::get("GBPUSD") == 10); + CHECK(symbol_scale::get("USDCAD") == 10); + CHECK(symbol_scale::get("EURNOK") == 10); + } + + SECTION("JPY pairs and metals") { + CHECK(symbol_scale::get("USDJPY") == 10); + CHECK(symbol_scale::get("GBPJPY") == 10); + CHECK(symbol_scale::get("EURJPY") == 10); + CHECK(symbol_scale::get("XAUUSD") == 1000); + CHECK(symbol_scale::get("XAGUSD") == 1000); + } + + SECTION("indices and commodities") { + CHECK(symbol_scale::get("USA500IDXUSD") == 100); + CHECK(symbol_scale::get("USATECHIDXUSD") == 100); + CHECK(symbol_scale::get("AUSIDXAUD") == 100); + CHECK(symbol_scale::get("BRENTCMDUSD") == 100); + } + + SECTION("boundary entries") { + CHECK(symbol_scale::get("AUDNZD") == 10); + CHECK(symbol_scale::get("XAGUSD") == 1000); + } +} + +TEST_CASE("symbol_scale::get rejects unknown and malformed symbols", "[symbolScale]") { + SECTION("unknown symbols return the sentinel") { + CHECK(symbol_scale::get("NOPE") == symbol_scale::kUnknown); + CHECK(symbol_scale::get("") == symbol_scale::kUnknown); + CHECK(symbol_scale::get("EURUSDX") == symbol_scale::kUnknown); + } + + SECTION("lookup is case sensitive") { + CHECK(symbol_scale::get("eurusd") == symbol_scale::kUnknown); + } + + SECTION("accepts std::string") { + std::string s = "USDCHF"; + CHECK(symbol_scale::get(s) == 10); + } +} diff --git a/tests/symbolScale.mm b/tests/symbolScale.mm deleted file mode 100644 index 4e583d1..0000000 --- a/tests/symbolScale.mm +++ /dev/null @@ -1,66 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2026 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#import -#import -#import "symbolScale.hpp" - -@interface SymbolScaleTests : XCTestCase -@end - -@implementation SymbolScaleTests - -- (void)testFourDigitFxPairs { - XCTAssertEqual(symbol_scale::get("EURUSD"), 10000); - XCTAssertEqual(symbol_scale::get("AUDUSD"), 10000); - XCTAssertEqual(symbol_scale::get("GBPUSD"), 10000); - XCTAssertEqual(symbol_scale::get("USDCAD"), 10000); - XCTAssertEqual(symbol_scale::get("EURNOK"), 10000); -} - -- (void)testJpyPairs { - XCTAssertEqual(symbol_scale::get("USDJPY"), 100); - XCTAssertEqual(symbol_scale::get("GBPJPY"), 100); - XCTAssertEqual(symbol_scale::get("EURJPY"), 100); -} - -- (void)testIndicesAndCommodities { - XCTAssertEqual(symbol_scale::get("USA500IDXUSD"), 1); - XCTAssertEqual(symbol_scale::get("USATECHIDXUSD"), 1); - XCTAssertEqual(symbol_scale::get("XAUUSD"), 1); - XCTAssertEqual(symbol_scale::get("BRENTCMDUSD"), 1); -} - -- (void)testBoundaryEntries { - XCTAssertEqual(symbol_scale::get("AUDNZD"), 10000); - XCTAssertEqual(symbol_scale::get("XAGUSD"), 1); -} - -- (void)testUnknownSymbolReturnsSentinel { - XCTAssertEqual(symbol_scale::get("NOPE"), symbol_scale::kUnknown); - XCTAssertEqual(symbol_scale::get(""), symbol_scale::kUnknown); - XCTAssertEqual(symbol_scale::get("EURUSDX"), symbol_scale::kUnknown); -} - -- (void)testCaseSensitive { - XCTAssertEqual(symbol_scale::get("eurusd"), symbol_scale::kUnknown); -} - -- (void)testAcceptsStdString { - std::string s = "USDCHF"; - XCTAssertEqual(symbol_scale::get(s), 10000); -} - -- (void)testCompileTimeFolding { - constexpr int eurusd = symbol_scale::get("EURUSD"); - constexpr int usdjpy = symbol_scale::get("USDJPY"); - static_assert(eurusd == 10000); - static_assert(usdjpy == 100); - XCTAssertEqual(eurusd, 10000); - XCTAssertEqual(usdjpy, 100); -} - -@end diff --git a/tests/tradeManager.cpp b/tests/tradeManager.cpp new file mode 100644 index 0000000..ce21f18 --- /dev/null +++ b/tests/tradeManager.cpp @@ -0,0 +1,843 @@ +// Backtesting Engine in C++ +// +// (c) 2025 Ryan McCaffery | https://mccaffers.com +// This code is licensed under MIT license (see LICENSE.txt for details) +// --------------------------------------- + +#include + +#include +#include // setenv — disable Elastic reporting for run() smoke tests +#include +#include +#include +#include +#include + +#include + +#include "shared/tradingDefinitions/configuration.hpp" + +import tradeManager; // TradeManager +import exitRules; // trading::exit_rules::checkExit +import reviewStopAndLimit; // trading::reviewStopAndLimit +import runLoop; // trading::runTicks, RiskLimits, RunStatus +import operations; // Operations::run +import strategy; // IStrategy +import priceData; // PriceData +import trade; // Direction, Trade + +// Pulls in the _dd user-defined literal so "1.23"_dd produces a decimal64_t +// directly. decimal64_t has no implicit conversion from double — the closest +// C# analogue is having to write `1.23m` instead of `1.23` for a decimal. PnL, +// size, balances and pip distances are still decimal; prices are not. +// +// Prices are scaled fixed-point INT32 now: the real price times the symbol's +// multiplier (EURUSD x100000, AUSIDXAUD x100 — see symbolScale). So EURUSD +// 1.10010 is 110010 and AUSIDXAUD 7000.50 is 700050. SL/TP distances are in the +// same integer price points, so 10 points on EURUSD == 0.0001 == one classic +// pip, and realized PnL is simply priceDiff_int * size. +using namespace boost::decimal::literals; + +namespace { + +// Minimal Configuration that drives Operations::run down the RandomStrategy +// path. selectStrategy only reads STRATEGY.TRADING_VARIABLES.STRATEGY, and +// RandomStrategy ignores everything else in the strategy block, so the OHLC +// and strategy-variable sections are left default-constructed. The pip / size +// values are plausible but irrelevant to the no-throw assertions below. +tradingDefinitions::Configuration makeRandomStrategyConfig() { + tradingDefinitions::Configuration config; + config.RUN_ID = "TEST_RUN"; + config.SYMBOLS = "EURUSD"; + config.LAST_MONTHS = 1; + config.STRATEGY.UUID = "test-strategy-uuid"; + auto& vars = config.STRATEGY.TRADING_VARIABLES; + vars.STRATEGY = "RandomStrategy"; + vars.STOP_DISTANCE_IN_PIPS = 10; + vars.LIMIT_DISTANCE_IN_PIPS = 10; + vars.TRADING_SIZE = 1; + return config; +} + +// Per-test TradingVariables so each runTicks case can dial SL/TP independently +// (e.g. stop=0 to isolate the take-profit path). STRATEGY is unused by runTicks. +tradingDefinitions::TradingVariables makeVars(int32_t stopPips, + int32_t limitPips, + int32_t size) { + tradingDefinitions::TradingVariables vars; + vars.STRATEGY = "Scripted"; + vars.STOP_DISTANCE_IN_PIPS = stopPips; + vars.LIMIT_DISTANCE_IN_PIPS = limitPips; + vars.TRADING_SIZE = size; + return vars; +} + +// Deterministic strategy that replays a pre-scripted sequence of signals, one +// per decide() call, returning nullopt ("no trade") once exhausted. This is the +// injectable seam that lets us assert exact bid/ask outcomes from the run loop +// without RandomStrategy's coin flips. +struct ScriptedStrategy : IStrategy { + std::vector> script; + std::size_t index = 0; + + explicit ScriptedStrategy(std::vector> signals) + : script(std::move(signals)) {} + + std::optional decide(const PriceData& /*tick*/) override { + return index < script.size() ? script[index++] : std::nullopt; + } + void during(const PriceData& /*tick*/, TradeManager& /*tradeManager*/) override {} +}; + +// Always signals LONG — used to probe re-entry behaviour (gating while a +// position is open; same-tick re-entry after a stop-out). +struct AlwaysLongStrategy : IStrategy { + std::optional decide(const PriceData& /*tick*/) override { + return Direction::LONG; + } + void during(const PriceData& /*tick*/, TradeManager& /*tradeManager*/) override {} +}; + +} // namespace + +TEST_CASE("TradeManager opens a trade", "[tradeManager]") { + TradeManager manager; + PriceData tick(10000000, 9900000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(tick, 1, Direction::LONG); + CHECK_FALSE(tradeId.empty()); + CHECK(manager.reviewAccount() == 1); +} + +TEST_CASE("TradeManager closes a trade", "[tradeManager]") { + TradeManager manager; + PriceData tick(10000000, 9900000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(tick, 1, Direction::LONG); + bool closed = manager.closeTrade(tradeId, 11000000, tick); + CHECK(closed); + CHECK(manager.reviewAccount() == 0); +} + +TEST_CASE("TradeManager tracks multiple trades", "[tradeManager]") { + TradeManager manager; + PriceData tick1(10000000, 9900000, std::chrono::system_clock::now(), "EURUSD"); + PriceData tick2(20000000, 19900000, std::chrono::system_clock::now(), "EURUSD"); + PriceData tick3(30000000, 29900000, std::chrono::system_clock::now(), "EURUSD"); + manager.openTrade(tick1, 1, Direction::LONG); + manager.openTrade(tick2, 2, Direction::SHORT); + manager.openTrade(tick3, 3, Direction::LONG); + + CHECK(manager.reviewAccount() == 3); +} + +TEST_CASE("TradeManager records trade details", "[tradeManager]") { + TradeManager manager; + PriceData tick(10000000, 9900000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(tick, 1, Direction::LONG); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + + REQUIRE(trade != trades.end()); + CHECK(trade->second.entryPrice == 10000000); + CHECK(trade->second.size == 1); + CHECK(trade->second.direction == Direction::LONG); +} + +// Regression: with a 1-pip EURUSD spread and a 1-pip stop, a LONG must not +// be stopped out on its own opening tick. The stop is measured from the +// adverse side (entry bid), not the execution price (entry ask) — otherwise +// the spread alone trips the stop. (1 classic pip == 10 integer points here.) +TEST_CASE("LONG does not exit on entry tick with a one-pip spread", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::LONG, 1, 1); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + REQUIRE(trade != trades.end()); + CHECK(trade->second.entryPrice == 110010); + CHECK(trade->second.exitReferencePrice == 110000); + + auto exit = trading::exit_rules::checkExit(trade->second, entryTick); + CHECK_FALSE(exit.has_value()); +} + +// Symmetric SHORT case: must not be stopped out on the opening tick. +TEST_CASE("SHORT does not exit on entry tick with a one-pip spread", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::SHORT, 1, 1); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + REQUIRE(trade != trades.end()); + CHECK(trade->second.entryPrice == 110000); + CHECK(trade->second.exitReferencePrice == 110010); + + auto exit = trading::exit_rules::checkExit(trade->second, entryTick); + CHECK_FALSE(exit.has_value()); +} + +// Sanity check: once price moves enough, the stop still fires — the fix +// shifts the threshold by one pip, it does not disable exits. +TEST_CASE("LONG stops out when bid drops one pip below entry bid", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::LONG, 1, 1); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + + PriceData laterTick(110000, 109990, std::chrono::system_clock::now(), "EURUSD"); + auto exit = trading::exit_rules::checkExit(trade->second, laterTick); + REQUIRE(exit.has_value()); + CHECK(*exit == 109990); +} + +// LONG × SL/TP × flat tick: passing the entry tick itself back through +// checkExit must not fire either side. This pins the spread-vs-stop +// invariant: SL is anchored on the entry bid (exitReferencePrice), not +// the execution ask. +TEST_CASE("checkExit: LONG flat tick does not fire", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110011, 110001, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::LONG, 1, 1); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + REQUIRE(trade != trades.end()); + + auto exit = trading::exit_rules::checkExit(trade->second, entryTick); + CHECK_FALSE(exit.has_value()); +} + +TEST_CASE("checkExit: LONG SL fires at bid", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110011, 110001, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::LONG, 1, 0); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + REQUIRE(trade != trades.end()); + + // The SL distance is 1 pip (10 points), so entry-bid 110001 minus 10 is + // 109991; the next-tick bid lands exactly on that level and trips it. + PriceData nextTick(110001, 109991, std::chrono::system_clock::now(), "EURUSD"); + auto exit = trading::exit_rules::checkExit(trade->second, nextTick); + REQUIRE(exit.has_value()); + CHECK(*exit == nextTick.bid); + CHECK(*exit == 109991); +} + +TEST_CASE("checkExit: SHORT SL fires at ask", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110011, 110001, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::SHORT, 1, 0); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + REQUIRE(trade != trades.end()); + + PriceData nextTick(110021, 110011, std::chrono::system_clock::now(), "EURUSD"); + auto exit = trading::exit_rules::checkExit(trade->second, nextTick); + REQUIRE(exit.has_value()); + CHECK(*exit == nextTick.ask); + CHECK(*exit == 110021); +} + +TEST_CASE("checkExit: LONG TP fires at bid", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110011, 110001, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::LONG, 0, 1); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + REQUIRE(trade != trades.end()); + + PriceData nextTick(110021, 110011, std::chrono::system_clock::now(), "EURUSD"); + auto exit = trading::exit_rules::checkExit(trade->second, nextTick); + REQUIRE(exit.has_value()); + CHECK(*exit == nextTick.bid); + CHECK(*exit == 110011); +} + +TEST_CASE("checkExit: SHORT TP fires at ask", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110011, 110001, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::SHORT, 0, 1); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + REQUIRE(trade != trades.end()); + + PriceData nextTick(110001, 109991, std::chrono::system_clock::now(), "EURUSD"); + auto exit = trading::exit_rules::checkExit(trade->second, nextTick); + REQUIRE(exit.has_value()); + CHECK(*exit == nextTick.ask); + CHECK(*exit == 110001); +} + +// Cross-symbol tick must not close a EURUSD trade. Without the symbol filter +// in reviewStopAndLimit, an AUSIDXAUD price (~700000) fed through checkExit +// against a EURUSD LONG lands far outside the EURUSD price band, so without the +// guard the trade would close at a nonsensical price. +TEST_CASE("reviewStopAndLimit skips trades for other symbols", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::LONG, 1, 1); + + PriceData ausTick(700000, 700000, std::chrono::system_clock::now(), "AUSIDXAUD"); + trading::reviewStopAndLimit(manager, ausTick); + + CHECK(manager.reviewAccount() == 1); + auto trades = manager.getActiveTrades(); + CHECK(trades.find(tradeId) != trades.end()); +} + +// Matching-symbol tick still closes — the filter must not over-block exits +// when the tick's symbol matches the trade's symbol. +TEST_CASE("reviewStopAndLimit closes a trade on a matching-symbol tick", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::LONG, 1, 1); + + PriceData stopTick(110000, 109990, std::chrono::system_clock::now(), "EURUSD"); + trading::reviewStopAndLimit(manager, stopTick); + + auto active = manager.getActiveTrades(); + CHECK(active.find(tradeId) == active.end()); + + const auto& closed = manager.getClosedTrades(); + REQUIRE(closed.size() == 1); + CHECK(closed.front().id == tradeId); + CHECK(closed.front().closePrice == stopTick.bid); + CHECK(closed.front().closePrice == 109990); +} + +// Symmetric cross-symbol case: an AUSIDXAUD trade (price ~700000) must not +// close on a EURUSD tick (~110000). +TEST_CASE("reviewStopAndLimit: AUSIDXAUD trade not closed by EURUSD tick", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(700050, 700000, std::chrono::system_clock::now(), "AUSIDXAUD"); + std::string tradeId = manager.openTrade(entryTick, 1, Direction::LONG, 1, 1); + + PriceData eurTick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + trading::reviewStopAndLimit(manager, eurTick); + + CHECK(manager.reviewAccount() == 1); + auto trades = manager.getActiveTrades(); + CHECK(trades.find(tradeId) != trades.end()); +} + +TEST_CASE("hasActiveTradeForSymbol: empty manager returns false", "[tradeManager]") { + TradeManager manager; + CHECK_FALSE(manager.hasActiveTradeForSymbol("EURUSD")); +} + +TEST_CASE("hasActiveTradeForSymbol: true for opened symbol, false for other", "[tradeManager]") { + TradeManager manager; + PriceData tick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + manager.openTrade(tick, 1, Direction::LONG); + + CHECK(manager.hasActiveTradeForSymbol("EURUSD")); + CHECK_FALSE(manager.hasActiveTradeForSymbol("GBPUSD")); +} + +TEST_CASE("hasActiveTradeForSymbol: false after closeTrade", "[tradeManager]") { + TradeManager manager; + PriceData tick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(tick, 1, Direction::LONG); + REQUIRE(manager.hasActiveTradeForSymbol("EURUSD")); + + bool closed = manager.closeTrade(tradeId, 110000, tick); + CHECK(closed); + CHECK_FALSE(manager.hasActiveTradeForSymbol("EURUSD")); +} + +TEST_CASE("Can open trades on different symbols simultaneously", "[tradeManager]") { + TradeManager manager; + PriceData eurTick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + manager.openTrade(eurTick, 1, Direction::LONG); + CHECK(manager.hasActiveTradeForSymbol("EURUSD")); + CHECK_FALSE(manager.hasActiveTradeForSymbol("AUSIDXAUD")); + + PriceData ausTick(700010, 700000, std::chrono::system_clock::now(), "AUSIDXAUD"); + manager.openTrade(ausTick, 1, Direction::LONG); + + CHECK(manager.getActiveTrades().size() == 2); + CHECK(manager.hasActiveTradeForSymbol("EURUSD")); + CHECK(manager.hasActiveTradeForSymbol("AUSIDXAUD")); +} + +// openTrade does not enforce same-symbol uniqueness, so callers rely on +// hasActiveTradeForSymbol to gate same-symbol re-entry. This pins the invariant +// that a single open is enough to flip the helper to true. +TEST_CASE("Helper reports symbol active after first open", "[tradeManager]") { + TradeManager manager; + PriceData tick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + manager.openTrade(tick, 1, Direction::LONG); + CHECK(manager.hasActiveTradeForSymbol("EURUSD")); +} + +// --- Entry-side bid/ask handling --- + +// A LONG buys at the ask, but its stop/limit must be measured from the bid (the +// price it would exit at), so entryPrice == ask, exitReferencePrice == bid. +// entryBid/entryAsk record the raw spread regardless of direction. +TEST_CASE("openTrade: LONG enters at ask and records the spread", "[tradeManager]") { + TradeManager manager; + PriceData tick(10000000, 9900000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(tick, 1, Direction::LONG); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + REQUIRE(trade != trades.end()); + + CHECK(trade->second.entryPrice == 10000000); + CHECK(trade->second.exitReferencePrice == 9900000); + CHECK(trade->second.entryAsk == 10000000); + CHECK(trade->second.entryBid == 9900000); +} + +// Symmetric SHORT: sells at the bid, exit reference is the ask. +TEST_CASE("openTrade: SHORT enters at bid and records the spread", "[tradeManager]") { + TradeManager manager; + PriceData tick(10000000, 9900000, std::chrono::system_clock::now(), "EURUSD"); + std::string tradeId = manager.openTrade(tick, 1, Direction::SHORT); + auto trades = manager.getActiveTrades(); + auto trade = trades.find(tradeId); + REQUIRE(trade != trades.end()); + + CHECK(trade->second.entryPrice == 9900000); + CHECK(trade->second.exitReferencePrice == 10000000); + CHECK(trade->second.entryAsk == 10000000); + CHECK(trade->second.entryBid == 9900000); +} + +// --- Operations::run loop invariants --- + +// Operations::run gates same-symbol re-entry on hasActiveTradeForSymbol and +// runs reviewStopAndLimit *before* the entry check on each tick, so a trade +// that stops out on a tick frees its symbol for re-entry on a later tick. +TEST_CASE("Run loop invariant: exit frees the symbol for re-entry", "[tradeManager]") { + TradeManager manager; + PriceData entryTick(110010, 110000, std::chrono::system_clock::now(), "EURUSD"); + std::string firstId = manager.openTrade(entryTick, 1, Direction::LONG, 1, 1); + REQUIRE(manager.hasActiveTradeForSymbol("EURUSD")); + + // Stop tick: bid drops 1 pip below the entry bid, so the LONG stops out. + PriceData stopTick(110000, 109990, std::chrono::system_clock::now(), "EURUSD"); + trading::reviewStopAndLimit(manager, stopTick); + + CHECK_FALSE(manager.hasActiveTradeForSymbol("EURUSD")); + const auto& closed = manager.getClosedTrades(); + REQUIRE(closed.size() == 1); + CHECK(closed.front().closePrice == stopTick.bid); + + // The gate is open, so the loop would now allow a fresh entry on this symbol. + std::string secondId = manager.openTrade(stopTick, 1, Direction::LONG, 1, 1); + CHECK(firstId != secondId); + CHECK(manager.hasActiveTradeForSymbol("EURUSD")); +} + +// --- Operations::run smoke tests --- + +// Operations::run owns its TradeManager internally and reports only to stdout +// and Elasticsearch, so there is no return value to assert against. These are +// deliberately smoke tests: with ELASTIC_ENABLED=0 the run must drive the full +// per-tick loop, summarise, and results path without throwing. RandomStrategy +// makes per-trade outcomes non-deterministic, so only the no-throw contract is +// checked. (Operations::run finishes by PUTting results to Elasticsearch; opt +// out so putTradingResults returns early — no network, no JSON serialisation.) + +TEST_CASE("Operations::run handles an empty tick stream without throwing", "[tradeManager]") { + setenv("ELASTIC_ENABLED", "0", 1); + const std::vector ticks; + const auto config = makeRandomStrategyConfig(); + CHECK_NOTHROW(Operations::run(ticks, config)); +} + +TEST_CASE("Operations::run processes a single tick without throwing", "[tradeManager]") { + setenv("ELASTIC_ENABLED", "0", 1); + const std::vector ticks{ + PriceData(110010, 110000, std::chrono::system_clock::now(), "EURUSD"), + }; + const auto config = makeRandomStrategyConfig(); + CHECK_NOTHROW(Operations::run(ticks, config)); +} + +TEST_CASE("Operations::run processes a multi-tick stream without throwing", "[tradeManager]") { + setenv("ELASTIC_ENABLED", "0", 1); + // A drifting EURUSD series so the 10-pip SL/TP can actually fire across the + // run, exercising both the entry and the reviewStopAndLimit exit paths. + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), + PriceData(110110, 110100, now, "EURUSD"), + PriceData(110210, 110200, now, "EURUSD"), + PriceData(110060, 110050, now, "EURUSD"), + PriceData(109910, 109900, now, "EURUSD"), + }; + const auto config = makeRandomStrategyConfig(); + CHECK_NOTHROW(Operations::run(ticks, config)); +} + +// --- Operations run loop (deterministic, end-to-end) --- + +// These drive trading::runTicks — the exact per-tick loop Operations::run +// executes — with a deterministic injected strategy and a TradeManager we own, +// so trade outcomes (entry side, exit side, realised PnL) can be asserted +// directly. Units: EURUSD has 10 stored price-points per pip. + +// LONG entry executes at the ask; the stop/limit reference is the bid. +TEST_CASE("runTicks: LONG opens at the ask", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({Direction::LONG}); + const auto vars = makeVars(10, 10, 1); + const std::vector ticks{ + PriceData(110010, 110000, std::chrono::system_clock::now(), "EURUSD"), + }; + + trading::runTicks(tm, strategy, ticks, vars); + + REQUIRE(tm.getActiveTrades().size() == 1); + CHECK(tm.getClosedTrades().size() == 0); + const Trade& trade = tm.getActiveTrades().begin()->second; + CHECK(trade.direction == Direction::LONG); + CHECK(trade.entryPrice == 110010); + CHECK(trade.exitReferencePrice == 110000); + CHECK(trade.entryAsk == 110010); + CHECK(trade.entryBid == 110000); +} + +// Symmetric SHORT: executes at the bid, exit reference is the ask. +TEST_CASE("runTicks: SHORT opens at the bid", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({Direction::SHORT}); + const auto vars = makeVars(10, 10, 1); + const std::vector ticks{ + PriceData(110010, 110000, std::chrono::system_clock::now(), "EURUSD"), + }; + + trading::runTicks(tm, strategy, ticks, vars); + + REQUIRE(tm.getActiveTrades().size() == 1); + const Trade& trade = tm.getActiveTrades().begin()->second; + CHECK(trade.direction == Direction::SHORT); + CHECK(trade.entryPrice == 110000); + CHECK(trade.exitReferencePrice == 110010); + CHECK(trade.entryAsk == 110010); + CHECK(trade.entryBid == 110000); +} + +// No signal -> no position, across many ticks. +TEST_CASE("runTicks: no signal opens nothing", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({}); // empty script: decide() always returns nullopt + const auto vars = makeVars(10, 10, 1); + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), + PriceData(110110, 110100, now, "EURUSD"), + PriceData(110210, 110200, now, "EURUSD"), + }; + + trading::runTicks(tm, strategy, ticks, vars); + + CHECK(tm.getActiveTrades().size() == 0); + CHECK(tm.getClosedTrades().size() == 0); +} + +// Re-entry is gated while a position is open: an always-signalling strategy on +// flat ticks (price never reaches the 10-pip SL/TP) must still open only one +// trade for the symbol, not one per tick. +TEST_CASE("runTicks: re-entry gated while active", "[tradeManager]") { + TradeManager tm; + AlwaysLongStrategy strategy; + const auto vars = makeVars(10, 10, 1); + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), + PriceData(110010, 110000, now, "EURUSD"), + PriceData(110010, 110000, now, "EURUSD"), + }; + + trading::runTicks(tm, strategy, ticks, vars); + + CHECK(tm.getActiveTrades().size() == 1); + CHECK(tm.getClosedTrades().size() == 0); +} + +// LONG take-profit: a 10-pip favourable move nets only 90 points (9 pips) +// because entry was at the ask (110010) while the TP is measured from the entry +// bid (110000) and closes at the bid. +TEST_CASE("runTicks: LONG TP closes at bid, PnL net of spread", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({Direction::LONG}); // opens once, no re-entry + const auto vars = makeVars(0, 10, 1); // TP only + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), // open LONG @ ask 110010 + PriceData(110110, 110100, now, "EURUSD"), // bid 110100 hits TP (ref 110000 + 100p) + }; + + trading::runTicks(tm, strategy, ticks, vars); + + CHECK(tm.getActiveTrades().size() == 0); + REQUIRE(tm.getClosedTrades().size() == 1); + const Trade& closed = tm.getClosedTrades().front(); + CHECK(closed.closePrice == 110100); + CHECK(closed.pnl == 90); +} + +// Symmetric SHORT take-profit: enters at the bid (110000), TP measured from the +// entry ask (110010), closes at the ask. Again 90 points net of the spread. +TEST_CASE("runTicks: SHORT TP closes at ask, PnL net of spread", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({Direction::SHORT}); + const auto vars = makeVars(0, 10, 1); // TP only + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), // open SHORT @ bid 110000 + PriceData(109910, 109900, now, "EURUSD"), // ask 109910 hits TP (ref 110010 - 100p) + }; + + trading::runTicks(tm, strategy, ticks, vars); + + CHECK(tm.getActiveTrades().size() == 0); + REQUIRE(tm.getClosedTrades().size() == 1); + const Trade& closed = tm.getClosedTrades().front(); + CHECK(closed.closePrice == 109910); + CHECK(closed.pnl == 90); +} + +// LONG stop-loss: a 10-pip adverse move loses 110 points (11 pips) because +// entry was at the ask 110010. Loss includes the spread. +TEST_CASE("runTicks: LONG SL closes at bid, negative PnL", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({Direction::LONG}); + const auto vars = makeVars(10, 0, 1); // SL only + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), // open LONG @ ask 110010 + PriceData(109910, 109900, now, "EURUSD"), // bid 109900 hits SL (ref 110000 - 100p) + }; + + trading::runTicks(tm, strategy, ticks, vars); + + CHECK(tm.getActiveTrades().size() == 0); + REQUIRE(tm.getClosedTrades().size() == 1); + const Trade& closed = tm.getClosedTrades().front(); + CHECK(closed.closePrice == 109900); + CHECK(closed.pnl == -110); +} + +// Exit-before-entry ordering within a single tick: on the tick that stops the +// first LONG out, reviewStopAndLimit closes it first, the symbol frees, and the +// always-LONG strategy immediately re-enters on that same tick. +TEST_CASE("runTicks: exit then same-tick re-entry", "[tradeManager]") { + TradeManager tm; + AlwaysLongStrategy strategy; + const auto vars = makeVars(10, 0, 1); // SL only + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), // LONG#1 @ ask 110010 + PriceData(109910, 109900, now, "EURUSD"), // stops LONG#1, re-opens LONG#2 + }; + + trading::runTicks(tm, strategy, ticks, vars); + + REQUIRE(tm.getClosedTrades().size() == 1); + REQUIRE(tm.getActiveTrades().size() == 1); + + const Trade& closed = tm.getClosedTrades().front(); + CHECK(closed.entryPrice == 110010); + CHECK(closed.closePrice == 109900); + + const Trade& reentry = tm.getActiveTrades().begin()->second; + CHECK(reentry.direction == Direction::LONG); + CHECK(reentry.entryPrice == 109910); + CHECK(reentry.exitReferencePrice == 109900); +} + +// Two symbols open simultaneously, each entering on the correct side of its own +// spread regardless of price scale (EURUSD ~110000 vs AUSIDXAUD ~700000). +TEST_CASE("runTicks: multi-symbol", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({Direction::LONG, Direction::LONG}); + const auto vars = makeVars(0, 0, 1); // no exits — both persist + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), + PriceData(700050, 700000, now, "AUSIDXAUD"), + }; + + trading::runTicks(tm, strategy, ticks, vars); + + REQUIRE(tm.getActiveTrades().size() == 2); + const Trade* eur = nullptr; + const Trade* aus = nullptr; + for (const auto& [id, trade] : tm.getActiveTrades()) { + if (trade.symbol == "EURUSD") eur = ™ + else if (trade.symbol == "AUSIDXAUD") aus = ™ + } + REQUIRE(eur != nullptr); + REQUIRE(aus != nullptr); + CHECK(eur->entryPrice == 110010); + CHECK(aus->entryPrice == 700050); +} + +// --- Account loss limit (fail fast) --- + +// FLOATING drawdown alone must trigger the cutoff: no stop-loss, so the open +// LONG's mark-to-market loss is the only thing the limit can see. The crash +// tick marks the trade at -1010 points; the floor is 10000 * 1% = 100 pips = +// 1000 points (pointsPerPip 10), so it breaches and the trade is liquidated. +TEST_CASE("runTicks: floating drawdown breach liquidates at mark", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({Direction::LONG}); + const auto vars = makeVars(0, 0, 1); // no SL/TP at all + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), // open LONG @ ask 110010 + PriceData(109010, 109000, now, "EURUSD"), // mark at bid: floating -1010 + PriceData(109010, 109000, now, "EURUSD"), // must never be processed + }; + const trading::RiskLimits limits{.startingBalance = "10000"_dd, + .maxLossPercent = "1"_dd, + .pointsPerPip = 10}; + + const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); + + CHECK(status == trading::RunStatus::LossLimitBreached); + CHECK(tm.getActiveTrades().size() == 0); + REQUIRE(tm.getClosedTrades().size() == 1); + const Trade& closed = tm.getClosedTrades().front(); + CHECK(closed.closePrice == 109000); + CHECK(closed.pnl == -1010); + CHECK(closed.liquidated); + CHECK(closed.floatingPnl == 0); + CHECK(tm.calculatePnl() == -1010); + CHECK(tm.unrealizedPnl() == 0); +} + +// On breach, EVERY open trade is liquidated — each at its own symbol's last +// marked price. EURUSD crash (-1010) breaches the 1000-point floor; AUSIDXAUD, +// marked only at its entry tick, closes at its own mark for the -50 spread cost. +TEST_CASE("runTicks: liquidation closes every symbol at its own mark", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({Direction::LONG, Direction::LONG}); + const auto vars = makeVars(0, 0, 1); // no SL/TP at all + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), // open EURUSD LONG + PriceData(700050, 700000, now, "AUSIDXAUD"), // open AUSIDXAUD LONG + PriceData(109010, 109000, now, "EURUSD"), // EURUSD -1010: breach + }; + const trading::RiskLimits limits{.startingBalance = "10000"_dd, + .maxLossPercent = "1"_dd, + .pointsPerPip = 10}; + + const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); + + CHECK(status == trading::RunStatus::LossLimitBreached); + CHECK(tm.getActiveTrades().size() == 0); + REQUIRE(tm.getClosedTrades().size() == 2); + CHECK(tm.calculatePnl() == -1060); + for (const Trade& closed : tm.getClosedTrades()) { + CHECK(closed.liquidated); + if (closed.symbol == "EURUSD") { + CHECK(closed.closePrice == 109000); + CHECK(closed.pnl == -1010); + } else { + CHECK(closed.closePrice == 700000); + CHECK(closed.pnl == -50); + } + } +} + +// MAX_OPEN_TRADES caps simultaneous positions across the whole run: with a +// cap of 1, the second symbol's signal is skipped while the first is open. +TEST_CASE("runTicks: max-open-trades cap blocks the second entry", "[tradeManager]") { + TradeManager tm; + ScriptedStrategy strategy({Direction::LONG, Direction::LONG}); + const auto vars = makeVars(0, 0, 1); // no exits — first stays open + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), + PriceData(700050, 700000, now, "AUSIDXAUD"), + }; + const trading::RiskLimits limits{.maxOpenTrades = 1}; + + const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); + + CHECK(status == trading::RunStatus::Completed); + REQUIRE(tm.getActiveTrades().size() == 1); + CHECK(tm.getActiveTrades().begin()->second.symbol == std::string("EURUSD")); +} + +// A stop-out that breaches the loss limit must end the run on that tick, BEFORE +// the entry phase — so the always-LONG strategy gets no same-tick re-entry, and +// later ticks never run. Floor: 10000 * 0.1% = 10 pips = 100 points; the single +// stop-out loses 110 points (incl. spread), so it breaches. +TEST_CASE("runTicks: loss-limit breach stops run before re-entry", "[tradeManager]") { + TradeManager tm; + AlwaysLongStrategy strategy; + const auto vars = makeVars(10, 0, 1); // SL only + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), // LONG#1 @ ask 110010 + PriceData(109910, 109900, now, "EURUSD"), // stops LONG#1: pnl -110, breach + PriceData(109910, 109900, now, "EURUSD"), // must never be processed + }; + const trading::RiskLimits limits{.startingBalance = "10000"_dd, + .maxLossPercent = "0.1"_dd, + .pointsPerPip = 10}; + + const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); + + CHECK(status == trading::RunStatus::LossLimitBreached); + REQUIRE(tm.getClosedTrades().size() == 1); + CHECK_FALSE(tm.getClosedTrades().front().liquidated); + CHECK(tm.getActiveTrades().size() == 0); + CHECK(tm.calculatePnl() == -110); +} + +// A realized loss inside the limit must not stop the run: same stop-out, but a +// 5% limit (floor 5000 points) comfortably absorbs the -110-point loss, so the +// run completes and the same-tick re-entry happens. +TEST_CASE("runTicks: loss within limit runs to completion", "[tradeManager]") { + TradeManager tm; + AlwaysLongStrategy strategy; + const auto vars = makeVars(10, 0, 1); // SL only + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), + PriceData(109910, 109900, now, "EURUSD"), // stop-out -110, within -500 + }; + const trading::RiskLimits limits{.startingBalance = "10000"_dd, + .maxLossPercent = "5"_dd, + .pointsPerPip = 10}; + + const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); + + CHECK(status == trading::RunStatus::Completed); + CHECK(tm.getClosedTrades().size() == 1); + CHECK(tm.getActiveTrades().size() == 1); +} + +// maxLossPercent <= 0 disables the check entirely — losses far past any +// percentage are ignored and the run completes. Cover both 0 and -1 spellings. +TEST_CASE("runTicks: loss limit disabled for zero and negative", "[tradeManager]") { + const auto vars = makeVars(10, 0, 1); // SL only + const auto now = std::chrono::system_clock::now(); + const std::vector ticks{ + PriceData(110010, 110000, now, "EURUSD"), + PriceData(109910, 109900, now, "EURUSD"), // stop-out -110 + }; + + for (const auto percent : {"0"_dd, -"1"_dd}) { + TradeManager tm; + AlwaysLongStrategy strategy; + // Tiny balance: -110 realized is over 100% of the account, yet with the + // limit disabled the run must still complete. + const trading::RiskLimits limits{.startingBalance = "10"_dd, + .maxLossPercent = percent}; + + const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); + + CHECK(status == trading::RunStatus::Completed); + CHECK(tm.getActiveTrades().size() == 1); + } +} diff --git a/tests/tradeManager.mm b/tests/tradeManager.mm deleted file mode 100644 index d0d84c0..0000000 --- a/tests/tradeManager.mm +++ /dev/null @@ -1,893 +0,0 @@ -// Backtesting Engine in C++ -// -// (c) 2025 Ryan McCaffery | https://mccaffers.com -// This code is licensed under MIT license (see LICENSE.txt for details) -// --------------------------------------- - -#import -#import // setenv — disable Elastic reporting for run() smoke tests -#import -#import -#import -#import -#import "tradeManager.hpp" -#import "exitRules.hpp" -#import "reviewStopAndLimit.hpp" -#import "runLoop.hpp" -#import "operations.hpp" -#import "strategies/strategy.hpp" -#import "trading_definitions/configuration.hpp" - -// Pulls in the _dd user-defined literal so "1.23"_dd produces a decimal64_t -// directly. decimal64_t has no implicit conversion from double — the closest -// C# analogue is having to write `1.23m` instead of `1.23` for a decimal. -using namespace boost::decimal::literals; - -namespace { - -// Minimal Configuration that drives Operations::run down the RandomStrategy -// path. selectStrategy only reads STRATEGY.TRADING_VARIABLES.STRATEGY, and -// RandomStrategy ignores everything else in the strategy block, so the OHLC -// and strategy-variable sections are left default-constructed. The pip / size -// values are plausible but irrelevant to the no-throw assertions below. -trading_definitions::Configuration makeRandomStrategyConfig() { - trading_definitions::Configuration config; - config.RUN_ID = "TEST_RUN"; - config.SYMBOLS = "EURUSD"; - config.LAST_MONTHS = 1; - config.STRATEGY.UUID = "test-strategy-uuid"; - auto& vars = config.STRATEGY.TRADING_VARIABLES; - vars.STRATEGY = "RandomStrategy"; - vars.STOP_DISTANCE_IN_PIPS = "10"_dd; - vars.LIMIT_DISTANCE_IN_PIPS = "10"_dd; - vars.TRADING_SIZE = "1.0"_dd; - return config; -} - -// Per-test TradingVariables so each runTicks case can dial SL/TP independently -// (e.g. stop=0 to isolate the take-profit path). STRATEGY is unused by runTicks. -trading_definitions::TradingVariables makeVars(boost::decimal::decimal64_t stopPips, - boost::decimal::decimal64_t limitPips, - boost::decimal::decimal64_t size) { - trading_definitions::TradingVariables vars; - vars.STRATEGY = "Scripted"; - vars.STOP_DISTANCE_IN_PIPS = stopPips; - vars.LIMIT_DISTANCE_IN_PIPS = limitPips; - vars.TRADING_SIZE = size; - return vars; -} - -// Deterministic strategy that replays a pre-scripted sequence of signals, one -// per decide() call, returning nullopt ("no trade") once exhausted. This is the -// injectable seam that lets us assert exact bid/ask outcomes from the run loop -// without RandomStrategy's coin flips. -struct ScriptedStrategy : IStrategy { - std::vector> script; - std::size_t index = 0; - - explicit ScriptedStrategy(std::vector> signals) - : script(std::move(signals)) {} - - std::optional decide(const PriceData& /*tick*/) override { - return index < script.size() ? script[index++] : std::nullopt; - } - void during(const PriceData& /*tick*/, TradeManager& /*tradeManager*/) override {} -}; - -// Always signals LONG — used to probe re-entry behaviour (gating while a -// position is open; same-tick re-entry after a stop-out). -struct AlwaysLongStrategy : IStrategy { - std::optional decide(const PriceData& /*tick*/) override { - return Direction::LONG; - } - void during(const PriceData& /*tick*/, TradeManager& /*tradeManager*/) override {} -}; - -} // namespace - -@interface TradeManagerTests : XCTestCase -@property (nonatomic) TradeManager* manager; -@end - -@implementation TradeManagerTests - -- (void)setUp { - self.manager = new TradeManager(); - // Operations::run finishes by PUTting results to Elasticsearch. There is no - // Elastic instance under test, so opt out: putTradingResults returns early - // (no network, no JSON serialisation) when ELASTIC_ENABLED=0. - setenv("ELASTIC_ENABLED", "0", 1); -} - -- (void)tearDown { - delete self.manager; - self.manager = nullptr; -} - -- (void)testOpenTrade { - PriceData tick("100.0"_dd, "99.0"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(tick, "1.0"_dd, Direction::LONG); - XCTAssertFalse(tradeId.empty(), "Trade ID should not be empty"); - XCTAssertEqual(self.manager->reviewAccount(), 1, "Should have 1 active trade"); -} - -- (void)testCloseTrade { - PriceData tick("100.0"_dd, "99.0"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(tick, "1.0"_dd, Direction::LONG); - bool closed = self.manager->closeTrade(tradeId, "110.0"_dd, tick); - XCTAssertTrue(closed, "Trade should be closed successfully"); - XCTAssertEqual(self.manager->reviewAccount(), 0, "Should have 0 active trades"); -} - -- (void)testMultipleTrades { - PriceData tick1("100.0"_dd, "99.0"_dd, std::chrono::system_clock::now(), "EURUSD"); - PriceData tick2("200.0"_dd, "199.0"_dd, std::chrono::system_clock::now(), "EURUSD"); - PriceData tick3("300.0"_dd, "299.0"_dd, std::chrono::system_clock::now(), "EURUSD"); - self.manager->openTrade(tick1, "1.0"_dd, Direction::LONG); - self.manager->openTrade(tick2, "2.0"_dd, Direction::SHORT); - self.manager->openTrade(tick3, "3.0"_dd, Direction::LONG); - - XCTAssertEqual(self.manager->reviewAccount(), 3, "Should have 3 active trades"); -} - -- (void)testTradeDetails { - PriceData tick("100.0"_dd, "99.0"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(tick, "1.0"_dd, Direction::LONG); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - XCTAssertEqual(trade->second.entryPrice, "100.0"_dd, "Entry price should match"); - XCTAssertEqual(trade->second.size, "1.0"_dd, "Size should match"); - XCTAssertTrue(trade->second.direction == Direction::LONG, "Trade should be long"); -} - -// Regression: with a 1-pip EURUSD spread and a 1-pip stop, a LONG must not -// be stopped out on its own opening tick. The stop is measured from the -// adverse side (entry bid), not the execution price (entry ask) — otherwise -// the spread alone trips the stop. -- (void)testLongDoesNotExitOnEntryTickWithOnePipSpread { - PriceData entryTick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::LONG, - "1"_dd, "1"_dd); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - XCTAssertEqual(trade->second.entryPrice, "1.1001"_dd, "LONG entry price should be ask"); - XCTAssertEqual(trade->second.exitReferencePrice, "1.1000"_dd, - "LONG exit reference should be entry bid"); - - auto exit = trading::exit_rules::checkExit(trade->second, entryTick); - XCTAssertFalse(exit.has_value(), - "LONG must not exit on its own entry tick when spread == stop distance"); -} - -// Symmetric SHORT case: must not be stopped out on the opening tick. -- (void)testShortDoesNotExitOnEntryTickWithOnePipSpread { - PriceData entryTick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::SHORT, - "1"_dd, "1"_dd); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - XCTAssertEqual(trade->second.entryPrice, "1.1000"_dd, "SHORT entry price should be bid"); - XCTAssertEqual(trade->second.exitReferencePrice, "1.1001"_dd, - "SHORT exit reference should be entry ask"); - - auto exit = trading::exit_rules::checkExit(trade->second, entryTick); - XCTAssertFalse(exit.has_value(), - "SHORT must not exit on its own entry tick when spread == stop distance"); -} - -// Sanity check: once price moves enough, the stop still fires — the fix -// shifts the threshold by one pip, it does not disable exits. -- (void)testLongStopsOutWhenBidDropsBelowEntryBidByOnePip { - PriceData entryTick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::LONG, - "1"_dd, "1"_dd); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - - PriceData laterTick("1.1000"_dd, "1.0999"_dd, std::chrono::system_clock::now(), "EURUSD"); - auto exit = trading::exit_rules::checkExit(trade->second, laterTick); - XCTAssertTrue(exit.has_value(), "LONG should stop when bid falls 1 pip below entry bid"); - XCTAssertEqual(*exit, "1.0999"_dd, "Stop closes at the current bid"); -} - -// LONG × SL/TP × flat tick: passing the entry tick itself back through -// checkExit must not fire either side. This pins the spread-vs-stop -// invariant: SL is anchored on the entry bid (exitReferencePrice), not -// the execution ask, so a 1-pip spread with a 1-pip stop sits exactly -// at the threshold without crossing it. -- (void)testCheckExit_LongFlatTick_NoFire { - PriceData entryTick("1.10011"_dd, "1.10001"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::LONG, - "1"_dd, "1"_dd); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - - auto exit = trading::exit_rules::checkExit(trade->second, entryTick); - XCTAssertFalse(exit.has_value(), - "LONG with 1-pip SL and TP must not fire on its own entry tick"); -} - -- (void)testCheckExit_LongSL_FiresAtBid { - PriceData entryTick("1.10011"_dd, "1.10001"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::LONG, - "1"_dd, "0"_dd); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - - // 1 pip on EURUSD == 0.0001 (the 4th decimal), so entry-bid 1.10001 minus - // 1 pip is 1.09991; the 5th decimal is a fractional pip and not enough - // to trip a 1-pip stop on its own. - PriceData nextTick("1.10001"_dd, "1.09991"_dd, std::chrono::system_clock::now(), "EURUSD"); - auto exit = trading::exit_rules::checkExit(trade->second, nextTick); - XCTAssertTrue(exit.has_value(), "LONG SL should fire when bid hits entry-bid - 1 pip"); - XCTAssertEqual(*exit, nextTick.bid, "LONG SL closes at the current bid"); - XCTAssertEqual(*exit, "1.09991"_dd, "LONG SL close price should equal next-tick bid"); -} - -- (void)testCheckExit_ShortSL_FiresAtAsk { - PriceData entryTick("1.10011"_dd, "1.10001"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::SHORT, - "1"_dd, "0"_dd); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - - PriceData nextTick("1.10021"_dd, "1.10011"_dd, std::chrono::system_clock::now(), "EURUSD"); - auto exit = trading::exit_rules::checkExit(trade->second, nextTick); - XCTAssertTrue(exit.has_value(), "SHORT SL should fire when ask hits entry-ask + 1 pip"); - XCTAssertEqual(*exit, nextTick.ask, "SHORT SL closes at the current ask"); - XCTAssertEqual(*exit, "1.10021"_dd, "SHORT SL close price should equal next-tick ask"); -} - -- (void)testCheckExit_LongTP_FiresAtBid { - PriceData entryTick("1.10011"_dd, "1.10001"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::LONG, - "0"_dd, "1"_dd); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - - PriceData nextTick("1.10021"_dd, "1.10011"_dd, std::chrono::system_clock::now(), "EURUSD"); - auto exit = trading::exit_rules::checkExit(trade->second, nextTick); - XCTAssertTrue(exit.has_value(), "LONG TP should fire when bid hits entry-bid + 1 pip"); - XCTAssertEqual(*exit, nextTick.bid, "LONG TP closes at the current bid"); - XCTAssertEqual(*exit, "1.10011"_dd, "LONG TP close price should equal next-tick bid"); -} - -- (void)testCheckExit_ShortTP_FiresAtAsk { - PriceData entryTick("1.10011"_dd, "1.10001"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::SHORT, - "0"_dd, "1"_dd); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - - PriceData nextTick("1.10001"_dd, "1.09991"_dd, std::chrono::system_clock::now(), "EURUSD"); - auto exit = trading::exit_rules::checkExit(trade->second, nextTick); - XCTAssertTrue(exit.has_value(), "SHORT TP should fire when ask hits entry-ask - 1 pip"); - XCTAssertEqual(*exit, nextTick.ask, "SHORT TP closes at the current ask"); - XCTAssertEqual(*exit, "1.10001"_dd, "SHORT TP close price should equal next-tick ask"); -} - -// Cross-symbol tick must not close a EURUSD trade. Without the symbol filter -// in reviewStopAndLimit, an AUSIDXAUD price (~7000) fed through checkExit -// against a EURUSD LONG (exit reference ~1.10, scale 10000) trivially trips -// the stop because the bid is thousands above the limit price and thousands -// below… well, it doesn't matter which side fires — the point is that any -// non-matching tick lands far outside the EURUSD price band, so without the -// guard the trade would close at a nonsensical price. -- (void)testReviewStopAndLimit_SkipsTradesForOtherSymbols { - PriceData entryTick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::LONG, - "1"_dd, "1"_dd); - - PriceData ausTick("7000.0"_dd, "7000.0"_dd, std::chrono::system_clock::now(), "AUSIDXAUD"); - trading::reviewStopAndLimit(*self.manager, ausTick); - - XCTAssertEqual(self.manager->reviewAccount(), 1, - "EURUSD trade must remain open when an AUSIDXAUD tick arrives"); - auto trades = self.manager->getActiveTrades(); - XCTAssertNotEqual(trades.find(tradeId), trades.end(), - "EURUSD trade should still be in active trades"); -} - -// Matching-symbol tick still closes — the filter must not over-block exits -// when the tick's symbol matches the trade's symbol. -- (void)testReviewStopAndLimit_MatchingSymbolTickClosesTrade { - PriceData entryTick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::LONG, - "1"_dd, "1"_dd); - - PriceData stopTick("1.1000"_dd, "1.0999"_dd, std::chrono::system_clock::now(), "EURUSD"); - trading::reviewStopAndLimit(*self.manager, stopTick); - - auto active = self.manager->getActiveTrades(); - XCTAssertEqual(active.find(tradeId), active.end(), - "EURUSD trade should have been removed from active trades"); - - const auto& closed = self.manager->getClosedTrades(); - XCTAssertEqual(closed.size(), 1, "Exactly one trade should be in closed trades"); - XCTAssertEqual(closed.front().id, tradeId, "Closed trade id should match the opened trade"); - XCTAssertEqual(closed.front().closePrice, stopTick.bid, - "LONG close price should equal the EURUSD tick bid"); - XCTAssertEqual(closed.front().closePrice, "1.0999"_dd, - "Recorded close price should be 1.0999"); -} - -// Symmetric cross-symbol case: an AUSIDXAUD trade (scale 1, price ~7000) must -// not close on a EURUSD tick (~1.10). Without the guard, the EURUSD bid sits -// far below the AUSIDXAUD stop level and would trip `tick.bid <= stopPrice` -// for a LONG, closing the trade at a nonsensical EURUSD price. -- (void)testReviewStopAndLimit_AusTradeNotClosedByEurUsdTick { - PriceData entryTick("7000.5"_dd, "7000.0"_dd, std::chrono::system_clock::now(), "AUSIDXAUD"); - std::string tradeId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::LONG, - "1"_dd, "1"_dd); - - PriceData eurTick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - trading::reviewStopAndLimit(*self.manager, eurTick); - - XCTAssertEqual(self.manager->reviewAccount(), 1, - "AUSIDXAUD trade must remain open when a EURUSD tick arrives"); - auto trades = self.manager->getActiveTrades(); - XCTAssertNotEqual(trades.find(tradeId), trades.end(), - "AUSIDXAUD trade should still be in active trades"); -} - -- (void)testHasActiveTradeForSymbol_EmptyManagerReturnsFalse { - XCTAssertFalse(self.manager->hasActiveTradeForSymbol("EURUSD"), - "Empty TradeManager must report no active trade for any symbol"); -} - -- (void)testHasActiveTradeForSymbol_TrueForOpenedSymbolFalseForOther { - PriceData tick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - self.manager->openTrade(tick, "1.0"_dd, Direction::LONG); - - XCTAssertTrue(self.manager->hasActiveTradeForSymbol("EURUSD"), - "EURUSD should be reported as active after openTrade"); - XCTAssertFalse(self.manager->hasActiveTradeForSymbol("GBPUSD"), - "GBPUSD must not be reported as active when only EURUSD is open"); -} - -- (void)testHasActiveTradeForSymbol_FalseAfterCloseTrade { - PriceData tick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(tick, "1.0"_dd, Direction::LONG); - XCTAssertTrue(self.manager->hasActiveTradeForSymbol("EURUSD"), - "Pre-condition: EURUSD should be active before close"); - - bool closed = self.manager->closeTrade(tradeId, "1.1000"_dd, tick); - XCTAssertTrue(closed, "closeTrade should succeed for an open trade id"); - XCTAssertFalse(self.manager->hasActiveTradeForSymbol("EURUSD"), - "EURUSD must no longer be active after the trade is closed"); -} - -- (void)testCanOpenTradesOnDifferentSymbolsSimultaneously { - PriceData eurTick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - self.manager->openTrade(eurTick, "1.0"_dd, Direction::LONG); - XCTAssertTrue(self.manager->hasActiveTradeForSymbol("EURUSD"), - "EURUSD should be active after the first open"); - XCTAssertFalse(self.manager->hasActiveTradeForSymbol("AUSIDXAUD"), - "AUSIDXAUD must not be active before its trade is opened"); - - PriceData ausTick("7000.1"_dd, "7000.0"_dd, std::chrono::system_clock::now(), "AUSIDXAUD"); - self.manager->openTrade(ausTick, "1.0"_dd, Direction::LONG); - - XCTAssertEqual(self.manager->getActiveTrades().size(), 2, - "Both EURUSD and AUSIDXAUD trades should be active simultaneously"); - XCTAssertTrue(self.manager->hasActiveTradeForSymbol("EURUSD"), - "EURUSD should still be active after opening AUSIDXAUD"); - XCTAssertTrue(self.manager->hasActiveTradeForSymbol("AUSIDXAUD"), - "AUSIDXAUD should be active after its trade is opened"); -} - -// TradeManager::openTrade (source/trading/tradeManager.cpp:23-38) does not -// enforce same-symbol uniqueness, so callers (e.g. source/operations.cpp:57) -// rely on hasActiveTradeForSymbol to gate same-symbol re-entry. This test -// pins the invariant that a single open is enough to flip the helper to true. -- (void)testHelperStillReportsSymbolActiveAfterFirstOpen { - PriceData tick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - self.manager->openTrade(tick, "1.0"_dd, Direction::LONG); - XCTAssertTrue(self.manager->hasActiveTradeForSymbol("EURUSD"), - "EURUSD must report as active after a single openTrade — production " - "re-entry gating depends on this"); -} - -#pragma mark - Entry-side bid/ask handling - -// Simple round-number spread (ask 100, bid 99) to pin which side of the spread -// each direction uses on entry. A LONG buys at the ask, but its stop/limit must -// be measured from the bid (the price it would exit at), so: -// entryPrice == ask, exitReferencePrice == bid. -// entryBid/entryAsk record the raw spread regardless of direction. -- (void)testOpenTrade_LongEntersAtAskAndRecordsSpread { - PriceData tick("100.0"_dd, "99.0"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(tick, "1.0"_dd, Direction::LONG); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - - XCTAssertEqual(trade->second.entryPrice, "100.0"_dd, "LONG executes at the ask"); - XCTAssertEqual(trade->second.exitReferencePrice, "99.0"_dd, - "LONG exit reference is the entry bid (close side)"); - XCTAssertEqual(trade->second.entryAsk, "100.0"_dd, "entryAsk records the tick ask"); - XCTAssertEqual(trade->second.entryBid, "99.0"_dd, "entryBid records the tick bid"); -} - -// Symmetric SHORT: sells at the bid, exit reference is the ask. -- (void)testOpenTrade_ShortEntersAtBidAndRecordsSpread { - PriceData tick("100.0"_dd, "99.0"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string tradeId = self.manager->openTrade(tick, "1.0"_dd, Direction::SHORT); - auto trades = self.manager->getActiveTrades(); - auto trade = trades.find(tradeId); - XCTAssertNotEqual(trade, trades.end(), "Trade should exist"); - - XCTAssertEqual(trade->second.entryPrice, "99.0"_dd, "SHORT executes at the bid"); - XCTAssertEqual(trade->second.exitReferencePrice, "100.0"_dd, - "SHORT exit reference is the entry ask (close side)"); - XCTAssertEqual(trade->second.entryAsk, "100.0"_dd, "entryAsk records the tick ask"); - XCTAssertEqual(trade->second.entryBid, "99.0"_dd, "entryBid records the tick bid"); -} - -#pragma mark - Operations::run loop invariants - -// Operations::run gates same-symbol re-entry on hasActiveTradeForSymbol and -// runs reviewStopAndLimit *before* the entry check on each tick, so a trade -// that stops out on a tick frees its symbol for re-entry on a later tick. -// This drives that exact sequence through the public building blocks the loop -// uses (reviewStopAndLimit + hasActiveTradeForSymbol) without invoking the -// random strategy, pinning the ordering the smoke tests below cannot observe. -- (void)testRunLoopInvariant_ExitFreesSymbolForReentry { - PriceData entryTick("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"); - std::string firstId = self.manager->openTrade(entryTick, "1.0"_dd, Direction::LONG, - "1"_dd, "1"_dd); - XCTAssertTrue(self.manager->hasActiveTradeForSymbol("EURUSD"), - "EURUSD must be active after the first open — re-entry is gated on this"); - - // Stop tick: bid drops 1 pip below the entry bid, so the LONG stops out. - PriceData stopTick("1.1000"_dd, "1.0999"_dd, std::chrono::system_clock::now(), "EURUSD"); - trading::reviewStopAndLimit(*self.manager, stopTick); - - XCTAssertFalse(self.manager->hasActiveTradeForSymbol("EURUSD"), - "Symbol must be free again once the trade stops out"); - const auto& closed = self.manager->getClosedTrades(); - XCTAssertEqual(closed.size(), 1, "Exactly one trade should have closed"); - XCTAssertEqual(closed.front().closePrice, stopTick.bid, - "LONG closes at the tick bid (the exit side)"); - - // The gate is open, so the loop would now allow a fresh entry on this symbol. - std::string secondId = self.manager->openTrade(stopTick, "1.0"_dd, Direction::LONG, - "1"_dd, "1"_dd); - XCTAssertNotEqual(firstId, secondId, "Re-entry must be a distinct trade"); - XCTAssertTrue(self.manager->hasActiveTradeForSymbol("EURUSD"), - "EURUSD active again after re-entry"); -} - -#pragma mark - Operations::run smoke tests - -// Operations::run owns its TradeManager internally and reports only to stdout -// and Elasticsearch, so there is no return value to assert against. These are -// deliberately smoke tests: with ELASTIC_ENABLED=0 (see setUp) the run must -// drive the full per-tick loop, summarise, and results path without throwing. -// The deterministic bid/ask behaviour the loop relies on is covered by the -// building-block tests above; RandomStrategy makes per-trade outcomes here -// non-deterministic, so only the no-throw contract is checked. - -- (void)testOperationsRun_EmptyTicks_DoesNotThrow { - const std::vector ticks; - const auto config = makeRandomStrategyConfig(); - XCTAssertNoThrow(Operations::run(ticks, config), - "run must handle an empty tick stream without throwing"); -} - -- (void)testOperationsRun_SingleTick_DoesNotThrow { - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"), - }; - const auto config = makeRandomStrategyConfig(); - XCTAssertNoThrow(Operations::run(ticks, config), - "run must process a single tick without throwing"); -} - -- (void)testOperationsRun_MultipleTicks_DoesNotThrow { - // A drifting EURUSD series so the 10-pip SL/TP can actually fire across the - // run, exercising both the entry and the reviewStopAndLimit exit paths. - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), - PriceData("1.1011"_dd, "1.1010"_dd, now, "EURUSD"), - PriceData("1.1021"_dd, "1.1020"_dd, now, "EURUSD"), - PriceData("1.1006"_dd, "1.1005"_dd, now, "EURUSD"), - PriceData("1.0991"_dd, "1.0990"_dd, now, "EURUSD"), - }; - const auto config = makeRandomStrategyConfig(); - XCTAssertNoThrow(Operations::run(ticks, config), - "run must process a multi-tick stream without throwing"); -} - -#pragma mark - Operations run loop (deterministic, end-to-end) - -// These drive trading::runTicks — the exact per-tick loop Operations::run -// executes — with a deterministic injected strategy and a TradeManager we own, -// so trade outcomes (entry side, exit side, realised PnL) can be asserted -// directly. EURUSD scale is 10000, so 1 pip == 0.0001. - -// LONG entry executes at the ask; the stop/limit reference is the bid (the -// close side), and both raw spread prices are recorded on the trade. -- (void)testRunTicks_LongOpensAtAsk { - TradeManager tm; - ScriptedStrategy strategy({Direction::LONG}); - const auto vars = makeVars("10"_dd, "10"_dd, "1.0"_dd); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"), - }; - - trading::runTicks(tm, strategy, ticks, vars); - - XCTAssertEqual(tm.getActiveTrades().size(), 1, "Exactly one trade should be open"); - XCTAssertEqual(tm.getClosedTrades().size(), 0, "Nothing should have closed"); - const Trade& trade = tm.getActiveTrades().begin()->second; - XCTAssertTrue(trade.direction == Direction::LONG, "Trade should be LONG"); - XCTAssertEqual(trade.entryPrice, "1.1001"_dd, "LONG executes at the ask"); - XCTAssertEqual(trade.exitReferencePrice, "1.1000"_dd, "LONG exit reference is the bid"); - XCTAssertEqual(trade.entryAsk, "1.1001"_dd, "entryAsk records the tick ask"); - XCTAssertEqual(trade.entryBid, "1.1000"_dd, "entryBid records the tick bid"); -} - -// Symmetric SHORT: executes at the bid, exit reference is the ask. -- (void)testRunTicks_ShortOpensAtBid { - TradeManager tm; - ScriptedStrategy strategy({Direction::SHORT}); - const auto vars = makeVars("10"_dd, "10"_dd, "1.0"_dd); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, std::chrono::system_clock::now(), "EURUSD"), - }; - - trading::runTicks(tm, strategy, ticks, vars); - - XCTAssertEqual(tm.getActiveTrades().size(), 1, "Exactly one trade should be open"); - const Trade& trade = tm.getActiveTrades().begin()->second; - XCTAssertTrue(trade.direction == Direction::SHORT, "Trade should be SHORT"); - XCTAssertEqual(trade.entryPrice, "1.1000"_dd, "SHORT executes at the bid"); - XCTAssertEqual(trade.exitReferencePrice, "1.1001"_dd, "SHORT exit reference is the ask"); - XCTAssertEqual(trade.entryAsk, "1.1001"_dd, "entryAsk records the tick ask"); - XCTAssertEqual(trade.entryBid, "1.1000"_dd, "entryBid records the tick bid"); -} - -// No signal -> no position, across many ticks. -- (void)testRunTicks_NoSignalOpensNothing { - TradeManager tm; - ScriptedStrategy strategy({}); // empty script: decide() always returns nullopt - const auto vars = makeVars("10"_dd, "10"_dd, "1.0"_dd); - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), - PriceData("1.1011"_dd, "1.1010"_dd, now, "EURUSD"), - PriceData("1.1021"_dd, "1.1020"_dd, now, "EURUSD"), - }; - - trading::runTicks(tm, strategy, ticks, vars); - - XCTAssertEqual(tm.getActiveTrades().size(), 0, "No trade should open without a signal"); - XCTAssertEqual(tm.getClosedTrades().size(), 0, "Nothing should close either"); -} - -// Re-entry is gated while a position is open: an always-signalling strategy on -// flat ticks (price never reaches the 10-pip SL/TP) must still open only one -// trade for the symbol, not one per tick. -- (void)testRunTicks_ReentryGatedWhileActive { - TradeManager tm; - AlwaysLongStrategy strategy; - const auto vars = makeVars("10"_dd, "10"_dd, "1.0"_dd); - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), - }; - - trading::runTicks(tm, strategy, ticks, vars); - - XCTAssertEqual(tm.getActiveTrades().size(), 1, - "Gate must suppress duplicate same-symbol entries while one is open"); - XCTAssertEqual(tm.getClosedTrades().size(), 0, "Flat price must not trigger SL/TP"); -} - -// LONG take-profit: a 10-pip favourable move nets only 9 pips because entry was -// at the ask (1.1001) while the TP is measured from the entry bid (1.1000) and -// closes at the bid. This pins that the spread is accounted for end-to-end. -- (void)testRunTicks_LongTP_ClosesAtBid_PnlNetOfSpread { - TradeManager tm; - ScriptedStrategy strategy({Direction::LONG}); // opens once, no re-entry - const auto vars = makeVars("0"_dd, "10"_dd, "1.0"_dd); // TP only - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), // open LONG @ ask 1.1001 - PriceData("1.1011"_dd, "1.1010"_dd, now, "EURUSD"), // bid 1.1010 hits TP (ref 1.1000 + 10p) - }; - - trading::runTicks(tm, strategy, ticks, vars); - - XCTAssertEqual(tm.getActiveTrades().size(), 0, "Position should be closed by TP"); - XCTAssertEqual(tm.getClosedTrades().size(), 1, "Exactly one closed trade"); - const Trade& closed = tm.getClosedTrades().front(); - XCTAssertEqual(closed.closePrice, "1.1010"_dd, "LONG TP closes at the tick bid"); - XCTAssertEqual(closed.pnl, "9"_dd, "10-pip move nets 9 pips after the 1-pip spread"); -} - -// Symmetric SHORT take-profit: enters at the bid (1.1000), TP measured from the -// entry ask (1.1001), closes at the ask. Again 9 pips net of the spread. -- (void)testRunTicks_ShortTP_ClosesAtAsk_PnlNetOfSpread { - TradeManager tm; - ScriptedStrategy strategy({Direction::SHORT}); - const auto vars = makeVars("0"_dd, "10"_dd, "1.0"_dd); // TP only - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), // open SHORT @ bid 1.1000 - PriceData("1.0991"_dd, "1.0990"_dd, now, "EURUSD"), // ask 1.0991 hits TP (ref 1.1001 - 10p) - }; - - trading::runTicks(tm, strategy, ticks, vars); - - XCTAssertEqual(tm.getActiveTrades().size(), 0, "Position should be closed by TP"); - XCTAssertEqual(tm.getClosedTrades().size(), 1, "Exactly one closed trade"); - const Trade& closed = tm.getClosedTrades().front(); - XCTAssertEqual(closed.closePrice, "1.0991"_dd, "SHORT TP closes at the tick ask"); - XCTAssertEqual(closed.pnl, "9"_dd, "10-pip move nets 9 pips after the 1-pip spread"); -} - -// LONG stop-loss: a 10-pip adverse move (entry bid 1.1000 down to 1.0990) loses -// 11 pips because entry was at the ask 1.1001. Loss includes the spread. -- (void)testRunTicks_LongSL_ClosesAtBid_NegativePnl { - TradeManager tm; - ScriptedStrategy strategy({Direction::LONG}); - const auto vars = makeVars("10"_dd, "0"_dd, "1.0"_dd); // SL only - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), // open LONG @ ask 1.1001 - PriceData("1.0991"_dd, "1.0990"_dd, now, "EURUSD"), // bid 1.0990 hits SL (ref 1.1000 - 10p) - }; - - trading::runTicks(tm, strategy, ticks, vars); - - XCTAssertEqual(tm.getActiveTrades().size(), 0, "Position should be stopped out"); - XCTAssertEqual(tm.getClosedTrades().size(), 1, "Exactly one closed trade"); - const Trade& closed = tm.getClosedTrades().front(); - XCTAssertEqual(closed.closePrice, "1.0990"_dd, "LONG SL closes at the tick bid"); - XCTAssertEqual(closed.pnl, -"11"_dd, "10-pip adverse move loses 11 pips including the spread"); -} - -// Exit-before-entry ordering within a single tick: on the tick that stops the -// first LONG out, reviewStopAndLimit closes it first, the symbol frees, and the -// always-LONG strategy immediately re-enters on that same tick — at the new -// tick's ask. Pins that the loop reviews exits before considering entries. -- (void)testRunTicks_ExitThenSameTickReentry { - TradeManager tm; - AlwaysLongStrategy strategy; - const auto vars = makeVars("10"_dd, "0"_dd, "1.0"_dd); // SL only - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), // LONG#1 @ ask 1.1001 - PriceData("1.0991"_dd, "1.0990"_dd, now, "EURUSD"), // stops LONG#1, re-opens LONG#2 - }; - - trading::runTicks(tm, strategy, ticks, vars); - - XCTAssertEqual(tm.getClosedTrades().size(), 1, "The first LONG should have closed"); - XCTAssertEqual(tm.getActiveTrades().size(), 1, "A re-entry should be open on the same tick"); - - const Trade& closed = tm.getClosedTrades().front(); - XCTAssertEqual(closed.entryPrice, "1.1001"_dd, "Closed trade was LONG#1, entered at tick1 ask"); - XCTAssertEqual(closed.closePrice, "1.0990"_dd, "LONG#1 stopped out at tick2 bid"); - - const Trade& reentry = tm.getActiveTrades().begin()->second; - XCTAssertTrue(reentry.direction == Direction::LONG, "Re-entry should be LONG"); - XCTAssertEqual(reentry.entryPrice, "1.0991"_dd, "Re-entry executes at tick2 ask"); - XCTAssertEqual(reentry.exitReferencePrice, "1.0990"_dd, "Re-entry exit reference is tick2 bid"); -} - -// Two symbols open simultaneously, each entering on the correct side of its own -// spread regardless of price scale (EURUSD ~1.10 vs AUSIDXAUD ~7000). -- (void)testRunTicks_MultiSymbol { - TradeManager tm; - ScriptedStrategy strategy({Direction::LONG, Direction::LONG}); - const auto vars = makeVars("0"_dd, "0"_dd, "1.0"_dd); // no exits — both persist - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), - PriceData("7000.5"_dd, "7000.0"_dd, now, "AUSIDXAUD"), - }; - - trading::runTicks(tm, strategy, ticks, vars); - - XCTAssertEqual(tm.getActiveTrades().size(), 2, "Both symbols should be open"); - const Trade* eur = nullptr; - const Trade* aus = nullptr; - for (const auto& [id, trade] : tm.getActiveTrades()) { - if (trade.symbol == "EURUSD") eur = ™ - else if (trade.symbol == "AUSIDXAUD") aus = ™ - } - XCTAssertTrue(eur != nullptr, "EURUSD trade should exist"); - XCTAssertTrue(aus != nullptr, "AUSIDXAUD trade should exist"); - XCTAssertEqual(eur->entryPrice, "1.1001"_dd, "EURUSD LONG enters at its ask"); - XCTAssertEqual(aus->entryPrice, "7000.5"_dd, "AUSIDXAUD LONG enters at its ask"); -} - -#pragma mark - Account loss limit (fail fast) - -// FLOATING drawdown alone must trigger the cutoff: no stop-loss, so the open -// LONG's mark-to-market loss is the only thing the limit can see. The crash -// tick marks the trade at -101 (floor: 10000 * 1% = 100), the run stops, and -// the trade is liquidated at that mark — so the reported PnL is the true -// account PnL, not 0 realized. -- (void)testRunTicks_FloatingDrawdownBreach_LiquidatesAtMark { - TradeManager tm; - ScriptedStrategy strategy({Direction::LONG}); - const auto vars = makeVars("0"_dd, "0"_dd, "1.0"_dd); // no SL/TP at all - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), // open LONG @ ask 1.1001 - PriceData("1.0901"_dd, "1.0900"_dd, now, "EURUSD"), // mark at bid: floating -101 - PriceData("1.0901"_dd, "1.0900"_dd, now, "EURUSD"), // must never be processed - }; - const trading::RiskLimits limits{.startingBalance = "10000"_dd, - .maxLossPercent = "1"_dd}; - - const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); - - XCTAssertTrue(status == trading::RunStatus::LossLimitBreached, - "Floating drawdown must count toward the loss limit"); - XCTAssertEqual(tm.getActiveTrades().size(), 0, "The open trade must be liquidated"); - XCTAssertEqual(tm.getClosedTrades().size(), 1, "Exactly one (liquidated) closed trade"); - const Trade& closed = tm.getClosedTrades().front(); - XCTAssertEqual(closed.closePrice, "1.0900"_dd, "Liquidation closes at the marked bid"); - XCTAssertEqual(closed.pnl, -"101"_dd, "Liquidated PnL is the marked floating loss"); - XCTAssertTrue(closed.liquidated, "Forced close must carry the liquidated flag"); - XCTAssertEqual(closed.floatingPnl, "0"_dd, "floatingPnl is zeroed once realized"); - XCTAssertEqual(tm.calculatePnl(), -"101"_dd, "True account PnL is fully realized"); - XCTAssertEqual(tm.unrealizedPnl(), "0"_dd, "Nothing floating remains after liquidation"); -} - -// On breach, EVERY open trade is liquidated — each at its own symbol's last -// marked price, not the breaching tick's. The EURUSD crash (-101) breaches the -// -100 floor; the AUSIDXAUD position, marked only at its entry tick, closes at -// its own mark 7000.0 for the -0.5 spread cost. True PnL = -101.5. -- (void)testRunTicks_Liquidation_ClosesEverySymbolAtItsOwnMark { - TradeManager tm; - ScriptedStrategy strategy({Direction::LONG, Direction::LONG}); - const auto vars = makeVars("0"_dd, "0"_dd, "1.0"_dd); // no SL/TP at all - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), // open EURUSD LONG - PriceData("7000.5"_dd, "7000.0"_dd, now, "AUSIDXAUD"), // open AUSIDXAUD LONG - PriceData("1.0901"_dd, "1.0900"_dd, now, "EURUSD"), // EURUSD -101: breach - }; - const trading::RiskLimits limits{.startingBalance = "10000"_dd, - .maxLossPercent = "1"_dd}; - - const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); - - XCTAssertTrue(status == trading::RunStatus::LossLimitBreached, - "Combined floating drawdown must breach the limit"); - XCTAssertEqual(tm.getActiveTrades().size(), 0, "Both positions must be liquidated"); - XCTAssertEqual(tm.getClosedTrades().size(), 2, "Both symbols produce a closed trade"); - XCTAssertEqual(tm.calculatePnl(), -"101.5"_dd, - "True PnL combines both liquidations (-101 EURUSD, -0.5 AUSIDXAUD spread)"); - for (const Trade& closed : tm.getClosedTrades()) { - XCTAssertTrue(closed.liquidated, "Every forced close must carry the liquidated flag"); - if (closed.symbol == "EURUSD") { - XCTAssertEqual(closed.closePrice, "1.0900"_dd, "EURUSD closes at the crash bid"); - XCTAssertEqual(closed.pnl, -"101"_dd, "EURUSD realizes the crash drawdown"); - } else { - XCTAssertEqual(closed.closePrice, "7000.0"_dd, - "AUSIDXAUD closes at its own last mark, not a EURUSD price"); - XCTAssertEqual(closed.pnl, -"0.5"_dd, "AUSIDXAUD realizes only its spread cost"); - } - } -} - -// MAX_OPEN_TRADES caps simultaneous positions across the whole run: with a -// cap of 1, the second symbol's signal is skipped while the first position is -// open. The uncapped variant of this setup is testRunTicks_MultiSymbol. -- (void)testRunTicks_MaxOpenTradesCap_BlocksSecondEntry { - TradeManager tm; - ScriptedStrategy strategy({Direction::LONG, Direction::LONG}); - const auto vars = makeVars("0"_dd, "0"_dd, "1.0"_dd); // no exits — first stays open - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), - PriceData("7000.5"_dd, "7000.0"_dd, now, "AUSIDXAUD"), - }; - const trading::RiskLimits limits{.maxOpenTrades = 1}; - - const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); - - XCTAssertTrue(status == trading::RunStatus::Completed, "Cap is not a failure condition"); - XCTAssertEqual(tm.getActiveTrades().size(), 1, "Cap of 1 must block the second entry"); - XCTAssertEqual(tm.getActiveTrades().begin()->second.symbol, std::string("EURUSD"), - "The first signal wins the only slot"); -} - -// A stop-out that breaches the loss limit must end the run on that tick, -// BEFORE the entry phase — so unlike testRunTicks_ExitThenSameTickReentry the -// always-LONG strategy gets no same-tick re-entry, and later ticks never run. -// Floor here: 10000 * 0.1% = 10; the single stop-out loses 11 (incl. spread). -- (void)testRunTicks_LossLimitBreach_StopsRunBeforeReentry { - TradeManager tm; - AlwaysLongStrategy strategy; - const auto vars = makeVars("10"_dd, "0"_dd, "1.0"_dd); // SL only - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), // LONG#1 @ ask 1.1001 - PriceData("1.0991"_dd, "1.0990"_dd, now, "EURUSD"), // stops LONG#1: pnl -11, breach - PriceData("1.0991"_dd, "1.0990"_dd, now, "EURUSD"), // must never be processed - }; - const trading::RiskLimits limits{.startingBalance = "10000"_dd, - .maxLossPercent = "0.1"_dd}; - - const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); - - XCTAssertTrue(status == trading::RunStatus::LossLimitBreached, - "Run must report the loss-limit breach"); - XCTAssertEqual(tm.getClosedTrades().size(), 1, "Only the stopped-out trade should exist"); - XCTAssertFalse(tm.getClosedTrades().front().liquidated, - "A stop-out is an organic close, not a liquidation"); - XCTAssertEqual(tm.getActiveTrades().size(), 0, - "Breach is checked before entries — no re-entry may open"); - XCTAssertEqual(tm.calculatePnl(), -"11"_dd, "Realized PnL at cutoff is the single stop-out"); -} - -// A realized loss inside the limit must not stop the run: same stop-out, but a -// 5% limit (floor -500) comfortably absorbs -11, so the run completes and the -// same-tick re-entry happens as normal. -- (void)testRunTicks_LossWithinLimit_RunsToCompletion { - TradeManager tm; - AlwaysLongStrategy strategy; - const auto vars = makeVars("10"_dd, "0"_dd, "1.0"_dd); // SL only - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), - PriceData("1.0991"_dd, "1.0990"_dd, now, "EURUSD"), // stop-out -11, within -500 - }; - const trading::RiskLimits limits{.startingBalance = "10000"_dd, - .maxLossPercent = "5"_dd}; - - const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); - - XCTAssertTrue(status == trading::RunStatus::Completed, "Run should not be cut off"); - XCTAssertEqual(tm.getClosedTrades().size(), 1, "The stop-out still closes"); - XCTAssertEqual(tm.getActiveTrades().size(), 1, "Same-tick re-entry proceeds as normal"); -} - -// maxLossPercent <= 0 disables the check entirely — losses far past any -// percentage are ignored and the run completes (the experimentation escape -// hatch, no extra flag needed). Cover both 0 and -1 spellings. -- (void)testRunTicks_LossLimitDisabled_ZeroAndNegative { - const auto vars = makeVars("10"_dd, "0"_dd, "1.0"_dd); // SL only - const auto now = std::chrono::system_clock::now(); - const std::vector ticks{ - PriceData("1.1001"_dd, "1.1000"_dd, now, "EURUSD"), - PriceData("1.0991"_dd, "1.0990"_dd, now, "EURUSD"), // stop-out -11 - }; - - for (const auto percent : {"0"_dd, -"1"_dd}) { - TradeManager tm; - AlwaysLongStrategy strategy; - // Tiny balance: -11 realized is over 100% of the account, yet with the - // limit disabled the run must still complete. - const trading::RiskLimits limits{.startingBalance = "10"_dd, - .maxLossPercent = percent}; - - const auto status = trading::runTicks(tm, strategy, ticks, vars, limits); - - XCTAssertTrue(status == trading::RunStatus::Completed, - "maxLossPercent <= 0 must disable the cutoff"); - XCTAssertEqual(tm.getActiveTrades().size(), 1, "Re-entry proceeds unchecked"); - } -} - -@end