#include "stralloc.h"
#include "strerr.h"
#include "messages.h"
#include "mime.h"
#include "die.h"
#include "idx.h"

/* takes a string pointed to by cpfrom and adds the next 'n' bytes to        */
/* outdata, replacing any Quoted-Printable codes with the real characters.   */
/* NUL and LF in the input are allowed, but anything that decodes to these   */
/* values is ignored. */

static const char char16table[128] = {
    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
     0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,
    -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
};

#define char16enc(c)  (((c) & 0x80) ? -1 : char16table[(int)(c)])

void decodeQ(const char *cpfrom,unsigned int n,stralloc *outdata)
/* does Q decoding of the string pointed to by cpfrom up to the character */
/* before the one pointed to by cpnext, and appends the results to outdata */
{
  const char *cp,*cpnext;
  char ch1,ch2;		/* need to be signed */
  char ch;

  cp = cpfrom;
  cpnext = cp + n;
  if (!stralloc_readyplus(outdata,n)) die_nomem();

  while (cp < cpnext) {
    ch = *cp++;
    if (ch == '_') ch = ' ';		/* '_' -> space */
    if (ch == '=') {			/* "=F8" -> '\xF8' */
      if (*cp == '\n') {		/* skip soft line break */
        ++cp;
        continue;
      }
      ch1 = char16enc(*cp); ++cp;
      if (cp >= cpnext)
        break;
      ch2 = char16enc(*cp); ++cp;
      if (ch1 >= 0 && ch2 >= 0) {	/* ignore illegals */
        ch = (ch1 << 4 | ch2) & 0xff;
      }
    }
    if (!stralloc_append(outdata,ch)) die_nomem();
  }
}      


