Scope

Table of Contents

Scope

Description

Run a scoped block and automatically deinitialize the object at the end. Executes scope_body and ensures obj_deinit(obj) is called afterward, regardless of the block’s control flow. This is similar to RAII-style resource management in C++ but implemented manually via a macro. The object is passed by pointer. It is not copied or moved. This macro ensures the object is only evaluated once by capturing it internally using TYPE_OF. The memory pointed to by obj is not cleared after deinitialization; if zeroing is needed, do it inside obj_deinit. Parameters:

Parameters

NameDirectionDescription
objinPointer to the object to manage.
obj_deinitinFunction or macro to deinitialize the object.
scope_bodyinBlock of code that uses the object. MyStruct s = MyStructInit(); Scope(&s, MyStructDeinit, { UseStruct(&s); });

Success

Always continues execution after scope.

Failure

Caller must handle errors inside the scoped body.

Usage example (Cross-references)

    
    Project project = {0};
    Scope(&project, ProjectDeinit, {
    // read project config
    Str config = StrInit();
    // read project config
    Str config = StrInit();
    Scope(&config, StrDeinit, {
    if (!ReadCompleteFile(config_path, &config.data, &config.length, &config.capacity)) {
    LOG_FATAL("Failed to read config file.");
    // recursively explore directories and get files that need documentation
    Strs file_paths = VecInit();
    Scope(&file_paths, VecDeinit, {
    // temporary vector to store all directory paths to explore files in
    Strs dir_paths = VecInitWithDeepCopy(NULL, StrDeinit);
    // temporary vector to store all directory paths to explore files in
    Strs dir_paths = VecInitWithDeepCopy(NULL, StrDeinit);
    Scope(&dir_paths, VecDeinit, {
    VecMerge(&dir_paths, &project.source_directories);
    VecMerge(&dir_paths, &project.test_directories);
    
    SysDirContents dir_contents = SysGetDirContents(dir_name.data);
    Scope(&dir_contents, VecDeinit, {
    VecForeach(&dir_contents, dir_entry, {
    // if it's a directory then store it for exploration later on
    VecForeach(&file_paths, file_path, {
    Str file_contents = StrInit();
    Scope(&file_contents, StrDeinit, {
    if (!ReadCompleteFile(
    file_path.data,
    
    Str output_path = StrInit();
    Scope(&output_path, StrDeinit, {
    StrMerge(&output_path, &file_path);
    LOG_INFO("{}", output_path);
    
    Str md_code = StrInit();
    Scope(&md_code, StrDeinit, {
    // Create template strings for StrWriteFmt with escaped braces
    const char* mdHeader =
    // dump code to output path
    FILE* f = fopen(output_path.data, "w");
    Scope(f, fclose, { fwrite(md_code.data, 1, md_code.length, f); });
    });
    });

Share :