HParsedToken *act_base64(const HParseResult *p, void* user_data) { assert(p->ast->token_type == TT_SEQUENCE); assert(p->ast->seq->used == 2); assert(p->ast->seq->elements[0]->token_type == TT_SEQUENCE); // grab b64_3 block sequence // grab and analyze b64 end block (_2 or _1) const HParsedToken *b64_3 = p->ast->seq->elements[0]; const HParsedToken *b64_2 = p->ast->seq->elements[1]; const HParsedToken *b64_1 = p->ast->seq->elements[1]; if(b64_2->token_type != TT_SEQUENCE) b64_1 = b64_2 = NULL; else if(b64_2->seq->elements[2]->uint == '=') b64_2 = NULL; else b64_1 = NULL; // allocate result sequence HParsedToken *res = H_MAKE_SEQ(); // concatenate base64_3 blocks for(size_t i=0; i<b64_3->seq->used; i++) { assert(b64_3->seq->elements[i]->token_type == TT_SEQUENCE); HParsedToken **digits = b64_3->seq->elements[i]->seq->elements; uint32_t x = bsfdig_value(digits[0]); x <<= 6; x |= bsfdig_value(digits[1]); x <<= 6; x |= bsfdig_value(digits[2]); x <<= 6; x |= bsfdig_value(digits[3]); seq_append_byte(res, (x >> 16) & 0xFF); seq_append_byte(res, (x >> 8) & 0xFF); seq_append_byte(res, x & 0xFF); } // append one trailing base64_2 or _1 block if(b64_2) { HParsedToken **digits = b64_2->seq->elements; uint32_t x = bsfdig_value(digits[0]); x <<= 6; x |= bsfdig_value(digits[1]); x <<= 6; x |= bsfdig_value(digits[2]); seq_append_byte(res, (x >> 10) & 0xFF); seq_append_byte(res, (x >> 2) & 0xFF); } else if(b64_1) {
const HParsedToken *act_base64(const HParseResult *p) { assert(p->ast->token_type == TT_SEQUENCE); assert(p->ast->seq->used == 2); assert(p->ast->seq->elements[0]->token_type == TT_SEQUENCE); HParsedToken *res = H_MAKE_SEQ(); // concatenate base64_3 blocks HCountedArray *seq = H_FIELD_SEQ(0); for(size_t i=0; i<seq->used; i++) h_seq_append(res, seq->elements[i]); // append one trailing base64_2 or _1 block const HParsedToken *tok = h_seq_index(p->ast, 1); if(tok->token_type == TT_SEQUENCE) h_seq_append(res, tok); return res; }