Showing posts with label Base64. Show all posts
Showing posts with label Base64. Show all posts

Sunday, February 2, 2014

Very Simple Base64 Reader

I've written this very simple Base64 reader. I wrote this as part of my loader for Tiled Map Editor files (see mapeditor.org). The code is very simple, but it works. The out_binary_data parameter is unsigned char * for simplicity as the code works in 8 bit chunks. Tiled actually uses 32 bit int variables so the pointer will need to be cast to int *. If you have anymore questions about the code, just leave a comment.


// converts a 6 bit value into the Base64 ASCII equivalent
unsigned char ASCIITo_6BitVal(char ch)
{
 if((ch >= 'A') && (ch <= 'Z')) return ch - 'A';
 else if((ch >= 'a') && (ch <= 'z')) return (ch - 'a') + 26;
 else if((ch >= '0') && (ch <= '9')) return (ch - '0') + 52;
 else if(ch == '+') return 62;
 else if(ch == '/') return 63;
 else if(ch == '=') return 64;
 else return 65;
}

// converts binary data to Base64, If the data will be used on a platform with a different endianness, the
// data 32 bit integers or the decoder will not be able to switch the endianness automatically
int Base64Binary(const char *in_base64_data, unsigned int in_base64_data_length,
                 unsigned char *out_binary_data, unsigned int in_binary_buffer_length, unsigned int &out_binary_data_length)
{
 out_binary_data_length = 0;

 for(unsigned int i = 0; i < in_base64_data_length; i += 4)
 {
  bool end_found = false;
  unsigned char b64_byte1 = ASCIITo_6BitVal(in_base64_data[i]);
  if(b64_byte1 > 63) return 1; // stop processing
  unsigned char b64_byte2 = ASCIITo_6BitVal(in_base64_data[i+1]);
  if(b64_byte2 > 63) return -1;
  unsigned char b64_byte3 = ASCIITo_6BitVal(in_base64_data[i+2]);
  if(b64_byte3 > 64) return -1; // this could be the end of the stream so it could also be '='
  unsigned char b64_byte4 = ASCIITo_6BitVal(in_base64_data[i+3]);
  if(b64_byte4 > 64) return -1; // this could be the end of the stream so it could also be '='

  int size = 3;
  // check for the end
  if(b64_byte4 == 64)
  {
   size = 2;
   end_found = true;
   b64_byte4 = 0;
  }
  if(b64_byte3 == 64)
  {
   size = 1;
   end_found = true;
   b64_byte3 = 0;
  }

  if(in_binary_buffer_length < (out_binary_data_length + size))
  {
   // the buffer is too small
   return -2;
  }

  out_binary_data[out_binary_data_length + 0] = (b64_byte1 << 2) | ((0x30 & b64_byte2) >> 4);
  if(size > 1)out_binary_data[out_binary_data_length + 1] = ((0xF & b64_byte2) << 4) | ((0x3C & b64_byte3) >> 2);
  if(size > 2)out_binary_data[out_binary_data_length + 2] = ((0x3 & b64_byte3) << 6) | b64_byte4;

  out_binary_data_length += size;

  if(end_found) break;
 }

 return 0;
}

Monday, January 27, 2014

Latest Updates 2014-01-28 and Base64

I had been spending a lot of time learning and exploring AngelScript. I won't be writing anymore AngelScript articles for Gamedev.net, but from time to time, I'll post blog entries on it.

These days, because of personal reasons of the other team members, Auxnet progress has slowed down a lot, but I hope to get back to it soon. While I wait for everyone to catch up, I've been experimenting with some new engine concepts. I've decided to build a little test engine currently code-named "Engine X" to try out the concepts. It'll be a multiplatform (Windows / Android) 2D tile-based engine that will use AngelScript as the scripting language. I'm not sure how much time I'll be able to devote to it though because it'll go on the back burner once things with Auxnet ramp up again.

I've got the base rendering and user input stuff working on Windows. Later I'll build it for Android. In the meantime, I've been working on adding support for a tile layer. I don't have time to make an editor so I'm going to use Tiled which can be found at mapeditor.org . I want to build a simple loader for it. The format is in XML so it's not overly complicated, but there was one thing that's new to me.

The tile data is stored in Base64. At first, I didn't know what this was so I decided to do a little research. Base64 is an encoding that takes data whether binary or text and encodes it using only 64 characters. This is useful when transmitting data over protocols that may alter the data. As it turns out, the pioneers of the Internet and email weren't forward thinking enough to think that more than 7-bits (thank you ASCII) would be needed for transmitting a text character. Base64 can also be used to store complex data inside things like XML. There are different forms of Base64, but they all work on the same general principle, It's used as a way to store binary data as plain text. It's not a complicated encoding. Basically you take three 8-bit bytes and break into four 6-bit units. The 6-bit units will be from 0-63. To make sure the values will be able to be transmitted without being garbled, the final character for each value is determined by the following table.


The above table is for Multipurpose Internet Mail Extensions (MIME). Other versions of Base64 use a similar table, but in some of them the characters used for values 62 and 63 are different. The above characters are good because they are supported by the majority of text encodings and aren't the same as any XML or HTML tags. For binary data to be converted into Base64, the number of bytes should be a multiple of three. If not, it should be padded with zeros. When this padding occurs, and special 65th character, '=', is used instead instead of the normal 0, 'A' character. This means '=' will only appear at the end if there was padding.

 Here's an example:


Now, I'll continue working on loading the map. Hope to have a working tiled-based rendering system within the next 7 days.