Home | History | Annotate | Download | only in ufortune
      1 /**************************************************************************
      2 *
      3 *   Copyright (C) 2001-2006, International Business Machines
      4 *   Corporation and others.  All Rights Reserved.
      5 *
      6 ***************************************************************************
      7 *
      8 *   ufortune - An ICU resources sample program
      9 *
     10 *      Demonstrates
     11 *         Defining resources for use by an application
     12 *         Compiling and packaging them into a dll
     13 *         Referencing the resource-containing dll from application code
     14 *         Loading resource data using ICU's API
     15 *
     16 *      Created Nov. 7, 2001  by Andy Heninger
     17 *
     18 *      ufortune is a variant of the Unix "fortune" command, with
     19 *               ICU resources that contain the fortune-cookie sayings.
     20 *               Using resources allows  fortunes in different languages to
     21 *               be selected based on locale.
     22 */
     23 
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <time.h>
     28 
     29 #include "unicode/udata.h"     /* ICU API for data handling.                 */
     30 #include "unicode/ures.h"      /* ICU API for resource loading               */
     31 #include "unicode/ustdio.h"    /* ICU API for reading & writing Unicode data */
     32                                /*   to files, possibly including character   */
     33                                /*   set conversions.                         */
     34 #include "unicode/ustring.h"
     35 
     36 #ifndef UFORTUNE_NOSETAPPDATA
     37 /*
     38  *  Resource Data Reference.  The data is packaged as a dll (or .so or
     39  *           whatever, depending on the platform) that exports a data
     40  *           symbol.  The application (that's us) references that symbol,
     41  *           here, and will pass the data address to ICU, which will then
     42  *           be able to fetch resources from the data.
     43  */
     44 extern  const void U_IMPORT *fortune_resources_dat;
     45 #endif
     46 
     47 void u_write(const UChar *what, int len);
     48 
     49 
     50 /*
     51  *  main()   This one function is all of the application code.
     52  */
     53 int main(int argc, char **argv)
     54 {
     55     UBool              displayUsage  = FALSE;    /* Set true if command line err or help      */
     56                                                  /*   option was requested.                   */
     57     UBool              verbose       = FALSE;    /* Set true if -v command line option.       */
     58     char              *optionError   = NULL;     /* If command line contains an unrecognized  */
     59                                                  /*   option, this will point to it.          */
     60     char              *locale=NULL;              /* Locale name.  Null for system default,    */
     61                                                  /*   otherwise set from command line.        */
     62     const char *       programName   = argv[0];  /* Program invocation name.                  */
     63 
     64 
     65     UFILE             *u_stdout;                 /* Unicode stdout file.                      */
     66     UErrorCode         err           = U_ZERO_ERROR;   /* Error return, used for most ICU     */
     67                                                        /*   functions.                        */
     68 
     69     UResourceBundle   *myResources;              /* ICU Resource "handles"                    */
     70     UResourceBundle   *fortunes_r;
     71 
     72     int32_t            numFortunes;              /* Number of fortune strings available.      */
     73     int                i;
     74 
     75     const UChar       *resString;                /* Points to strings fetched from Resources. */
     76     int32_t            len;
     77 
     78 
     79     /*  Process command line options.
     80      *     -l  locale          specify a locale
     81      *     -v                  verbose mode.  Display extra messages.
     82      *     -? or --help        display a usage line
     83      */
     84     for (i=1; i<argc; i++) {
     85         if (strcmp(argv[i], "-l") ==0) {
     86             if (++i < argc) {
     87                 locale = argv[i];
     88             }
     89             continue;
     90         }
     91         if (strcmp(argv[i], "-v") == 0) {
     92             verbose = TRUE;
     93             continue;}
     94         if (strcmp(argv[i], "-?") == 0 ||
     95             strcmp(argv[i], "--help") == 0) {
     96             displayUsage = TRUE;
     97             continue;}
     98         optionError = argv[i];
     99         displayUsage = TRUE;
    100         break;
    101     }
    102 
    103     /* ICU's icuio package provides a convenient way to write Unicode
    104      *    data to stdout.  The string data that we get from resources
    105      *    will be UChar * strings, which icuio can handle nicely.
    106      */
    107     u_stdout = u_finit(stdout, NULL /*locale*/,  NULL /*codepage */);
    108     if (verbose) {
    109         u_fprintf(u_stdout, "%s:  checking output via icuio.\n", programName);
    110     }
    111 
    112 #ifndef UFORTUNE_NOSETAPPDATA
    113     /* Tell ICU where our resource data is located in memory.
    114      *   The data lives in the Fortune_Resources dll, and we just
    115      *   pass the address of an exported symbol from that library
    116      *   to ICU.
    117      */
    118     udata_setAppData("fortune_resources", &fortune_resources_dat, &err);
    119     if (U_FAILURE(err)) {
    120         fprintf(stderr, "%s: udata_setAppData failed with error \"%s\"\n", programName, u_errorName(err));
    121         exit(-1);
    122     }
    123 #endif
    124 
    125     /* Open our resources.
    126     */
    127     myResources = ures_open("fortune_resources", locale, &err);
    128     if (U_FAILURE(err)) {
    129         fprintf(stderr, "%s: ures_open failed with error \"%s\"\n", programName, u_errorName(err));
    130         exit(-1);
    131     }
    132     if (verbose) {
    133         u_fprintf(u_stdout, "status from ures_open(\"fortune_resources\", %s) is %s\n",
    134             locale? locale: " ", u_errorName(err));
    135     }
    136 
    137     /*
    138      * Display any command line option usage errors and/or the
    139      *     usage help message.  These messages come from our resource bundle.
    140      */
    141     if (optionError != NULL) {
    142         const UChar *msg = ures_getStringByKey(myResources, "optionMessage", &len, &err);
    143         if (U_FAILURE(err)) {
    144             fprintf(stderr, "%s: ures_getStringByKey(\"optionMessage\") failed, %s\n",
    145                 programName, u_errorName(err));
    146             exit(-1);
    147         }
    148         u_file_write(msg,  len, u_stdout);              /* msg is UChar *, from resource    */
    149         u_fprintf(u_stdout, " %s\n", optionError);      /* optionError is char *, from argv */
    150     }
    151 
    152     if (displayUsage) {
    153         const UChar *usage;
    154         int          returnValue=0;
    155 
    156         usage = ures_getStringByKey(myResources, "usage", &len, &err);
    157         if (U_FAILURE(err)) {
    158             fprintf(stderr, "%s: ures_getStringByKey(\"usage\") failed, %s\n", programName, u_errorName(err));
    159             exit(-1);
    160         }
    161         u_file_write(usage,  len, u_stdout);
    162         if (optionError != NULL) {returnValue = -1;}
    163         return returnValue;
    164     }
    165 
    166     /*
    167      * Open the "fortunes" resources from within the already open resources
    168      */
    169     fortunes_r = ures_getByKey(myResources, "fortunes", NULL, &err);
    170     if (U_FAILURE(err)) {
    171         fprintf(stderr, "%s: ures_getByKey(\"fortunes\") failed, %s\n", programName, u_errorName(err));
    172         exit(-1);
    173     }
    174 
    175 
    176     /*
    177      * Pick up and display a random fortune
    178      *
    179      */
    180     numFortunes = ures_countArrayItems(myResources, "fortunes", &err);
    181     if (U_FAILURE(err)) {
    182         fprintf(stderr, "%s: ures_countArrayItems(\"fortunes\") failed, %s\n", programName, u_errorName(err));
    183         exit(-1);
    184     }
    185     if (numFortunes <= 0) {
    186         fprintf(stderr, "%s: no fortunes found.\n", programName);
    187         exit(-1);
    188     }
    189 
    190     i = (int)time(NULL) % numFortunes;    /*  Use time to pick a somewhat-random fortune.  */
    191     resString = ures_getStringByIndex(fortunes_r, i, &len, &err);
    192     if (U_FAILURE(err)) {
    193         fprintf(stderr, "%s: ures_getStringByIndex(%d) failed, %s\n", programName, i, u_errorName(err));
    194         exit(-1);
    195     }
    196 
    197     u_file_write(resString, len, u_stdout);      /* Write out the message           */
    198 	u_fputc(0x0a, u_stdout);                     /*   and a trailing newline	    */
    199 
    200     return 0;
    201 }
    202 
    203