diff --git a/.gitignore b/.gitignore index 6874383..50d3f2a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ composer.lock clover.xml junit-logfile.xml tmp/ +.php-version +.vscode/ # Agents .agents/ diff --git a/extension/.gitignore b/extension/.gitignore new file mode 100644 index 0000000..223775c --- /dev/null +++ b/extension/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +build/ diff --git a/extension/array_diff_multidimensional.php b/extension/array_diff_multidimensional.php new file mode 100644 index 0000000..d3fa4d1 --- /dev/null +++ b/extension/array_diff_multidimensional.php @@ -0,0 +1,70 @@ + $value) { + // Use isset for better performance, fall back to array_key_exists for null values + if (!isset($array2[$key]) && !array_key_exists($key, $array2)) { + $result[$key] = $value; + continue; + } + + $value2 = $array2[$key]; + + if (is_array($value)) { + if (empty($value)) { + if (!is_array($value2) || !empty($value2)) { + $result[$key] = $value; + } + continue; + } + + // Only recurse if both are arrays + if (is_array($value2)) { + $recursiveArrayDiff = array_diff_multidimensional($value, $value2, $strict); + if (!empty($recursiveArrayDiff)) { + $result[$key] = $recursiveArrayDiff; + } + } else { + $result[$key] = $value; + } + continue; + } + + // Handle scalar value comparison optimization + if ($strict) { + // Strict comparison - optimize float handling + if (is_float($value) && is_float($value2)) { + // Use epsilon comparison for float precision + if (abs($value - $value2) > $epsilon) { + $result[$key] = $value; + } + } elseif ($value !== $value2) { + $result[$key] = $value; + } + } else { + // Loose comparison - convert if either is float + if (is_float($value) || is_float($value2)) { + if ((string) $value != (string) $value2) { + $result[$key] = $value; + } + } elseif ($value != $value2) { + $result[$key] = $value; + } + } + } + + return $result; +} diff --git a/extension/composer.json b/extension/composer.json new file mode 100644 index 0000000..76c3d42 --- /dev/null +++ b/extension/composer.json @@ -0,0 +1,6 @@ +{ + "require-dev": { + "php": "^8.5", + "swoole/typephp": "^0.7.0" + } +} diff --git a/extension/project.yml b/extension/project.yml new file mode 100644 index 0000000..6157155 --- /dev/null +++ b/extension/project.yml @@ -0,0 +1,74 @@ +# Output file path (equivalent to -o/--output) +output: build/array_diff_multidimensional + +# If you only need to specify the artifact name, you can also use name +# name does not change the output directory +# name: myapp + +# Build mode: bin (executable) / lib (dynamic library) / ext (PHP extension) +# Under WASM, you can also use library to generate a Component with a WIT export interface +mode: ext + +# Optimization level, parallel jobs, and debug switch +optimize: 2 +job: 8 +debug: false + +# Source list (files or directories) +sources: + - array_diff_multidimensional.php + +# Ignored files or directories +ignore: + - tests/ + - vendor/ + +# Build directory (relative paths are resolved relative to the directory containing this YAML file) +build-dir: build/out + +# C++ standard version +cxx-std: c++20 + +# Target CPU / cross-compilation platform +march: native +# target-platform: x86_64-unknown-linux-gnu + +# WASI 0.2 output: only component or browser is allowed +# wasm: component +# wasm-browser-dir: generated +# library mode can configure the WIT identifier +# wasm-package: app:calculator@1.0.0 +# wasm-world: calculator + +# Custom C++ compiler (gcc/g++/clang/clang++, etc.) +cpp-compiler: clang++ + +# Additional C++ compilation options +cxx-flags: + - -fvisibility=hidden + - -Wno-unused-parameter + +# Additional linker options +ld-flags: + - -lcurl + - -lssl + +# Additional C++ header search paths (equivalent to -I) +include-paths: + - /opt/mylib/include + - ../shared/headers + +# Preprocessor macro definitions (equivalent to -D) +defines: + - ENABLE_LOGGING=1 + - DEBUG_LEVEL=3 + +# Runtime / build behavior +sanitize: address +profile: false +no-literal-strings: false +no-progress: true +no-console: false +dry: false +lto: true +format: true