e5fc9c0efaec244715bb5c72a134787a48d2a3a4
[platform/upstream/fribidi.git] / bin / fribidi-benchmark.c
1 /* FriBidi
2  * fribidi-benchmark.c - command line benchmark tool for libfribidi
3  *
4  * Authors:
5  *   Behdad Esfahbod, 2001, 2002, 2004
6  *   Dov Grobgeld, 1999, 2000
7  *
8  * Copyright (C) 2004 Sharif FarsiWeb, Inc
9  * Copyright (C) 2001,2002 Behdad Esfahbod
10  * Copyright (C) 1999,2000 Dov Grobgeld
11  * 
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  * 
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  * 
22  * You should have received a copy of the GNU Lesser General Public License
23  * along with this library, in a file named COPYING; if not, write to the
24  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA
26  * 
27  * For licensing issues, contact <fribidi.license@gmail.com>.
28  */
29
30 #include <common.h>
31
32 #include <fribidi.h>
33 #include <fribidi-deprecated.h>
34
35 #include <stdio.h>
36 #ifdef STDC_HEADERS
37 # include <stdlib.h>
38 # include <stddef.h>
39 #else
40 # if HAVE_STDLIB_H
41 #  include <stdlib.h>
42 # endif
43 #endif
44 #ifdef HAVE_STRING_H
45 # if !STDC_HEADERS && HAVE_MEMORY_H
46 #  include <memory.h>
47 # endif
48 # include <string.h>
49 #endif
50 #ifdef HAVE_STRINGS_H
51 # include <strings.h>
52 #endif
53 #ifdef HAVE_SYS_TIMES_H
54 # include <sys/times.h>
55 #endif
56 #ifdef _WIN32
57 #include <windows.h>
58 #endif /* _WIN32 */
59
60 #include "getopt.h"
61
62 #define appname "fribidi_benchmark"
63
64 #define MAX_STR_LEN 1000
65 #define NUM_ITER 2000
66
67 static void
68 die2 (
69   const char *fmt,
70   const char *arg
71 )
72 {
73   fprintf (stderr, "%s: ", appname);
74   if (fmt)
75     fprintf (stderr, fmt, arg);
76   fprintf (stderr, "Try `%s --help' for more information.\n", appname);
77   exit (-1);
78 }
79
80 #define TEST_STRING \
81   "a THE QUICK -123,456 (FOX JUMPS ) DOG the quick !1@7#4&5^ over the dog " \
82   "123,456 OVER THE 5%+ 4.0 LAZY"
83 #define TEST_STRING_EXPLICIT \
84   "this is _LJUST_o a _lsimple _Rte%ST_o th_oat  HAS A _LPDF missing" \
85   "AnD hOw_L AbOuT, 123,987 tHiS_o a GO_oOD - _L_oTE_oST. " \
86   "here_L is_o_o_o _R a good one_o And _r 123,987_LT_oHE_R next_o oNE:" \
87   "_R_r and the last _LONE_o IS THE _rbest _lONE and" \
88   "a _L_L_L_LL_L_L_L_L_L_L_L_L_Rbug_o_o_o_o_o_o" \
89   "_R_r and the last _LONE_o IS THE _rbest _lONE and" \
90   "A REAL BIG_l_o BUG! _L _l_r_R_L_laslaj siw_o_Rlkj sslk" \
91   "a _L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_L_Rbug" \
92   "here_L is_o_o_o _R ab  one_o _r 123,987_LT_oHE_R t_o oNE:" \
93
94 static void
95 help (
96   void
97 )
98 {
99   printf
100     ("Usage: " appname " [OPTION]...\n"
101      "A program for benchmarking the speed of the " FRIBIDI_NAME
102      " library.\n" "\n"
103      "  -h, --help            Display this information and exit\n"
104      "  -V, --version         Display version information and exit\n"
105      "  -n, --niter N         Number of iterations. Default is %d.\n"
106      "\nReport bugs online at\n<" FRIBIDI_BUGREPORT ">.\n", NUM_ITER);
107   exit (0);
108 }
109
110 static void
111 version (
112   void
113 )
114 {
115   printf (appname " %s", fribidi_version_info);
116   exit (0);
117 }
118
119 static double
120 utime (
121   void
122 )
123 {
124 #ifdef _WIN32
125   FILETIME creationTime, exitTime, kernelTime, userTime;
126   HANDLE currentProcess = GetCurrentProcess();
127   if (GetProcessTimes(currentProcess, &creationTime, &exitTime, &kernelTime, &userTime))
128   {
129       unsigned __int64 myTime = userTime.dwHighDateTime;
130       myTime = (myTime << 32) | userTime.dwLowDateTime;
131       return 1e-7 * myTime;
132   }
133   else
134       return 0.0;
135 #else /* !_WIN32 */
136 #ifdef HAVE_SYS_TIMES_H
137   struct tms tb;
138   times (&tb);
139   return 0.01 * tb.tms_utime;
140 #else
141 #warning Please fill in here to use other functions for determining time.
142   return 0.0;
143 #endif
144 #endif
145 }
146
147 static void
148 benchmark (
149   const char *S_,
150   int niter
151 )
152 {
153   int len, i;
154   FriBidiChar us[MAX_STR_LEN], out_us[MAX_STR_LEN];
155   FriBidiStrIndex positionLtoV[MAX_STR_LEN], positionVtoL[MAX_STR_LEN];
156   FriBidiLevel embedding_list[MAX_STR_LEN];
157   FriBidiParType base;
158   double time0, time1;
159
160   {
161     int j;
162     len = strlen (S_);
163     for (i = 0, j = 0; i < len; i++)
164       {
165         if (S_[i] == '_')
166           switch (S_[++i])
167             {
168             case '>':
169               us[j++] = FRIBIDI_CHAR_LRM;
170               break;
171             case '<':
172               us[j++] = FRIBIDI_CHAR_RLM;
173               break;
174             case 'l':
175               us[j++] = FRIBIDI_CHAR_LRE;
176               break;
177             case 'r':
178               us[j++] = FRIBIDI_CHAR_RLE;
179               break;
180             case 'L':
181               us[j++] = FRIBIDI_CHAR_LRO;
182               break;
183             case 'R':
184               us[j++] = FRIBIDI_CHAR_RLO;
185               break;
186             case 'o':
187               us[j++] = FRIBIDI_CHAR_PDF;
188               break;
189             case '_':
190               us[j++] = '_';
191               break;
192             default:
193               us[j++] = '_';
194               i--;
195               break;
196             }
197         else
198           us[j++] = S_[i];
199         if (us[j] >= 'A' && us[j] <= 'F')
200           us[j] += FRIBIDI_CHAR_ARABIC_ALEF - 'A';
201         else if (us[j] >= 'G' && us[j] <= 'Z')
202           us[j] += FRIBIDI_CHAR_HEBREW_ALEF - 'G';
203         else if (us[j] >= '6' && us[j] <= '9')
204           us[j] += FRIBIDI_CHAR_ARABIC_ZERO - '0';
205       }
206     len = j;
207   }
208
209   /* Start timer */
210   time0 = utime ();
211
212   for (i = 0; i < niter; i++)
213     {
214       /* Create a bidi string */
215       base = FRIBIDI_PAR_ON;
216 FRIBIDI_BEGIN_IGNORE_DEPRECATIONS
217       if (!fribidi_log2vis (us, len, &base,
218                             /* output */
219                             out_us, positionVtoL, positionLtoV,
220                             embedding_list))
221         die2
222           ("something failed in fribidi_log2vis.\n"
223            "perhaps memory allocation failure.", NULL);
224 FRIBIDI_END_IGNORE_DEPRECATIONS
225     }
226
227   /* stop timer */
228   time1 = utime ();
229
230   /* output result */
231   printf ("Length = %d\n", len);
232   printf ("Iterations = %d\n", niter);
233   printf ("%d len*iterations in %f seconds\n", len * niter, time1 - time0);
234   printf ("= %.0f kilo.length.iterations/second\n",
235           1.0 * len * niter / 1000 / (time1 - time0));
236
237   return;
238 }
239
240 int
241 main (
242   int argc,
243   char *argv[]
244 )
245 {
246   int niter = NUM_ITER;
247
248   /* Parse the command line */
249   argv[0] = appname;
250   while (1)
251     {
252       int option_index = 0, c;
253       static struct option long_options[] = {
254         {"help", 0, 0, 'h'},
255         {"version", 0, 0, 'V'},
256         {"niter", 0, 0, 'n'},
257         {0, 0, 0, 0}
258       };
259
260       c = getopt_long (argc, argv, "hVn:", long_options, &option_index);
261       if (c == -1)
262         break;
263
264       switch (c)
265         {
266         case 0:
267           break;
268         case 'h':
269           help ();
270           break;
271         case 'V':
272           version ();
273           break;
274         case 'n':
275           niter = atoi (optarg);
276           if (niter <= 0)
277             die2 ("invalid number of iterations `%s'\n", optarg);
278           break;
279         case ':':
280         case '?':
281           die2 (NULL, NULL);
282           break;
283         default:
284           break;
285         }
286     }
287
288   printf ("* Without explicit marks:\n");
289   benchmark (TEST_STRING, niter);
290   printf ("\n");
291   printf ("* With explicit marks:\n");
292   benchmark (TEST_STRING_EXPLICIT, niter);
293
294   return 0;
295 }
296
297 /* Editor directions:
298  * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
299  */