diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..86f7aa8a --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,216 @@ +# OpenGraph Copilot Instructions + +This file contains coding guidelines and conventions for AI assistants working on the OpenGraph project. + +## Quick Reference + +### Key Principles +- Use `swift-testing` framework with `#expect` macro (not XCTest) +- Follow OpenGraph C++ and Swift interop patterns +- Trim trailing whitespaces automatically +- Use 4-space indentation consistently + +## Testing Guidelines + +### Testing Framework + +- Use the `swift-testing` framework with the `#expect` macro for all test assertions +- Import testing framework with: `import Testing` +- Do NOT use XCTest framework unless specifically required for compatibility + +### Test Structure + +```swift +import Testing + +struct OpenGraphTests { + @Test + func functionality() { + let value = SomeType() + + #expect(value.property == expectedValue) + #expect(value.method() == expectedResult) + } + + @Test + func errorConditions() { + #expect(throws: SomeError.self) { + try riskyOperation() + } + } +} +``` + +### Test Conventions + +- **Do NOT write any comments in test case body** - keep test code clean and self-explanatory +- Use descriptive test function names that clearly indicate what is being tested +- Group related tests using `// MARK: -` sections +- Use `#expect` for all assertions instead of XCTest assertions +- Prefer multiple focused tests over one large test +- Do not add test prefix to test function names (e.g., `testFunctionality` should be `functionality`) +- Use `@Test` attribute for test functions + +## Code Organization + +### File Structure +- Use `// MARK: -` to separate different topics and sections within files +- Organize code logically with clear separation of concerns +- Place imports at the top, followed by type definitions, then implementations + +### Example MARK Usage +```swift +// MARK: - A + +... + +// MARK: - B + +... + +// MARK: - C + +... +``` + +## Swift Coding Style + +### Access Control Hierarchy + +1. `public` - External API surface +2. `internal` - Module-internal APIs (default and should be omitted if not needed) +3. `private` - Implementation details + +### Naming Conventions + +- Follow Swift API Design Guidelines +- Use descriptive names that clearly indicate purpose +- Prefer full words over abbreviations +- Use camelCase for variables, functions, and properties +- Use PascalCase for types, protocols, and cases + +### Code Formatting Rules + +- **Automatically trim trailing whitespaces including whitespace-only lines** +- Use consistent indentation (4 spaces, not tabs) +- Place opening braces on the same line as the declaration +- Use proper spacing around operators and after commas +- Align code vertically when it improves readability +- Maximum line length: 120 characters (soft limit) + +## C++ Coding Style + +### OpenGraphCxx Guidelines + +- Follow existing OpenGraph C++ patterns and conventions +- Use `OG_INLINE` and `OG_CONSTEXPR` macros for inline and constexpr functions +- Use `OG_NOEXCEPT` for exception specifications +- Maintain compatibility with existing OpenGraph APIs +- Use proper header guards with project-specific naming + +### Memory Management + +- Use RAII principles for resource management +- Prefer smart pointers and custom deleters for automatic cleanup +- Use `ptr` template for OpenGraph-specific pointer management +- Implement proper validation and assertion mechanisms + +### Template Usage + +```cpp +template +class ptr { + // Implementation following OpenGraph patterns +}; +``` + +## Architecture Patterns + +### OpenGraph Compatibility +- Maintain API compatibility with existing OpenGraph functionality +- Use similar naming conventions and parameter patterns +- Implement protocols and extensions that mirror OpenGraph's design + +### Module Organization +- Keep related functionality in appropriate modules +- Use clear module boundaries between OpenGraphCxx and Swift layers +- Avoid circular dependencies between modules + +### C++/Swift Interop +- Use proper bridging headers for C++ integration +- Ensure memory safety across language boundaries +- Handle exceptions and errors appropriately at boundaries + +## Documentation + +### Code Comments +- Write clear, concise comments for complex logic +- Use documentation comments (`///`) for APIs documentation +- Avoid obvious comments that don't add value +- Keep comments up-to-date with code changes + +### API Documentation +```swift +/// A brief description of what this function does. +/// +/// - Parameter value: Description of the parameter +/// - Returns: Description of the return value +/// - Throws: Description of potential errors +func someFunction(value: String) throws -> Int { + // Implementation +} +``` + +## Performance Considerations + +- Optimize memory allocation patterns using OpenGraph's table/page system +- Use lazy initialization for expensive computations +- Consider memory management and avoid retain cycles +- Optimize for common use cases while maintaining flexibility +- Profile memory usage patterns in graph operations + +## Dependencies and Imports + +### Swift Files +- Minimize external dependencies +- Use conditional compilation for platform-specific code +- Import only what is needed +- Organize imports alphabetically within groups + +### C++ Files +- Use proper header inclusion guards +- Include OpenGraph base headers first +- Follow dependency order in include statements +- Use forward declarations when possible + +## Platform Compatibility + +- Support multiple Apple platforms (iOS, macOS, watchOS, tvOS, visionOS) +- Use availability annotations when using platform-specific APIs +- Test on supported platform versions +- Use feature detection rather than version checking when possible +- Handle platform differences in C++ code using preprocessor directives + +## Memory and Data Management + +### OpenGraph Patterns +- Use `data::table` for memory region management +- Implement proper page allocation and deallocation +- Use `ptr` for type-safe offset-based pointers +- Follow OpenGraph's zone-based memory organization + +### Validation and Assertions +- Use `assert_valid` methods for pointer validation +- Implement proper precondition checking +- Use OpenGraph's assertion macros consistently +- Handle edge cases gracefully + +--- + +## Troubleshooting + +### Common Issues +- **Build errors**: Check C++/Swift bridging and header paths +- **Test failures**: Ensure using `#expect` not XCTest assertions +- **Memory issues**: Verify proper pointer validation and table usage +- **Interop problems**: Check Swift/C++ type compatibility diff --git a/Sources/OpenGraphCxx/include/OpenGraphCxx/Data/zone.hpp b/Sources/OpenGraphCxx/include/OpenGraphCxx/Data/zone.hpp index 3ca30182..955f4920 100644 --- a/Sources/OpenGraphCxx/include/OpenGraphCxx/Data/zone.hpp +++ b/Sources/OpenGraphCxx/include/OpenGraphCxx/Data/zone.hpp @@ -43,7 +43,7 @@ class zone { return info(zone_id(), deleted); } private: - enum { + enum : uint32_t { zone_id_mask = 0x7fffffff, deleted = 0x80000000, }; diff --git a/Sources/OpenGraphCxx/include/OpenGraphCxx/Util/cf_ptr.hpp b/Sources/OpenGraphCxx/include/OpenGraphCxx/Util/cf_ptr.hpp new file mode 100644 index 00000000..59f78326 --- /dev/null +++ b/Sources/OpenGraphCxx/include/OpenGraphCxx/Util/cf_ptr.hpp @@ -0,0 +1,107 @@ +// +// cf_ptr.hpp +// OpenGraphCxx +// +// Status: Complete +// Modified based Compute code + +#ifndef OPENGRAPH_CXX_UTIL_CF_PTR_HPP +#define OPENGRAPH_CXX_UTIL_CF_PTR_HPP + +#include +#include + +OG_ASSUME_NONNULL_BEGIN + +namespace util { + +template class cf_ptr { +private: + CFTypeRef _storage; + + static OG_INLINE CFTypeRef to_storage(T ref) { return (CFTypeRef)(ref); } + static OG_INLINE T from_storage(CFTypeRef storage) { return (T)storage; } + +public: + OG_CONSTEXPR cf_ptr() OG_NOEXCEPT : _storage(nullptr) {} + OG_CONSTEXPR cf_ptr(std::nullptr_t) OG_NOEXCEPT : _storage(nullptr) {} + + explicit cf_ptr(T ref) : _storage(to_storage(ref)) { + if (_storage) { + CFRetain(_storage); + } + } + + ~cf_ptr() { + if (_storage) { + CFRelease(_storage); + } + } + + // Copy and move constructors + + cf_ptr(const cf_ptr &other) OG_NOEXCEPT : _storage(other._storage) { + if (_storage) { + CFRetain(_storage); + } + }; + + cf_ptr(cf_ptr &&other) OG_NOEXCEPT : _storage(std::exchange(other._storage, nullptr)) {}; + + // Copy and move assignment operators + + cf_ptr &operator=(const cf_ptr &other) OG_NOEXCEPT { + if (this != &other) { + if (_storage) { + CFRelease(_storage); + } + _storage = other._storage; + if (_storage) { + CFRetain(_storage); + } + } + return *this; + }; + + cf_ptr &operator=(cf_ptr &&other) OG_NOEXCEPT { + if (this != &other) { + if (_storage) { + CFRelease(_storage); + } + _storage = other._storage; + other._storage = nullptr; + } + return *this; + } + + // Modifiers + + void reset() OG_NOEXCEPT { reset(nullptr); } + + void reset(T ref = nullptr) OG_NOEXCEPT { + if (_storage != ref) { + if (_storage) { + CFRelease(_storage); + } + _storage = to_storage(ref); + if (_storage) { + CFRetain(_storage); + } + } + } + + // Observers + + T get() const OG_NOEXCEPT { return from_storage(_storage); }; + + explicit operator bool() const OG_NOEXCEPT { return _storage != nullptr; } +}; /* class cf_ptr */ + +using cf_data_ptr = cf_ptr; +using cf_mutable_data_ptr = cf_ptr; + +} /* namespace util */ + +OG_ASSUME_NONNULL_END + +#endif /* OPENGRAPH_CXX_UTIL_CF_PTR_HPP */ diff --git a/Sources/OpenGraphCxx/include/OpenGraphCxx/Util/free_deleter.hpp b/Sources/OpenGraphCxx/include/OpenGraphCxx/Util/free_deleter.hpp new file mode 100644 index 00000000..820b2093 --- /dev/null +++ b/Sources/OpenGraphCxx/include/OpenGraphCxx/Util/free_deleter.hpp @@ -0,0 +1,30 @@ +// +// free_deleter.hpp +// OpenGraphCxx +// +// Status: Complete +// Modified based Compute code + +#ifndef OPENGRAPH_CXX_UTIL_FREE_DELETER_HPP +#define OPENGRAPH_CXX_UTIL_FREE_DELETER_HPP + +#include + +OG_ASSUME_NONNULL_BEGIN + +namespace util { + +class free_deleter { +public: + template void operator()(T *_Nullable ptr) { + if (ptr) { + free((void *)ptr); + } + } +}; /* class free_deleter */ + +} /* namespace util */ + +OG_ASSUME_NONNULL_END + +#endif /* OPENGRAPH_CXX_UTIL_FREE_DELETER_HPP */ diff --git a/Sources/OpenGraphCxx/include/OpenGraphCxx/Util/objc_ptr.hpp b/Sources/OpenGraphCxx/include/OpenGraphCxx/Util/objc_ptr.hpp new file mode 100644 index 00000000..4e1d0e17 --- /dev/null +++ b/Sources/OpenGraphCxx/include/OpenGraphCxx/Util/objc_ptr.hpp @@ -0,0 +1,115 @@ +// +// objc_ptr.hpp +// OpenGraphCxx +// +// Status: Complete +// Modified based Compute code + +#ifndef OPENGRAPH_CXX_UTIL_OBJC_PTR_HPP +#define OPENGRAPH_CXX_UTIL_OBJC_PTR_HPP + +#include + +#if OG_TARGET_OS_DARWIN +#include +#include + +OG_ASSUME_NONNULL_BEGIN + +// Redeclare APIs from the Objective-C runtime. +// These functions are not available through public headers, but are guaranteed +// to exist on OS X >= 10.9 and iOS >= 7.0. +OBJC_EXPORT id objc_retain(id obj); +OBJC_EXPORT void objc_release(id obj); + +namespace util { + +template class objc_ptr { +private: + id _storage; + + static OG_INLINE id to_storage(T obj) { return (id)obj; } + static OG_INLINE T from_storage(id storage) { return (T)storage; } + +public: + OG_CONSTEXPR objc_ptr() OG_NOEXCEPT : _storage(nil) {} + OG_CONSTEXPR objc_ptr(std::nullptr_t) OG_NOEXCEPT : _storage(nil) {} + + explicit objc_ptr(T obj) : _storage(to_storage(obj)) { + if (_storage) { + objc_retain(_storage); + } + } + + ~objc_ptr() { + if (_storage) { + objc_release(_storage); + } + } + + // MARK: - Copy and move constructors + + objc_ptr(const objc_ptr &other) OG_NOEXCEPT : _storage(other._storage) { + if (_storage) { + objc_retain(_storage); + } + } + + objc_ptr(objc_ptr &&other) OG_NOEXCEPT : _storage(other._storage) { + other._storage = nil; + } + + // MARK: - Copy and move assignment operators + + objc_ptr &operator=(const objc_ptr &other) OG_NOEXCEPT { + if (this != &other) { + if (_storage) { + objc_release(_storage); + } + _storage = other._storage; + if (_storage) { + objc_retain(_storage); + } + } + return *this; + } + + objc_ptr &operator=(objc_ptr &&other) OG_NOEXCEPT { + if (this != &other) { + if (_storage) { + objc_release(_storage); + } + _storage = other._storage; + other._storage = nil; + } + return *this; + } + + // MARK: - Modifiers + + void reset() OG_NOEXCEPT { reset(nil); } + + void reset(T obj = nil) OG_NOEXCEPT { + if (_storage != obj) { + if (_storage) { + objc_release(_storage); + } + _storage = to_storage(obj); + if (_storage) { + objc_retain(_storage); + } + } + } + + T get() const OG_NOEXCEPT { return from_storage(_storage); } + + explicit operator bool() const OG_NOEXCEPT { return _storage != nil; } +}; /* class objc_ptr */ + +} /* namespace util */ + +OG_ASSUME_NONNULL_END + +#endif + +#endif /* OPENGRAPH_CXX_UTIL_OBJC_PTR_HPP */ diff --git a/Sources/OpenGraphCxx/include/module.private.modulemap b/Sources/OpenGraphCxx/include/module.private.modulemap index 224fd911..62efad57 100644 --- a/Sources/OpenGraphCxx/include/module.private.modulemap +++ b/Sources/OpenGraphCxx/include/module.private.modulemap @@ -44,6 +44,13 @@ module OpenGraphCxx_Private.Runtime { export * } +module OpenGraphCxx_Private.Util { + requires cplusplus + umbrella "OpenGraphCxx/Util" + export * + module * { export * } +} + module OpenGraphCxx_Private.Vector { requires cplusplus umbrella "OpenGraphCxx/Vector"