CS318 - Pintos
Pintos source browser for JHU CS318 course
stdlib.c
Go to the documentation of this file.
1 #include <ctype.h>
2 #include <debug.h>
3 #include <random.h>
4 #include <stdlib.h>
5 #include <stdbool.h>
6 
7 /** Converts a string representation of a signed decimal integer
8  in S into an `int', which is returned. */
9 int
10 atoi (const char *s)
11 {
12  bool negative;
13  int value;
14 
15  ASSERT (s != NULL);
16 
17  /* Skip white space. */
18  while (isspace ((unsigned char) *s))
19  s++;
20 
21  /* Parse sign. */
22  negative = false;
23  if (*s == '+')
24  s++;
25  else if (*s == '-')
26  {
27  negative = true;
28  s++;
29  }
30 
31  /* Parse digits. We always initially parse the value as
32  negative, and then make it positive later, because the
33  negative range of an int is bigger than the positive range
34  on a 2's complement system. */
35  for (value = 0; isdigit (*s); s++)
36  value = value * 10 - (*s - '0');
37  if (!negative)
38  value = -value;
39 
40  return value;
41 }
42 
43 /** Compares A and B by calling the AUX function. */
44 static int
45 compare_thunk (const void *a, const void *b, void *aux)
46 {
47  int (**compare) (const void *, const void *) = aux;
48  return (*compare) (a, b);
49 }
50 
51 /** Sorts ARRAY, which contains CNT elements of SIZE bytes each,
52  using COMPARE. When COMPARE is passed a pair of elements A
53  and B, respectively, it must return a strcmp()-type result,
54  i.e. less than zero if A < B, zero if A == B, greater than
55  zero if A > B. Runs in O(n lg n) time and O(1) space in
56  CNT. */
57 void
58 qsort (void *array, size_t cnt, size_t size,
59  int (*compare) (const void *, const void *))
60 {
61  sort (array, cnt, size, compare_thunk, &compare);
62 }
63 
64 /** Swaps elements with 1-based indexes A_IDX and B_IDX in ARRAY
65  with elements of SIZE bytes each. */
66 static void
67 do_swap (unsigned char *array, size_t a_idx, size_t b_idx, size_t size)
68 {
69  unsigned char *a = array + (a_idx - 1) * size;
70  unsigned char *b = array + (b_idx - 1) * size;
71  size_t i;
72 
73  for (i = 0; i < size; i++)
74  {
75  unsigned char t = a[i];
76  a[i] = b[i];
77  b[i] = t;
78  }
79 }
80 
81 /** Compares elements with 1-based indexes A_IDX and B_IDX in
82  ARRAY with elements of SIZE bytes each, using COMPARE to
83  compare elements, passing AUX as auxiliary data, and returns a
84  strcmp()-type result. */
85 static int
86 do_compare (unsigned char *array, size_t a_idx, size_t b_idx, size_t size,
87  int (*compare) (const void *, const void *, void *aux),
88  void *aux)
89 {
90  return compare (array + (a_idx - 1) * size, array + (b_idx - 1) * size, aux);
91 }
92 
93 /** "Float down" the element with 1-based index I in ARRAY of CNT
94  elements of SIZE bytes each, using COMPARE to compare
95  elements, passing AUX as auxiliary data. */
96 static void
97 heapify (unsigned char *array, size_t i, size_t cnt, size_t size,
98  int (*compare) (const void *, const void *, void *aux),
99  void *aux)
100 {
101  for (;;)
102  {
103  /* Set `max' to the index of the largest element among I
104  and its children (if any). */
105  size_t left = 2 * i;
106  size_t right = 2 * i + 1;
107  size_t max = i;
108  if (left <= cnt && do_compare (array, left, max, size, compare, aux) > 0)
109  max = left;
110  if (right <= cnt
111  && do_compare (array, right, max, size, compare, aux) > 0)
112  max = right;
113 
114  /* If the maximum value is already in element I, we're
115  done. */
116  if (max == i)
117  break;
118 
119  /* Swap and continue down the heap. */
120  do_swap (array, i, max, size);
121  i = max;
122  }
123 }
124 
125 /** Sorts ARRAY, which contains CNT elements of SIZE bytes each,
126  using COMPARE to compare elements, passing AUX as auxiliary
127  data. When COMPARE is passed a pair of elements A and B,
128  respectively, it must return a strcmp()-type result, i.e. less
129  than zero if A < B, zero if A == B, greater than zero if A >
130  B. Runs in O(n lg n) time and O(1) space in CNT. */
131 void
132 sort (void *array, size_t cnt, size_t size,
133  int (*compare) (const void *, const void *, void *aux),
134  void *aux)
135 {
136  size_t i;
137 
138  ASSERT (array != NULL || cnt == 0);
139  ASSERT (compare != NULL);
140  ASSERT (size > 0);
141 
142  /* Build a heap. */
143  for (i = cnt / 2; i > 0; i--)
144  heapify (array, i, cnt, size, compare, aux);
145 
146  /* Sort the heap. */
147  for (i = cnt; i > 1; i--)
148  {
149  do_swap (array, 1, i, size);
150  heapify (array, 1, i - 1, size, compare, aux);
151  }
152 }
153 
154 /** Searches ARRAY, which contains CNT elements of SIZE bytes
155  each, for the given KEY. Returns a match is found, otherwise
156  a null pointer. If there are multiple matches, returns an
157  arbitrary one of them.
158 
159  ARRAY must be sorted in order according to COMPARE.
160 
161  Uses COMPARE to compare elements. When COMPARE is passed a
162  pair of elements A and B, respectively, it must return a
163  strcmp()-type result, i.e. less than zero if A < B, zero if A
164  == B, greater than zero if A > B. */
165 void *
166 bsearch (const void *key, const void *array, size_t cnt,
167  size_t size, int (*compare) (const void *, const void *))
168 {
169  return binary_search (key, array, cnt, size, compare_thunk, &compare);
170 }
171 
172 /** Searches ARRAY, which contains CNT elements of SIZE bytes
173  each, for the given KEY. Returns a match is found, otherwise
174  a null pointer. If there are multiple matches, returns an
175  arbitrary one of them.
176 
177  ARRAY must be sorted in order according to COMPARE.
178 
179  Uses COMPARE to compare elements, passing AUX as auxiliary
180  data. When COMPARE is passed a pair of elements A and B,
181  respectively, it must return a strcmp()-type result, i.e. less
182  than zero if A < B, zero if A == B, greater than zero if A >
183  B. */
184 void *
185 binary_search (const void *key, const void *array, size_t cnt, size_t size,
186  int (*compare) (const void *, const void *, void *aux),
187  void *aux)
188 {
189  const unsigned char *first = array;
190  const unsigned char *last = array + size * cnt;
191 
192  while (first < last)
193  {
194  size_t range = (last - first) / size;
195  const unsigned char *middle = first + (range / 2) * size;
196  int cmp = compare (key, middle, aux);
197 
198  if (cmp < 0)
199  last = middle;
200  else if (cmp > 0)
201  first = middle + size;
202  else
203  return (void *) middle;
204  }
205 
206  return NULL;
207 }
208 
qsort
void qsort(void *array, size_t cnt, size_t size, int(*compare)(const void *, const void *))
Sorts ARRAY, which contains CNT elements of SIZE bytes each, using COMPARE.
Definition: stdlib.c:58
sort
void sort(void *array, size_t cnt, size_t size, int(*compare)(const void *, const void *, void *aux), void *aux)
Sorts ARRAY, which contains CNT elements of SIZE bytes each, using COMPARE to compare elements,...
Definition: stdlib.c:132
NULL
#define NULL
Definition: stddef.h:4
compare_thunk
static int compare_thunk(const void *a, const void *b, void *aux)
Compares A and B by calling the AUX function.
Definition: stdlib.c:45
heapify
static void heapify(unsigned char *array, size_t i, size_t cnt, size_t size, int(*compare)(const void *, const void *, void *aux), void *aux)
"Float down" the element with 1-based index I in ARRAY of CNT elements of SIZE bytes each,...
Definition: stdlib.c:97
atoi
int atoi(const char *s)
Converts a string representation of a signed decimal integer in S into an ‘int’, which is returned.
Definition: stdlib.c:10
stdbool.h
bsearch
void * bsearch(const void *key, const void *array, size_t cnt, size_t size, int(*compare)(const void *, const void *))
Searches ARRAY, which contains CNT elements of SIZE bytes each, for the given KEY.
Definition: stdlib.c:166
binary_search
void * binary_search(const void *key, const void *array, size_t cnt, size_t size, int(*compare)(const void *, const void *, void *aux), void *aux)
Searches ARRAY, which contains CNT elements of SIZE bytes each, for the given KEY.
Definition: stdlib.c:185
random.h
ctype.h
isspace
static int isspace(int c)
Definition: ctype.h:12
ASSERT
#define ASSERT(CONDITION)
This is outside the header guard so that debug.h may be included multiple times with different settin...
Definition: debug.h:31
value
A linked list element.
Definition: list.c:22
s
static uint8_t s[256]
RC4-based pseudo-random number generator (PRNG).
Definition: random.c:17
do_compare
static int do_compare(unsigned char *array, size_t a_idx, size_t b_idx, size_t size, int(*compare)(const void *, const void *, void *aux), void *aux)
Compares elements with 1-based indexes A_IDX and B_IDX in ARRAY with elements of SIZE bytes each,...
Definition: stdlib.c:86
stdlib.h
do_swap
static void do_swap(unsigned char *array, size_t a_idx, size_t b_idx, size_t size)
Swaps elements with 1-based indexes A_IDX and B_IDX in ARRAY with elements of SIZE bytes each.
Definition: stdlib.c:67
isdigit
static int isdigit(int c)
Definition: ctype.h:7
debug.h