Skip to content

Instantly share code, notes, and snippets.

@mina86

mina86/rfc1123.c

Created Jan 16, 2010
Embed
What would you like to do?
A simple parser converting RFC1123 date into an argument date util accepts.
/*
* RFC1123 date parser.
* Copyright (c) 2010 by Michal Nazarewicz (mina86/AT/mina86.com)
* Distributed under the terms of Academic Free License 3.0
*/
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
static const char months[] = "janfebmaraprmayjunjulaugsepoctnovdec";
static const char tzs[] = "gmtutc";
static void acceptWS(void);
static unsigned acceptStr(const char *strings);
static unsigned acceptInt(unsigned min, unsigned max);
static void ensure(int cond) {
if (!cond) {
exit(EXIT_FAILURE);
}
}
static char *input;
int main(void) {
unsigned day, mon, year, hour, min, sec;
char line[128];
ensure(fgets(line, sizeof line, stdin) != 0);
input = line;
acceptStr(0); ensure(*input++ == ',');
day = acceptInt(1, 31);
mon = acceptStr(months) + 1;
year = acceptInt(2010, 2100);
hour = acceptInt(0, 23); ensure(*input++ == ':');
min = acceptInt(0, 59); ensure(*input++ == ':');
sec = acceptInt(0, 59);
acceptStr(tzs); acceptWS(); ensure(*input == 0);
printf("%02u%02u%02u%02u%04u.%02u\n", mon, day, hour, min, year, sec);
return EXIT_SUCCESS;
}
static void acceptWS(void) {
while (isspace(*input)) {
++input;
}
}
static unsigned acceptStr(const char *strings) {
char *f;
acceptWS();
for (f = input; 1; ++input) {
if (isupper(*input)) {
*input = tolower(*input);
} else if (!islower(*input)) {
break;
}
}
ensure(input - f == 3);
if (strings) {
const char *s = strings;
while (*s && (f[0] != s[0] || f[1] != s[1] || f[2] != s[2])) {
s += 3;
}
ensure(*s != 0);
return (unsigned)(s - strings) / 3u;
}
return 0;
}
static unsigned acceptInt(unsigned min, unsigned max) {
unsigned long ret;
errno = 0;
ret = strtoul(input, &input, 10);
ensure(!errno && ret >= min && ret <= max);
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment