August 22, 2010

QuickConnectFamily 1.6.3 is now available

Posted in Android Development, Blackberry development, iPhone development tagged , , , , , , , , , , at 12:47 am by tetontech

I am uploading to sourceForge the latest version of QuickConnect right now.

This new version of QC is a maintenance version and has two fixes in it.

The first is a fix to the display of iAdds.  Previously the iAdd seemed to disappear but was still taking up screen space and masking the area it was covering.

The second fix regarded a crash when using native databases with null values in fields.

Both of these defects have been fixed.

November 17, 2009

QCiPhone 1.6 beta 4 is now available.

Posted in iPhone development, Uncategorized tagged , , , , , at 6:55 am by tetontech

A new beta of QC 1.6, beta 4, is now available on sourceforge.  I has the following fixes and changes

  1. DBScript can now be used with native databases.
  2. All examples shipping in the download of the beta are now converted to the 1.6 file structure.  A few of the examples have not been ported yet and so I have not included them yet.  I’ll put them in the next beta.
  3. ServerAccessObject timeout defect fixed that triggered multiple calls to VCO’s
  4. Cleaned up DataAccessObject batch method (a support method for DBScript.  Don’t use it directly).  Simplified batch completion checking.
  5. Fixed DataAccessObject transaction handling that caused transactions not to appear to fail if database constraints were violated.
  6. SQLite updated to version 3.6.20 with support for FTS3 query syntax added
  7. Added missing NativeFooter Example
  8. Fixed failure to hide native footer defect
  9. Added new JQTouch example showing the JQTouch developer demo

September 24, 2009

QuickConnectiPhone 1.6 Beta 1 is now available

Posted in iPhone development tagged , , , , , , , , , , , , , at 9:42 pm by tetontech

QCiPhone 1.6 beta 1 is now available from the sourceForge repository.  It includes access to the Contacts API via JavaScript as well as a new way of doing GPS locations and tracking.  There are two new examples to show how to use the new functionality, GPSExample and Contacts Example.

The old in-application map functionality has been commented out in anticipation of Beta 2 which will include the access to the new 3.0 Map API and in-application email.

Push from within JavaScript and receiving pushes in JavaScript planned for Beta 3.

August 29, 2009

QuickConnectiPhone 1.5.0 is now available

Posted in erlang development, iPhone development, mac development, Uncategorized tagged , , , , , , , , , , , , , , , at 9:05 pm by tetontech

QCiPhone 1.5.0 has just been uploaded to sourceForge.  They are saying that it may take about 15 minutes to become visible as the default download for OS X machines.

A note to 3.0 API users. The dashcode QC template no longer appears as an option.  I am looking for ways to get it to show up again.End

Because of the 3.0 Dashcode changes I have not been able to update the Dashcode examples to the latest QC source.  All of the Xcode examples are updated.

The release includes examples of how to use the video and audio tags in booth QCiPhone and QCMac applications.

QuickConnectMac 1.0 is also included in this release.  It allows you to create hybrid applications that run on Mac machines just like you do for the iPhone and iPod touch.

QuickConnectPHP 1.0 is another template that can be used on the Mac side.  It isn’t used to create hybrid applications but is used to create PHP web applications.

Also included, for those interested, is QCErlang 1.0.  It is an updated version of an Xcode template for developing erlang applications.  It includes auto-completes for most of the commonly used functions.

Defect fixes in this release include:

1.  UIWebView no longer ends up with a black background after re-displaying the Default.png file while the page loads.

2.  DataAccessObject in-browser database use fixed and updated to new methodology for the retention of which BCF in the stack is to be called next.

3.  Updated the embedded map code to use the current data passing scheme from and to Objective-C

4.  HTML Elements with touch events inside of Elements made scrollable no longer react to ontouchstart, ontouchmove, and ontouchend unless the event is not due to scrolling

November 29, 2008

QuickConnectiPhone 1.0 RC3 available

Posted in iPhone development, mac development, misc, PHP tagged , , , , , , , , , , , , , , , , , , , , at 7:38 am by tetontech

The latest release candidate, 3, is now available for QuickConnectiPhone a framework that allows you to build your installable iPhone applications in HTML, CSS, and JavaScript. If you want to create an iPhone application but don’t have time to or maybe don’t want to learn Objective-C you can use QuickConnect instead.

This release, like RC 2, includes an installer.

It also includes support for embedding Google maps in your installable JavaScript application. This new functionallity, in addition to the previously added capabilities of GPS location, acceleration, JavaScript debugging in Xcode, device vibration and sound, etc., adds new power to your applications easily. All you need to do is make one JavaScript method call that includes the locations where you want a pin dropped and a description. The framework does the rest and your custom map is displayed.

Database access is just as easy. A wrapper for the SQLite database used natively on the iPhone is included in the framework. It supplies you with two methods, getData and setData, that are easily used to access and modify your data.

AJAX is also supported by a wrapper with getData and setData methods.

In addition, this installer will install QuickConnectMac. You can now quickly port your JavaScript application from your iPhone to a Mac. Most of this porting will consist of changing your HTML and CSS to fit the larger screen.

Also, QuickConnectPHP is included. This is an implementation of the QuickConnect framework in PHP. It allows you to create web applications quickly and easily using the same engineered approach that you use for your iPhone and Mac applications. It includes a MySQL wrapper that supplies both of the getData and setData methods as well.

November 21, 2008

QuickConnectiPhone installer available in Release Candidate 2

Posted in iPhone development tagged , , , , , , , , , , , , at 6:49 am by tetontech

I have just completed an installer for QuickConnectiPhone. You no longer need to copy the template directories to Xcode and Dashcode. The installer does it for you.
Download it
here.

This new version, Release Candidate 2, contains the installer as well as the examples found in RC1.

I hope this makes it easier to use.

June 28, 2008

iPhone Objective-C SQLite development

Posted in iPhone development tagged , , , , , , , , , , , , , , at 5:46 pm by tetontech

The code included here is now available in QuickConnectiPhone 1.1.3 and can be downloaded from the sourceforge repository. A 1.5 Beta 8 version is also available.  The Beta 8 version is much more flexible and stable than the simple code you see here.

I have been working on the Objective-C version of QuickConnect.  Included in it is a simple wrapper for interacting with the SQLite database.  QuickConnectOC will, when I have finished testing it, work for both the iPhone and for Mac applications.  Of course on a Mac you could use the CoreData Framework but this is not available, from what I can tell, as a framework for the iPhone.  

This SQLiteDataAccess class depends on Shawn Ericksons’ good work in creating an easy to use class for creating singletons in Objective-C, FTSWAbstractSingleton.

Since SQLiteDataAccess is a singleton, you can call it from anywhere in your code without passing pointers to it all over the place.  It is also thread safe for those who are creating multi-threaded apps.

Here is an example of me using it to retrieve some information from a database for an iPhone eBook application framework I am writing.

I have just refreshed the code on this page to include some bug fixes.

SQLiteDataAccess *theDatabase = [SQLiteDataAccess getInstance:@"data.sqlite" isWriteable:FALSE];
NSString* SQL = @"Select * from book_info";
DataAccessResult *aDAResult = [theDatabase getData:SQL withParameters:nil];
/*
* Retrieve the data from the DAResult and return it.
* You do not want to return the DAResult since that would tightly couple
* the database implementation to many other areas of the application.
*
* If you are going to use the error checking or the other information
* found in the DAResult object you need to use it here.
*/
//we are only interested in the first row. That is all there should be anyway.
NSArray *data = [[aDAResult results] objectAtIndex:0];
[aDAResult release];

As you can see it is simple to use.  When you want to retrieve information you use the ‘getData’ method and when you want to modify the database in any way you use the ‘setData’ method.  This is the same as the other QuickConnect DataAccess classes in the various languages and for various databases.  It is also the same API as when using the ServerAccessObject JavaScript class, an AJAX wrapper, in the QuickConnectiPhone framework.  

I am posting here the incomplete and only partially tested source code so that you can see how to use prepared statements, etc. with SQLite and Objective-C.  This code has only been tested for simple SQL statements that are not prepared statements or transactions at this time.  I expect that the current code is close to being ‘right’ but can’t guarantee it.  I expect to soon have it tested to a degree that I am more comfortable with.

When I am more confident in the code I will post it as part of QuickConnectOC on the QuickConnect sourceForge web site.

When complete it will also include such items as helper functions that return the auto-generated id for calls that INSERT INTO tables with auto-incrementing id fields, etc.

Header File

 
// SQLiteDataAccess.h

/*
Copyright 2008 Lee S. Barney

This file is part of QuickConnectOC.

QuickConnectOC is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

QuickConnectOC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with QuickConnectOC. If not, see .

*/

#import
#import
#import "DataAccessResult.h"
#import "FTSWAbstractSingleton.h"

@interface SQLiteDataAccess : FTSWAbstractSingleton {
// Opaque reference to the SQLite database.
sqlite3 *database;
// Opaque reference to the dictionary that maps strings to binding function names
NSDictionary *bindTypeDictionary;
}

- (DataAccessResult*)getData:(NSString*)SQL withParameters:(NSArray*)parameters;
- (DataAccessResult*)setData:(NSString*)SQL withParameters:(NSArray*)parameters;
- (DataAccessResult*)startTransaction;
- (void)endTransaction;
- (void)rollback;
- (void)close;

+ (SQLiteDataAccess*)getInstance: (NSString*) dbName isWriteable: (BOOL) isWriteable;

 

 

 

 

@end
Implementation file
// SQLiteDataAccess.m

/*
Copyright 2008 Lee S. Barney

This file is part of QuickConnectOC.

QuickConnectOC is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

QuickConnectOC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with QuickConnectOC. If not, see .

*/

#import "SQLiteDataAccess.h"
#import "QCParameter.h"

// Private interface for AppDelegate - internal only methods.
@interface SQLiteDataAccess (Private)
- (DataAccessResult*)dbAccess:(NSString*)SQL withParameters:(NSArray*)parameters treatAsChangeData:(BOOL)treatAsChangeData;
//internal bind methods
- (int) bind_blob:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_double:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_int:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_text:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_zeroblob:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_null:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
/*
* private initialization method
*/
- (SQLiteDataAccess*)initWithDatabase: (NSString*) dbName isWriteable: (BOOL) isWriteable;

@end

// SQLiteDataAccess.m

/*
Copyright 2008 Lee S. Barney

This file is part of QuickConnectOC.

QuickConnectAJAX is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

QuickConnectAJAX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with QuickConnectAJAX. If not, see .

*/

#import "SQLiteDataAccess.h"
#import "QCParameter.h"

// Private interface for AppDelegate - internal only methods.
@interface SQLiteDataAccess (Private)
- (DataAccessResult*)dbAccess:(NSString*)SQL withParameters:(NSArray*)parameters treatAsChangeData:(BOOL)treatAsChangeData;
//internal bind methods
- (int) bind_blob:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_double:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_int:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_text:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_zeroblob:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
- (int) bind_null:(sqlite3_stmt*)statement withIndex:(int) withBindVariable:(id)aVariable;
/*
* private initialization method
*/
- (SQLiteDataAccess*)initWithDatabase: (NSString*) dbName isWriteable: (BOOL) isWriteable;

@end

@implementation SQLiteDataAccess

/*
* static method to implement singleton pattern
*/
+ (SQLiteDataAccess*)getInstance: (NSString*) dbName isWriteable:(BOOL)isWriteable{
/*SQLiteDataAccess* mySelf = [self singleton];
return [mySelf initWithDatabase:dbName isWriteable:isWriteable];
*/
//since this line is declared static it will only be executed once.
static SQLiteDataAccess *mySelfSQLiteDA = nil;

@synchronized([SQLiteDataAccess class]) {
if (mySelfSQLiteDA == nil) {
mySelfSQLiteDA = [SQLiteDataAccess singleton];
mySelfSQLiteDA = [mySelfSQLiteDA initWithDatabase:dbName isWriteable:isWriteable];
}
}
return mySelfSQLiteDA;
}
- (SQLiteDataAccess*)initWithDatabase: (NSString*) dbName isWriteable: (BOOL) isWriteable{
//if (self = [super init]) {
NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"data.sqlite"];
if(isWriteable){

// The application ships with a default database in its bundle. If anything in the application
// bundle is altered, the code sign will fail. We want the database to be editable by users,
// so we need to create a copy of it in the application's Documents directory.

BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"data.sqlite"];
NSLog(writableDBPath);
success = [fileManager fileExistsAtPath:writableDBPath];
if (!success){
// The writable database does not exist, so copy the default to the appropriate location.
success = [fileManager copyItemAtPath:path toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
return nil;
}
}
path = writableDBPath;
}
sqlite3 *aDatabase;
NSLog(@"path: %@",path);
if (sqlite3_open([path UTF8String], &aDatabase) == SQLITE_OK) {
NSLog(@"database opened");
self->database = aDatabase;

NSLog(@"assigned");
//create the dictionary that maps parameter types to bind method calls
NSArray *keys = [NSArray arrayWithObjects:@"b", @"d", @"i", @"i63", @"t", @"t16", @"z", @"nil",nil];
NSLog(@"keys");
NSArray *values = [NSArray arrayWithObjects:@"bind_blob:withIndex:withBindVariable", @"bind_double:withIndex:withBindVariable",
@"bind_int:withIndex:withBindVariable", @"bind_int64:withIndex:withBindVariable",
@"bind_text:withIndex:withBindVariable", @"bind_text16:withIndex:withBindVariable",
@"bind_zeroblob:withIndex:withBindVariable", @"bind_null:withIndex:withBindVariable", nil];

NSLog(@"keys and objects ready");
NSDictionary *aDictionary = [NSDictionary dictionaryWithObjects:values forKeys:keys];

NSLog(@"dictionary ready");
self->bindTypeDictionary = aDictionary;
NSLog(@"dictionary set");
NSLog(@"successfully loaded database");
return self;
}
else{
//since we failed to open the database completely close it down to make sure that everyting is cleaned up
sqlite3_close(aDatabase);
NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(aDatabase));
}
//}
return nil;
}

- (DataAccessResult*)getData:(NSString*)SQL withParameters:(NSArray*)parameters{
NSLog(@"getting data");
return [self dbAccess:SQL withParameters:parameters treatAsChangeData:FALSE];
}

- (DataAccessResult*)setData:(NSString*)SQL withParameters:(NSArray*)parameters{
return [self dbAccess:SQL withParameters:parameters treatAsChangeData:TRUE];
}

