Monday, September 27, 2010

Internet Explorer 9: Will it reverse the trend?!

A direct answer: not so sure it will. When I first looked at the beta, I thought it had a good chance. But my perception changed since then. The reason: Microsoft is pushing the developers away (once again).

From end user perspective, it is very likely your favorite browser extension does not work well in IE9. So unless the extension developer decides to go through the pain of adjusting it, you may now have a good reason switching to Chrome, Firefox, or Flock to name few, where the same developer may have the same extension ready and waiting for you already.

As a software vendor or developer, if you happen to have software that runs into the browser as a browser helper object (a fancy name for an extension) or application automating the browser core through the ActiveX supplied, you may be in trouble. If you added mshtml.tlb to your project, so you can handle document events or manipulate the html with early bound compiled code you are definitely in trouble. You deserve some explanation at this point. Time for a little history..

When Google released the shiny new Chrome, it came with the fastest JavaScript engine called V8. Among other things V8 had tendency of shuffling object methods around, i.e. the methods/properties attached to an object, during enumeration, did not occur in the order in which they were attached to the object. Not too bad thing in a dynamic language like JavaScript. A bad thing, if transferred to objects manipulated by a statically bound at compile time vtable references.

Though I did not invest time in inspecting html object vtables and confirming with tests the order of methods in a JavaScript manipulated object is in flux in IE9, the corrupt stack asserts seen and the V8 behavior known were good enough clues. Instead of hoping to see a solution to the problem in the released IE9, decided to take action and remove any compile time dependencies on mshtml.tlb from my code. The IUnknown, IDispatch do not seem affected by the JavaScript edits (otherwise nothing would have worked). As result one still has the option of making late bound calls through IDispatch (or IDispatchEx) Invoke.

In a small test, replacing the early bound calls with invocations through IDispatch got rid of the stack corruption asserts and yielded correct results. Still the calls looked bulky with all the variant pack/unpack and QueryInterface calls. Decidde to write a small template library that would absorb all the glue code. It was the right way to go, considering the total of 20-30 early bound calls to transform. Managed to get it all covered in a day. Attaching the code to this note. Hope the code serves you well! Should you have notes about the code feel free to post them in the comments section.

--
P.S. One thing the code does not cover is a generic reader/writer for primitive types. I only needed to handle long and BSTR types. For them, instead of something truly generic, decided to write a template specialization instead. While you may create you own specialization for let's say VARIANT_BOOL a generic enough Get/Put that handles well all but the ref variant types is the path to follow.



#pragma once
#include


#define DYNAMIC_ASSERT


// simple type assert T1 inherits from T2
template struct AssertOfType {
static void constraints(T1* a) { T2* b = a; ( void )b;}
AssertOfType() { void(*p)(T1*) = constraints; p = 0; }
};


