Thotz/Thotz.html
 

NSString randomEnglishString

This method was created for an application that was never released. The various methods will either return a random, short English word, or a concatenation of several such words in “CamelCase”.  Note that there is no actual “randomEnglishString” method -- that is just a more descriptive title.

The original use was to create memorable filenames without user intervention: “DarkDance” or “DreamCost” is easier to recognize/remember than “134295” or some UUID gibberish. It could be used as the basis for part of a password generator (mix in some numerics and punctuation) or a code-word generator.

If being used on Tiger or later there is a lot of fiddling that can be removed from the randomization call. The word list supplied (“shortwords.txt”) has been human-filtered to avoid most unpleasant concatenations.

The seemingly peculiar line:

NSBundle * bundle = [NSBundle bundleForClass: [HKRandomEnglishString class]];

Isn’t as peculiar as it looks -- it lets this category and its resource file be included in a framework and still find the resource file easily.

This code depends on lines.

-------------- Interface -------------

(HKNSStringRandomEnglishString.h)


#import <Cocoa/Cocoa.h>


@interface NSString (RandomEnglishString)

+ (NSString *) randomCompositeString;

+ (NSString *) randomCompositeStringWithWordCount:(int) count;

+ (NSArray *) wordList;

+ (NSString *) randomEnglishWord;

+ (NSString *) wordlistFilename;


@end




-------------- Implementation -------------


#import "HKNSStringRandomEnglishString.h"


@interface HKRandomEnglishString: NSObject

{ // dummy, just to allow "BundleForClass" call

    

}

@end


@implementation HKRandomEnglishString

@end


@implementation NSString (RandomEnglishString)


static BOOL _random_is_initialized;


+ (NSString *) randomCompositeString

{

     return [self randomCompositeStringWithWordCount: 2];

}


+ (NSString *) randomCompositeStringWithWordCount:(int) count

{

     NSString * result = [NSString string];

     NSArray * words = [NSArray array];

     int ix;

     for(ix = 0; ix < count;)

          {

          NSString * word = [[self randomEnglishWord] capitalizedString];

          if(![words containsObject: word])

               {

               words = [words arrayByAddingObject: word];

               ++ix;

               }

          }

     result = [words componentsJoinedByString: @""];

     return result;

}


extern int opendev(char *, int, int, char **) __attribute__((weak_import));

extern u_int32_t arc4random(void) __attribute__((weak_import));


extern void srandomdev(void) __attribute__((weak_import));



+ (NSString *) randomEnglishWord

{

unsigned long randomNumber;

if(arc4random)

     {

     randomNumber = arc4random();

     }

else

     {

#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1030)


     if(!srandomdev)

          {

          NSLog(@"srandomdev is not available!");

          }

     if(srandomdev && !_random_is_initialized)

          {


          srandomdev();

          _random_is_initialized = YES;

          }

     else

#else

#warning srandomdev compiled out!

#endif

          {

          srandom((unsigned) [NSDate timeIntervalSinceReferenceDate]);

          _random_is_initialized = YES;

//         

          }

//#warning ignore the immediately following warning about random...

     if(random)

          { // checking for existance of random, ignore warning

          randomNumber = random(); // not rand() at least.

          }

     else

          {

          randomNumber = rand();

          }

     }

    

     NSArray * wordList = [self wordList];

     int count = [wordList count];

     int randomIndex = randomNumber % count;

     return [wordList objectAtIndex: randomIndex];

}


+ (NSArray *) wordList

{

static NSArray * result = nil;

if(!result)

     {

     NSBundle * bundle = [NSBundle bundleForClass: [HKRandomEnglishString class]];

     NSString * name = [self wordlistFilename];

     NSString * path = [bundle pathForResource: name ofType: nil];

     if(path)

          {

          NSString * words = [NSString stringWithContentsOfFile: path];

          if(words)

               {

               result = [[words lines] retain];

               }

          }    

     }

return result;

}


+ (NSString *) wordlistFilename

{

     return @"shortwords.txt";

}


@end