#include "duktape.h"
#include "duk_codepage_conv.h"

/* http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT */
unsigned int cp1252[256] = {
	(unsigned int) 0x0000,
	(unsigned int) 0x0001,
	(unsigned int) 0x0002,
	(unsigned int) 0x0003,
	(unsigned int) 0x0004,
	(unsigned int) 0x0005,
	(unsigned int) 0x0006,
	(unsigned int) 0x0007,
	(unsigned int) 0x0008,
	(unsigned int) 0x0009,
	(unsigned int) 0x000A,
	(unsigned int) 0x000B,
	(unsigned int) 0x000C,
	(unsigned int) 0x000D,
	(unsigned int) 0x000E,
	(unsigned int) 0x000F,
	(unsigned int) 0x0010,
	(unsigned int) 0x0011,
	(unsigned int) 0x0012,
	(unsigned int) 0x0013,
	(unsigned int) 0x0014,
	(unsigned int) 0x0015,
	(unsigned int) 0x0016,
	(unsigned int) 0x0017,
	(unsigned int) 0x0018,
	(unsigned int) 0x0019,
	(unsigned int) 0x001A,
	(unsigned int) 0x001B,
	(unsigned int) 0x001C,
	(unsigned int) 0x001D,
	(unsigned int) 0x001E,
	(unsigned int) 0x001F,
	(unsigned int) 0x0020,
	(unsigned int) 0x0021,
	(unsigned int) 0x0022,
	(unsigned int) 0x0023,
	(unsigned int) 0x0024,
	(unsigned int) 0x0025,
	(unsigned int) 0x0026,
	(unsigned int) 0x0027,
	(unsigned int) 0x0028,
	(unsigned int) 0x0029,
	(unsigned int) 0x002A,
	(unsigned int) 0x002B,
	(unsigned int) 0x002C,
	(unsigned int) 0x002D,
	(unsigned int) 0x002E,
	(unsigned int) 0x002F,
	(unsigned int) 0x0030,
	(unsigned int) 0x0031,
	(unsigned int) 0x0032,
	(unsigned int) 0x0033,
	(unsigned int) 0x0034,
	(unsigned int) 0x0035,
	(unsigned int) 0x0036,
	(unsigned int) 0x0037,
	(unsigned int) 0x0038,
	(unsigned int) 0x0039,
	(unsigned int) 0x003A,
	(unsigned int) 0x003B,
	(unsigned int) 0x003C,
	(unsigned int) 0x003D,
	(unsigned int) 0x003E,
	(unsigned int) 0x003F,
	(unsigned int) 0x0040,
	(unsigned int) 0x0041,
	(unsigned int) 0x0042,
	(unsigned int) 0x0043,
	(unsigned int) 0x0044,
	(unsigned int) 0x0045,
	(unsigned int) 0x0046,
	(unsigned int) 0x0047,
	(unsigned int) 0x0048,
	(unsigned int) 0x0049,
	(unsigned int) 0x004A,
	(unsigned int) 0x004B,
	(unsigned int) 0x004C,
	(unsigned int) 0x004D,
	(unsigned int) 0x004E,
	(unsigned int) 0x004F,
	(unsigned int) 0x0050,
	(unsigned int) 0x0051,
	(unsigned int) 0x0052,
	(unsigned int) 0x0053,
	(unsigned int) 0x0054,
	(unsigned int) 0x0055,
	(unsigned int) 0x0056,
	(unsigned int) 0x0057,
	(unsigned int) 0x0058,
	(unsigned int) 0x0059,
	(unsigned int) 0x005A,
	(unsigned int) 0x005B,
	(unsigned int) 0x005C,
	(unsigned int) 0x005D,
	(unsigned int) 0x005E,
	(unsigned int) 0x005F,
	(unsigned int) 0x0060,
	(unsigned int) 0x0061,
	(unsigned int) 0x0062,
	(unsigned int) 0x0063,
	(unsigned int) 0x0064,
	(unsigned int) 0x0065,
	(unsigned int) 0x0066,
	(unsigned int) 0x0067,
	(unsigned int) 0x0068,
	(unsigned int) 0x0069,
	(unsigned int) 0x006A,
	(unsigned int) 0x006B,
	(unsigned int) 0x006C,
	(unsigned int) 0x006D,
	(unsigned int) 0x006E,
	(unsigned int) 0x006F,
	(unsigned int) 0x0070,
	(unsigned int) 0x0071,
	(unsigned int) 0x0072,
	(unsigned int) 0x0073,
	(unsigned int) 0x0074,
	(unsigned int) 0x0075,
	(unsigned int) 0x0076,
	(unsigned int) 0x0077,
	(unsigned int) 0x0078,
	(unsigned int) 0x0079,
	(unsigned int) 0x007A,
	(unsigned int) 0x007B,
	(unsigned int) 0x007C,
	(unsigned int) 0x007D,
	(unsigned int) 0x007E,
	(unsigned int) 0x007F,
	(unsigned int) 0x20AC,
	(unsigned int) 0xFFFD,  /* undefined */
	(unsigned int) 0x201A,
	(unsigned int) 0x0192,
	(unsigned int) 0x201E,
	(unsigned int) 0x2026,
	(unsigned int) 0x2020,
	(unsigned int) 0x2021,
	(unsigned int) 0x02C6,
	(unsigned int) 0x2030,
	(unsigned int) 0x0160,
	(unsigned int) 0x2039,
	(unsigned int) 0x0152,
	(unsigned int) 0xFFFD,  /* undefined */
	(unsigned int) 0x017D,
	(unsigned int) 0xFFFD,  /* undefined */
	(unsigned int) 0xFFFD,  /* undefined */
	(unsigned int) 0x2018,
	(unsigned int) 0x2019,
	(unsigned int) 0x201C,
	(unsigned int) 0x201D,
	(unsigned int) 0x2022,
	(unsigned int) 0x2013,
	(unsigned int) 0x2014,
	(unsigned int) 0x02DC,
	(unsigned int) 0x2122,
	(unsigned int) 0x0161,
	(unsigned int) 0x203A,
	(unsigned int) 0x0153,
	(unsigned int) 0xFFFD,  /* undefined */
	(unsigned int) 0x017E,
	(unsigned int) 0x0178,
	(unsigned int) 0x00A0,
	(unsigned int) 0x00A1,
	(unsigned int) 0x00A2,
	(unsigned int) 0x00A3,
	(unsigned int) 0x00A4,
	(unsigned int) 0x00A5,
	(unsigned int) 0x00A6,
	(unsigned int) 0x00A7,
	(unsigned int) 0x00A8,
	(unsigned int) 0x00A9,
	(unsigned int) 0x00AA,
	(unsigned int) 0x00AB,
	(unsigned int) 0x00AC,
	(unsigned int) 0x00AD,
	(unsigned int) 0x00AE,
	(unsigned int) 0x00AF,
	(unsigned int) 0x00B0,
	(unsigned int) 0x00B1,
	(unsigned int) 0x00B2,
	(unsigned int) 0x00B3,
	(unsigned int) 0x00B4,
	(unsigned int) 0x00B5,
	(unsigned int) 0x00B6,
	(unsigned int) 0x00B7,
	(unsigned int) 0x00B8,
	(unsigned int) 0x00B9,
	(unsigned int) 0x00BA,
	(unsigned int) 0x00BB,
	(unsigned int) 0x00BC,
	(unsigned int) 0x00BD,
	(unsigned int) 0x00BE,
	(unsigned int) 0x00BF,
	(unsigned int) 0x00C0,
	(unsigned int) 0x00C1,
	(unsigned int) 0x00C2,
	(unsigned int) 0x00C3,
	(unsigned int) 0x00C4,
	(unsigned int) 0x00C5,
	(unsigned int) 0x00C6,
	(unsigned int) 0x00C7,
	(unsigned int) 0x00C8,
	(unsigned int) 0x00C9,
	(unsigned int) 0x00CA,
	(unsigned int) 0x00CB,
	(unsigned int) 0x00CC,
	(unsigned int) 0x00CD,
	(unsigned int) 0x00CE,
	(unsigned int) 0x00CF,
	(unsigned int) 0x00D0,
	(unsigned int) 0x00D1,
	(unsigned int) 0x00D2,
	(unsigned int) 0x00D3,
	(unsigned int) 0x00D4,
	(unsigned int) 0x00D5,
	(unsigned int) 0x00D6,
	(unsigned int) 0x00D7,
	(unsigned int) 0x00D8,
	(unsigned int) 0x00D9,
	(unsigned int) 0x00DA,
	(unsigned int) 0x00DB,
	(unsigned int) 0x00DC,
	(unsigned int) 0x00DD,
	(unsigned int) 0x00DE,
	(unsigned int) 0x00DF,
	(unsigned int) 0x00E0,
	(unsigned int) 0x00E1,
	(unsigned int) 0x00E2,
	(unsigned int) 0x00E3,
	(unsigned int) 0x00E4,
	(unsigned int) 0x00E5,
	(unsigned int) 0x00E6,
	(unsigned int) 0x00E7,
	(unsigned int) 0x00E8,
	(unsigned int) 0x00E9,
	(unsigned int) 0x00EA,
	(unsigned int) 0x00EB,
	(unsigned int) 0x00EC,
	(unsigned int) 0x00ED,
	(unsigned int) 0x00EE,
	(unsigned int) 0x00EF,
	(unsigned int) 0x00F0,
	(unsigned int) 0x00F1,
	(unsigned int) 0x00F2,
	(unsigned int) 0x00F3,
	(unsigned int) 0x00F4,
	(unsigned int) 0x00F5,
	(unsigned int) 0x00F6,
	(unsigned int) 0x00F7,
	(unsigned int) 0x00F8,
	(unsigned int) 0x00F9,
	(unsigned int) 0x00FA,
	(unsigned int) 0x00FB,
	(unsigned int) 0x00FC,
	(unsigned int) 0x00FD,
	(unsigned int) 0x00FE,
	(unsigned int) 0x00FF
};

/* Exercise all 3 byte lengths: any ASCII character is 1 byte, 0xFC maps to
 * U+00FC which is 2 bytes, and 0x80 maps to U+20AC which is 3 bytes.
 */
static const char *example_source = "print('Hello w\xfcrld - \x80');";

static duk_ret_t duk__print(duk_context *ctx) {
	duk_push_string(ctx, " ");
	duk_insert(ctx, 0);
	duk_join(ctx, duk_get_top(ctx) - 1);
	printf("%s\n", duk_safe_to_string(ctx, -1));
	return 0;
}

/* Example: compile and run test source encoded in Windows codepage 1252. */
int main(int argc, char *argv[]) {
	duk_context *ctx;

	(void) argc; (void) argv;

	ctx = duk_create_heap_default();
	if (!ctx) {
		printf("Failed to create Duktape heap.\n");
		return 1;
	}

	/* Minimal print() provider. */
	duk_push_c_function(ctx, duk__print, DUK_VARARGS);
	duk_put_global_string(ctx, "print");

	duk_decode_string_codepage(ctx, example_source, strlen(example_source), cp1252);
	duk_eval_noresult(ctx);

	duk_destroy_heap(ctx);
	return 0;
}
