Iterable Resources
May 26, 2025 ยท View on GitHub
The iterable functional system in the doTheWorld library allows you to easily iterate over DtwResource objects, apply filters, and map data into various formats. This documentation covers the different iteration and mapping methods available for resources and schemas, including examples for each method.
Table of Contents
Each
The DtwResource_foreach function allows you to iterate over all sub-resources of a DtwResource. You can customize the iteration with a callback function to process each resource, a filtration callback to include or exclude resources, a start index (defaults to 0), and a total number of elements to process (defaults to all).
Example: Iterating Over Resources with Filtration
#include "doTheWorldOne.c"
DtwRandonizer *randomizer;
typedef struct {
int age;
} Filtrage;
void print_user(DtwResource *user, void *filtrage) {
printf("Age: %ld\n", DtwResource_get_long_from_sub_resource(user, "age"));
printf("Name: %s\n", DtwResource_get_string_from_sub_resource(user, "name"));
}
bool verify_if_print_user(DtwResource *user, void *filtrage) {
Filtrage *f = (Filtrage *)filtrage;
long age = DtwResource_get_long_from_sub_resource(user, "age");
return age < f->age;
}
void create_x_users(DtwResource *users, long quantity) {
for (int i = 0; i < quantity; i++) {
DtwResource *current = DtwResource_sub_resource_random(users, NULL);
char formatted_name[20] = {0};
sprintf(formatted_name, "user%d", i);
long age = DtwRandonizer_generate_num(randomizer, 100);
DtwResource_set_string_in_sub_resource(current, "name", formatted_name);
DtwResource_set_long_in_sub_resource(current, "age", age);
}
}
int main() {
randomizer = newDtwRandonizer();
DtwResource *users = new_DtwResource("users");
create_x_users(users, 100);
DtwResourceForeachProps props = DtwResource_create_foreach_props(print_user);
Filtrage f;
f.age = 18;
props.filtrage_callback = verify_if_print_user;
props.args = &f;
DtwResource_foreach(users, props);
DtwResource_free(users);
DtwRandonizer_free(randomizer);
return 0;
}
Explanation
- Initialization: A
DtwResourcenamedusersis created, and 100 user sub-resources are added with random ages and formatted names. - Filtration: The
verify_if_print_userfunction filters users under 18 years old. - Iteration: The
print_usercallback prints the name and age of each filtered user. - Props Configuration: The
DtwResourceForeachPropsstruct allows customization of the iteration behavior, including the filtration callback and arguments.
Schema Each
The DtwResource_schema_foreach function enables iteration over resources within a schema. This is useful when working with structured data defined by a DtwDatabaseSchema.
Example: Iterating Over Schema Resources
#include "doTheWorldOne.c"
DtwRandonizer *randomizer;
typedef struct {
int age;
} Filtrage;
void print_user(DtwResource *user, void *filtrage) {
printf("Age: %ld\n", DtwResource_get_long_from_sub_resource(user, "age"));
printf("Name: %s\n", DtwResource_get_string_from_sub_resource(user, "name"));
}
bool verify_if_print_user(DtwResource *user, void *filtrage) {
Filtrage *f = (Filtrage *)filtrage;
long age = DtwResource_get_long_from_sub_resource(user, "age");
return age < f->age;
}
void create_x_users(DtwResource *users, long quantity) {
for (int i = 0; i < quantity; i++) {
DtwResource *current = DtwResource_new_schema_insertion(users);
char formatted_name[20] = {0};
sprintf(formatted_name, "user%d", i);
long age = DtwRandonizer_generate_num(randomizer, 100);
DtwResource_set_string_in_sub_resource(current, "name", formatted_name);
DtwResource_set_long_in_sub_resource(current, "age", age);
}
}
void create_schemas(DtwResource *database) {
DtwDatabaseSchema *schema = DtwResource_newDatabaseSchema(database);
DtwSchema *users = DtwDatabaseSchema_new_subSchema(schema, "users");
DtwSchema_add_primary_key(users, "name");
}
int main() {
randomizer = newDtwRandonizer();
DtwResource *database = new_DtwResource("database");
create_schemas(database);
DtwResource *users = DtwResource_sub_resource(database, "users");
create_x_users(users, 100);
Filtrage f;
f.age = 18;
DtwResourceForeachProps props = DtwResource_create_foreach_props(print_user);
props.filtrage_callback = verify_if_print_user;
props.args = &f;
DtwResource_schema_foreach(users, props);
DtwResource_free(database);
DtwRandonizer_free(randomizer);
return 0;
}
Explanation
- Schema Creation: A database schema is defined with a
userssubschema and a primary key onname. - Data Insertion: Users are added using
DtwResource_new_schema_insertionto adhere to the schema structure. - Iteration: The
DtwResource_schema_foreachfunction iterates over the schema resources, applying the same filtration and printing logic as in theEachexample.
Map
The DtwResource_map function allows you to transform resources into a custom data structure. You provide an object to store results, a retrieval function to create transformed data, and an append function to add transformed data to your object.
Example: Mapping Resources to a cJSON Array
#include "doTheWorldOne.c"
DtwRandonizer *randomizer;
typedef struct {
int age;
} Filtrage;
cJSON *return_user(DtwResource *user, void *filtrage) {
cJSON *created_object = cJSON_CreateObject();
cJSON_AddStringToObject(created_object, "name", DtwResource_get_string_from_sub_resource(user, "name"));
cJSON_AddNumberToObject(created_object, "age", DtwResource_get_long_from_sub_resource(user, "age"));
return created_object;
}
bool verify_if_print_user(DtwResource *user, void *filtrage) {
Filtrage *f = (Filtrage *)filtrage;
long age = DtwResource_get_long_from_sub_resource(user, "age");
return age < f->age;
}
void create_x_users(DtwResource *users, long quantity) {
for (int i = 0; i < quantity; i++) {
DtwResource *current = DtwResource_sub_resource_random(users, NULL);
char formatted_name[20] = {0};
sprintf(formatted_name, "user%d", i);
long age = DtwRandonizer_generate_num(randomizer, 100);
DtwResource_set_string_in_sub_resource(current, "name", formatted_name);
DtwResource_set_long_in_sub_resource(current, "age", age);
}
}
int main() {
randomizer = newDtwRandonizer();
DtwResource *database = new_DtwResource("database");
DtwResource *users = DtwResource_sub_resource(database, "users");
create_x_users(users, 100);
Filtrage f;
f.age = 18;
cJSON *items = cJSON_CreateArray();
DtwResourceMapProps props = DtwResource_create_map_props(
items,
(void (*)(void*, void*))cJSON_AddItemToArray,
(void* (*)(DtwResource *, void*))return_user
);
props.filtrage_callback = verify_if_print_user;
props.args = &f;
DtwResource_map(users, props);
char *content = cJSON_Print(items);
printf("%s\n", content);
cJSON_Delete(items);
free(content);
DtwResource_free(database);
DtwRandonizer_free(randomizer);
return 0;
}
Explanation
- Transformation: The
return_userfunction converts eachDtwResourceinto acJSONobject withnameandagefields. - Filtration: Only users under 18 are included in the mapping.
- Result Storage: The transformed data is appended to a
cJSONarray usingcJSON_AddItemToArray.
Schema Map
The DtwResource_schema_map function works similarly to DtwResource_map but operates on schema-based resources.
Example: Mapping Schema Resources to a cJSON Array
#include "doTheWorldOne.c"
DtwRandonizer *randomizer;
typedef struct {
int age;
} Filtrage;
cJSON *return_user(DtwResource *user, void *filtrage) {
cJSON *created_object = cJSON_CreateObject();
cJSON_AddStringToObject(created_object, "name", DtwResource_get_string_from_sub_resource(user, "name"));
cJSON_AddNumberToObject(created_object, "age", DtwResource_get_long_from_sub_resource(user, "age"));
return created_object;
}
bool verify_if_print_user(DtwResource *user, void *filtrage) {
Filtrage *f = (Filtrage *)filtrage;
long age = DtwResource_get_long_from_sub_resource(user, "age");
return age < f->age;
}
void create_x_users(DtwResource *users, long quantity) {
for (int i = 0; i < quantity; i++) {
DtwResource *current = DtwResource_new_schema_insertion(users);
char formatted_name[20] = {0};
sprintf(formatted_name, "user%d", i);
long age = DtwRandonizer_generate_num(randomizer, 100);
DtwResource_set_string_in_sub_resource(current, "name", formatted_name);
DtwResource_set_long_in_sub_resource(current, "age", age);
}
}
void create_schemas(DtwResource *database) {
DtwDatabaseSchema *schema = DtwResource_newDatabaseSchema(database);
DtwSchema *users = DtwDatabaseSchema_new_subSchema(schema, "users");
DtwSchema_add_primary_key(users, "name");
}
int main() {
randomizer = newDtwRandonizer();
DtwResource *database = new_DtwResource("database");
create_schemas(database);
DtwResource *users = DtwResource_sub_resource(database, "users");
create_x_users(users, 100);
Filtrage f;
f.age = 18;
cJSON *items = cJSON_CreateArray();
DtwResourceMapProps props = DtwResource_create_map_props(
items,
(void (*)(void*, void*))cJSON_AddItemToArray,
(void* (*)(DtwResource *, void*))return_user
);
props.filtrage_callback = verify_if_print_user;
props.args = &f;
DtwResource_schema_map(users, props);
char *content = cJSON_Print(items);
printf("%s\n", content);
cJSON_Delete(items);
free(content);
DtwResource_free(database);
DtwRandonizer_free(randomizer);
return 0;
}
Explanation
- Schema Context: Similar to the
Mapexample, but data is inserted using schema-specific functions. - Mapping: The
DtwResource_schema_mapfunction processes schema resources, applying the same transformation and filtration logic.
cJSON Array Map
The DtwResource_map_cJSONArray function provides a convenient way to directly map resources into a cJSON array without manually defining append functions.
Example: Direct Mapping to cJSON Array
#include "doTheWorldOne.c"
DtwRandonizer *randomizer;
typedef struct {
int age;
} Filtrage;
cJSON *return_user(DtwResource *user, void *filtrage) {
cJSON *created_object = cJSON_CreateObject();
cJSON_AddStringToObject(created_object, "name", DtwResource_get_string_from_sub_resource(user, "name"));
cJSON_AddNumberToObject(created_object, "age", DtwResource_get_long_from_sub_resource(user, "age"));
return created_object;
}
bool verify_if_print_user(DtwResource *user, void *filtrage) {
Filtrage *f = (Filtrage *)filtrage;
long age = DtwResource_get_long_from_sub_resource(user, "age");
return age < f->age;
}
void create_x_users(DtwResource *users, long quantity) {
for (int i = 0; i < quantity; i++) {
DtwResource *current = DtwResource_sub_resource_random(users, NULL);
char formatted_name[20] = {0};
sprintf(formatted_name, "user%d", i);
long age = DtwRandonizer_generate_num(randomizer, 100);
DtwResource_set_string_in_sub_resource(current, "name", formatted_name);
DtwResource_set_long_in_sub_resource(current, "age", age);
}
}
int main() {
randomizer = newDtwRandonizer();
DtwResource *database = new_DtwResource("database");
DtwResource *users = DtwResource_sub_resource(database, "users");
create_x_users(users, 100);
Filtrage f;
f.age = 18;
DtwResourcecJSONArrayMapProps props = DtwResource_create_cJSONArrayMapProps(return_user);
props.filtrage_callback = verify_if_print_user;
props.args = &f;
cJSON *items = DtwResource_map_cJSONArray(users, props);
char *content = cJSON_Print(items);
printf("%s\n", content);
cJSON_Delete(items);
free(content);
DtwResource_free(database);
DtwRandonizer_free(randomizer);
return 0;
}
Explanation
- Simplified Mapping: The
DtwResource_map_cJSONArrayfunction handles the creation and population of acJSONarray internally, simplifying the process compared to the genericDtwResource_map.
cJSON Object Map
The DtwResource_map_cJSONObject function maps resources into a cJSON object, where each resource is associated with a unique key provided by a key_provider function.
Example: Mapping to cJSON Object with Keys
#include "doTheWorldOne.c"
DtwRandonizer *randomizer;
typedef struct {
int age;
} Filtrage;
cJSON *return_user(DtwResource *user, void *filtrage) {
cJSON *created_object = cJSON_CreateObject();
cJSON_AddStringToObject(created_object, "name", DtwResource_get_string_from_sub_resource(user, "name"));
cJSON_AddNumberToObject(created_object, "age", DtwResource_get_long_from_sub_resource(user, "age"));
return created_object;
}
char *get_key(DtwResource *user, void *filtrage) {
return DtwResource_get_string_from_sub_resource(user, "name");
}
bool verify_if_print_user(DtwResource *user, void *filtrage) {
Filtrage *f = (Filtrage *)filtrage;
long age = DtwResource_get_long_from_sub_resource(user, "age");
return age < f->age;
}
void create_x_users(DtwResource *users, long quantity) {
for (int i = 0; i < quantity; i++) {
DtwResource *current = DtwResource_sub_resource_random(users, NULL);
char formatted_name[20] = {0};
sprintf(formatted_name, "user%d", i);
long age = DtwRandonizer_generate_num(randomizer, 100);
DtwResource_set_string_in_sub_resource(current, "name", formatted_name);
DtwResource_set_long_in_sub_resource(current, "age", age);
}
}
int main() {
randomizer = newDtwRandonizer();
DtwResource *database = new_DtwResource("database");
DtwResource *users = DtwResource_sub_resource(database, "users");
create_x_users(users, 100);
Filtrage f;
f.age = 18;
DtwResourcecJSONObjectMapProps props = DtwResource_create_cJSONObjectProps(return_user, get_key);
props.filtrage_callback = verify_if_print_user;
props.args = &f;
cJSON *items = DtwResource_map_cJSONObject(users, props);
char *content = cJSON_Print(items);
printf("%s\n", content);
cJSON_Delete(items);
free(content);
DtwResource_free(database);
DtwRandonizer_free(randomizer);
return 0;
}
Explanation
- Key Provision: The
get_keyfunction provides a unique key (the user's name) for eachcJSONobject entry. - Object Mapping: The resulting
cJSONobject uses these keys to organize the transformed user data.
CHash Array Map
The DtwResource_map_CHashArray function maps resources into a CHashArray from the CHashManipulator library. This requires defining DTW_ALLOW_CHASH and including the appropriate header.
Example: Mapping to CHash Array
#define DTW_CHASH_PATH "CHashManipulator.h"
#define DTW_ALLOW_CHASH
#include "doTheWorldOne.c"
CHashNamespace hash;
DtwRandonizer *randomizer;
typedef struct {
int age;
} Filtrage;
CHashObject *return_user(DtwResource *user, void *filtrage) {
return newCHashObject(
"name", hash.newString(DtwResource_get_string_from_sub_resource(user, "name")),
"age", hash.newNumber(DtwResource_get_long_from_sub_resource(user, "age"))
);
}
bool verify_if_print_user(DtwResource *user, void *filtrage) {
Filtrage *f = (Filtrage *)filtrage;
long age = DtwResource_get_long_from_sub_resource(user, "age");
return age < f->age;
}
void create_x_users(DtwResource *users, long quantity) {
for (int i = 0; i < quantity; i++) {
DtwResource *current = DtwResource_sub_resource_random(users, NULL);
char formatted_name[20] = {0};
sprintf(formatted_name, "user%d", i);
long age = DtwRandonizer_generate_num(randomizer, 100);
DtwResource_set_string_in_sub_resource(current, "name", formatted_name);
DtwResource_set_long_in_sub_resource(current, "age", age);
}
}
int main() {
hash = newCHashNamespace();
randomizer = newDtwRandonizer();
DtwResource *database = new_DtwResource("database");
DtwResource *users = DtwResource_sub_resource(database, "users");
create_x_users(users, 100);
Filtrage f;
f.age = 18;
DtwResourceCHashArrayMapProps props = DtwResource_create_CHashArrayMapProps(return_user);
props.filtrage_callback = verify_if_print_user;
props.args = &f;
CHashArray *items = DtwResource_map_CHashArray(users, props);
char *content = hash.dump_to_json_string(items);
printf("%s\n", content);
hash.free(items);
free(content);
DtwResource_free(database);
DtwRandonizer_free(randomizer);
return 0;
}
Explanation
- CHash Integration: The
CHashManipulatorlibrary is used to create aCHashArrayof user objects. - Configuration: The
DTW_ALLOW_CHASHmacro must be defined to enable this feature, as it is not included in the default amalgamation.