- (DataAccessResult*)dbAccess:(NSString*)SQL withParameters:(NSArray*)parameters treatAsChangeData:(BOOL)treatAsChangeData{
NSLog(@"in dbAccess");
DataAccessResult *theResult;
theResult = [DataAccessResult alloc];
if(parameters != nil && [parameters count] > 0){
//make sure the the number of parameters is equal to the number of qestion marks in the SQL string
}
NSMutableArray* results = [[NSMutableArray alloc] initWithCapacity:0];
int numResultColumns = 0;
sqlite3_stmt *statement = nil; // Preparing a statement compiles the SQL query into a byte-code program in the SQLite library.
// The third parameter is either the length of the SQL string or -1 to read up to the first null terminator.
const char* SQLChar = [SQL UTF8String];
NSLog(@"about to prepare %@",SQL);
if (sqlite3_prepare_v2(database, SQLChar, -1, &statement, NULL) == SQLITE_OK) {
if(!treatAsChangeData){
NSLog(@"columns not changing");
//retrieve the number of columns in the result of the execution of the select statement
numResultColumns = sqlite3_column_count(statement);
NSLog(@"numRecentColumns: %i",numResultColumns);
NSMutableArray *fieldNames = [[NSMutableArray alloc] initWithCapacity:0];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for(int i = 0; i < numResultColumns; i++){
const char *name = sqlite3_column_name(statement, i);
NSString * columnName = [[NSString alloc]initWithCString:name encoding:NSUTF8StringEncoding];
[fieldNames addObject:columnName];
}
[theResult setFieldNames:fieldNames];

[pool release];
}
if(parameters != nil){
int numParams = [parameters count];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (int i = 0; i < numParams; i++) {
QCParameter *parameter = [parameters objectAtIndex:i];
NSString *name = [parameter name];
id value = [parameter value];
NSString *funcType = [bindTypeDictionary objectForKey:name];
SEL aSelector = NSSelectorFromString(funcType);
//bind the variables here
objc_msgSend(self, aSelector, statement, i, value);

}
[pool release];
}
NSMutableArray *results = [[NSMutableArray alloc] initWithCapacity:0];

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// We "step" through the results - once for each row.
// if the statement executed is not a select statement sqlite3_step will return SQLITE_DONE on the first iteration.
while (sqlite3_step(statement) == SQLITE_ROW) {
if([theResult columnTypes] == nil){
NSMutableArray *columnTypes = [[NSMutableArray alloc] initWithCapacity:0];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for(int i = 0; i < numResultColumns; i++){
NSNumber * columnType = [NSNumber numberWithInt:sqlite3_column_type(statement,i)];
[columnTypes addObject:columnType];
}
[theResult setColumnTypes:columnTypes];
[pool release];
}
NSMutableArray *row = [[NSMutableArray alloc] initWithCapacity:numResultColumns];
/*
* Iterate over all of the columns. Determine their type and retrieve its value
* SQLITE_INTEGER
* SQLITE_FLOAT
* SQLITE_BLOB
* SQLITE_NULL
* SQLITE_TEXT
*/

for(int i = 0; i < numResultColumns; i++){
int type = [[[theResult columnTypes] objectAtIndex:i] intValue];
if(type == SQLITE_INTEGER){
NSLog(@"integer: %i",sqlite3_column_int(statement, i));
NSNumber *aNum = [[NSNumber alloc] initWithInt:sqlite3_column_int(statement, i)];
[row addObject:aNum];
}
else if(type == SQLITE_FLOAT){
NSLog(@"float");
NSNumber *aFloat = [[NSNumber alloc] initWithFloat:sqlite3_column_double(statement, i)];
[row addObject:aFloat];
}
else if(type == SQLITE_TEXT){
NSLog(@"text");
NSString *aText = [[NSString alloc]initWithCString:sqlite3_column_text(statement, i) encoding:NSASCIIStringEncoding];
[row addObject:aText];
}
else if(type == SQLITE_BLOB){
NSLog(@"blob");
NSData *aData = [[NSData alloc]dataWithBytes:sqlite3_column_blob(statement, i) length:sqlite3_column_bytes(statement,i)];
[row addObject:aData];

}
else{//if([[columnTypes objectAtIndex:i] intValue] == SQLITE_NULL){
[row addObject:@"null"];
}
}
[results addObject:row];
}
[pool release];
[theResult setResults:results];
}
else{
NSString *error;
error = [[NSString alloc]initWithCString:sqlite3_errmsg(database) encoding:NSASCIIStringEncoding];
[theResult setErrorDescription:error];
[error release];
}
// "Finalize" the statement - releases the resources associated with the statement.
sqlite3_finalize(statement);

return theResult;
}

- (DataAccessResult*)startTransaction{
NSString* sql = @"BEGIN EXCLUSIVE TRANSACTION";
return [self setData:sql withParameters:nil];
}
- (void)endTransaction{
NSString* sql = @"COMMIT";
[self setData:sql withParameters:nil];

}
- (void)rollback{
NSString* sql = @"ROLLBACK";
[self setData:sql withParameters:nil];
}

- (void)close{
if (sqlite3_close(database) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to close database with message '%s'.", sqlite3_errmsg(database));
}
}

// internal bind methods

- (int) bind_blob:(sqlite3_stmt*)statement withIndex:(int)parameterIndex withBindVariable:(NSData*)aVariable{

if (![aVariable respondsToSelector:@selector(lengthOfBytes:)]) {
return -1;
}
//by default have the library make a copy, SQLITE_TRANSIENT, since we don't know if the variable may be changed
//by something else in the application.
return sqlite3_bind_blob(statement, parameterIndex, aVariable, [aVariable length], SQLITE_TRANSIENT);
}
- (int) bind_double:(sqlite3_stmt*)statement withIndex:(int)parameterIndex withBindVariable:(double)aVariable{
return sqlite3_bind_double(statement, parameterIndex, aVariable);
}
- (int) bind_int:(sqlite3_stmt*)statement withIndex:(int)parameterIndex withBindVariable:(int)aVariable{
return sqlite3_bind_int(statement, parameterIndex, aVariable);
}
- (int) bind_text:(sqlite3_stmt*)statement withIndex:(int)parameterIndex withBindVariable:(id)aVariable{
//assume an ASCII string
return sqlite3_bind_blob(statement, parameterIndex, aVariable, [aVariable lengthOfBytesUsingEncoding:NSASCIIStringEncoding], SQLITE_TRANSIENT);

}
- (int) bind_zeroblob:(sqlite3_stmt*)statement withIndex:(int)parameterIndex withBindVariable:(int)aVariable{
return sqlite3_bind_zeroblob(statement, parameterIndex, aVariable);
}
- (int) bind_null:(sqlite3_stmt*)statement withIndex:(int)parameterIndex withBindVariable:(id)aVariable{
return sqlite3_bind_null(statement, parameterIndex);
}

@end

May 29, 2008

iPhone hybrid UIWebView applications can now use the SQLite database

Posted in iPhone development tagged , , , , , , at 10:17 pm by tetontech

It works! The latest beta (6) of the iPhone OS includes the ability to use the SQLite database from JavaScript. This is the last step required to begin to create standalone applications on the iPhone written completely in HTML, CSS, and JavaScript. These are not web applications. These are fully fledged applications in their own right. You no longer need to know how to write Objective-C in order to create standalone applications.

You can now store the current state of you application on exiting and restore it when the application is started up again. This will allow you to use the links that start the Calendar, Contacts, music, videos, etc. When such a link is selected you app is exited and the other one started. You then exit that app and start yours again. Prior to this database fix your application could not restore its’ state at startup.

The source code for the library that does this is to large to place here as an example but a followup posting will include an example of how to easily access and use the database functionality built into WebKit. If you go to the QuickConnectiPhone download you can get an Xcode and Dashcode project that includes sample code. They show how to interact with the database easily without knowing the unique requirements of SQLite.

for an explanation of these projects and what the QuickConnectiPhone framework is see my previous post.

May 24, 2008

Handling very large integers in Erlang

Posted in erlang development tagged , , , , , , , , , , at 5:03 pm by tetontech

As mentioned in a previous post, Erlang appears to handle very large integers whose limit is RAM and other hardware limitations of the machine. In fact I have calculated 50,000! several times on my machine.
Multiplication, subtraction, and addition all work with these numbers without any programmer interference in Erlang. Division and other functionality uses the underlying OS functionality and so do not work with these large numbers.
I have written some code that allows division to work with these large numbers as well as a few other items such as m_choose_n, factorial, and floor. I have not spent time to evaluate speed optimizations for the code other than to use bit shifting to handle the actual division.
The division functions are:

  1. big_rem – similar to mod. It returns only the remainder of the division
  2. big_div_with_rem – returns both an integer quotient and remainder
  3. big_divide – returns a floating point value if it is possible to calculate it or an integer quotient and remainder if it is not possible

The code below is part of my simulation engine written in Erlang and is used in conjunction with the sim_dist library that contains random number distribution streams such as normal, binomial, negative binomial, and other types of streams the code for which will become available on sourceforge when I have finished testing it.
%% Copyright 2008 Lee S. Barney

%% This file is part of erl_sim.

%% erl_sim is free software: you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as published by
%% the Free Software Foundation, either version 3 of the License, or
%% (at your option) any later version.
%%
%% erl_sim is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%% GNU Lesser General Public License for more details.
%%
%% You should have received a copy of the GNU Lesser General Public License
%% along with QuickConnectiPhoneHybrid. If not, see http://www.gnu.org/licenses/.
%% Description: This file contains functions for doing division with very large numbers as well as some other
%% useful functions
-module(sim_math).

