Created
March 16, 2026 22:34
-
-
Save imaami/79fda3bc4011ebf039487254d5174050 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <errno.h> | |
| #include <stddef.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include "example_obj.h" | |
| struct obj | |
| obj (char const *name) | |
| { | |
| struct obj ret = {0}; | |
| if (!name) { | |
| ret.error = EFAULT; | |
| return ret; | |
| } | |
| int e = snprintf(ret.name.arr, sizeof ret.name.arr, "%s", name); | |
| if (e < 0) { | |
| ret.error = errno; | |
| return ret; | |
| } | |
| if (e >= (int)sizeof ret.name.arr) { | |
| /* Name truncated, allocate memory */ | |
| char *name_ptr = strdup(name); | |
| if (!name_ptr) { | |
| ret.error = errno; | |
| return ret; | |
| } | |
| ret.name.ptr = name_ptr; | |
| ret.flags |= OBJ_NAME_ALLOC; | |
| } | |
| return ret; | |
| } | |
| int | |
| obj_init (struct obj *dest, | |
| char const *name) | |
| { | |
| if (!dest) | |
| return EFAULT; | |
| *dest = obj(name); | |
| return dest->error; | |
| } | |
| void | |
| obj_fini (struct obj *dest) | |
| { | |
| if (dest) { | |
| if (dest->flags & OBJ_NAME_ALLOC) | |
| free(dest->name.ptr); | |
| *dest = (struct obj){0}; | |
| } | |
| } | |
| struct obj * | |
| obj_create (char const *name) | |
| { | |
| struct obj *ret = malloc(sizeof *ret); | |
| if (ret) | |
| *ret = obj(name); | |
| return ret; | |
| } | |
| void | |
| obj_destroy (struct obj **p_dest) | |
| { | |
| if (p_dest && *p_dest) { | |
| struct obj *ptr = *p_dest; | |
| *p_dest = nullptr; | |
| obj_fini(ptr); | |
| free(ptr); | |
| } | |
| } | |
| static inline char const * | |
| obj_get_name_ (struct obj const *src) | |
| { | |
| return (src->flags & OBJ_NAME_ALLOC) | |
| ? src->name.ptr : src->name.arr; | |
| } | |
| char const * | |
| obj_get_name (struct obj const *src) | |
| { | |
| return src ? obj_get_name_(src) : nullptr; | |
| } | |
| int | |
| obj_get_error (struct obj const *src) | |
| { | |
| return src ? src->error : -1; | |
| } | |
| void | |
| obj_print_error (struct obj const *src) | |
| { | |
| if (src && src->error) { | |
| char const *msg = strerror(src->error); | |
| char const *name = obj_get_name_(src); | |
| if (name && *name) | |
| fprintf(stderr, "%s: %s\n", name, msg); | |
| else | |
| fprintf(stderr, "%s\n", msg); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef EXAMPLE_OBJ_H_ | |
| #define EXAMPLE_OBJ_H_ | |
| enum obj_flags { | |
| OBJ_NAME_ALLOC = 1 | |
| }; | |
| /* Example object with a name string. */ | |
| struct obj { | |
| union { | |
| char arr[sizeof (char *)]; | |
| char *ptr; | |
| } name; | |
| unsigned flags; | |
| int error; | |
| }; | |
| /* Initializes and returns a new object by-value. | |
| * May allocate memory for members if necessary. | |
| */ | |
| extern struct obj | |
| obj (char const *name); | |
| /* Initializes, but does not allocate, an object. | |
| * May allocate memory for members. Returns 0 on | |
| * success and an error number on failure. | |
| */ | |
| extern int | |
| obj_init (struct obj *dest, | |
| char const *name); | |
| /* Frees allocated member data, if any, but not | |
| * the object itself. | |
| */ | |
| extern void | |
| obj_fini (struct obj *dest); | |
| /* Allocates and initializes a new object. | |
| * returns a pointer to created object. | |
| */ | |
| extern struct obj * | |
| obj_create (char const *name); | |
| /* Uninitializes and frees the object, then | |
| * sets caller's object pointer to nullptr. | |
| */ | |
| extern void | |
| obj_destroy (struct obj **p_dest); | |
| /* Returns pointer to name or nullptr. */ | |
| extern char const * | |
| obj_get_name (struct obj const *src); | |
| /* Returns the error number, if any. */ | |
| extern int | |
| obj_get_error (struct obj const *src); | |
| /* Prints error description or nullptr. */ | |
| extern void | |
| obj_print_error (struct obj const *src); | |
| #endif /* EXAMPLE_OBJ_H_ */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include "example_obj.h" | |
| int | |
| main (int c, | |
| char **v) | |
| { | |
| struct obj program = obj(v[0]); | |
| fputs(obj_get_name(&program), stdout); | |
| for (int i = 0; ++i < c;) { | |
| struct obj *arg = obj_create(v[i]); | |
| if (!arg) | |
| continue; | |
| char const *name = obj_get_name(arg); | |
| if (name) | |
| printf(" %s", name); | |
| obj_destroy(&arg); | |
| } | |
| putchar('\n'); | |
| obj_fini(&program); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment