glib-mini.c revision 1d1a2af599bfd91357cbc44b3cf20b1ab104f4ab
124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// Copyright 2014 The Android Open Source Project
224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//
324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// This software is licensed under the terms of the GNU General Public
424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// License version 2, as published by the Free Software Foundation, and
524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// may be copied, distributed, and modified under those terms.
624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne//
724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// This program is distributed in the hope that it will be useful,
824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// but WITHOUT ANY WARRANTY; without even the implied warranty of
924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// GNU General Public License for more details.
1124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <glib.h>
1324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
1424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <limits.h>
1524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <stdarg.h>
1624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <stdio.h>
1724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <stdlib.h>
1824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#include <string.h>
1924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
2024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// Print a panic message then exit the program immediately.
2124018467ddb13857b764182f7753764d2f32f87dPeter Collingbournestatic  __attribute__((noreturn)) void g_panic(const char* fmt, ...){
22651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  va_list args;
2324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  fprintf(stderr, "MiniGLib:PANIC: ");
24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  va_start(args, fmt);
2524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  vfprintf(stderr, fmt, args);
2624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  va_end(args);
2724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  exit(1);
2824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
2924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
301ec5750908039701b206fc32dd2b95c45cd5cce8James Dennett
3124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne// Heap allocation.
3224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
3324018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid* g_malloc(size_t size) {
3424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (size == 0)
3524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return NULL;
3624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
3724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void* ptr = malloc(size);
3824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (ptr == NULL)
39ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie    g_panic("Can't allocate %zu bytes!\n", size);
401ec5750908039701b206fc32dd2b95c45cd5cce8James Dennett
4124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return ptr;
42ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie}
431ec5750908039701b206fc32dd2b95c45cd5cce8James Dennett
4424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
45ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikievoid* g_malloc0(size_t size) {
461ec5750908039701b206fc32dd2b95c45cd5cce8James Dennett  void* ptr = g_malloc(size);
471ec5750908039701b206fc32dd2b95c45cd5cce8James Dennett  if (ptr == NULL)
481ec5750908039701b206fc32dd2b95c45cd5cce8James Dennett    return NULL;
491ec5750908039701b206fc32dd2b95c45cd5cce8James Dennett
501ec5750908039701b206fc32dd2b95c45cd5cce8James Dennett  memset(ptr, 0, size);
5124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return ptr;
5224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
5324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
5424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
5524018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid* g_realloc(void* ptr, size_t size) {
5624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (size == 0) {
5724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    g_free(ptr);
5824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return NULL;
5924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
6024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  void* new_ptr = realloc(ptr, size);
6124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (new_ptr == NULL)
6224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    g_panic("Can't reallocate pointer %p to %zu bytes!\n", ptr, size);
6324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
6424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return new_ptr;
6524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
6624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
67ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
6824018467ddb13857b764182f7753764d2f32f87dPeter Collingbournevoid g_free(void* ptr) {
6924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (ptr)
7024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    free(ptr);
7124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
7224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
73ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie// Strings.
7424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
7524018467ddb13857b764182f7753764d2f32f87dPeter Collingbournechar* g_strdup(const char* str) {
76ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  if (str == NULL)
7724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    return NULL;
7824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
79ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  size_t len = strlen(str);
8024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  char* copy = g_malloc(len + 1);
8124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  memcpy(copy, str, len + 1);
8224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return copy;
8324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
8424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
8524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
86ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikiechar* g_strndup(const char* str, size_t size) {
8724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  const char *end = memchr(str, 0, size);
8824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  char *copy;
8924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (end)
91ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie    size = end - str;
9224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  copy = g_malloc(size + 1);
94ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  memcpy(copy, str, size);
9524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  copy[size] = 0;
9624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return copy;
9724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
9824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
9924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
10024018467ddb13857b764182f7753764d2f32f87dPeter Collingbournechar* g_strdup_printf(const char* fmt, ...) {
1011ec5750908039701b206fc32dd2b95c45cd5cce8James Dennett  char* result;
10224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  va_list args;
10324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  va_start(args, fmt);
10424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  g_vasprintf(&result, fmt, args);
10524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  va_end(args);
10624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return result;
10724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne}
108ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
10924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
11024018467ddb13857b764182f7753764d2f32f87dPeter Collingbournechar* g_strdup_vprintf(const char* fmt, va_list args) {
11124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  char* result;
11224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  g_vasprintf(&result, fmt, args);
11324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  return result;
114ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie}
11524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
11624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
11724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourneint g_vasprintf(char** str, const char* fmt, va_list args) {
11824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne#ifdef _WIN32
11924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // On Win32, vsnprintf() is broken and always returns -1 in case of truncation,
120ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  // so make an educated guess, and try again if that fails with a larger pool.
12124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  size_t capacity = 128;
12224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  char* buffer = g_malloc(capacity);
123ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  for (;;) {
12424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    va_list args2;
12524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    va_copy(args2, args);
126ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie    int len = vsnprintf(buffer, capacity, fmt, args2);
12724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (len >= 0) {
12824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      *str = buffer;
129ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie      return len;
13024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    }
13124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    va_end(args2);
132ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
13324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    capacity *= 2;
13424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    if (capacity > INT_MAX)
13524018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne      g_panic("Formatted string is too long!\n");
13624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
13724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    buffer = g_realloc(buffer, capacity);
13824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  }
139ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie#else
14024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // On other systems, vsnprintf() works properly and returns the size of the
14124018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  // formatted string without truncation.
14224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  va_list args2;
14324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  va_copy(args2, args);
14424018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  int len = vsnprintf(NULL, 0, fmt, args2);
145ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  va_end(args2);
14624018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  if (len < 0)
14724018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne    g_panic("Can't format string!\n");
148ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
14924018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  char* result = g_malloc(len + 1);
15024018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  va_copy(args2, args);
151ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  vsnprintf(result, (size_t)len, fmt, args2);
15224018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne  va_end(args2);
15324018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne
154c831d8b977a09bf2907d03128b48b5c914a2fafdRichard Smith  *str = result;
155c831d8b977a09bf2907d03128b48b5c914a2fafdRichard Smith  return len;
156ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie#endif
157c831d8b977a09bf2907d03128b48b5c914a2fafdRichard Smith}
15824018467ddb13857b764182f7753764d2f32f87dPeter Collingbourne