%%
%% Include files
%%

%%
%% Exported Functions
%%
-export([big_divide/2, big_div_with_rem/2, big_rem/2, floor/1,
factorial/1, m_choose_n/2]).

%%
%% API Functions
%%

%%
%% TODO: Add description of div_with_rem/function_arity
%%
big_div_with_rem(Dividend, Divisor) ->
if
Divisor /= 0 ->
{ok,New_divisor,Cnt} = count_div_shifts(abs(Dividend), abs(Divisor), 0),
case big_div_with_rem_helper(abs(Dividend), abs(New_divisor),Cnt,0) of
{ok, Quotient, Remainder} when (Dividend < 0) xor (Divisor
{ok,-Quotient,-Remainder};
{ok, Quotient, Remainder} ->
{ok, Quotient, Remainder};
{error,Why} ->
{error,Why};
true ->
{error,"Unknown error"}
end;
true ->
{error,"Division by Zero error"}
end.

%%
%% TODO: Add description of big_divide/function_arity
%%
big_divide(Dividend, Divisor)->
%double limit. Erlang uses underlying system algorithms for floating point mathematics
Limit = math:pow(2,1023),
case big_div_with_rem(Dividend, Divisor) of
{ok,Quotient,Remainder} ->
if
Remainder == 0 ->
{ok, Quotient};

%the quotient must be less than the limit or else and error will happen
%when the result floating point value is added to it
%the remainder and the divisor must be less than the limit or else the
%division will fail.

Remainder < Limit andalso Divisor < Limit andalso Quotient
Result = Remainder/abs(Divisor),
io:format("Remainder/Divisor:~p Quotient:~p~n",[Result,Quotient]),
{ok, Quotient+Result};
true ->
{ok, Quotient,Remainder}
end;
{error,Why} ->
{error,Why}
end.

%%
%% TODO: Add description of big_rem/function_arity
%%
big_rem(A, B) ->
if
B /= 0 ->
{ok,New_divisor,Cnt} = count_div_shifts(abs(A), abs(B), 0),
case big_div_with_rem_helper(abs(A), abs(New_divisor),Cnt,0) of
{ok, Quotient, Remainder} when (A < 0) xor (B
{ok,-Remainder};
{ok, Quotient, Remainder} ->
{ok, Remainder};
{error,Why} ->
{error,Why};
true ->
{error,"Unknown error"}
end;
true ->
{error,"Division by Zero error"}
end.

%%
%% TODO: Add description of floor/function_arity
%%
floor(X) ->
T = trunc(X),
case X - T T - 1;
false -> T
end.

%factorial of N

factorial(N) ->
fact_helper(N, 1).

fact_helper(0, Product) ->
Product;
fact_helper(1, Product) ->
Product;
fact_helper(N, Product) ->
%io:format("N: ~p Product: ~p~n",[N, Product]),
fact_helper(N - 1, Product * N).

m_choose_n(M,N) ->
if
N > M orelse N < 0 orelse M 0;
true ->
factorial(M)/(factorial(N)*factorial(M-N))
end.

%%
%% Local Functions
%%
big_div_with_rem_helper(Dividend, Divisor, Count, Quotient) ->
%io:format("Dividend:~p Divisor:~p Count:~p~n",[Dividend, Divisor, Count, Quotient]),
if
Count
{ok, Quotient, Dividend};
true ->
if
Divisor =
big_div_with_rem_helper(Dividend-Divisor, Divisor bsr 1, Count-1, (Quotient bsl 1) +1);
true ->
big_div_with_rem_helper(Dividend, Divisor bsr 1, Count -1, Quotient bsl 1)
end
end.

count_div_shifts(Dividend, Divisor, Cnt) ->
if
Divisor =
count_div_shifts(Dividend, Divisor bsl 1, Cnt+1);
true ->
{ok,Divisor bsr 1, Cnt -1}
end.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: