glib-mini.c revision fd77237e061fbae1abac9466c4de604137ffbb5d
1// Copyright 2014 The Android Open Source Project 2// 3// This software is licensed under the terms of the GNU General Public 4// License version 2, as published by the Free Software Foundation, and 5// may be copied, distributed, and modified under those terms. 6// 7// This program is distributed in the hope that it will be useful, 8// but WITHOUT ANY WARRANTY; without even the implied warranty of 9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10// GNU General Public License for more details. 11 12#include <glib.h> 13 14#include <limits.h> 15#include <stdarg.h> 16#include <stdio.h> 17#include <stdlib.h> 18#include <string.h> 19 20// Print a panic message then exit the program immediately. 21void g_panic(const char* fmt, ...){ 22 va_list args; 23 fprintf(stderr, "MiniGLib:PANIC: "); 24 va_start(args, fmt); 25 vfprintf(stderr, fmt, args); 26 va_end(args); 27 exit(1); 28} 29 30 31// Heap allocation. 32 33void* g_malloc(size_t size) { 34 if (size == 0) 35 return NULL; 36 37 void* ptr = malloc(size); 38 if (ptr == NULL) 39 g_panic("Can't allocate %zu bytes!\n", size); 40 41 return ptr; 42} 43 44 45void* g_malloc0(size_t size) { 46 void* ptr = g_malloc(size); 47 if (ptr == NULL) 48 return NULL; 49 50 memset(ptr, 0, size); 51 return ptr; 52} 53 54 55void* g_realloc(void* ptr, size_t size) { 56 if (size == 0) { 57 g_free(ptr); 58 return NULL; 59 } 60 void* new_ptr = realloc(ptr, size); 61 if (new_ptr == NULL) 62 g_panic("Can't reallocate pointer %p to %zu bytes!\n", ptr, size); 63 64 return new_ptr; 65} 66 67 68void g_free(void* ptr) { 69 if (ptr) 70 free(ptr); 71} 72 73// Strings. 74 75char* g_strdup(const char* str) { 76 if (str == NULL) 77 return NULL; 78 79 size_t len = strlen(str); 80 char* copy = g_malloc(len + 1); 81 memcpy(copy, str, len + 1); 82 return copy; 83} 84 85 86char* g_strndup(const char* str, size_t size) { 87 const char *end = memchr(str, 0, size); 88 char *copy; 89 90 if (end) 91 size = end - str; 92 93 copy = g_malloc(size + 1); 94 memcpy(copy, str, size); 95 copy[size] = 0; 96 return copy; 97} 98 99 100char* g_strdup_printf(const char* fmt, ...) { 101 char* result; 102 va_list args; 103 va_start(args, fmt); 104 g_vasprintf(&result, fmt, args); 105 va_end(args); 106 return result; 107} 108 109 110char* g_strdup_vprintf(const char* fmt, va_list args) { 111 char* result; 112 g_vasprintf(&result, fmt, args); 113 return result; 114} 115 116 117int g_vasprintf(char** str, const char* fmt, va_list args) { 118#ifdef _WIN32 119 // On Win32, vsnprintf() is broken and always returns -1 in case of truncation, 120 // so make an educated guess, and try again if that fails with a larger pool. 121 size_t capacity = 128; 122 char* buffer = g_malloc(capacity); 123 for (;;) { 124 va_list args2; 125 va_copy(args2, args); 126 int len = vsnprintf(buffer, capacity, fmt, args2); 127 if (len >= 0) { 128 *str = buffer; 129 return len; 130 } 131 va_end(args2); 132 133 capacity *= 2; 134 if (capacity > INT_MAX) 135 g_panic("Formatted string is too long!\n"); 136 137 buffer = g_realloc(buffer, capacity); 138 } 139#else 140 // On other systems, vsnprintf() works properly and returns the size of the 141 // formatted string without truncation. 142 va_list args2; 143 va_copy(args2, args); 144 int len = vsnprintf(NULL, 0, fmt, args2); 145 va_end(args2); 146 if (len < 0) 147 g_panic("Can't format string!\n"); 148 149 char* result = g_malloc(len + 1); 150 va_copy(args2, args); 151 vsnprintf(result, (size_t)len, fmt, args2); 152 va_end(args2); 153 154 *str = result; 155 return len; 156#endif 157} 158