[runtime] Fix DISABLE_REFLECTION_EMIT build.
[mono.git] / mono / utils / parse.c
1 /**
2  * \file
3  * Parsing for GC options.
4  *
5  * Copyright (C) 2015 Xamarin Inc
6  *
7  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <ctype.h>
15 #include <stdlib.h>
16
17 #include "parse.h"
18
19 /**
20  * mono_gc_parse_environment_string_extract_number:
21  * \param str points to the first digit of the number
22  * \param out pointer to the variable that will receive the value
23  * Tries to extract a number from the passed string, taking in to account m, k
24  * and g suffixes
25  * \returns TRUE if passing was successful
26  */
27 gboolean
28 mono_gc_parse_environment_string_extract_number (const char *str, size_t *out)
29 {
30         char *endptr;
31         int len = strlen (str), shift = 0;
32         size_t val;
33         gboolean is_suffix = FALSE;
34         char suffix;
35
36         if (!len)
37                 return FALSE;
38
39         suffix = str [len - 1];
40
41         switch (suffix) {
42                 case 'g':
43                 case 'G':
44                         shift += 10;
45                 case 'm':
46                 case 'M':
47                         shift += 10;
48                 case 'k':
49                 case 'K':
50                         shift += 10;
51                         is_suffix = TRUE;
52                         break;
53                 default:
54                         if (!isdigit (suffix))
55                                 return FALSE;
56                         break;
57         }
58
59         errno = 0;
60         val = strtol (str, &endptr, 10);
61
62         if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
63                         || (errno != 0 && val == 0) || (endptr == str))
64                 return FALSE;
65
66         if (is_suffix) {
67                 size_t unshifted;
68
69                 if (*(endptr + 1)) /* Invalid string. */
70                         return FALSE;
71
72                 unshifted = (size_t)val;
73                 val <<= shift;
74                 if (((size_t)val >> shift) != unshifted) /* value too large */
75                         return FALSE;
76         }
77
78         *out = val;
79         return TRUE;
80 }