diff --git a/pdf.c b/pdf.c index b6e2089a4d77bd6376b50a97ccf1486352ed9435..cf3c3089808bbd8ef4d80d8ec80b72a2a5165020 100644 --- a/pdf.c +++ b/pdf.c @@ -244,6 +244,8 @@ act_a85zero(const HParseResult *p, void *u) return H_MAKE_UINT(b); } +#include <math.h> /* pow() */ + HParsedToken * act_a85digit(const HParseResult *p, void *u) { @@ -255,14 +257,13 @@ act_a85digit(const HParseResult *p, void *u) } HParsedToken * -act_a85group(const HParseResult *p, void *u) +act_a85fivedigits(const HParseResult *p, void *u) { uint64_t fourbytes = 0; HCountedArray *seq = H_CAST_SEQ(p->ast); HParsedToken **digits = h_seq_elements(p->ast); /* 2^32-1, the max value the group can hold as per spec */ - // XXX test with "s8W-!" #define A85GRPMAX 4294967295 /* Only for groups that do not need to padded to 5 */ @@ -274,12 +275,43 @@ act_a85group(const HParseResult *p, void *u) fourbytes += H_CAST_UINT(digits[4]); assert(fourbytes <= A85GRPMAX); - // XXX make it generic with H_ACT_APPLY - // XXX but partial groups are at least 2 characters long - return H_MAKE_UINT(fourbytes); } +HParsedToken * +act_a85group(const HParseResult *p, void *u) +{ + +} + +HParsedToken * +act_a85partial2group(const HParseResult *p, void *u) +{ + +} + +HParsedToken * +act_a85partial3group(const HParseResult *p, void *u) +{ + +} + +HParsedToken * +act_a85partial4group(const HParseResult *p, void *u) +{ + +} + +/* Checking the following condition in the spec: + * The value represented by a group of 5 characters is greater than 2^32 - 1. +*/ +bool +validate_a85fivedigits(HParseResult *p, void *u) +{ + // XXX test with "s8W-!" + return H_CAST_UINT(p->ast) <= A85GRPMAX; +} + HParsedToken * act_nat(const HParseResult *p, void *u) { @@ -1143,9 +1175,35 @@ ASCII85Decode(const Dict *parms, HBytes b, HParser *p) H_RULE(a85eod, SEQ(h_ch('~'), OPT(h_many(lwchar)), h_ch('>'))); H_ARULE(a85zero, h_ch('z')); + H_ARULE(a85digit, h_ch_range('!', 'u')); - fprintf(stderr, "ASCII85Decode: not implemented\n"); - return NULL; + /* Line whitespace can occur between any digit and has to be ignored, */ + /* Comments are not allowed inside streams, and % character should cause + * a parse error. */ + H_RULE(lws, IGN(h_many(IGN(lwchar)))); + #define MANY_LWS(X) h_many(CHX(lws, X)) + + /* This encoding of zero is not allowed */ + H_RULE(a85fiveexcl, h_repeat_n(MANY_LWS(h_ch('!')), 5)); + H_VARULE(a85fivedigits, SEQ(h_and(h_not(a85fiveexcl)), h_repeat_n(MANY_LWS(a85digit), 5))); + //H_RULE(a85digitws, SEQ(a85digit, OPT( + H_ARULE(a85group, CHX(a85zero, h_repeat_n(MANY_LWS(a85digit), 5))); + // XXX semantic actions need cleaning + + H_ARULE(a85partial2group, h_repeat_n(MANY_LWS(a85digit), 2)); + H_ARULE(a85partial3group, h_repeat_n(MANY_LWS(a85digit), 3)); + H_ARULE(a85partial4group, h_repeat_n(MANY_LWS(a85digit), 4)); + + H_RULE(a85string, SEQ(h_many(a85group), OPT(CHX(a85partial2group, a85partial3group, a85partial4group)), a85eod)); + + res = h_parse(a85string, b.token, b.len); + if(!res) + { + fprintf(stderr, "parse error in ASCII85Decode filter\n"); + return NULL; + } + + return res; } /*