OSDN Git Service

Some code refactoring.
[mhash384/mhash384.git] / src / utilities.h
1 /* ---------------------------------------------------------------------------------------------- */
2 /* MHash-384 - Example application (utility functions)                                            */
3 /* Copyright(c) 2016 LoRd_MuldeR <mulder2@gmx.de>                                                 */
4 /*                                                                                                */
5 /* Permission is hereby granted, free of charge, to any person obtaining a copy of this software  */
6 /* and associated documentation files (the "Software"), to deal in the Software without           */
7 /* restriction, including without limitation the rights to use, copy, modify, merge, publish,     */
8 /* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the  */
9 /* Software is furnished to do so, subject to the following conditions:                           */
10 /*                                                                                                */
11 /* The above copyright notice and this permission notice shall be included in all copies or       */
12 /* substantial portions of the Software.                                                          */
13 /*                                                                                                */
14 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING  */
15 /* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND     */
16 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   */
17 /* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
18 /* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        */
19 /* ---------------------------------------------------------------------------------------------- */
20
21 #ifndef MHASH_CLI_UTILS_INCLUDED
22 #define MHASH_CLI_UTILS_INCLUDED
23
24 /*Enable large files*/
25 #define __USE_LARGEFILE64 1
26
27 /*Includes*/
28 #include "compat.h"
29 #include "sysinfo.h"
30
31 /*CRT includes*/
32 #include <stdio.h>
33 #include <sys/stat.h>
34 #include <signal.h>
35
36 /*Hash size*/
37 #ifdef __cplusplus
38 static const uint16_t HASH_LENGTH = mhash_384::MHash384::HASH_LEN;
39 #else
40 static const uint16_t HASH_LENGTH = MHASH_384_LEN;
41 #endif
42
43 /*Parameters*/
44 typedef struct param_t
45 {
46         const CHAR *filename;
47         int enable_bench;
48         int show_progress;
49         int test_mode;
50         int use_upper_case;
51 }
52 param_t;
53
54 /*Version*/
55 typedef struct version_t
56 {
57         uint16_t major;
58         uint16_t minor;
59         uint16_t patch;
60 }
61 version_t;
62
63 /*Get version*/
64 static version_t get_version(void)
65 {
66         version_t version_info;
67 #ifdef __cplusplus
68         mhash_384::MHash384::version(version_info.major, version_info.minor, version_info.patch);
69 #else
70         version_info.major = MHASH_384_VERSION_MAJOR;
71         version_info.minor = MHASH_384_VERSION_MINOR;
72         version_info.patch = MHASH_384_VERSION_PATCH;
73 #endif
74         return version_info;
75 }
76
77 /*The logo*/
78 static void print_logo(void)
79 {
80         const version_t version = get_version();
81         fprintf(stderr, "\nMHash384 v%u.%u.%u, simple fast portable header-only hashing library [%s]\n", version.major, version.minor, version.patch, __DATE__);
82         fprintf(stderr, "Copyright(c) 2016 LoRd_MuldeR <mulder2@gmx.de>, released under the MIT License.\n\n");
83 }
84
85 /*File name suffix*/
86 #ifdef _WIN32
87 #define EXE_SUFFIX ".exe"
88 #else
89 #define EXE_SUFFIX ""
90 #endif
91
92 /*Print help screen*/
93 static void print_help(void)
94 {
95         fprintf(stderr, "Built with " COMPILER_TYPE " v%u.%u.%u on " SYSTEM_TYPE " [" COMPILER_ARCH "]\n\n", COMPILER_VERS_MAJOR, COMPILER_VERS_MINOR, COMPILER_VERS_PATCH);
96         fprintf(stderr, "Usage:\n");
97         fprintf(stderr, "  mhash384" EXE_SUFFIX " [options] [input_file]\n\n");
98         fprintf(stderr, "Options:\n");
99         fprintf(stderr, "  -p, --progress  show progress while processing\n");
100         fprintf(stderr, "  -u, --upper     print digest in upper case letters\n");
101         fprintf(stderr, "  -b, --bench     compute and print throughput\n");
102         fprintf(stderr, "  -v, --version   print the version string and exit\n");
103         fprintf(stderr, "  -t, --test      execute self-test and exit\n");
104         fprintf(stderr, "  -h, --help      print this help screen and exit\n\n");
105         fprintf(stderr, "If no input file is specified, input will be read from STDIN.\n\n");
106 }
107
108 /*Parse arguments*/
109 static int parse_arguments(param_t *param, int argc, CHAR *argv[])
110 {
111         int i, stop = 0;
112         memset(param, 0, sizeof(param_t));
113         for (i = 1; i < argc; ++i)
114         {
115                 if (!stop)
116                 {
117                         if (!STRICMP(argv[i], T("--")))
118                         {
119                                 stop = 1;
120                                 continue;
121                         }
122                         else if (!STRICMP(argv[i], T("-b")) || !STRICMP(argv[i], T("--bench")))
123                         {
124                                 param->enable_bench = 1;
125                                 continue;
126                         }
127                         else if (!STRICMP(argv[i], T("-t")) || !STRICMP(argv[i], T("--test")))
128                         {
129                                 param->test_mode = 1;
130                                 continue;
131                         }
132                         else if (!STRICMP(argv[i], T("-p")) || !STRICMP(argv[i], T("--progress")))
133                         {
134                                 param->show_progress = 1;
135                                 continue;
136                         }
137                         else if (!STRICMP(argv[i], T("-u")) || !STRICMP(argv[i], T("--upper")))
138                         {
139                                 param->use_upper_case = 1;
140                                 continue;
141                         }
142                         else if (!STRICMP(argv[i], T("-h")) || !STRICMP(argv[i], T("--help")) || !STRICMP(argv[i], T("/?")))
143                         {
144                                 print_logo();
145                                 print_help();
146                                 return 0;
147                         }
148                         else if (!STRICMP(argv[i], T("-v")) || !STRICMP(argv[i], T("--version")))
149                         {
150                                 const version_t version = get_version();
151                                 printf("mhash-384 version %u.%u.%u (built %s)\n", version.major, version.minor, version.patch, __DATE__);
152                                 return 0;
153                         }
154                         else if ((argv[i][0] == T('-')) && (argv[i][1] != T('\0')))
155                         {
156                                 print_logo();
157                                 fprintf(stderr, "Unknown option:\n" FMT_S "\n\n", argv[i]);
158                                 return 0;
159                         }
160                 }
161                 if (!param->filename)
162                 {
163                         param->filename = argv[i];
164                 }
165                 else
166                 {
167                         print_logo();
168                         fprintf(stderr, "Excess argument:\n" FMT_S "\n\n", argv[i]);
169                         return 0;
170                 }
171         }
172         if (param->filename && (!STRICMP(param->filename, T("-"))) && (!stop))
173         {
174                 param->filename = NULL;
175         }
176         return 1;
177 }
178
179 /*file size*/
180 static uint64_t get_file_size(FILE *const file)
181 {
182         struct stat64 info;
183         if (fstat64(fileno(file), &info) || ((info.st_mode & S_IFMT) != S_IFREG))
184         {
185                 return 0;
186         }
187         return (uint64_t) info.st_size;
188 }
189
190 /*progress*/
191 static void print_progress(const uint64_t size_total, const uint64_t size_processed)
192 {
193         if (size_total)
194         {
195                 fprintf(stderr, "\r%.1f%% of %" PRIu64 " bytes processed...", ((double)size_processed) / ((double)size_total) * 100.0, size_total);
196         }
197         else
198         {
199                 fprintf(stderr, "\r%" PRIu64 " bytes processed...", size_processed);
200         }
201 }
202
203 /*print digest*/
204 #define PUT_HEX_CHAR(X,Y,Z) putchar(X[((Y) >> (Z)) & 0xFU])
205 static void print_digest(const uint8_t *const digest, const int uppercase)
206 {
207         static const char *const HEX_UPR = "0123456789ABCDEF";
208         static const char *const HEX_LWR = "0123456789abcdef";
209         const char *const hex = uppercase ? HEX_UPR : HEX_LWR;
210         uint16_t count;
211         for (count = 0; count < HASH_LENGTH; ++count)
212         {
213                 PUT_HEX_CHAR(hex, digest[count], 4);
214                 PUT_HEX_CHAR(hex, digest[count], 0);
215         }
216         printf("\n");
217 }
218
219 /*sigint handler*/
220 static volatile int g_interrupted = 0;
221 static void sigint_handler(int sig_no)
222 {
223         g_interrupted = 1;
224         signal(sig_no, sigint_handler);
225         fclose(stdin);
226 }
227
228 #endif /*MHASH_CLI_UTILS_INCLUDED*/