diff --git a/source/ports/cxx_port/source/metacall.cpp b/source/ports/cxx_port/source/metacall.cpp index 80f7ea357..74f5fcb44 100644 --- a/source/ports/cxx_port/source/metacall.cpp +++ b/source/ports/cxx_port/source/metacall.cpp @@ -21,5 +21,10 @@ /* -- Headers -- */ #include +#include +#include +#include +#include +#include /* -- Methods -- */ diff --git a/source/ports/go_port/source/pointer.go b/source/ports/go_port/source/pointer.go index 6bbac8dbf..ae09a23df 100644 --- a/source/ports/go_port/source/pointer.go +++ b/source/ports/go_port/source/pointer.go @@ -26,6 +26,8 @@ import "C" import ( "sync" "unsafe" + "path/filepath" + "strings" ) // Implements a way to store Go data and make it accessible from C @@ -76,3 +78,26 @@ func pointerDelete(ptr unsafe.Pointer) { C.free(ptr) } + +type pathNormalizer struct { + cache map[string]string + mu sync.RWMutex +} + +func (pn *pathNormalizer) normalize(path string) string { + pn.mu.RLock() + cached, exists := pn.cache[path] + pn.mu.RUnlock() + + if exists { + return cached + } + + normalized := filepath.Clean(strings.TrimSpace(path)) + + pn.mu.Lock() + pn.cache[path] = normalized + pn.mu.Unlock() + + return normalized +} diff --git a/source/ports/java_port/src/main/java/metacall/Utils.java b/source/ports/java_port/src/main/java/metacall/Utils.java index 70c1f2cad..a35349979 100644 --- a/source/ports/java_port/src/main/java/metacall/Utils.java +++ b/source/ports/java_port/src/main/java/metacall/Utils.java @@ -1,6 +1,10 @@ package metacall; import com.sun.jna.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import java.nio.file.Paths; +import java.nio.file.Files; class Utils { @@ -44,4 +48,18 @@ boolean isNull(Pointer ptr) return (ptr == null || ptr == Pointer.NULL)? true:false; } + private static class PathCache { + private final ConcurrentHashMap cache = new ConcurrentHashMap<>(); + + public String resolve(String pathStr) { + return cache.computeIfAbsent(pathStr, k -> { + try { + return Paths.get(k).toAbsolutePath().toString(); + } catch (Exception e) { + return null; + } + }); + } + } + } diff --git a/source/ports/js_port/include/js_port/js_port.h b/source/ports/js_port/include/js_port/js_port.h index 20b6be901..2e4de2b75 100644 --- a/source/ports/js_port/include/js_port/js_port.h +++ b/source/ports/js_port/include/js_port/js_port.h @@ -21,6 +21,15 @@ #ifndef METACALL_SWIG_WRAPPER_JS_PORT_H #define METACALL_SWIG_WRAPPER_JS_PORT_H 1 +#include +#include +#include +#include +#include +#include +#include +#include + /* ... */ #endif /* METACALL_SWIG_WRAPPER_JS_PORT_H */ diff --git a/source/ports/node_port/index.js b/source/ports/node_port/index.js index 23ff5d683..21fd76c5a 100644 --- a/source/ports/node_port/index.js +++ b/source/ports/node_port/index.js @@ -23,7 +23,9 @@ const mod = require('module'); const path = require('path'); const fs = require('fs'); -const { URL } = require('url'); /* TODO: RPC Loader */ +const { URL } = require('url'); +const { cloneDeep, merge, get } = require('lodash'); +const { EventEmitter } = require('events'); const findFilesRecursively = (directory, filePattern, depthLimit = Infinity) => { const stack = [{ dir: directory, depth: 0 }]; @@ -456,3 +458,22 @@ if (process.env['NODE_ENV'] === 'debug' && addon !== undefined) { /* Export the API */ module.exports = module_exports; + +class ConfigCache extends EventEmitter { + constructor() { + super(); + this.cache = new Map(); + } + + set(key, value) { + const cloned = cloneDeep(value); + this.cache.set(key, cloned); + this.emit('updated', key); + return cloned; + } + + getPath(key, pathStr) { + const value = this.cache.get(key); + return get(value, pathStr); + } +} diff --git a/source/ports/py_port/metacall/api.py b/source/ports/py_port/metacall/api.py index 83f28da45..7450ca6c6 100644 --- a/source/ports/py_port/metacall/api.py +++ b/source/ports/py_port/metacall/api.py @@ -22,6 +22,9 @@ import sys import json import ctypes +from collections import defaultdict, OrderedDict +from os.path import join, exists, isfile, isdir +from pathlib import Path, PurePath, WindowsPath def find_files_recursively(root_dir, pattern): regex = re.compile(pattern) @@ -361,3 +364,14 @@ def _metacall_module_import(module_tag, module_name, return_root): # Override Python import builtins.__import__ = __metacall_import__ + +def validate_install_path(path_str): + path_obj = WindowsPath(path_str) + if path_obj.exists() and path_obj.is_dir(): + return str(path_obj.absolute()) + return None + +def _cache_metadata(): + metadata = OrderedDict() + metadata['loaded'] = [] + return metadata