@@ -119,6 +119,7 @@ static inline int fossil_sys_bitwise_has(uint64_t bits, uint64_t bit) {
119119}
120120
121121#include < string>
122+ #include < stdexcept>
122123
123124/* *
124125 * Fossil namespace.
@@ -127,51 +128,347 @@ namespace fossil {
127128
128129 /* *
129130 * System namespace.
131+ *
132+ * Contains helpers for working with tables of bitwise flags.
133+ * The functions in this namespace act as a thin C++ wrapper around the
134+ * underlying C API for bitmask parsing, formatting, validation, and lookup.
130135 */
131136 namespace sys {
132137
138+ /* *
139+ * @class Bitwise
140+ *
141+ * @brief Utility class providing C++-style access to bitmask parsing and
142+ * manipulation functions.
143+ *
144+ * This class is a thin wrapper around the C API for working with bitwise
145+ * tables. It allows you to convert between string representations of flags
146+ * (like "read|write") and their numeric bitmask values, look up individual
147+ * flag names, and validate or count bits in a mask. Where possible, the
148+ * interface is made more idiomatic for C++ by using std::string, bool, and
149+ * exceptions for error handling.
150+ */
133151 class Bitwise {
134152 public:
135153 /* *
136- * Parses a string like "read|write" into a bitmask using the given table.
137- *
138- * @param input The input string to parse.
139- * @param table The bitwise table to use for parsing.
140- * @return The parsed bitmask.
154+ * @brief Parse a string into a bitmask.
155+ *
156+ * Given a string containing one or more symbolic flag names separated
157+ * by the pipe character ('|'), this function returns the corresponding
158+ * numeric bitmask.
159+ *
160+ * Example:
161+ * @code
162+ * uint64_t mask = Bitwise::parse("read|write", table);
163+ * @endcode
164+ *
165+ * @param input The input string to parse (e.g., "read|write").
166+ * @param table Pointer to the bitwise table that defines valid flags.
167+ * @return A 64-bit bitmask with the corresponding bits set.
141168 */
142169 static uint64_t parse (const std::string &input, const fossil_sys_bitwise_table_t *table) {
143170 return fossil_sys_bitwise_parse (input.c_str (), table);
144171 }
145172
146173 /* *
147- * Formats a bitmask into a string like "read|write".
148- *
149- * @param bits The bitmask to format.
150- * @param table The bitwise table to use for formatting.
151- * @param out The output buffer to write the formatted string into.
152- * @param out_size The size of the output buffer.
153- * @return 0 on success, or an error code on failure.
174+ * @brief Format a bitmask into a string using a caller-provided buffer.
175+ *
176+ * This is a direct wrapper around the C API. The caller is responsible
177+ * for providing a buffer of sufficient size. The formatted string will
178+ * list all set bits separated by '|'.
179+ *
180+ * Example:
181+ * @code
182+ * char buf[128];
183+ * Bitwise::format(mask, table, buf, sizeof(buf));
184+ * printf("Mask = %s\n", buf);
185+ * @endcode
186+ *
187+ * @param bits The bitmask to format.
188+ * @param table Pointer to the bitwise table that defines valid flags.
189+ * @param out Caller-provided output buffer.
190+ * @param out_size Size of the output buffer, including space for null terminator.
191+ * @return 0 on success, or a non-zero error code on failure.
154192 */
155193 static int format (uint64_t bits, const fossil_sys_bitwise_table_t *table, char *out, size_t out_size) {
156194 return fossil_sys_bitwise_format (bits, table, out, out_size);
157195 }
158196
159197 /* *
160- * Looks up a string in the bitwise table and returns the corresponding bit.
161- *
162- * @param name The name to look up.
163- * @param table The bitwise table to use for lookup.
164- * @param out_bit Pointer to store the resulting bit.
165- * @return 0 on success, or an error code on failure.
198+ * @brief Format a bitmask into a std::string.
199+ *
200+ * Unlike the buffer-based version, this overload allocates a temporary
201+ * buffer and returns the result as a std::string. If the buffer is not
202+ * large enough, an exception is thrown. This is the preferred C++-style
203+ * interface for most users.
204+ *
205+ * Example:
206+ * @code
207+ * std::string result = Bitwise::format(mask, table);
208+ * std::cout << "Mask = " << result << std::endl;
209+ * @endcode
210+ *
211+ * @param bits The bitmask to format.
212+ * @param table Pointer to the bitwise table that defines valid flags.
213+ * @return A std::string containing the formatted representation.
214+ *
215+ * @throws std::runtime_error if formatting fails.
216+ */
217+ static std::string format (uint64_t bits, const fossil_sys_bitwise_table_t *table) {
218+ char buffer[1024 ]; // Reasonable default; adjust if tables can be very large
219+ int rc = fossil_sys_bitwise_format (bits, table, buffer, sizeof (buffer));
220+ if (rc != 0 ) {
221+ throw std::runtime_error (" fossil_sys_bitwise_format failed" );
222+ }
223+ return std::string (buffer);
224+ }
225+
226+ /* *
227+ * @brief Look up a single flag name and return its corresponding bit value.
228+ *
229+ * Example:
230+ * @code
231+ * uint64_t bit;
232+ * if (Bitwise::lookup("read", table, bit) == 0) {
233+ * // bit now contains 1 << 0
234+ * }
235+ * @endcode
236+ *
237+ * @param name The flag name to look up.
238+ * @param table Pointer to the bitwise table.
239+ * @param out_bit Reference that will receive the bit value.
240+ * @return 0 if found, or non-zero if the name was not recognized.
166241 */
167242 static int lookup (const std::string &name, const fossil_sys_bitwise_table_t *table, uint64_t &out_bit) {
168243 return fossil_sys_bitwise_lookup (name.c_str (), table, &out_bit);
169244 }
245+
246+ /* *
247+ * @brief Return a bitmask containing all valid bits in the table.
248+ *
249+ * This is useful for quickly constructing masks that represent "everything".
250+ *
251+ * Example:
252+ * @code
253+ * uint64_t all_flags = Bitwise::all(table);
254+ * @endcode
255+ *
256+ * @param table Pointer to the bitwise table.
257+ * @return A mask with all defined bits set.
258+ */
259+ static uint64_t all (const fossil_sys_bitwise_table_t *table) {
260+ return fossil_sys_bitwise_all (table);
261+ }
262+
263+ /* *
264+ * @brief Validate that a bitmask contains only recognized bits.
265+ *
266+ * This is useful for catching bugs where invalid bits are accidentally set.
267+ *
268+ * Example:
269+ * @code
270+ * if (!Bitwise::validate(mask, table)) {
271+ * std::cerr << "Invalid bitmask!" << std::endl;
272+ * }
273+ * @endcode
274+ *
275+ * @param bits The bitmask to validate.
276+ * @param table Pointer to the bitwise table.
277+ * @return true if valid, false if any unknown bits are present.
278+ */
279+ static bool validate (uint64_t bits, const fossil_sys_bitwise_table_t *table) {
280+ return fossil_sys_bitwise_validate (bits, table) == 0 ;
281+ }
282+
283+ /* *
284+ * @brief Find the name corresponding to a single bit.
285+ *
286+ * Example:
287+ * @code
288+ * std::string name = Bitwise::name(1 << 0, table);
289+ * // name == "read"
290+ * @endcode
291+ *
292+ * @param bit The bit value to look up (must be a single bit, not a mask).
293+ * @param table Pointer to the bitwise table.
294+ * @return The name as a std::string, or an empty string if the bit is unknown.
295+ */
296+ static std::string name (uint64_t bit, const fossil_sys_bitwise_table_t *table) {
297+ const char *n = fossil_sys_bitwise_name (bit, table);
298+ return n ? std::string (n) : std::string ();
299+ }
300+
301+ /* *
302+ * @brief Count how many bits are set in the mask.
303+ *
304+ * Example:
305+ * @code
306+ * size_t num_flags = Bitwise::count(mask);
307+ * @endcode
308+ *
309+ * @param bits The bitmask to count.
310+ * @return The number of set bits.
311+ */
312+ static size_t count (uint64_t bits) {
313+ return fossil_sys_bitwise_count (bits);
314+ }
315+
316+ /* *
317+ * @brief Test whether a specific bit is set in the mask.
318+ *
319+ * Example:
320+ * @code
321+ * if (Bitwise::has(mask, MY_FLAG)) {
322+ * // do something
323+ * }
324+ * @endcode
325+ *
326+ * @param bits The bitmask to check.
327+ * @param bit The bit to test.
328+ * @return true if the bit is set, false otherwise.
329+ */
330+ static bool has (uint64_t bits, uint64_t bit) {
331+ return (bits & bit) != 0 ;
332+ }
333+
334+ /* *
335+ * @brief Bitwise OR operator for combining flags.
336+ *
337+ * Example:
338+ * @code
339+ * uint64_t mask = Bitwise::OR(READ, WRITE);
340+ * // Or use the operator directly:
341+ * uint64_t mask = READ | WRITE;
342+ * @endcode
343+ */
344+ static inline uint64_t OR (uint64_t lhs, uint64_t rhs) {
345+ return lhs | rhs;
346+ }
347+
348+ /* *
349+ * @brief Bitwise AND operator for masking flags.
350+ *
351+ * Example:
352+ * @code
353+ * if (Bitwise::AND(mask, READ)) { ... }
354+ * // Or use the operator directly:
355+ * if (mask & READ) { ... }
356+ * @endcode
357+ */
358+ static inline uint64_t AND (uint64_t lhs, uint64_t rhs) {
359+ return lhs & rhs;
360+ }
361+
362+ /* *
363+ * @brief Bitwise XOR operator for toggling flags.
364+ */
365+ static inline uint64_t XOR (uint64_t lhs, uint64_t rhs) {
366+ return lhs ^ rhs;
367+ }
368+
369+ /* *
370+ * @brief Bitwise NOT operator for inverting a mask.
371+ */
372+ static inline uint64_t NOT (uint64_t bits) {
373+ return ~bits;
374+ }
170375 };
171376
172- }
377+ // ---------- Global Operator Overloads for fossil_sys_bitwise_entry_t ----------
378+ //
379+ // These allow you to work with fossil_sys_bitwise_entry_t entries as if
380+ // they were strongly-typed bitmask constants, producing uint64_t results.
381+ //
382+
383+ // --- Bitwise OR ---
384+ inline uint64_t operator |(uint64_t lhs, const fossil_sys_bitwise_entry_t &rhs) {
385+ return lhs | rhs.bit ;
386+ }
387+ inline uint64_t operator |(const fossil_sys_bitwise_entry_t &lhs, uint64_t rhs) {
388+ return lhs.bit | rhs;
389+ }
390+ inline uint64_t operator |(const fossil_sys_bitwise_entry_t &lhs, const fossil_sys_bitwise_entry_t &rhs) {
391+ return lhs.bit | rhs.bit ;
392+ }
393+
394+ // --- Bitwise AND ---
395+ inline uint64_t operator &(uint64_t lhs, const fossil_sys_bitwise_entry_t &rhs) {
396+ return lhs & rhs.bit ;
397+ }
398+ inline uint64_t operator &(const fossil_sys_bitwise_entry_t &lhs, uint64_t rhs) {
399+ return lhs.bit & rhs;
400+ }
401+ inline uint64_t operator &(const fossil_sys_bitwise_entry_t &lhs, const fossil_sys_bitwise_entry_t &rhs) {
402+ return lhs.bit & rhs.bit ;
403+ }
404+
405+ // --- Bitwise XOR ---
406+ inline uint64_t operator ^(uint64_t lhs, const fossil_sys_bitwise_entry_t &rhs) {
407+ return lhs ^ rhs.bit ;
408+ }
409+ inline uint64_t operator ^(const fossil_sys_bitwise_entry_t &lhs, uint64_t rhs) {
410+ return lhs.bit ^ rhs;
411+ }
412+ inline uint64_t operator ^(const fossil_sys_bitwise_entry_t &lhs, const fossil_sys_bitwise_entry_t &rhs) {
413+ return lhs.bit ^ rhs.bit ;
414+ }
415+
416+ // --- Bitwise NOT ---
417+ inline uint64_t operator ~(const fossil_sys_bitwise_entry_t &entry) {
418+ return ~entry.bit ;
419+ }
420+
421+ // --- Compound Assignment Operators (modify lhs) ---
422+ inline uint64_t &operator |=(uint64_t &lhs, const fossil_sys_bitwise_entry_t &rhs) {
423+ lhs |= rhs.bit ;
424+ return lhs;
425+ }
426+ inline uint64_t &operator &=(uint64_t &lhs, const fossil_sys_bitwise_entry_t &rhs) {
427+ lhs &= rhs.bit ;
428+ return lhs;
429+ }
430+ inline uint64_t &operator ^=(uint64_t &lhs, const fossil_sys_bitwise_entry_t &rhs) {
431+ lhs ^= rhs.bit ;
432+ return lhs;
433+ }
434+
435+ // --- Comparison Operators (check equality of bits) ---
436+ inline bool operator ==(uint64_t lhs, const fossil_sys_bitwise_entry_t &rhs) {
437+ return lhs == rhs.bit ;
438+ }
439+
440+ inline bool operator ==(const fossil_sys_bitwise_entry_t &lhs, uint64_t rhs) {
441+ return lhs.bit == rhs;
442+ }
443+
444+ inline bool operator ==(const fossil_sys_bitwise_entry_t &lhs, const fossil_sys_bitwise_entry_t &rhs) {
445+ return lhs.bit == rhs.bit ;
446+ }
447+
448+ inline bool operator !=(uint64_t lhs, const fossil_sys_bitwise_entry_t &rhs) {
449+ return lhs != rhs.bit ;
450+ }
451+
452+ inline bool operator !=(const fossil_sys_bitwise_entry_t &lhs, uint64_t rhs) {
453+ return lhs.bit != rhs;
454+ }
455+
456+ inline bool operator !=(const fossil_sys_bitwise_entry_t &lhs, const fossil_sys_bitwise_entry_t &rhs) {
457+ return lhs.bit != rhs.bit ;
458+ }
459+
460+ // --- Convenience Predicate: "Is bit set?" ---
461+ inline bool operator &&(uint64_t lhs, const fossil_sys_bitwise_entry_t &rhs) {
462+ return (lhs & rhs.bit ) != 0 ;
463+ }
464+
465+ inline bool operator &&(const fossil_sys_bitwise_entry_t &lhs, uint64_t rhs) {
466+ return (lhs.bit & rhs) != 0 ;
467+ }
173468
174- }
469+ } // namespace sys
470+
471+ } // namespace fossil
175472
176473#endif
177474
0 commit comments