class Dynamic: CComDispatchDriver {
protected:
Dynamic(void):CComDispatchDriver(){
; }


public:
Dynamic( IDispatch * pUnk ):CComDispatchDriver( pUnk ) {
; }

template static HRESULT Get( IDispatch* pSrc, LPCWSTR name, T* pRet ) {
Dynamic d(pSrc); return d.Get( name, pRet ); }
template static HRESULT Put( IDispatch* pSrc, LPCWSTR name, T& val ){
Dynamic d(pSrc); return d.Put( name, val ); }

// working with raw IDispatch here..
template static HRESULT GetRef( IDispatch* pSrc, LPCWSTR name, T** pRet ){
Dynamic d(pSrc); return d.GetRef( name, pRet ); }
template static HRESULT PutRef( IDispatch* pSrc, LPCWSTR name, T* val ){
Dynamic d(pSrc); return d.PutRef( &d, name, val ); }

template HRESULT Get( LPCWSTR name, T* pRet ) {
// keep the following line as is, until a generic
// template version is not made available to the caller
this should not compile!!!
}

template <> HRESULT Get( LPCWSTR name, long* pRet ) {
CComVariant var;
HRESULT hr = Get(name, &var);
if ( SUCCEEDED( hr ) && ( var.vt != VT_I4 ) && ( var.vt != VT_UI4 ) ) {
hr = var.ChangeType( VT_I4 ); }
if ( SUCCEEDED( hr ) ) {
*pRet = var.lVal; }
#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}


template HRESULT Put( LPCWSTR name, T& val ) {
HRESULT hr = S_FALSE;
if ( !p ) { hr = E_POINTER; }
if ( !name ) { hr = E_INVALIDARG; }
CComVariant v(val);
if ( SUCCEEDED( hr ) ) {
hr = this->Put( name, v ); }
#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}

// specialization: variant handler
template<> HRESULT Get( LPCWSTR name, VARIANT* pRet ) {
HRESULT hr = S_FALSE;
if ( !p ) { hr = E_POINTER; }
if ( !name ) { hr = E_INVALIDARG; }
if ( !pRet ) { hr = E_INVALIDARG; }
if ( SUCCEEDED( hr ) && ( ( *pRet ).vt != VT_EMPTY ) ) {
hr = ::VariantClear( pRet ); }
if ( SUCCEEDED( hr ) ) {
if ( wcscmp( name, L"__newEnum" ) == 0 ) {
hr = this->GetProperty( DISPID_NEWENUM, pRet ); }
else {
hr = this->GetPropertyByName( name, pRet ); } }
#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}

// specialization: variant handler
template<> HRESULT Put( LPCWSTR name, VARIANT& val ) {
HRESULT hr = S_FALSE;
if ( !p ) { hr = E_POINTER; }
if ( !name ) { hr = E_INVALIDARG; }
if ( SUCCEEDED( hr ) ) {
hr = this->PutPropertyByName( name, &val ); }
#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}


// specialization: BSTR
template <> HRESULT Get( LPCWSTR name, BSTR* pRet ) {
HRESULT hr = S_FALSE;
if ( !p ) { hr = E_POINTER; }
if ( !pRet ) { hr = E_INVALIDARG; }
if ( !name ) { hr = E_INVALIDARG; }

CComVariant var;
if ( SUCCEEDED( hr ) ) { hr = Get( name, &var ); }
if ( SUCCEEDED( hr ) ) { hr = var.ChangeType( VT_BSTR ); }
if ( SUCCEEDED( hr ) ) {
if ( *pRet ) { ::SysFreeString( *pRet ); *pRet = 0; }
*pRet = var.bstrVal; var.vt = VT_EMPTY; }

#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}

// generic COM interface handling
template HRESULT GetRef( LPCWSTR name, T** pRet ) {
AssertOfType< T, IUnknown >();
CComVariant var;

HRESULT hr = S_FALSE;
if ( !p ) { hr = E_POINTER; }
if ( !pRet ) { hr = E_INVALIDARG; }
if ( !name ) { hr = E_INVALIDARG; }

CComPtr pUnk;
if ( SUCCEEDED( hr ) ) {
hr = GetRef( name, &pUnk ); }
if ( SUCCEEDED( hr ) ) {
hr = GetQIPtr( pUnk, pRet ); }

#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}


// specialization: IUnkown need different that the other COM interfaces handing
template <> HRESULT GetRef( LPCWSTR name, IUnknown** pRet ) {
CComVariant var;

HRESULT hr = S_FALSE;
if ( !p ) { hr = E_POINTER; }
if ( !pRet ) { hr = E_INVALIDARG; }
if ( !name ) { hr = E_INVALIDARG; }

if ( SUCCEEDED( hr ) ) { hr = Get( name, &var ); }
if ( ( SUCCEEDED( hr ) ) && ( !( ( var.vt == VT_DISPATCH ) || ( var.vt == VT_UNKNOWN ) ) ) ) {
hr = E_NOINTERFACE; }
if ( SUCCEEDED( hr ) ) {
CComPtr p = ( var.vt == VT_BYREF ) ? *var.ppunkVal : var.punkVal;
if ( *pRet ) { ( *pRet )->Release(); }
if ( p ) { *pRet = p.Detach(); }
else { *pRet = 0; }
}
#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}


template HRESULT PutRef( LPCWSTR name, T* val ){
HRESULT hr = S_FALSE;
AssertOfType< T, IUnknown >();
if ( !p ) { hr = E_POINTER; }
if ( !name ) { hr = E_INVALIDARG; }
if ( SUCCEEDED( hr ) ) {
CComVariant var( val );
hr = this->Put( name, var ); }
#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}

// statics pointing to the instance members
template< class R > static HRESULT InvokeRef( IDispatch* pSrc, LPCWSTR name, R** pRet ) {
Dynamic d(pSrc); return d.InvokeRef(name, pRet); }
template< class T, class R > static HRESULT InvokeRef( IDispatch* pSrc, LPCWSTR name, T & arg1, R** pRet ) {
Dynamic d(pSrc); return d.InvokeRef(name, arg1, pRet); }
template< class T1, class T2, class R > static HRESULT InvokeRef( IDispatch* pSrc, LPCWSTR name, T1 & arg1, T2 & arg2, R** pRet ) {
Dynamic d(pSrc); return d.InvokeRef(name, arg1, arg2, pRet); }

template< class R > HRESULT InvokeRef( LPCWSTR name, R** pRet ) {
HRESULT hr = S_FALSE;
AssertOfType< R, IUnknown >();

if ( !p ) { hr = E_POINTER; }
if ( !pRet ) { hr = E_INVALIDARG; }
if ( !name ) { hr = E_INVALIDARG; }

CComVariant r;
if ( SUCCEEDED( hr ) ) {
hr = Invoke0(name, &r); }
if ( SUCCEEDED( hr ) ) {
hr = GetQIPtr< R >( r, pRet ); }

#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}

template< class T, class R > HRESULT InvokeRef( LPCWSTR name, T & arg1, R** pRet ) {
HRESULT hr = S_FALSE;
AssertOfType< R, IUnknown >();

if ( !p ) { hr = E_POINTER; }
if ( !pRet ) { hr = E_INVALIDARG; }
if ( !name ) { hr = E_INVALIDARG; }

CComVariant r, varg1(arg1);
if ( SUCCEEDED( hr ) ) {
hr = Invoke1( name, &varg1, &r); }
if ( SUCCEEDED( hr ) ) {
hr = GetQIPtr< R >( r, pRet ); }

#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}

template< class T1, class T2, class R > HRESULT InvokeRef( LPCWSTR name, T1 & arg1, T2 & arg2, R** pRet ) {
HRESULT hr = S_FALSE;
AssertOfType< R, IUnknown >();

if ( !p ) { hr = E_POINTER; }
if ( !pRet ) { hr = E_INVALIDARG; }
if ( !name ) { hr = E_INVALIDARG; }

CComVariant r, varg1(arg1), varg2(arg2);
if ( SUCCEEDED( hr ) ) {
hr = Invoke2( name, &varg1, &varg2, &r); }

if ( SUCCEEDED( hr ) ) {
hr = GetQIPtr< R >( r, pRet ); }

#ifdef DYNAMIC_ASSERT
_ASSERTE( SUCCEEDED( hr ) );
#endif
return hr;
}

protected:
template< class T > static HRESULT GetQIPtr( VARIANT & var, T** pRet ) {
AssertOfType< T, IUnknown >( );
HRESULT hr = S_FALSE;

CComPtr pUnk;
if ( SUCCEEDED( hr ) ) {
hr = GetQIPtr( var, &pUnk ); }
if ( pRet && SUCCEEDED( hr ) ) {
hr = GetQIPtr< T >( pUnk, pRet); }
return hr;
}

template<> static HRESULT GetQIPtr( VARIANT & var, IUnknown** pRet ) {
HRESULT hr = S_FALSE;
if ( !( ( var.vt == VT_DISPATCH ) || ( var.vt == VT_UNKNOWN ) ) ) {
hr = E_NOINTERFACE; }
if ( SUCCEEDED( hr ) ) {
CComPtr< IUnknown > p = ( var.vt == VT_BYREF ) ? *var.ppunkVal : var.punkVal;
if ( pRet && *pRet ) { ( *pRet )->Release(); }
if ( pRet ) {
if ( p ) { *pRet = p.Detach(); }
else { *pRet = 0; }
}
}
return hr;
}

template< class T > static HRESULT GetQIPtr( IUnknown * pUnk, T** pRet ) {
AssertOfType< T, IUnknown >();
HRESULT hr = S_OK;
CComQIPtr< T > p = pUnk;

if ( p ) {
if ( pRet ) {
if ( *pRet ) { ( *pRet )->Release(); *pRet = 0; }
*pRet = p.Detach(); } }
else if ( !pUnk ) {
if ( pRet ) {
if ( *pRet ) { ( *pRet )->Release(); }
*pRet = 0; } }
else {
hr = E_NOINTERFACE; }

return hr;
}

template<> static HRESULT GetQIPtr< IUnknown >( IUnknown * pUnk, IUnknown ** pRet ) {
if ( pRet && *pRet ) { ( *pRet )->Release(); *pRet = 0; }
if ( pRet ) { CComPtr p(pUnk); *pRet = p.Detach(); } }
};


// this should be it

Wednesday, July 28, 2010

Hubble

Had to work outside of the office this morning. It did not take much hesitation and I found myself at the Liberty Science Center (LSC): free Wi Fi, good looking but otherwise not so good and too expensive cafe (while on the cafe subject, it does not open until 10am, an entire hour after LSC itself; had to buy a coffee from a vending machine).

There was an IMAX movie titled Hubble. The last time in the IMAX dome was 6-7 months ago, so decided to give it a try. The movie was just 45 min: not a big time waste, regardless of content quality.

It was great though. Guilty of not following much news apart from Techcrunch, Venturebeat, Scientific American (has anyone seen it anywhere lately?!), about two minutes in the movie, I found out that after the originally stated by NASA "nah, too risky, not gonna do it" in 2004, a service mission did actually take place last year. Not just that, during the service mission, Hubble got an infrared capability.

Why am I sharing all that, exposing my partial ignorance to news? Surprisingly, there might be a hope for us as species.

The movie mentioned about ~10,000 people were involved in the Hubble creation. Digging into my corporation experience, may be the project needed fewer people (the major project contributors may back me up here, though I am not looking for any type appraisal for this "insight"). One way or another, Hubble is one of the most considerable projects, and not just by man*hour measure our typical focus falls on. Keeping Hubble alive for few more years, until the launch of the infrared space telescope, let us collect more invaluable data and more importantly have no gaps in observation. The telescope will, with no doubt, have many implications on the future state of Physics. Another NASA project that comes to mind is Pioneer, though it might not have been a disruptive from Physics perspective until the Pioneer anomaly.

Collectively, the anomalies discovered by either projects, challenge the Physical models we've built, let us gain better understanding of the big world we live in, adjust, improve, develop new technologies, and ultimately give us a chance to survive as species in a long run.

Not knowing the development during the 2 years of "not going to do it" and not considering the motivations of the parties involved, we should all thank Sen. Mukilski for keeping one of the most significant human projects operational. Senator, thank you!

Tuesday, May 25, 2010

Udemy rocked the startup alley at Techcrunch Disrupt

Udemy's co-founder Gagan Biyani, after 11 straight hours talking to people in the startup alley, did the impossible: Udemy few short of just few votes joining the startup battlefield.

To understand the achievement, one has to compare how Udemy and the startup alley winner got their votes. At one point, the winning team had about five people recruiting potential voters. While they had a fine product, their focus was on the votes and the votes only. At the same time, Udemy got support thanks to just Gagan's excellent presentation and the quality of the product offered.

While the later approach did not pay off entirely yesterday, falling short of 4 votes indicates something great. And it is all well deserved, once we look at the functionality Udemy has to offer. While the site hosts prepackaged courses, real time communication tools, like chat, camera, and white board, allow for a different experience. Without them, teaching classes will be difficult. There is improved experience viewing static course content too. Video and presentation content are seen side by side. No need to switch between different applications. The content is of excellent quality, where and when you need it. With no doubt, we'll soon see and hear more about the academy of you.



Saturday, May 15, 2010

Tuesday, March 23, 2010

Up to the promise given long time ago..

Some time ago in the blog, there was a note about SQLite and my support and willingness to contribute source code back to the project. As a first step, decided to post small code snippets directly in the blog every other week. Will figure if anything else can be done with them later. This is the first installment...

Every once in a while, one has to extract a piece of information, dependent upon a related field in the record. Consider for instance a web page title. It changes overtime. Not necessarily every single day, but it does change. Assuming we want to go back in time, it is practical to keep note of the new title once it changes. This leaves us with holes in the daily/hourly history. We end up with a slowly changing dimension. The slowly changing dimensions are long recognized. There is standard ways of dealing with them, but for the purpose of this note, let's assume, we do not want to define and maintain a date range on the record itself, or even better, assume for whatever reason, we want to get the longest ever tile. Then we are left with no choice, but to write a SQL query that goes against the history table twice: once fetching the last known title change record prior to the date in question (record with longest title); then in a second step, using this record identifier (and/or date if part of a unique index), we get the title. Assuming [title] table with [url], [date] and title [value] field, something in the lines of

select [t].[value]
from [title] [t] inner join
( select [url], min([date]) [date]
from [title] where [url] =<> and [date] <= <> group by [url] ) [f] on [f].[url] = [t].[url] and [f].[date] = [t].[date]

or

select max( [t].[value] ) // there may be two or more titles with the same length
from [title] [t] inner join
( select [url], max( length( [value] ) ) [len]
from [title] where [url] =<> group by [url] ) [f]
on [f].[url] = [t].[url] and [f].[len] = length( [t].[value] )

Not too difficult. Not pretty looking, though. Still when dealing with small lists (and the title change for a particular url over a week or month period is a small list), there might be an easier way if we were given min/max aggregation functions that operate on a condition field and return a dependent value from the record pinpointed by the condition. So, I and up writing SQLite min_indexed and max_indexed extension functions. With them, one constructs the following to get the title as of given date

select max_indexed( [date], [value] ) from [title] where [url] = <> and [date] <= <>

or

select max_indexed( length( [value] ), [value] ) from [title] where [url] = <>

to get the longest title. Simple.

Once more, a thing to consider is the amount of data the aggregation iterates through. The more complex two step query will give better performance in case of a large dataset and suitable indices defined. But if you have no good index on the condition, you may be better off choosing the simple min/max indexed query. It is easier to read and maintain.

Hope you find other interesting uses for the min/max indexed. Just post a note if you do. Happy coding!

Oh, yeah.. The code snippet follows:



extern const sqlite3_api_routines * sqlite3_api;


typedef struct minmaxAggData {

int flag;

int size;

union {

void* buffer; // allocated by sqlite3_malloc

sqlite_int64 i;

double d;

};

} minmaxAggData;


static int compareValue( sqlite3_value * val, minmaxAggData * base ) {

int valType;


assert( val );

assert( base );


valType = sqlite3_value_type( val );

if ( ( base->flag == SQLITE_INTEGER ) || ( base->flag == SQLITE_FLOAT ) ) {

int conversionAttempted = 0;


integerCompare:

switch( valType ) {

case SQLITE_INTEGER:

case SQLITE_FLOAT:

// direct compare possible

if ( ( base->flag == SQLITE_INTEGER ) && ( valType == SQLITE_INTEGER ) ) {

sqlite_int64 i = sqlite3_value_int64( val );

return ( base->i == i ) ? 0 : ( ( base->i > i ) ? -1: 1 );

}

{

double d1 = ( base->flag == SQLITE_INTEGER ) ? ( ( double ) base->i ) : base->d ;

double d2 = sqlite3_value_double( val );

return ( d1 == d2 ) ? 0 : ( ( d1 > d2 ) ? -1: 1 );

}

break;

case SQLITE_NULL:

return -1;

break;

default:

if ( !conversionAttempted ) {

valType = sqlite3_value_numeric_type( val );

conversionAttempted = 1;

goto integerCompare;

}

else {

return -2;

}

break;

}

}

else if ( ( base->flag == SQLITE_BLOB ) || ( base->flag == SQLITE_TEXT ) ) {

int b1 = base->size, b2 = sqlite3_value_bytes( val ), result = 0;

const void * v2 = ( base->flag == SQLITE_BLOB ) ? sqlite3_value_blob( val ) : sqlite3_value_text( val );

if ( v2 ) result = memcmp( v2 , base->buffer, ( b1 <>

if ( ( result == 0 ) && ( b1 != b2 ) ) { result = ( b1 > b2 ) ? 1: -1; }

return result;

}

else if ( ( base->flag == SQLITE_NULL ) || ( base->flag == 0 ) ) {

return ( valType != SQLITE_NULL ) ? 1 : 0;

}

else {

assert( 0 && "unknown datatype" );

return -2;

}

}


static void releaseValue( minmaxAggData * dest) {

assert( dest );

// need to free the buffer

if ( ( dest->flag == SQLITE_TEXT ) || ( dest->flag == SQLITE_BLOB ) ) {

if ( dest->buffer ) {

sqlite3_free( dest->buffer ); } }

memset( dest, 0, sizeof ( minmaxAggData ) );

}


static int copyValue( sqlite3_value * val, minmaxAggData * dest ) {

int valType;


assert( val );

assert( dest );


valType = sqlite3_value_type( val );


releaseValue( dest );


switch( valType ) {

case SQLITE_INTEGER:

dest->i = sqlite3_value_int64( val );

break;


case SQLITE_FLOAT:

dest->d = sqlite3_value_double( val );

break;


case SQLITE_BLOB:

case SQLITE_TEXT:

{

int sz = sqlite3_value_bytes( val );

const void * src = ( valType == SQLITE_TEXT ) ? sqlite3_value_text( val ): sqlite3_value_blob( val );

if ( ( sz ) && ( src ) ) {

if ( ( dest->buffer = sqlite3_malloc( sz + 1 ) ) != 0 ) {

memmove( dest->buffer, src, ( size_t ) sz );

*( ( char* ) dest->buffer + sz ) = 0; // make sure the string is zero terminated

dest->size = sz; } }

}

break;



case SQLITE_NULL:

break;

case 0: // initialized or empty

break;


default:

assert( 0 && "unknown or insupported data type" );

return 0;

}

dest->flag = valType;

return 1;

}


// ---

// Implementation of the min_indexed(), max_indexed()

//

// the call syntax from sql

// min_indexed( , )

//

static void minmaxStep( sqlite3_context *context, int argc, sqlite3_value **argv, int max ) {

minmaxAggData* pBest;


// validate the parameter count

if ( argc != 2 ) {

sqlite3_result_error( context, "exactly two parameters expected by the indexed min/max functions.", -1);

return; }


if( sqlite3_value_type( argv[0] )==SQLITE_NULL ) return;

pBest = ( minmaxAggData* ) sqlite3_aggregate_context( context, 2 * sizeof( *pBest ) );

if ( !pBest ) return;


if ( pBest[0].flag ) {

switch( compareValue( argv[0], &pBest[0] ) ) {

case 1:

if ( max ) {

copyValue( argv[0], &pBest[0] );

copyValue( argv[1], &pBest[1] );

}

break;


case -1:

if ( !max ) {

copyValue( argv[0], &pBest[0] );

copyValue( argv[1], &pBest[1] );

}

break;


default:

// no action

break;

}

}

else {

// the best value to compare against

copyValue( argv[0], &pBest[0] );

// the value to return

copyValue( argv[1], &pBest[1] );

}

}

void minStep( sqlite3_context *context, int argc, sqlite3_value **argv ) {

minmaxStep( context, argc, argv, 0 ); }

void maxStep( sqlite3_context *context, int argc, sqlite3_value **argv ) {

minmaxStep( context, argc, argv, 1 ); }


void minmaxFinalize( sqlite3_context *context ) {

minmaxAggData* pBest;

pBest = ( minmaxAggData* ) sqlite3_aggregate_context( context, 2 * sizeof( *pBest ) );

if ( !pBest ) {

sqlite3_result_null( context ); return ;}


releaseValue( &pBest[0] );

switch( pBest[1].flag ) {

case SQLITE_INTEGER: sqlite3_result_int64( context, pBest[1].i ); break;

case SQLITE_FLOAT: sqlite3_result_double( context, pBest[1].d ); break;

case SQLITE_BLOB: sqlite3_result_blob( context, pBest[1].buffer, pBest[1].size, sqlite3_free ); break;

case SQLITE_TEXT: sqlite3_result_text( context, ( char * ) pBest[1].buffer, pBest[1].size, sqlite3_free ); break;

default: sqlite3_result_null( context ) ;break;

}

// no need to release the return value. sqlite will take care of that

}


Monday, March 8, 2010

Beautiful and entrancing new music game for iPhone


Founder Institute company Monstrous is offering their iPhone game Entranced for FREE Tuesday, March 9th only. It is always pleasure seeing a good looking game. This time the game is created by a peer at the Founder Institute. Go Monstrous!

http://bit.ly/GetEntrancedForFree

Wednesday, March 3, 2010

The Startup Expenses and the link to Taxes

The other day I was looking if some of the expenses prior to incorporating a business may be deducted. It turns out they can, however...

The startup costs go on the corporation return and have to amortized. The amortization period is unbelievably long: 15 years! IRS proudly announce they let you deduct up to $5K ( in case overall startup expenses are <$50K ) in the first year. But unless you had the business registered in the first quarter or you had the product ready by the time you incorporated, though you can carry the $5K loss to the next year, amortizing over 15 year period ( and of course describing each and every expense ) will end up eating more time and money than it will save in taxes. Seems unfair. May be IRS had to close a loophole. Whatever the case, it is not worth the effort including any startup costs on a C Corp tax return.

Monday, January 11, 2010