/** * Sets multiple bitflags in a bitfield. * * The flags specified in `...` are set in `flags`. The bitfield size is * supplied in `size`. TRUE is returned when changes were made, FALSE * otherwise. * * WARNING: FLAG_END must be the final argument in the `...` list. */ bool flags_set(bitflag *flags, const size_t size, ...) { size_t flag_offset; int flag_binary; int f; va_list args; bool delta = FALSE; va_start(args, size); /* Process each flag in the va-args */ for (f = va_arg(args, int); f != FLAG_END; f = va_arg(args, int)) { flag_offset = FLAG_OFFSET(f); flag_binary = FLAG_BINARY(f); assert(flag_offset < size); /* !flag_has() */ if (!(flags[flag_offset] & flag_binary)) delta = TRUE; /* flag_on() */ flags[flag_offset] |= flag_binary; } va_end(args); return delta; }
/** * Tests if a flag is "on" in a bitflag set. * * TRUE is returned when `flag` is on in `flags`, and FALSE otherwise. * The flagset size is supplied in `size`. */ bool flag_has(const bitflag *flags, const size_t size, const int flag) { const size_t flag_offset = FLAG_OFFSET(flag); const int flag_binary = FLAG_BINARY(flag); if (flag == FLAG_END) return FALSE; assert(flag_offset < size); if (flags[flag_offset] & flag_binary) return TRUE; return FALSE; }
/** * Clears one flag in a bitfield. * * The bitflag identified by `flag` is cleared in `flags`. The bitfield size * is supplied in `size`. TRUE is returned when changes were made, FALSE * otherwise. */ bool flag_off(bitflag *flags, const size_t size, const int flag) { const size_t flag_offset = FLAG_OFFSET(flag); const int flag_binary = FLAG_BINARY(flag); assert(flag_offset < size); if (!(flags[flag_offset] & flag_binary)) return FALSE; flags[flag_offset] &= ~flag_binary; return TRUE; }
/** * Interates over the flags which are "on" in a bitflag set. * * Returns the next on flag in `flags`, starting from (and including) * `flag`. FLAG_END will be returned when the end of the flag set is reached. * Iteration will start at the beginning of the flag set when `flag` is * FLAG_END. The bitfield size is supplied in `size`. */ int flag_next(const bitflag *flags, const size_t size, const int flag) { const int max_flags = FLAG_MAX(size); int f, flag_offset, flag_binary; for (f = flag; f < max_flags; f++) { flag_offset = FLAG_OFFSET(f); flag_binary = FLAG_BINARY(f); if (flags[flag_offset] & flag_binary) return f; } return FLAG_END; }
bool flag_has_dbg(const bitflag *flags, const size_t size, const int flag, const char *fi, const char *fl) { const size_t flag_offset = FLAG_OFFSET(flag); const int flag_binary = FLAG_BINARY(flag); if (flag == FLAG_END) return FALSE; if (flag_offset >= size) { quit_fmt("Error in flag_has(%s, %s): FlagID[%d] Size[%u] FlagOff[%u] FlagBV[%d]\n", fi, fl, flag, (unsigned int) size, (unsigned int) flag_offset, flag_binary); } assert(flag_offset < size); if (flags[flag_offset] & flag_binary) return TRUE; return FALSE; }
bool flag_on_dbg(bitflag *flags, const size_t size, const int flag, const char *fi, const char *fl) { const size_t flag_offset = FLAG_OFFSET(flag); const int flag_binary = FLAG_BINARY(flag); /* EFG this assert needs to be in most functions, or else the need for * it removed. Without it, got a crash with no ability to backtrace. */ assert (flag >= FLAG_START); if (flag_offset >= size) { quit_fmt("Error in flag_on(%s, %s): FlagID[%d] Size[%u] FlagOff[%u] FlagBV[%d]\n", fi, fl, flag, (unsigned int) size, (unsigned int) flag_offset, flag_binary); } assert(flag_offset < size); if (flags[flag_offset] & flag_binary) return FALSE; flags[flag_offset] |= flag_binary; return TRUE; }