forgot to add files. yikes
This commit is contained in:
parent
18b61b0f1b
commit
4de940606e
|
@ -0,0 +1,171 @@
|
|||
#include "formatstring.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
|
||||
void formatstring_error(const char *format, size_t index, const char *message) {
|
||||
fprintf(stderr, "illegal format string:%zu: %s\n\n\t%s\n\t", index + 1, message, format);
|
||||
while (index > 0) {
|
||||
fprintf(stderr, "-");
|
||||
-- index;
|
||||
}
|
||||
fprintf(stderr, "^\n");
|
||||
}
|
||||
|
||||
#define IS_VAR_NAME(PTR, LEN, NAME) (strncmp((PTR), (NAME), MIN(sizeof (NAME), LEN)) == 0)
|
||||
|
||||
#define WRITE_STR(STR, LEN) \
|
||||
{ \
|
||||
const size_t COPY_STR_rem = endptr > bufptr ? endptr - bufptr : 0; \
|
||||
const size_t COPY_STR_cpylen = MIN((LEN), COPY_STR_rem); \
|
||||
memcpy(bufptr, (STR), COPY_STR_cpylen); \
|
||||
bufptr += (LEN); \
|
||||
}
|
||||
|
||||
#define HEX_CHARS "0123456789ABCDEF"
|
||||
|
||||
#define WRITE_HEX(NUM) \
|
||||
{ \
|
||||
size_t WRITE_HEX_size = sizeof(NUM); \
|
||||
size_t WRITE_HEX_rem = (NUM); \
|
||||
while (WRITE_HEX_size) { \
|
||||
-- WRITE_HEX_size; \
|
||||
char *WRITE_HEX_outptr = bufptr + 2 * WRITE_HEX_size; \
|
||||
if (WRITE_HEX_outptr < endptr) { \
|
||||
*WRITE_HEX_outptr = HEX_CHARS[(WRITE_HEX_rem >> 4) & 0xF]; \
|
||||
} \
|
||||
++ WRITE_HEX_outptr; \
|
||||
if (WRITE_HEX_outptr < endptr) { \
|
||||
*WRITE_HEX_outptr = HEX_CHARS[WRITE_HEX_rem & 0xF]; \
|
||||
} \
|
||||
WRITE_HEX_rem >>= 8; \
|
||||
} \
|
||||
bufptr += 2 * sizeof(NUM); \
|
||||
}
|
||||
|
||||
#define WRITE_CHAR(CH) \
|
||||
if (bufptr < endptr) { \
|
||||
*bufptr = (CH); \
|
||||
} \
|
||||
++ bufptr;
|
||||
|
||||
#define WRITE_DEC(NUM) \
|
||||
if ((NUM) == 0) { \
|
||||
WRITE_CHAR('0'); \
|
||||
} else { \
|
||||
size_t WRITE_DEC_isize = 0; \
|
||||
size_t WRITE_DEC_n = (NUM); \
|
||||
while (WRITE_DEC_n) { \
|
||||
WRITE_DEC_n /= 10; \
|
||||
++ WRITE_DEC_isize; \
|
||||
} \
|
||||
WRITE_DEC_n = (NUM); \
|
||||
size_t WRITE_DEC_index = WRITE_DEC_isize; \
|
||||
while (WRITE_DEC_n) { \
|
||||
-- WRITE_DEC_index; \
|
||||
const size_t WRITE_DEC_v = WRITE_DEC_n % 10; \
|
||||
char *WRITE_DEC_outptr = bufptr + WRITE_DEC_index; \
|
||||
if (WRITE_DEC_outptr < endptr) { \
|
||||
*WRITE_DEC_outptr = '0' + WRITE_DEC_v; \
|
||||
} \
|
||||
WRITE_DEC_n /= 10; \
|
||||
} \
|
||||
bufptr += WRITE_DEC_isize; \
|
||||
}
|
||||
|
||||
ssize_t formatstring(char *buffer, size_t buffer_size, const char *format, const char *filename,
|
||||
size_t index, size_t offset, size_t size, const char *ext) {
|
||||
assert(buffer_size == 0 || buffer != NULL);
|
||||
assert(format != NULL);
|
||||
assert(filename != NULL);
|
||||
assert(ext != NULL);
|
||||
|
||||
const char *fmtptr = format;
|
||||
char *bufptr = buffer_size == 0 ? NULL : buffer;
|
||||
const char *endptr = bufptr + buffer_size;
|
||||
const size_t filename_len = strlen(filename);
|
||||
const size_t ext_len = strlen(ext);
|
||||
|
||||
while (*fmtptr) {
|
||||
const char *nextptr = fmtptr;
|
||||
while (*nextptr && *nextptr != '{' && *nextptr != '}') {
|
||||
++ nextptr;
|
||||
}
|
||||
|
||||
if (nextptr != fmtptr) {
|
||||
const size_t len = nextptr - fmtptr;
|
||||
WRITE_STR(fmtptr, len);
|
||||
fmtptr = nextptr;
|
||||
}
|
||||
|
||||
if (*fmtptr == '}') {
|
||||
++ fmtptr;
|
||||
if (*fmtptr == '}') {
|
||||
WRITE_CHAR('}');
|
||||
++ fmtptr;
|
||||
} else {
|
||||
formatstring_error(format, fmtptr - format, "expected '}'");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
} else if (*fmtptr == '{') {
|
||||
++ fmtptr;
|
||||
if (*fmtptr == '{') {
|
||||
WRITE_CHAR('{');
|
||||
++ fmtptr;
|
||||
} else {
|
||||
nextptr = fmtptr;
|
||||
while (*nextptr && *nextptr != '}') {
|
||||
++ nextptr;
|
||||
}
|
||||
|
||||
if (fmtptr == nextptr) {
|
||||
formatstring_error(format, fmtptr - format, "expected a variable name");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t len = nextptr - fmtptr;
|
||||
if (IS_VAR_NAME(fmtptr, len, "filename")) {
|
||||
WRITE_STR(filename, filename_len);
|
||||
} else if (IS_VAR_NAME(fmtptr, len, "ext")) {
|
||||
WRITE_STR(ext, ext_len);
|
||||
} else if (IS_VAR_NAME(fmtptr, len, "offset")) {
|
||||
WRITE_HEX(offset);
|
||||
} else if (IS_VAR_NAME(fmtptr, len, "index")) {
|
||||
WRITE_DEC(index);
|
||||
} else if (IS_VAR_NAME(fmtptr, len, "size")) {
|
||||
WRITE_DEC(size);
|
||||
} else {
|
||||
formatstring_error(format, fmtptr - format, "unknown variable name");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fmtptr = nextptr + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bufptr < endptr) {
|
||||
*bufptr = 0;
|
||||
} else if (buffer_size > 0) {
|
||||
buffer[buffer_size - 1] = 0;
|
||||
}
|
||||
++ bufptr;
|
||||
|
||||
const size_t strsize = bufptr - buffer;
|
||||
|
||||
if (strsize > SSIZE_MAX) {
|
||||
formatstring_error(format, fmtptr - format, "string too long");
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (ssize_t) strsize;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef MEDIAEXTRACT_FORMATSTRING_H__
|
||||
#define MEDIAEXTRACT_FORMATSTRING_H__
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// {filename}_{offset}.{ext}
|
||||
|
||||
ssize_t formatstring(char *buffer, size_t buffer_size, const char *format, const char *filename,
|
||||
size_t index, size_t offset, size_t size, const char *ext);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue