return r; \
}
-/* replacement for snprintf(), which is not supported by C89
- * sprintf() would be the supported one, but it's labelled unsafe,
- * so some modern static analyzer will flag it as such, making it unusable.
- * formatString_u() replaces snprintf() for the specific case where there are only %u arguments */
+static size_t uintSize(unsigned value)
+{
+ size_t size = 1;
+ while (value >= 10) {
+ size++;
+ value /= 10;
+ }
+ return size;
+}
+
+// Note: presume @buffer is large enough
+static void writeUint_varLen(char* buffer, size_t capacity, unsigned value)
+{
+ int endPos = (int)uintSize(value) - 1;
+ assert(uintSize(value) >= 1);
+ assert(uintSize(value) < capacity); (void)capacity;
+ while (endPos >= 0) {
+ char c = '0' + (char)(value % 10);
+ buffer[endPos--] = c;
+ value /= 10;
+ }
+}
+
+/* replacement for snprintf(), which is not supported by C89.
+ * sprintf() would be the supported one, but it's labelled unsafe:
+ * modern static analyzer will flag sprintf() as dangerous, making it unusable.
+ * formatString_u() replaces snprintf() for the specific case where there is only one %u argument */
static int formatString_u(char* buffer, size_t buffer_size, const char* formatString, unsigned int value)
{
+ size_t const valueSize = uintSize(value);
size_t written = 0;
int i;
- assert(value <= 100);
- for (i = 0; formatString[i] != '\0' && written < buffer_size - 1; ++i) {
+ for (i = 0; formatString[i] != '\0' && written < buffer_size - 1; i++) {
if (formatString[i] != '%') {
buffer[written++] = formatString[i];
continue;
}
- if (formatString[++i] == 'u') {
- /* Handle single digit */
- if (value < 10) {
- buffer[written++] = '0' + (char)value;
- } else if (value < 100) {
- /* Handle two digits */
- if (written >= buffer_size - 2) {
- return -1; /* buffer overflow */
- }
- buffer[written++] = '0' + (char)(value / 10);
- buffer[written++] = '0' + (char)(value % 10);
- } else { /* 100 */
- if (written >= buffer_size - 3) {
- return -1; /* buffer overflow */
- }
- buffer[written++] = '1';
- buffer[written++] = '0';
- buffer[written++] = '0';
- }
+ i++;
+ if (formatString[i] == 'u') {
+ if (written + valueSize >= buffer_size) abort(); /* buffer not large enough */
+ writeUint_varLen(buffer + written, buffer_size - written, value);
+ written += valueSize;
} else if (formatString[i] == '%') { /* Check for escaped percent sign */
buffer[written++] = '%';
} else {
- return -1; /* unsupported format */
+ abort(); /* unsupported format */
}
}
if (written < buffer_size) {
buffer[written] = '\0';
} else {
- buffer[0] = '\0'; /* Handle truncation */
+ abort(); /* buffer not large enough */
}
return (int)written;