Skip to content
Snippets Groups Projects
Commit 9d277ec9 authored by Julian Rother's avatar Julian Rother
Browse files

Cleanup and restructuring

parent 9a3250d8
No related branches found
No related tags found
No related merge requests found
...@@ -19,8 +19,10 @@ static char *getxmlattr(xmlAttr *a, char *name, char *err) ...@@ -19,8 +19,10 @@ static char *getxmlattr(xmlAttr *a, char *name, char *err)
char *get_xmpchapters(char *xmp) char *get_xmpchapters(char *xmp)
{ {
int i, len, maxlen; int i;
char *out; char *ptr;
size_t size;
FILE *stream;
xmlDocPtr doc; xmlDocPtr doc;
xmlXPathContextPtr xpath; xmlXPathContextPtr xpath;
xmlXPathObjectPtr res; xmlXPathObjectPtr res;
...@@ -41,51 +43,52 @@ char *get_xmpchapters(char *xmp) ...@@ -41,51 +43,52 @@ char *get_xmpchapters(char *xmp)
res = xmlXPathEvalExpression("/x:xmpmeta/rdf:RDF/rdf:Description/xmpDM:Tracks/rdf:Bag/rdf:li/rdf:Description/xmpDM:markers/rdf:Seq/rdf:li/rdf:Description", xpath); res = xmlXPathEvalExpression("/x:xmpmeta/rdf:RDF/rdf:Description/xmpDM:Tracks/rdf:Bag/rdf:li/rdf:Description/xmpDM:markers/rdf:Seq/rdf:li/rdf:Description", xpath);
if (!res || !res->nodesetval) if (!res || !res->nodesetval)
return ""; return "";
len = 0; maxlen = res->nodesetval->nodeNr*200; ptr = 0;
out = malloc(maxlen); size = 0;
len += xsnprintf(out+len, maxlen-len-1, "["); if (!(stream = open_memstream(&ptr, &size)))
exit(99);
fprintf(stream, "[");
for (i = 0; i < res->nodesetval->nodeNr; i ++) for (i = 0; i < res->nodesetval->nodeNr; i ++)
{ {
start = atoi(getxmlattr(res->nodesetval->nodeTab[i]->properties, "startTime", "0"))/framerate; start = atoi(getxmlattr(res->nodesetval->nodeTab[i]->properties, "startTime", "0"))/framerate;
if (i) if (i)
len += xsnprintf(out+len, maxlen-len-1, ","); fprintf(stream, ",");
len += xsnprintf(out+len, maxlen-len-1, "{\"time\": %f, \"text\": \"%s\"}", fprintf(stream, "{\"time\": %f, \"text\": \"%s\"}", start,
start, jescape(getxmlattr(res->nodesetval->nodeTab[i]->properties, "name", ""))); jescape(getxmlattr(res->nodesetval->nodeTab[i]->properties, "name", "")));
} }
len += xsnprintf(out+len, maxlen-len-1, "]"); fprintf(stream, "]");
return out; fclose(stream);
return ptr;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int jobid; int err;
char path[100], *xmp; char *path, *xmp;
AVFormatContext *demux, *mux; AVFormatContext *demux, *mux;
AVDictionaryEntry *tag; AVDictionaryEntry *tag;
AVDictionary *opts; AVDictionary *opts;
if (argc != 5) if (argc != 5)
return 1; return 1;
av_register_all(); av_register_all();
av_log_set_callback(avlogbuf_callback); init_avlogbuf();
jobid = atoi(argv[1]); jobid = atoi(argv[1]);
xsnprintf(BL(path), "%s/%s", CONFIG_VIDEOS_RAW, path = mprintf("%s/%s", CONFIG_VIDEOS_RAW, jstr(jlookup(argv[4], "path"), ""));
jstr(jlookup(argv[4], "path"), ""));
ping_job(jobid, "running", 0); ping_job(jobid, "running", 0);
opts = 0; opts = 0;
av_dict_set_int(&opts, "export_xmp", 1, 0); av_dict_set_int(&opts, "export_xmp", 1, 0);
demux = 0; demux = 0;
if (avformat_open_input(&demux, path, 0, &opts)) if (err = avformat_open_input(&demux, path, 0, &opts))
goto fail; job_failed("Opening input file failed: %s", av_err2str(err));
avformat_find_stream_info(demux, 0); avformat_find_stream_info(demux, 0);
if (tag = av_dict_get(demux->metadata, "xmp", 0, 0)) if (tag = av_dict_get(demux->metadata, "xmp", 0, 0))
ping_job(jobid, "finished", "{\"xmp_chapters\": %s, \"duration\": %f, \"log\": \"%s\"}", get_xmpchapters(tag->value), demux->duration*av_q2d(AV_TIME_BASE_Q), get_avlogbuf()); ping_job(jobid, "finished", "{\"xmp_chapters\": %s, \"duration\": %f, \"log\": \"%s\"}",
get_xmpchapters(tag->value), demux->duration*av_q2d(AV_TIME_BASE_Q),
jescape(get_avlogbuf()));
else else
ping_job(jobid, "finished", "{\"duration\": %f, \"log\": \"%s\"}", demux->duration*av_q2d(AV_TIME_BASE_Q), get_avlogbuf()); ping_job(jobid, "finished", "{\"duration\": %f, \"log\": \"%s\"}",
demux->duration*av_q2d(AV_TIME_BASE_Q), jescape(get_avlogbuf()));
return 0; return 0;
fail:
ping_job(jobid, "failed", "{\"log\": \"%s\"}", get_avlogbuf());
return 1;
} }
...@@ -42,9 +42,9 @@ void parse_chapters(AVFormatContext *ctx, char *s, int duration) ...@@ -42,9 +42,9 @@ void parse_chapters(AVFormatContext *ctx, char *s, int duration)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int jobid, i; int i, err;
int *idxmap; int *idxmap;
char *p, path[100], tmp[100]; char *p, *path, *tmp;
AVFormatContext *demux, *mux; AVFormatContext *demux, *mux;
AVPacket pkt; AVPacket pkt;
AVStream *stream; AVStream *stream;
...@@ -52,19 +52,18 @@ int main(int argc, char *argv[]) ...@@ -52,19 +52,18 @@ int main(int argc, char *argv[])
if (argc != 5) if (argc != 5)
return 1; return 1;
av_register_all(); av_register_all();
av_log_set_callback(avlogbuf_callback); init_avlogbuf();
memset(&pkt, 0, sizeof(pkt)); memset(&pkt, 0, sizeof(pkt));
av_init_packet(&pkt); av_init_packet(&pkt);
jobid = atoi(argv[1]); jobid = atoi(argv[1]);
xsnprintf(BL(path), "%s/%s", CONFIG_VIDEOS_RELEASED, path = mprintf("%s/%s", CONFIG_VIDEOS_RELEASED, jstr(jlookup(argv[4], "path"), ""));
jstr(jlookup(argv[4], "path"), "")); tmp = mprintf("%s/.tmp-%i", CONFIG_VIDEOS_TMP, jobid);
xsnprintf(BL(tmp), "%s/.tmp-%i", CONFIG_VIDEOS_TMP, jobid);
ping_job(jobid, "running", 0); ping_job(jobid, "running", 0);
demux = 0; demux = 0;
if (avformat_open_input(&demux, path, 0, 0)) if (err = avformat_open_input(&demux, path, 0, 0))
goto fail; job_failed("Opening input file failed: %s", av_err2str(err));
avformat_find_stream_info(demux, 0); avformat_find_stream_info(demux, 0);
avformat_alloc_output_context2(&mux, 0, jstr(jlookup(argv[4], "format"), 0), path); avformat_alloc_output_context2(&mux, 0, jstr(jlookup(argv[4], "format"), 0), path);
av_dict_copy(&mux->metadata, demux->metadata, 0); av_dict_copy(&mux->metadata, demux->metadata, 0);
...@@ -89,8 +88,8 @@ int main(int argc, char *argv[]) ...@@ -89,8 +88,8 @@ int main(int argc, char *argv[])
avio_open(&mux->pb, tmp, AVIO_FLAG_WRITE); avio_open(&mux->pb, tmp, AVIO_FLAG_WRITE);
muxopts = 0; muxopts = 0;
parse_dict(&muxopts, jlookup(argv[4], "options")); parse_dict(&muxopts, jlookup(argv[4], "options"));
if (avformat_write_header(mux, &muxopts) < 0) if ((err = avformat_write_header(mux, &muxopts)) < 0)
goto fail; job_failed("Writing temporary file failed: %s", av_err2str(err));
while (!av_read_frame(demux, &pkt)) while (!av_read_frame(demux, &pkt))
{ {
if (pkt.stream_index >= demux->nb_streams if (pkt.stream_index >= demux->nb_streams
...@@ -104,21 +103,16 @@ int main(int argc, char *argv[]) ...@@ -104,21 +103,16 @@ int main(int argc, char *argv[])
pkt.duration = av_rescale_q(pkt.duration, demux->streams[pkt.stream_index]->time_base, pkt.duration = av_rescale_q(pkt.duration, demux->streams[pkt.stream_index]->time_base,
mux->streams[pkt.stream_index]->time_base); mux->streams[pkt.stream_index]->time_base);
pkt.pos = -1; pkt.pos = -1;
if (av_interleaved_write_frame(mux, &pkt)) if (err = av_interleaved_write_frame(mux, &pkt))
goto fail; job_failed("Could not write frame: %s", av_err2str(err));
} }
av_interleaved_write_frame(mux, 0); av_interleaved_write_frame(mux, 0);
if (av_write_trailer(mux)) if (err = av_write_trailer(mux))
goto fail; job_failed("Error writing trailer to temporary file", av_err2str(err));
avio_closep(&mux->pb); avio_closep(&mux->pb);
if (rename(tmp, path)) if (rename(tmp, path))
goto fail; job_failed("Overwriting output file failed: %s", strerror(errno));
unlink(tmp); unlink(tmp);
ping_job(jobid, "finished", "{\"log\": \"%s\"}", get_avlogbuf()); ping_job(jobid, "finished", "{\"log\": \"%s\"}", jescape(get_avlogbuf()));
return 0; return 0;
fail:
unlink(tmp);
ping_job(jobid, "failed", "{\"log\": \"%s\"}", get_avlogbuf());
return 1;
} }
...@@ -24,8 +24,8 @@ AVFrame *scale_frame(AVFrame *frame, enum AVPixelFormat pix_fmt, ...@@ -24,8 +24,8 @@ AVFrame *scale_frame(AVFrame *frame, enum AVPixelFormat pix_fmt,
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int jobid, vidx; int err, vidx;
char lectureid[JSTR_SIZE], src[100], tmp[100], dest[100]; char lectureid[JSTR_SIZE], *src, *tmp, *dest;
AVFormatContext *demux, *mux; AVFormatContext *demux, *mux;
AVCodecContext *dec, *enc; AVCodecContext *dec, *enc;
AVPacket pkt; AVPacket pkt;
...@@ -33,25 +33,23 @@ int main(int argc, char *argv[]) ...@@ -33,25 +33,23 @@ int main(int argc, char *argv[])
if (argc != 5) if (argc != 5)
return 1; return 1;
av_register_all(); av_register_all();
av_log_set_callback(avlogbuf_callback); init_avlogbuf();
/* Prepare arguments */ /* Prepare arguments */
jobid = atoi(argv[1]); jobid = atoi(argv[1]);
jstrb(jlookup(argv[4], "lectureid"), "-1", lectureid); jstrb(jlookup(argv[4], "lectureid"), "-1", lectureid);
xsnprintf(BL(src), "%s/%s", CONFIG_VIDEOS_RELEASED, src = mprintf("%s/%s", CONFIG_VIDEOS_RELEASED, jstr(jlookup(argv[4], "path"), ""));
jstr(jlookup(argv[4], "path"), "")); tmp = mprintf("%s/.tmp-%i", CONFIG_VIDEOS_TMP, jobid);
xsnprintf(BL(tmp), "%s/.tmp-%i", CONFIG_VIDEOS_TMP, jobid); dest = mprintf("%s/thumbnail/l_%s.jpg", CONFIG_VIDEOS_RELEASED, lectureid);
xsnprintf(BL(dest), "%s/thumbnail/l_%s.jpg", CONFIG_VIDEOS_RELEASED,
lectureid);
ping_job(jobid, "running", 0); ping_job(jobid, "running", 0);
/* Open src */ /* Open src */
demux = 0; demux = 0;
if (avformat_open_input(&demux, src, 0, 0)) if (err = avformat_open_input(&demux, src, 0, 0))
goto fail; job_failed("Opening input file failed: %s", av_err2str(err));
avformat_find_stream_info(demux, 0); avformat_find_stream_info(demux, 0);
if ((vidx = av_find_best_stream(demux, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0)) < 0) if ((vidx = av_find_best_stream(demux, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0)) < 0)
goto fail; job_failed("Could not find video stream in input file");
dec = avcodec_alloc_context3(avcodec_find_decoder(demux->streams[vidx]->codecpar->codec_id)); dec = avcodec_alloc_context3(avcodec_find_decoder(demux->streams[vidx]->codecpar->codec_id));
avcodec_parameters_to_context(dec, demux->streams[vidx]->codecpar); avcodec_parameters_to_context(dec, demux->streams[vidx]->codecpar);
avcodec_open2(dec, dec->codec, 0); avcodec_open2(dec, dec->codec, 0);
...@@ -71,8 +69,8 @@ int main(int argc, char *argv[]) ...@@ -71,8 +69,8 @@ int main(int argc, char *argv[])
avio_open(&mux->pb, tmp, AVIO_FLAG_WRITE); avio_open(&mux->pb, tmp, AVIO_FLAG_WRITE);
avcodec_open2(enc, enc->codec, 0); avcodec_open2(enc, enc->codec, 0);
avcodec_parameters_from_context(mux->streams[0]->codecpar, enc); avcodec_parameters_from_context(mux->streams[0]->codecpar, enc);
if (avformat_write_header(mux, 0) < 0) if ((err = avformat_write_header(mux, 0)) < 0)
goto fail; job_failed("Writing temporary file failed: %s", av_err2str(err));
/* Create thumbnail */ /* Create thumbnail */
av_seek_frame(demux, -1, (2L*demux->duration)/5L, 0); av_seek_frame(demux, -1, (2L*demux->duration)/5L, 0);
...@@ -81,8 +79,8 @@ int main(int argc, char *argv[]) ...@@ -81,8 +79,8 @@ int main(int argc, char *argv[])
frame = av_frame_alloc(); frame = av_frame_alloc();
do do
{ {
if (av_read_frame(demux, &pkt)) if (err = av_read_frame(demux, &pkt))
goto fail; job_failed("Reading frame failed: %s", av_err2str(err));
if (pkt.stream_index == vidx) if (pkt.stream_index == vidx)
avcodec_send_packet(dec, &pkt); avcodec_send_packet(dec, &pkt);
} }
...@@ -97,17 +95,12 @@ int main(int argc, char *argv[]) ...@@ -97,17 +95,12 @@ int main(int argc, char *argv[])
av_interleaved_write_frame(mux, &pkt); av_interleaved_write_frame(mux, &pkt);
} }
av_interleaved_write_frame(mux, 0); av_interleaved_write_frame(mux, 0);
if (av_write_trailer(mux)) if (err = av_write_trailer(mux))
goto fail; job_failed("Error writing trailer to temporary file: %s", av_err2str(err));
avio_closep(&mux->pb); avio_closep(&mux->pb);
if (rename(tmp, dest)) if (rename(tmp, dest))
goto fail; job_failed("Overwriting output file failed: %s", strerror(errno));
unlink(tmp); unlink(tmp);
ping_job(jobid, "finished", "{\"log\": \"%s\"}", get_avlogbuf()); ping_job(jobid, "finished", "{\"log\": \"%s\"}", jescape(get_avlogbuf()));
return 0; return 0;
fail:
unlink(tmp);
ping_job(jobid, "failed", "{\"log\": \"%s\"}", get_avlogbuf());
return 1;
} }
...@@ -4,14 +4,19 @@ ...@@ -4,14 +4,19 @@
/* Generic */ /* Generic */
#define SL(s) (s), (sizeof(s)-1) #define SL(s) (s), (sizeof(s)-1)
#define BL(b) (b), (sizeof(b)) #define BL(b) (b), (sizeof(b))
size_t xvsnprintf(char *p, size_t len, const char *fmt, va_list ap); extern int jobid;
size_t xsnprintf(char *p, size_t len, const char *fmt, ...);
char *vmprintf(const char *fmt, va_list ap);
char *mprintf(const char *fmt, ...);
/* Logging */
void init_avlogbuf(void);
void avlogbuf_callback(void *classp, int level, const char *fmt, va_list ap); void avlogbuf_callback(void *classp, int level, const char *fmt, va_list ap);
char *get_avlogbuf(void); char *get_avlogbuf(void);
/* API */ /* API */
int ping_job(int id, char *state, char *status, ...); int ping_job(int id, char *state, char *status, ...);
void job_failed(char *msg, ...);
/* JSON parser */ /* JSON parser */
#define JSTR_SIZE 100 #define JSTR_SIZE 100
...@@ -24,4 +29,6 @@ char *jenter(char *s); ...@@ -24,4 +29,6 @@ char *jenter(char *s);
char *jnext(char *s); char *jnext(char *s);
char *jvalue(char *s); char *jvalue(char *s);
char *jlookup(char *s, char *key); char *jlookup(char *s, char *key);
/* JSON util */
char *jescape(char *s); char *jescape(char *s);
#include <curl/curl.h> #include <curl/curl.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
...@@ -9,7 +10,7 @@ ...@@ -9,7 +10,7 @@
static size_t curl_write_cb(char *ptr, size_t size, size_t nmemb, void *user) static size_t curl_write_cb(char *ptr, size_t size, size_t nmemb, void *user)
{ {
return size; return size*nmemb;
} }
int ping_job(int id, char *state, char *status, ...) int ping_job(int id, char *state, char *status, ...)
...@@ -17,39 +18,44 @@ int ping_job(int id, char *state, char *status, ...) ...@@ -17,39 +18,44 @@ int ping_job(int id, char *state, char *status, ...)
int ret; int ret;
CURL *curl; CURL *curl;
va_list ap; va_list ap;
char *e_host, *e_status, *e_apikey, *e_state; char *p, *url, *e_host, *e_status, *e_apikey, *e_state;
char url[100], buf[500]; char hostbuf[HOST_NAME_MAX+1];
if (!(curl = curl_easy_init())) if (!(curl = curl_easy_init()))
return -1; return -1;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
e_apikey = curl_easy_escape(curl, CONFIG_APIKEY, 0); e_apikey = curl_easy_escape(curl, CONFIG_APIKEY, 0);
e_state = curl_easy_escape(curl, state, 0); e_state = curl_easy_escape(curl, state, 0);
if (gethostname(BL(buf))) if (gethostname(BL(hostbuf)))
strcpy(buf, "localhost"); strcpy(hostbuf, "localhost");
buf[sizeof(buf)-1] = 0; e_host = curl_easy_escape(curl, hostbuf, 0);
e_host = curl_easy_escape(curl, buf, 0);
if (status) if (status)
{ {
va_start(ap, status); va_start(ap, status);
xvsnprintf(BL(buf), status, ap); p = vmprintf(status, ap);
va_end(ap); va_end(ap);
} }
else else
strcpy(buf, "{}"); p = strdup("{}");
e_status = curl_easy_escape(curl, buf, 0); e_status = curl_easy_escape(curl, p, 0);
xsnprintf(BL(buf), "apikey=%s&state=%s&host=%s&status=%s", free(p);
e_apikey, e_state, e_host, e_status); p = mprintf("apikey=%s&state=%s&host=%s&status=%s", e_apikey, e_state,
e_host, e_status);
curl_free(e_apikey); curl_free(e_apikey);
curl_free(e_state); curl_free(e_state);
curl_free(e_host); curl_free(e_host);
curl_free(e_status); curl_free(e_status);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, p);
xsnprintf(BL(url), "%s/internal/jobs/api/job/%i/ping", CONFIG_APIBASE, id); url = mprintf("%s/internal/jobs/api/job/%i/ping", CONFIG_APIBASE, id);
curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_URL, url);
ret = curl_easy_perform(curl); ret = curl_easy_perform(curl);
free(p);
free(url);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if (ret) if (ret)
{
fprintf(stderr, "API call to \"%s\" failed: %s\n", url, curl_easy_strerror(ret));
return -1; return -1;
}
else else
return 0; return 0;
} }
...@@ -3,41 +3,38 @@ ...@@ -3,41 +3,38 @@
#include "../util.h" #include "../util.h"
static char *logbuffer = 0; static char *logbuffer;
static size_t logoffset = 0, logsize = 0; static size_t logsize;
static pthread_mutex_t loglock = PTHREAD_MUTEX_INITIALIZER;; static FILE *logstream;
void init_avlogbuf(void)
{
logbuffer = 0;
logsize = 0;
if (!(logstream = open_memstream(&logbuffer, &logsize)))
exit(99);
av_log_set_callback(avlogbuf_callback);
}
void avlogbuf_callback(void *class, int level, const char *fmt, va_list ap) void avlogbuf_callback(void *class, int level, const char *fmt, va_list ap)
{ {
int len, print_prefix; int print_prefix;
char buf[200];
if (level >= AV_LOG_VERBOSE) if (level >= AV_LOG_VERBOSE)
return; return;
av_log_default_callback(class, level, fmt, ap);
if (pthread_mutex_lock(&loglock))
return;
if (logsize-logoffset < 1024)
logbuffer = realloc(logbuffer, (logsize += 1024));
if (!logbuffer)
return;
print_prefix = 1; print_prefix = 1;
len = av_log_format_line2(class, level, fmt, ap, logbuffer+logoffset, av_log_format_line(class, level, fmt, ap, BL(buf), &print_prefix);
logsize-logoffset, &print_prefix); fputs(buf, logstream);
if (len < logsize-logoffset)
logoffset += len;
else
logoffset = logsize-1;
pthread_mutex_unlock(&loglock);
} }
char *get_avlogbuf(void) char *get_avlogbuf(void)
{ {
char *ret, *p; char *p;
if (!logbuffer || pthread_mutex_lock(&loglock)) if (!logstream)
return strdup(""); return "";
ret = strdup(logbuffer); fclose(logstream);
pthread_mutex_unlock(&loglock); p = logbuffer;
for (p = ret; *p; p ++) init_avlogbuf();
if (*p == '"') fputs(p, logstream);
*p = '\''; return p;
return ret;
} }
#include <stdio.h>
#include <stdlib.h>
#include "../util.h"
char *jescape(char *s)
{
int i;
char *ptr;
size_t size;
FILE *stream;
if (!(stream = open_memstream(&ptr, &size)))
exit(99);
for (; *s; s ++)
switch (*s)
{
case '"':
fputs("\\\"", stream); break;
case '\\':
fputs("\\\\", stream); break;
case '\b':
fputs("\\b", stream); break;
case '\f':
fputs("\\f", stream); break;
case '\n':
fputs("\\n", stream); break;
case '\r':
fputs("\\r", stream); break;
case '\t':
fputs("\\t", stream); break;
default:
if (*s <= 0x1f)
fprintf(stream, "\\u%04x", *s);
else
fputc(*s, stream);
}
fclose(stream);
return ptr;
}
#include <stdio.h>
#include <stdlib.h>
#include "../util.h"
int jobid;
void job_failed(char *msg, ...)
{
va_list ap;
va_start(ap, msg);
ping_job(jobid, "failed", "{\"reason\": \"%s\", \"log\": \"%s\"}",
jescape(vmprintf(msg, ap)), jescape(get_avlogbuf()));
va_end(ap);
exit(2);
}
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
#include "../util.h" #include "../util.h"
static char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'};
static char *skip_ws(char *s) static char *skip_ws(char *s)
{ {
for (; *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'; s ++); for (; *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'; s ++);
...@@ -213,41 +210,3 @@ char *jlookup(char *s, char *key) ...@@ -213,41 +210,3 @@ char *jlookup(char *s, char *key)
return jvalue(s); return jvalue(s);
return 0; return 0;
} }
char *jescape(char *s)
{
int i;
static __thread char buf[JSTR_SIZE];
for (i = 0; *s && i+7 < sizeof(buf); s ++)
switch (*s)
{
case '"':
buf[i ++] = '\\'; buf[i ++] = '"'; break;
case '\\':
buf[i ++] = '\\'; buf[i ++] = '\\'; break;
case '\b':
buf[i ++] = '\\'; buf[i ++] = 'b'; break;
case '\f':
buf[i ++] = '\\'; buf[i ++] = 'f'; break;
case '\n':
buf[i ++] = '\\'; buf[i ++] = 'n'; break;
case '\r':
buf[i ++] = '\\'; buf[i ++] = 'r'; break;
case '\t':
buf[i ++] = '\\'; buf[i ++] = 't'; break;
default:
if (*s <= 0x1f)
{
buf[i ++] = '\\';
buf[i ++] = 'u';
buf[i ++] = '0';
buf[i ++] = '0';
buf[i ++] = hex[*s >> 4];
buf[i ++] = hex[*s & 0xf];
}
else
buf[i ++] = *s;
}
buf[i] = 0;
return buf;
}
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "../util.h"
char *vmprintf(const char *fmt, va_list ap)
{
char *ptr;
size_t size;
FILE *stream;
ptr = 0;
size = 0;
if (!(stream = open_memstream(&ptr, &size)))
exit(99);
if (vfprintf(stream, fmt, ap) < 0)
exit(99);
fclose(stream);
return ptr;
}
char *mprintf(const char *fmt, ...)
{
char *ret;
va_list ap;
va_start(ap, fmt);
ret = vmprintf(fmt, ap);
va_end(ap);
return ret;
}
#include <stdio.h>
#include <stdarg.h>
#include "../util.h"
size_t xvsnprintf(char *p, size_t len, const char *fmt, va_list ap)
{
int ret;
if ((ret = vsnprintf(p, len, fmt, ap)) >= len)
{
p[len-1] = 0;
return len;
}
return ret;
}
size_t xsnprintf(char *p, size_t len, const char *fmt, ...)
{
size_t ret;
va_list ap;
va_start(ap, fmt);
ret = vsnprintf(p, len, fmt, ap);
va_end(ap);
return ret;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment