ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
examples.c
Go to the documentation of this file.
1
7#include <ascii-chat/options/manpage/content/examples.h>
8#include <ascii-chat/log/logging.h>
9#include <ascii-chat/common.h>
10#include <ascii-chat/options/manpage.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <time.h>
15
19typedef struct {
20 uint32_t bit;
21 const char *name;
23
24static const mode_bit_name_t mode_bit_names[] = {
25 {(1 << 0), "server"}, // MODE_SERVER
26 {(1 << 1), "client"}, // MODE_CLIENT
27 {(1 << 2), "mirror"}, // MODE_MIRROR
28 {(1 << 3), "discovery-service"}, // MODE_DISCOVERY_SERVICE
29 {(1 << 4), NULL}, // MODE_DISCOVERY (no mode prefix)
30 {0, NULL} // Terminator
31};
32
43static const char **get_all_mode_names_from_bitmask(uint32_t mode_bitmask, size_t *count) {
44 // Skip binary-only examples (OPTION_MODE_BINARY = 0x100)
45 if (mode_bitmask & 0x100 && !(mode_bitmask & 0x1F)) {
46 *count = 0;
47 return NULL; // Binary-level example, no mode name
48 }
49
50 // Count how many mode bits are set
51 size_t num_modes = 0;
52 for (size_t i = 0; mode_bit_names[i].bit != 0; i++) {
53 if ((mode_bitmask & mode_bit_names[i].bit) && mode_bit_names[i].name) {
54 num_modes++;
55 }
56 }
57
58 if (num_modes == 0) {
59 *count = 0;
60 return NULL;
61 }
62
63 // Allocate array for mode names (plus NULL terminator)
64 const char **names = SAFE_MALLOC((num_modes + 1) * sizeof(char *), const char **);
65
66 // Fill in mode names
67 size_t idx = 0;
68 for (size_t i = 0; mode_bit_names[i].bit != 0; i++) {
69 if ((mode_bitmask & mode_bit_names[i].bit) && mode_bit_names[i].name) {
70 names[idx++] = mode_bit_names[i].name;
71 }
72 }
73 names[idx] = NULL;
74
75 *count = num_modes;
76 return names;
77}
78
79char *manpage_content_generate_examples(const options_config_t *config) {
80 if (!config || config->num_examples == 0) {
81 char *buffer = SAFE_MALLOC(1, char *);
82 buffer[0] = '\0';
83 return buffer;
84 }
85
86 // Seed random number generator for mode selection
87 // Use config pointer address for deterministic-but-varied seed
88 srand((unsigned int)((uintptr_t)config));
89
90 // Allocate growing buffer for examples section
91 size_t buffer_capacity = 8192;
92 char *buffer = SAFE_MALLOC(buffer_capacity, char *);
93 size_t offset = 0;
94
95 for (size_t i = 0; i < config->num_examples; i++) {
96 const example_descriptor_t *example = &config->examples[i];
97
98 // Get all mode names from bitmask (examples can apply to multiple modes)
99 // For man pages, we only show each example once, randomly selecting one mode
100 size_t num_modes = 0;
101 const char **mode_names = get_all_mode_names_from_bitmask(example->mode_bitmask, &num_modes);
102
103 // Ensure buffer is large enough
104 if (offset + 512 >= buffer_capacity) {
105 buffer_capacity *= 2;
106 buffer = SAFE_REALLOC(buffer, buffer_capacity, char *);
107 }
108
109 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, ".TP\n");
110 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, ".B ascii-chat");
111
112 // Add mode name if applicable (randomly select one mode for multi-mode examples)
113 if (num_modes > 0) {
114 size_t selected_mode = (size_t)rand() % num_modes;
115 if (mode_names[selected_mode]) {
116 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, " %s", mode_names[selected_mode]);
117 }
118 }
119
120 if (example->args) {
121 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, " %s", example->args);
122 }
123 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, "\n");
124
125 if (example->description) {
126 offset +=
127 safe_snprintf(buffer + offset, buffer_capacity - offset, "%s\n", escape_groff_special(example->description));
128 }
129
130 // Free mode names array
131 if (mode_names) {
132 SAFE_FREE(mode_names);
133 }
134 }
135
136 offset += safe_snprintf(buffer + offset, buffer_capacity - offset, "\n");
137
138 return buffer;
139}
140
141void manpage_content_free_examples(char *content) {
142 if (content) {
143 SAFE_FREE(content);
144 }
145}
char * manpage_content_generate_examples(const options_config_t *config)
Definition examples.c:79
void manpage_content_free_examples(char *content)
Definition examples.c:141
const char * escape_groff_special(const char *str)
Mode name mapping for bitmask extraction.
Definition examples.c:19
const char * name
Definition examples.c:21
uint32_t bit
Definition examples.c:20
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Safe formatted string printing to buffer.
Definition system.c:456