[runtime] Cycle the finalizer thread if there are too many outstanding hazard pointer...
[mono.git] / mono / utils / parse.c
1 /*
2  * parse.c: Parsing for GC options.
3  *
4  * Copyright (C) 2015 Xamarin Inc
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License 2.0 as published by the Free Software Foundation;
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License 2.0 along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include <config.h>
21 #include <glib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <ctype.h>
25 #include <stdlib.h>
26
27 #include "parse.h"
28
29 /**
30  * mono_gc_parse_environment_string_extract_number:
31  *
32  * @str: points to the first digit of the number
33  * @out: pointer to the variable that will receive the value
34  *
35  * Tries to extract a number from the passed string, taking in to account m, k
36  * and g suffixes
37  *
38  * Returns true if passing was successful
39  */
40 gboolean
41 mono_gc_parse_environment_string_extract_number (const char *str, size_t *out)
42 {
43         char *endptr;
44         int len = strlen (str), shift = 0;
45         size_t val;
46         gboolean is_suffix = FALSE;
47         char suffix;
48
49         if (!len)
50                 return FALSE;
51
52         suffix = str [len - 1];
53
54         switch (suffix) {
55                 case 'g':
56                 case 'G':
57                         shift += 10;
58                 case 'm':
59                 case 'M':
60                         shift += 10;
61                 case 'k':
62                 case 'K':
63                         shift += 10;
64                         is_suffix = TRUE;
65                         break;
66                 default:
67                         if (!isdigit (suffix))
68                                 return FALSE;
69                         break;
70         }
71
72         errno = 0;
73         val = strtol (str, &endptr, 10);
74
75         if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
76                         || (errno != 0 && val == 0) || (endptr == str))
77                 return FALSE;
78
79         if (is_suffix) {
80                 size_t unshifted;
81
82                 if (*(endptr + 1)) /* Invalid string. */
83                         return FALSE;
84
85                 unshifted = (size_t)val;
86                 val <<= shift;
87                 if (((size_t)val >> shift) != unshifted) /* value too large */
88                         return FALSE;
89         }
90
91         *out = val;
92         return TRUE;
93 }