2012年12月21日星期五

C++ Check File Exists

Check whether a file exists:


#include <sys/stat.h>
// Function: fileExists
/**
    Check if a file exists
@param[in] filename - the name of the file to check

@return    true if the file exists, else false

*/
bool fileExists(const std::string& filename)
{
    struct stat buf;
    if (stat(filename.c_str(), &buf) != -1)
    {
        return true;
    }
    return false;
}

Not sure whether it works on all platforms.

Source:StackOverFlow

C++ Split String

Making some cross-platform stuffs and shifted back to C++ recently.
Trying to do something like NSString's componentsSeparatedByString function in C++.

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}


in the while loop, add those string into an array and return it back can do similiar job.

ref:cpluscplus.com

2012年7月24日星期二

"UPSERT " - Update or Insert in Sqlite

"INSERT OR REPLACE" is NOT equal to "UPDATE IF EXIST ,ELSE INSERT"
Since REPLACE is actually and "delete + create" action, not update.
Users need to insert values for ALL columns.

This thread on StackOverFlow provided a better solution to this issue.

Using UPDATE OR REPLACE together with SELECT and coalesce is an alternative to it.

2012年7月23日星期一

Little Trick for Multiple Sql Commands by FMDB

Just consumed an hour for debugging a "fault" caused by putting a NSString contain multiple sql commands into a FMDB executeUpdate: function.

A question on StackOverFlow stated that FMDB doesn't support multiple commands in a single executeUpdate: call and I testified it by reading the code of FMDB.


Here is a little trick to do so:


    FMDatabase *db_ = [[FMDatabase alloc] initWithPath:yourPath];

    [db_ open];

    [db_ beginTransaction];
    
    NSArray *sqlCommands = [DATABASE_TEMPLATE componentsSeparatedByString:@";"];
    for (NSString *sql in sqlCommands)
    {
        [db_ executeUpdate:sql];
    }
    
    return [db_ commit];


It is particularly useful when creating many tables, and the string may come from some data files.

2012年7月20日星期五

Installing SqlCipher, a Sqlite Encryption Tool, on Mac


Sqlite database file can be encrypted with the sqlite extension - SqlCipher
(Official encryption extension cost USD$2000)

SqlCipher is an open source project, could be cloned on git.
It is cross-platform and could be built on Unix/Linux/iOS/Android (and Windows?) since it is written by C.
Used some time to figure out what is going on, since I am not familiar with building terminal shell library. Writing it down should help me a lot in future.

The official iOS/Xcode tutorial is good enough for making it works, but it suggests to add sub-projects to the project which need its features that I think is not really necessary in my case, since this would need a much larger compile time when I clean-build my project.
After building the library files, just add them to my own project is fine.

However, I need command line support for convenience purpose.
It took me some time to install the command line sqlite3 with sqlcipher.

The description in the README of the git directory stated that:


This directory contains source code to 

    SQLite: An Embeddable SQL Database Engine

To compile the project, first create a directory in which to place
the build products.  It is recommended, but not required, that the
build directory be separate from the source directory.  Cd into the
build directory and then from the build directory run the configure
script found at the root of the source tree.  Then run "make".

For example:

    tar xzf sqlite.tar.gz    ;#  Unpack the source tree into "sqlite"
    mkdir bld                ;#  Build will occur in a sibling directory
    cd bld                   ;#  Change to the build directory
    ../sqlite/configure      ;#  Run the configure script
    make                     ;#  Run the makefile.
    make install             ;#  (Optional) Install the build products




My method is making a new folder named "bld ".
and type
"../sqlcipher-sqlcipher/configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="-lcrypto""
"make"
"sudo make install"

 in Terminal.

And then go to /usr/local/bin, there would hv a newly built "sqlite3" file.
To use it directly in the Terminal, copy it to usr/bin (for safety, backup ur old version of sqlite3)


After that, you should see the version of sqlite version is updated and the sqlciper_export() function is supported.

2012年6月26日星期二

Protocol in Extension in Objective C

For cases that a class should implement a Protocol (Interface in some other languages), but may not favorable to be seen by all the class.
A solution could be implementing the protocol at the Category declaration.

For example, I wanna implement the NSXMLParserDelegate in a class but just want the selectors to be
called as delegate.

at .h declaration:
@interface ClassName : NSObject
{
    //sth.....
}
@end

at .m file (or other .h file in some cases) declaring the extension:
@interface ClassName(NSXMLParserDelegate) <NSXMLParserDelegate>
    //some function in the NSXMLParserDelegate protocol.....
@end

@implementation ClassName(NSXMLParserDelegate)
    //do sth...
@end

@implementation ClassName
    //.......
@end

Reference: Stackoverflow

Good UML/Diagram Tools

Just found a handy UML diagram tool on Chrome Web Store - Diagramly.
It is totally free and support syncing with google drive. May not be very professional one but is really amazing for normal use.


Xcode stuck at “Attaching to (app name)”

My project failed to launch after I added a folder reference with the same name as one of the Group of the project.
Xcode didn't prompt me for any errors, but after sometime when I run my app on the simulator the console showed "error: failed to attach to process id 0" to me.

This drove me crazy.
Becoz remove the folder reference doesn't work, and even I opened a new blank project with the same Product Name doesn't work.
I turned to restart my computer and Xcode, used a new Product Name for my new project, and added that folder reference with a different name.

This used almost 3 hours to fix that.......

reference: StackOverflow

2012年3月1日星期四

differiate iPhone and iPad programmatically

Used the old-skool method for more than a year to find out what the device is.

size_t size;
 // Set 'oldp' parameter to NULL to get the size of the data
 // returned so we can allocate appropriate amount of space
 sysctlbyname("hw.machine", NULL, &size, NULL, 0); 
 
 // Allocate the space to store name
 char *name = malloc(size);
 
 // Get the platform name
 sysctlbyname("hw.machine", name, &size, NULL, 0);
 
 // Place name into a string
 NSString *machine = [NSString stringWithCString:name encoding:NSUnicodeStringEncoding];
 
 // Done with this
 free(name);
 
 return machine;

but iOS App Programming Guide in fact got a more decent way to do this.

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
// The device is an iPad running iOS 3.2 or later.
}
else {
// The device is an iPhone or iPod touch.
}

2012年2月8日星期三

Objective-c MD5 file checksum

Can match with PHP "md5_file" function.

#import <CommonCrypto/CommonDigest.h>
@implementation NSData (MyExtensions)
- (NSString*)md5
{
    unsigned char result[16];
    CC_MD5( self.bytes, self.length, result );
    return [NSString stringWithFormat:
            @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            result[0], result[1], result[2], result[3], 
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]
            ];  
}
@end

Reference: StackOverFlow

For large files:
+(NSString*)fileMD5:(NSString*)path
{
 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
 if( handle== nil ) return @"ERROR GETTING FILE MD5"; // file didnt exist
 
 CC_MD5_CTX md5;

 CC_MD5_Init(&md5);
 
 BOOL done = NO;
 while(!done)
 {
  NSData* fileData = [handle readDataOfLength: CHUNK_SIZE ];
  CC_MD5_Update(&md5, [fileData bytes], [fileData length]);
  if( [fileData length] == 0 ) done = YES;
 }
 unsigned char digest[CC_MD5_DIGEST_LENGTH];
 CC_MD5_Final(digest, &md5);
 NSString* s = [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
       digest[0], digest[1], 
       digest[2], digest[3],
       digest[4], digest[5],
       digest[6], digest[7],
       digest[8], digest[9],
       digest[10], digest[11],
       digest[12], digest[13],
       digest[14], digest[15]];
 return s;
}
Reference: iPhone Dev SDK