[Bug #21331] Prohibit modification during stlike loop
[ruby.git] / prism / util / pm_integer.h
bloba9e2966703408be962b2479817817b8afadacc0c
1 /**
2 * @file pm_integer.h
4 * This module provides functions for working with arbitrary-sized integers.
5 */
6 #ifndef PRISM_NUMBER_H
7 #define PRISM_NUMBER_H
9 #include "prism/defines.h"
10 #include "prism/util/pm_buffer.h"
12 #include <assert.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <stdlib.h>
17 /**
18 * A structure represents an arbitrary-sized integer.
20 typedef struct {
21 /**
22 * The number of allocated values. length is set to 0 if the integer fits
23 * into uint32_t.
25 size_t length;
27 /**
28 * List of 32-bit integers. Set to NULL if the integer fits into uint32_t.
30 uint32_t *values;
32 /**
33 * Embedded value for small integer. This value is set to 0 if the value
34 * does not fit into uint32_t.
36 uint32_t value;
38 /**
39 * Whether or not the integer is negative. It is stored this way so that a
40 * zeroed pm_integer_t is always positive zero.
42 bool negative;
43 } pm_integer_t;
45 /**
46 * An enum controlling the base of an integer. It is expected that the base is
47 * already known before parsing the integer, even though it could be derived
48 * from the string itself.
50 typedef enum {
51 /** The default decimal base, with no prefix. Leading 0s will be ignored. */
52 PM_INTEGER_BASE_DEFAULT,
54 /** The binary base, indicated by a 0b or 0B prefix. */
55 PM_INTEGER_BASE_BINARY,
57 /** The octal base, indicated by a 0, 0o, or 0O prefix. */
58 PM_INTEGER_BASE_OCTAL,
60 /** The decimal base, indicated by a 0d, 0D, or empty prefix. */
61 PM_INTEGER_BASE_DECIMAL,
63 /** The hexadecimal base, indicated by a 0x or 0X prefix. */
64 PM_INTEGER_BASE_HEXADECIMAL,
66 /**
67 * An unknown base, in which case pm_integer_parse will derive it based on
68 * the content of the string. This is less efficient and does more
69 * comparisons, so if callers know the base ahead of time, they should use
70 * that instead.
72 PM_INTEGER_BASE_UNKNOWN
73 } pm_integer_base_t;
75 /**
76 * Parse an integer from a string. This assumes that the format of the integer
77 * has already been validated, as internal validation checks are not performed
78 * here.
80 * @param integer The integer to parse into.
81 * @param base The base of the integer.
82 * @param start The start of the string.
83 * @param end The end of the string.
85 void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end);
87 /**
88 * Compare two integers. This function returns -1 if the left integer is less
89 * than the right integer, 0 if they are equal, and 1 if the left integer is
90 * greater than the right integer.
92 * @param left The left integer to compare.
93 * @param right The right integer to compare.
94 * @return The result of the comparison.
96 int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right);
98 /**
99 * Reduce a ratio of integers to its simplest form.
101 * If either the numerator or denominator do not fit into a 32-bit integer, then
102 * this function is a no-op. In the future, we may consider reducing even the
103 * larger numbers, but for now we're going to keep it simple.
105 * @param numerator The numerator of the ratio.
106 * @param denominator The denominator of the ratio.
108 void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator);
111 * Convert an integer to a decimal string.
113 * @param buffer The buffer to append the string to.
114 * @param integer The integer to convert to a string.
116 PRISM_EXPORTED_FUNCTION void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer);
119 * Free the internal memory of an integer. This memory will only be allocated if
120 * the integer exceeds the size of a single node in the linked list.
122 * @param integer The integer to free.
124 PRISM_EXPORTED_FUNCTION void pm_integer_free(pm_integer_t *integer);
126 #endif