[docs] Enable documentation for utils.
[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  *
22  * @str: points to the first digit of the number
23  * @out: pointer to the variable that will receive the value
24  *
25  * Tries to extract a number from the passed string, taking in to account m, k
26  * and g suffixes
27  *
28  * Returns true if passing was successful
29  */
30 gboolean
31 mono_gc_parse_environment_string_extract_number (const char *str, size_t *out)
32 {
33         char *endptr;
34         int len = strlen (str), shift = 0;
35         size_t val;
36         gboolean is_suffix = FALSE;
37         char suffix;
38
39         if (!len)
40                 return FALSE;
41
42         suffix = str [len - 1];
43
44         switch (suffix) {
45                 case 'g':
46                 case 'G':
47                         shift += 10;
48                 case 'm':
49                 case 'M':
50                         shift += 10;
51                 case 'k':
52                 case 'K':
53                         shift += 10;
54                         is_suffix = TRUE;
55                         break;
56                 default:
57                         if (!isdigit (suffix))
58                                 return FALSE;
59                         break;
60         }
61
62         errno = 0;
63         val = strtol (str, &endptr, 10);
64
65         if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
66                         || (errno != 0 && val == 0) || (endptr == str))
67                 return FALSE;
68
69         if (is_suffix) {
70                 size_t unshifted;
71
72                 if (*(endptr + 1)) /* Invalid string. */
73                         return FALSE;
74
75                 unshifted = (size_t)val;
76                 val <<= shift;
77                 if (((size_t)val >> shift) != unshifted) /* value too large */
78                         return FALSE;
79         }
80
81         *out = val;
82         return TRUE;
83 }