| 46 | static u32 gInstructionCountLimit = kUnlimitedInstructionCount; |
| 47 | |
| 48 | static void Base64Encode(const void * data, size_t len, DataSink * sink) |
| 49 | { |
| 50 | const char * table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 51 | |
| 52 | const u8 * b = static_cast<const u8 *>(data); |
| 53 | const u8 * e = b + len; |
| 54 | |
| 55 | size_t out_len = ((len+2)/3) * 4; |
| 56 | char * buffer = static_cast<char *>(malloc( out_len )); |
| 57 | char * dst = buffer; |
| 58 | |
| 59 | const u8 * src = b; |
| 60 | for ( ; src + 2 < e; src += 3) |
| 61 | { |
| 62 | u32 v = (src[0] << 16) | (src[1] << 8) | src[2]; |
| 63 | |
| 64 | dst[0] = table[(v >> 18) & 0x3f]; |
| 65 | dst[1] = table[(v >> 12) & 0x3f]; |
| 66 | dst[2] = table[(v >> 6) & 0x3f]; |
| 67 | dst[3] = table[(v >> 0) & 0x3f]; |
| 68 | |
| 69 | dst += 4; |
| 70 | } |
| 71 | |
| 72 | if (src < e) |
| 73 | { |
| 74 | u32 c0 = src[0]; |
| 75 | u32 c1 = src+1 < e ? src[1] : 0; |
| 76 | u32 c2 = src+2 < e ? src[2] : 0; |
| 77 | |
| 78 | u32 v = (c0 << 16) | (c1 << 8) | c2; |
| 79 | |
| 80 | dst[0] = table[(v >> 18) & 0x3f]; |
| 81 | dst[1] = table[(v >> 12) & 0x3f]; |
| 82 | dst[2] = src+1 < e ? table[(v >> 6) & 0x3f] : '='; |
| 83 | dst[3] = src+2 < e ? table[(v >> 0) & 0x3f] : '='; |
| 84 | |
| 85 | dst += 4; |
| 86 | } |
| 87 | |
| 88 | DAEDALUS_ASSERT(dst == buffer+out_len, "Oops"); |
| 89 | sink->Write(buffer, out_len); |
| 90 | free(buffer); |
| 91 | } |
| 92 | |
| 93 | class HTMLDebugOutput : public DLDebugOutput |
| 94 | { |