• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*************************************************************************
2 *
3 *   © 2016 and later: Unicode, Inc. and others.
4 *   License & terms of use: http://www.unicode.org/copyright.html
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  */
50 extern  const void U_IMPORT *fortune_resources_dat;
51 #endif
52 
53 void u_write(const UChar *what, int len);
54 
55 
56 /*
57  *  main()   This one function is all of the application code.
58  */
main(int argc,char ** argv)59 int 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 = 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