]> de.git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - util.c
Fix windows builds, add strip target for makefiles, update distro build makefiles...
[xonotic/gmqcc.git] / util.c
diff --git a/util.c b/util.c
index f454ae7a1739c4e152edb99dc78f5e2fad84a89d..f6b9808657f272125381bc06cb6e9ab39ad619db 100644 (file)
--- a/util.c
+++ b/util.c
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#include <string.h>
-#include <stdlib.h>
-
+#define GMQCC_PLATFORM_HEADER
 #include "gmqcc.h"
+#include "platform.h"
 
 /*
  * Initially this was handled with a table in the gmqcc.h header, but
@@ -224,80 +223,103 @@ size_t util_optimizationtostr(const char *in, char *out, size_t outsz) {
     return util_strtransform(in, out, outsz, "_ ", 'a'-'A');
 }
 
-/*
- * Portable implementation of vasprintf/asprintf. Assumes vsnprintf
- * exists, otherwise compiler error.
- *
- * TODO: fix for MSVC ....
- */
-int util_vasprintf(char **dat, const char *fmt, va_list args) {
-    int   ret;
-    int   len;
-    char *tmp = NULL;
-
-    /*
-     * For visual studio _vsnprintf doesn't tell you the length of a
-     * formatted string if it overflows. However there is a MSVC
-     * intrinsic (which is documented wrong) called _vcsprintf which
-     * will return the required amount to allocate.
-     */
-    #ifdef _MSC_VER
-        if ((len = _vscprintf(fmt, args)) < 0) {
-            *dat = NULL;
-            return -1;
-        }
-
-        tmp = (char*)mem_a(len + 1);
-        if ((ret = _vsnprintf_s(tmp, len+1, len+1, fmt, args)) != len) {
-            mem_d(tmp);
-            *dat = NULL;
-            return -1;
-        }
-        *dat = tmp;
-        return len;
-    #else
-        /*
-         * For everything else we have a decent conforming vsnprintf that
-         * returns the number of bytes needed.  We give it a try though on
-         * a short buffer, since efficiently speaking, it could be nice to
-         * above a second vsnprintf call.
-         */
-        char    buf[128];
-        va_list cpy;
-        va_copy(cpy, args);
-        len = vsnprintf(buf, sizeof(buf), fmt, cpy);
-        va_end (cpy);
-
-        if (len < (int)sizeof(buf)) {
-            *dat = util_strdup(buf);
-            return len;
-        }
+int util_snprintf(char *str, size_t size, const char *fmt, ...) {
+    va_list  arg;
+    int      ret;
 
-        /* not large enough ... */
-        tmp = (char*)mem_a(len + 1);
-        if ((ret = vsnprintf(tmp, len + 1, fmt, args)) != len) {
-            mem_d(tmp);
-            *dat = NULL;
-            return -1;
-        }
+    va_start(arg, fmt);
+    ret = platform_vsnprintf(str, size, fmt, arg);
+    va_end(arg);
 
-        *dat = tmp;
-        return len;
-    #endif
+    return ret;
 }
+
 int util_asprintf(char **ret, const char *fmt, ...) {
     va_list  args;
     int      read;
+
     va_start(args, fmt);
-    read = util_vasprintf(ret, fmt, args);
+    read = platform_vasprintf(ret, fmt, args);
     va_end  (args);
 
     return read;
 }
 
-void util_seed(uint32_t value) {
-    srand((int)value);
+int util_sscanf(const char *str, const char *format, ...) {
+    va_list  args;
+    int      read;
+
+    va_start(args, format);
+    read = platform_vsscanf(str, format, args);
+    va_end(args);
+
+    return read;
+}
+
+char *util_strncpy(char *dest, const char *src, size_t n) {
+    return platform_strncpy(dest, src, n);
+}
+char *util_strncat(char *dest, const char *src, size_t n) {
+    return platform_strncat(dest, src, n);
+}
+char *util_strcat(char *dest, const char *src) {
+    return platform_strcat(dest, src);
 }
+const char *util_strerror(int err) {
+    return platform_strerror(err);
+}
+
+const struct tm *util_localtime(const time_t *timer) {
+    return platform_localtime(timer);
+}
+const char *util_ctime(const time_t *timer) {
+    return platform_ctime(timer);
+}
+
+bool util_isatty(fs_file_t *file) {
+    if (file == (fs_file_t*)stdout) return !!platform_isatty(STDOUT_FILENO);
+    if (file == (fs_file_t*)stderr) return !!platform_isatty(STDERR_FILENO);
+    return false;
+}
+
+const char *util_tmpnam(char *str) {
+    return platform_tmpnam(str);
+}
+
+/*
+ * A small noncryptographic PRNG based on:
+ * http://burtleburtle.net/bob/rand/smallprng.html
+ */
+static uint32_t util_rand_state[4] = {
+    0xF1EA5EED, 0x00000000,
+    0x00000000, 0x00000000
+};
+
+#define util_rand_rot(X, Y) (((X)<<(Y))|((X)>>(32-(Y))))
+
 uint32_t util_rand() {
-    return rand();
+    uint32_t last;
+
+    last               = util_rand_state[0] - util_rand_rot(util_rand_state[1], 27);
+    util_rand_state[0] = util_rand_state[1] ^ util_rand_rot(util_rand_state[2], 17);
+    util_rand_state[1] = util_rand_state[2] + util_rand_state[3];
+    util_rand_state[2] = util_rand_state[3] + last;
+    util_rand_state[3] = util_rand_state[0] + last;
+
+    return util_rand_state[3];
 }
+
+#undef util_rand_rot
+
+void util_seed(uint32_t value) {
+    size_t i;
+
+    util_rand_state[0] = 0xF1EA5EED;
+    util_rand_state[1] = value;
+    util_rand_state[2] = value;
+    util_rand_state[3] = value;
+
+    for (i = 0; i < 20; ++i)
+        (void)util_rand();
+}
+