Browse Source

feat(gblibc): add qsort, rand, alloca

greatbridf 2 years ago
parent
commit
e4159f941b
5 changed files with 80 additions and 0 deletions
  1. 1 0
      gblibc/CMakeLists.txt
  2. 16 0
      gblibc/include/alloca.h
  3. 7 0
      gblibc/include/stdlib.h
  4. 6 0
      gblibc/src/alloca.c
  5. 50 0
      gblibc/src/stdlib.c

+ 1 - 0
gblibc/CMakeLists.txt

@@ -15,6 +15,7 @@ add_library(gblibc STATIC
     src/errno.c
     src/init.c
     src/internal.c
+    src/alloca.c
 )
 
 add_library(crt0 OBJECT

+ 16 - 0
gblibc/include/alloca.h

@@ -0,0 +1,16 @@
+#ifndef __GBLIBC_ALLOCA_H_
+#define __GBLIBC_ALLOCA_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void* alloca(size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 7 - 0
gblibc/include/stdlib.h

@@ -14,6 +14,13 @@ void __attribute__((noreturn)) exit(int status);
 void* malloc(size_t size);
 void free(void* ptr);
 
+typedef int (*comparator_t)(const void* a, const void* b);
+void qsort(void* base, size_t num, size_t size, comparator_t comparator);
+
+int rand(void);
+int rand_r(unsigned int* seedp);
+void srand(unsigned int seed);
+
 #ifdef __cplusplus
 }
 #endif

+ 6 - 0
gblibc/src/alloca.c

@@ -0,0 +1,6 @@
+#include <alloca.h>
+
+void* alloca(size_t size)
+{
+    return __builtin_alloca(size);
+}

+ 50 - 0
gblibc/src/stdlib.c

@@ -1,8 +1,10 @@
+#include <alloca.h>
 #include <priv-vars.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <syscall.h>
 #include <unistd.h>
+#include <string.h>
 
 int atoi(const char* str)
 {
@@ -139,3 +141,51 @@ void free(void* ptr)
     p->flag &= ~MEM_ALLOCATED;
     _union(p);
 }
+
+static inline void _swap(void* a, void* b, size_t sz)
+{
+    void* tmp = alloca(sz);
+    memcpy(tmp, a, sz);
+    memcpy(a, b, sz);
+    memcpy(b, tmp, sz);
+}
+
+void qsort(void* arr, size_t len, size_t sz, comparator_t cmp) {
+    if (len <= 1)
+        return;
+
+    char* pivot = alloca(sz);
+    memcpy(pivot, arr + sz * (rand() % len), sz);
+
+    int i = 0, j = 0, k = len;
+    while (i < k) {
+        int res = cmp(arr + sz * i, pivot);
+        if (res < 0)
+            _swap(arr + sz * i++, arr + sz * j++, sz);
+        else if (res > 0)
+            _swap(arr + sz * i, arr + sz * --k, sz);
+        else
+            i++;
+    }
+
+    qsort(arr, j, sz, cmp);
+    qsort(arr + sz * k, len - k, sz, cmp);
+}
+
+static unsigned int __next_rand;
+int rand(void)
+{
+    return rand_r(&__next_rand);
+}
+
+int rand_r(unsigned int* seedp)
+{
+    *seedp = *seedp * 1103515245 + 12345;
+    return (unsigned int) (*seedp / 65536) % 32768;
+}
+
+void srand(unsigned int seed)
+{
+    __next_rand = seed;
+    rand();
+}