# DL File System Operations Library ## Overview The `dl_fs.h` header provides a comprehensive set of file system operations for the Bella Engine SDK. This library abstracts platform-specific file operations and provides UTF-8 filename support across Windows, macOS, and Linux. It's designed to be more convenient and safer than standard C file operations. ## Key Concepts for C++ Beginners - **`DL_API`**: A macro that handles proper function export/import across different platforms - **`constexpr`**: Declares constants that are evaluated at compile time - **Namespaces**: `dl::fs` organizes functions to avoid naming conflicts - **Default Parameters**: Functions can have optional parameters with default values (e.g., `bool create = true`) - **Reference Parameters**: `String& out` means the function will modify the passed string ## Platform Constants ### Path Separators and Quote Characters ```cpp #if DL_IS_WIN32 constexpr const char* sep = "\\"; // Windows uses backslash constexpr const char* quot = "\""; // Windows uses double quotes #else constexpr const char* sep = "/"; // Unix/Linux/macOS use forward slash constexpr const char* quot = "'"; // Unix systems use single quotes #endif ``` **Usage Example:** ```cpp #include "dl_fs.h" using namespace dl::fs; // Build a path that works on any platform String configPath = homeDir() + sep + "config" + sep + "settings.txt"; ``` ## File Operations (Enhanced stdio wrappers) These functions provide UTF-8 filename support and are safer alternatives to standard C file functions. ### Fopen - Open a File ```cpp FILE* Fopen(String path, String mode); ``` **What it does:** Opens a file with UTF-8 filename support **Parameters:** - `path`: File path to open - `mode`: File mode ("r", "w", "rb", "wb", etc.) **Returns:** FILE pointer or nullptr on failure **Example:** ```cpp // Open a text file for reading FILE* file = Fopen("config.txt", "r"); if (file) { // File opened successfully // ... read operations ... Fclose(file); } else { // Failed to open file std::cout << "Could not open config.txt" << std::endl; } // Open a binary file for writing FILE* binFile = Fopen("data.bin", "wb"); if (binFile) { // Write binary data Fclose(binFile); } ``` ### Complete File Operations API ********************************* * * File Operations Flow: * * Fopen() ──→ File Handle ──→ Fread()/Fwrite() * │ │ * │ ↓ * │ Fseek()/Ftell() * │ │ * └────────────────────────→ Fclose() * ********************************* [Figure [diagram]: File operations workflow showing the typical sequence of file handling functions.] ### Directory Operations #### Creating and Removing Directories ```cpp bool mkDir(String dir); // Create a directory bool rmDir(String dir); // Remove an empty directory ``` **Example:** ```cpp // Create a directory structure if (mkDir("projects")) { std::cout << "Created projects directory" << std::endl; if (mkDir("projects/my_game")) { std::cout << "Created game project directory" << std::endl; } } // Remove directory (must be empty) if (rmDir("projects/old_project")) { std::cout << "Removed old project directory" << std::endl; } ``` ### File Browser Dialogs These functions provide native file browser dialogs for user interaction. ```cpp String browseFile( String title = "Open File", String initialFile = "", String description = "All Files", StringVector extensions = StringVector() ); StringVector browseFiles( // Multiple file selection String title = "Open Files", String initialDir = "", String description = "All Files", StringVector extensions = StringVector() ); ``` **Example - Open file dialog:** ```cpp // Let user select an image file StringVector imageExtensions = {"png", "jpg", "jpeg", "bmp", "gif"}; String selectedImage = browseFile( "Select Image File", // Dialog title "", // No initial file "Image Files", // File type description imageExtensions // Allowed extensions ); if (!selectedImage.empty()) { std::cout << "User selected: " << selectedImage << std::endl; // Process the selected image } else { std::cout << "User cancelled file selection" << std::endl; } ``` ## Archive Operations ### ZIP File Operations ```cpp struct ZipProgress { String info; // Information about current operation Real progress; // Progress from 0.0 to 1.0 }; StringVector readZip(String zipPath, String outDir, std::function callback); bool writeZip(String zipPath, StringVector inputFiles, std::function callback); ``` **Example - Extract ZIP with progress:** ```cpp void zipProgressCallback(ZipProgress progress) { std::cout << progress.info << " (" << (progress.progress * 100) << "%)" << std::endl; } // Extract a ZIP file String zipFile = "archive.zip"; String extractDir = "extracted"; if (exists(zipFile)) { mkDir(extractDir); // Create extraction directory StringVector extractedFiles = readZip(zipFile, extractDir, zipProgressCallback); std::cout << "Extracted " << extractedFiles.size() << " files:" << std::endl; for (const auto& file : extractedFiles) { std::cout << " " << file << std::endl; } } ``` ## Path Resolution and Asset Management ### Advanced Path Finding ```cpp String resolvePath( String path, StringVector searchDirs = {}, StringVector allowedExtensions = {} ); ``` **What it does:** Finds files using search directories and extension resolution **Parameters:** - `path`: The file to find (can end with ".*" for extension matching) - `searchDirs`: Directories to search in - `allowedExtensions`: Valid file extensions for ".*" matching **Example - Asset loading system:** ```cpp // Set up search directories for game assets StringVector assetDirs = { currentDir() + sep + "assets", currentDir() + sep + "assets" + sep + "textures", currentDir() + sep + "assets" + sep + "models", homeDir() + sep + "shared_assets" }; // Find a texture file (try multiple formats) StringVector imageExtensions = {"png", "jpg", "tga", "bmp"}; String texturePath = resolvePath("wood.*", assetDirs, imageExtensions); if (!texturePath.empty()) { std::cout << "Found texture: " << texturePath << std::endl; // Load the texture file } else { std::cout << "Could not find wood texture in any format" << std::endl; } ``` ## System and Application Paths ### Executable Path Information ```cpp String exePath(); // Full path to executable String exeDir(); // Directory containing executable String appDir(); // Application directory (different on macOS) String resDir(); // Resources directory ``` ### System Directories There are two versions of each function: - **get* functions**: Return `bool` for success/failure, result in reference parameter - **Direct functions**: Return the path string, or `currentDir()` on failure ```cpp // Reference parameter versions (safer) bool getCurrentDir(String& out); bool getHomeDir(String& out); bool getTempDir(String& out); // Direct return versions (more convenient) String currentDir(); String homeDir(); String tempDir(); ``` ### Bella-Specific Directories ```cpp // Reference parameter versions bool getBellaUserDir(String& out, bool create = true); bool getBellaConfigDir(String& out, bool create = true); bool getBellaOutputDir(String& out, bool create = true); bool getBellaPreviewDir(String& out, bool create = true); // Direct return versions String bellaUserDir(bool create = true); String bellaConfigDir(bool create = true); String bellaOutputDir(bool create = true); String bellaPreviewDir(bool create = true); String bellaNodeHelpPath(bool asUrl); ``` ## Complete Usage Examples ### File Management Utility ```cpp #include "dl_fs.h" using namespace dl::fs; class FileManager { public: void organizePhotos() { String photosDir = homeDir() + sep + "Photos"; String organizedDir = photosDir + sep + "Organized"; // Create organized directory mkDir(organizedDir); // Get all image files StringVector imageTypes = {"jpg", "jpeg", "png", "tiff", "bmp"}; StringVector photos = listFiles(photosDir, imageTypes); for (const auto& photo : photos) { String fullPath = photosDir + sep + photo; String destPath = organizedDir + sep + photo; if (copyFile(fullPath, destPath)) { std::cout << "Organized: " << photo << std::endl; } } } void cleanTempFiles() { String temp = tempDir(); StringVector tempFiles = listFiles(temp); for (const auto& file : tempFiles) { if (file.find("temp_") == 0) { // Files starting with "temp_" String fullPath = temp + sep + file; if (rmFile(fullPath)) { std::cout << "Deleted temp file: " << file << std::endl; } } } } }; ``` ### Configuration Manager ```cpp class ConfigManager { private: String configDir; String configFile; public: ConfigManager() { // Set up configuration directory if (!getBellaConfigDir(configDir, true)) { configDir = currentDir(); // Fallback } configFile = configDir + sep + "app_config.json"; } bool loadConfig() { if (!exists(configFile)) { createDefaultConfig(); return false; } FILE* file = Fopen(configFile, "r"); if (!file) return false; // Read configuration data char buffer[4096]; size_t bytesRead = Fread(buffer, 1, sizeof(buffer) - 1, file); buffer[bytesRead] = '\0'; Fclose(file); std::cout << "Loaded config: " << buffer << std::endl; return true; } void createDefaultConfig() { const char* defaultConfig = R"({ "window_width": 1920, "window_height": 1080, "fullscreen": false, "auto_save": true })"; FILE* file = Fopen(configFile, "w"); if (file) { Fwrite(defaultConfig, 1, strlen(defaultConfig), file); Fclose(file); std::cout << "Created default config at: " << configFile << std::endl; } } }; ``` ## Best Practices 1. **Always check return values** for file operations and existence before proceeding 2. **Use the safer reference parameter versions** of path functions when error handling is important 3. **Create directories before writing files** to them 4. **Close files promptly** after use to free resources 5. **Use platform-agnostic path construction** with the `sep` constant 6. **Leverage path resolution** for flexible asset loading 7. **Provide progress callbacks** for long-running archive operations This documentation should give you a solid foundation for using the dl_fs library in your C++ projects!