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é:
|
|
HTML – View online as a web page |
|
|
PDF – View/save the PDF 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