R-Link Research and Consulting, Inc.
Home|Rates & Contact

I’ve played a key role in a plethora of successful commercial projects over the last decade. Whether implementing a new product, building tools, designing a new API, architecting an infrastructure or just applying a new technology to an old solution, the results of my work are top-notch and on time.

Résumé:


View online as a web page HTML – View online as a web page
View/save the PDF version of my résumé PDF – View/save the PDF version
View/save the MS-Word version Word – View/save the MS-Word version

Code


Although most of the code I’ve produced is under NDA, occaisionally I code for myself or my friends. You can see some snippets on My Blog. Most are web-programming related because they were produced in lieu of building and maintaining a dozen or so web sites in my spare time. But, I’m not really a web developer…

Here’s a Base64 encoder I wrote in Objective-C for use on the iPad:

Open Unformatted Code In New Window

// Copyright (c) 2010 R-Link Research and Consulting, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this 
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice, 
//    this list of conditions and the following disclaimer in the documentation 
//    and/or other materials provided with the distribution.
// 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
//    may be used to endorse or promote products derived from this software 
//    without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
// POSSIBILITY OF SUCH DAMAGE.

#import "RCBase64Encoder.h"

// function: __rcb64_getEncodingTable
//
// Return is the table of encoding chars.
unsigned char * __rcb64_getEncodingTable()
{
	static unsigned char encTable[64] =
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

	return encTable;
}

// function: __rcb64_getDecodingTable
//
// Return is the decoding table
unsigned char * __rcb64_getDecodingTable()
{
	static int initialized = 0;
	static unsigned char decTable[128];
	
	if(initialized == 0)
	{
		// Clear
		//******
		memset(decTable, 0, sizeof(decTable));
		
		// Set the bytes corresponding to the
		// encoding chars to their 6-bit (0-64)
		// index values.
		//*************************************
		unsigned char * pEncTable = __rcb64_getEncodingTable();
		
		for(unsigned char i = 0; i < 64; i++)
		{
			int asciiVal = (int) pEncTable[i];
			
			decTable[asciiVal] = i;
		}
		
		initialized = 1;
	}
	
	return decTable;
}


// function: __rcb64dec_getPaddingLength
//
// Get the number of pad chars at the end of the buffer
int __rcb64dec_getPaddingLength(const char * pRaw, int inputLength)
{
	char * pByte = (char*) (pRaw + (inputLength - 1));
	int ret = 0;
	
	for(int i = inputLength - 1; i >= 0; i--, pByte--)
	{
		char nextByte = *pByte;
		
		if(nextByte != '=')
		{
			break;
		}
		
		ret++;
	}
	
	return ret;
}

// function: __rcb64dec_calcDecodedLength
//
// Calculate the decoded length
int __rcb64dec_calcDecodedLength(int inputLength, int paddingLength)
{
	int baseLength = inputLength - paddingLength;
	
	int inputBits = baseLength * 6;
	
	int ret = inputBits / 8;

	return ret;
}

// function: __rcb64_decode
//
// Decode C-String 
unsigned char * __rcb64_decode(const char * pRaw)
{
	unsigned char * pDecTable = __rcb64_getDecodingTable();
	
	int inputLength = strlen(pRaw);
	
	int paddingLength = __rcb64dec_getPaddingLength(pRaw, inputLength);
	int decodedLength = __rcb64dec_calcDecodedLength(inputLength, paddingLength);
	
	unsigned char *pDec = malloc(decodedLength + 1);
	unsigned char *pRet = pDec;
	pDec[decodedLength] = 0;
	
	char *pEnc = (char*) pRaw;
	
	int decBitIndex = 0;
	
	// Iterate through the input, decoding 
	// each char completely before moving on 
	// to the next (assumes MSB first).
	//**************************************
	for(int i = 0; i < inputLength; i++,pEnc++)
	{
		char nextEncByte = *pEnc;
		
		if(decBitIndex == 0)
		{
			// all 6 bits of encoded sextet
			// first 6 bits of decoded byte
			*pDec = pDecTable[nextEncByte] << 2;
			decBitIndex = 6;
		}
		else if(decBitIndex == 6)
		{
			// first 2 bits from encoded sextet
			// last 2 bits of decoded byte
			*pDec |= (pDecTable[nextEncByte] & 0x30) >> 4;
			pDec++;
			
			// last 4 bits from sextet
			// first 4 bits of decoded byte
			*pDec = (pDecTable[nextEncByte] & 0x0F) << 4;
			decBitIndex = 4;
		}
		else if(decBitIndex == 4)
		{
			// first 4 bits from encoded sextet
			// last 4 bits of decoded byte
			*pDec |= (pDecTable[nextEncByte] & 0x3C) >> 2;
			pDec++;
			
			// last 2 bits from encoded sextet
			// first 2 bits of decoded byte
			*pDec = (pDecTable[nextEncByte] & 0x03) << 6;
			decBitIndex = 2;
		}
		else if(decBitIndex == 2)
		{
			// all 6 bits from encoded sextet
			// last 6 bits of decoded byte
			*pDec |= pDecTable[nextEncByte];
			pDec++;
			decBitIndex = 0;
		}
	}
	
	return pRet;
}

// function: __rcb64enc_CalcEncodingLength
//
// Calculate encoding length
int __rcb64enc_CalcEncodingLength(int inputLength)
{
	// total bits to encode
	int inputBitCount = inputLength * 8;
	
	// total bytes necessary to re-encode
	// as 6-bit bytes
	int baseLength = inputBitCount / 6;
	
	if(inputBitCount % 6 > 0)
	// need 1 more byte to encode the remainder 
	{
		baseLength++;
	}	
	
	return baseLength;
}

// function: __rcb64enc_CalcPaddingLength
//
// Calculate padding length
int __rcb64enc_CalcPaddingLength(int encodingLength)
{	
	int encodingBitsRequired = encodingLength * 8;
	
	// will be 0, 8, or 16
	int finalQuantum = encodingBitsRequired % 24;
	
	if(finalQuantum == 8)
	{
		return 2;
	}
	else if(finalQuantum == 16)
	{
		return 1;
	}
	
	return 0;
}

// function: __rcb64_encode
//
// Encode buffer.
char * __rcb64_encode(void * pRaw, int length)
{
	unsigned char * pEncTable = __rcb64_getEncodingTable();
	
	int encodingLength = __rcb64enc_CalcEncodingLength(length);
	int paddingLength = __rcb64enc_CalcPaddingLength(length);
	
	char * pRet = malloc(encodingLength + paddingLength + 1); 
	char * pEnc = pRet;
	
	int encBitIndex = 0;
	char encByte = 0;
	char rawByte = 0;
	
	char * pBytes = (char*) pRaw;
	
	for(int i  = 0; i < length; i++, pBytes++)
	{
		rawByte = *pBytes;
		
		if(encBitIndex == 0)
		{
			// first 6 bits of the raw byte
			// enc byte full
			encByte = (rawByte & 0xFC) >> 2;
			*pEnc = pEncTable[encByte];
			pEnc++;
			encBitIndex = 0;
			
			// last 2 bits of the raw byte, 
			// first 2 bits of enc byte
			encByte = (rawByte & 0x03) << 4;
			encBitIndex = 2;				
		}
		else if(encBitIndex == 2)
		{
			// first 4 bits of the raw byte,
			// last 4 bits of enc byte
			encByte |= (rawByte & 0xF0) >> 4;
			*pEnc = pEncTable[encByte];
			pEnc++;
			encBitIndex = 0;
			
			// last 4 bits of the raw byte,
			// first 4 bits of enc byte
			encByte = (rawByte & 0x0F) << 2;
			encBitIndex = 4;
		}
		else
		// encBitIndex == 4
		{
			// first 2 bits of raw byte
			// last 2 bits of enc byte
			encByte |= (rawByte & 0xC0) >> 6;
			*pEnc = pEncTable[encByte];
			pEnc++;
			encBitIndex = 0;
			
			// last 6 bits of raw byte
			// enc byte full
			encByte = rawByte & 0x3F;
			*pEnc = pEncTable[encByte];
			pEnc++;
			encBitIndex = 0;
		}
	}
	
	// remainder
	if(encBitIndex > 0)
	{
		*pEnc = pEncTable[encByte];
		pEnc++;
	}
	
	// padding
	for(int i = 0; i < paddingLength; i++)
	{
		*pEnc = '=';
		pEnc++;
	}
	
	// terminating zero
	*pEnc = 0;
	
	return pRet;
}

//******************************************************************************
// class: RCBase64Encoder
//
// Encode/decode text and arbitrary data in Base64.
//******************************************************************************
@implementation RCBase64Encoder

// method: encodeString
//
// Assumes UTF-8 encoding.
+ (NSString*) encodeString:(NSString*) raw;
{
	if(raw == nil)
	{
		return @"";
	}
	
	// Convert to C string
	//********************
	const char * pRaw = [raw cStringUsingEncoding:NSUTF8StringEncoding];
	int length = strlen(pRaw);
	
	// Encode
	//*******
	const char * pEnc = __rcb64_encode((void*) pRaw, length);
	
	NSString * ret = 
		[[NSString alloc] 
			initWithCString:pEnc 
			encoding:NSUTF8StringEncoding];
	
	return ret;
}

// method: decodeStringAsString
//
// Assumes UTF-8 encoded string as output.
+ (NSString*) decodeStringAsString:(NSString*) raw
{
	if(raw == nil)
	{
		return @"";
	}
	
	// Convert to C string
	//********************
	const char * pRaw = [raw cStringUsingEncoding:NSUTF8StringEncoding];
	
	// Decode
	//*******
	unsigned char * pDec = __rcb64_decode(pRaw);
	
	NSString *ret = 
		[[NSString alloc] 
			initWithCString:(char*) pDec 
			encoding:NSUTF8StringEncoding];

	return ret;
}

@end
// end RCBase64Encoder