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