BLGetCStringRepresentation.c [plain text]
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <CoreFoundation/CoreFoundation.h>
#include "bless.h"
#include "bless_private.h"
#if !defined(NO_GETCSTRING) || !NO_GETCSTRING
static pthread_once_t blcstr_once_control = PTHREAD_ONCE_INIT;
static pthread_key_t blcstr_key = 0;
static void initkey(void);
static void releasestorage(void *addr);
struct stringer {
size_t size;
char * string;
};
char *BLGetCStringDescription(CFTypeRef typeRef) {
CFStringRef desc = NULL;
int ret;
struct stringer *storage;
CFIndex strsize;
if(typeRef == NULL)
return NULL;
ret = pthread_once(&blcstr_once_control, initkey);
if(ret)
return NULL;
if(CFGetTypeID(typeRef) == CFStringGetTypeID()) {
desc = CFRetain(typeRef);
} else {
desc = CFCopyDescription(typeRef);
}
if(desc == NULL)
return NULL;
strsize = CFStringGetLength(desc);
strsize = 3*strsize + 1;
storage = (struct stringer *)pthread_getspecific(blcstr_key);
if(storage == NULL) {
storage = malloc(sizeof(*storage));
storage->size = (size_t)strsize;
storage->string = malloc(storage->size);
ret = pthread_setspecific(blcstr_key, storage);
if(ret) {
CFRelease(desc);
free(storage->string);
free(storage);
fprintf(stderr, "pthread_setspecific failed\n");
return NULL;
}
} else if(storage->size < strsize) {
storage->size = (size_t)strsize;
free(storage->string);
storage->string = malloc(storage->size);
}
if(!CFStringGetCString(desc, storage->string, (CFIndex)storage->size, kCFStringEncodingUTF8)) {
CFRelease(desc);
fprintf(stderr, "CFStringGetCString failed\n");
return NULL;
}
CFRelease(desc);
return storage->string;
}
static void initkey(void)
{
int ret;
ret = pthread_key_create(&blcstr_key, releasestorage);
if(ret)
fprintf(stderr, "pthread_key_create failed\n");
}
static void releasestorage(void *addr)
{
struct stringer *storage = (struct stringer *)addr;
free(storage->string);
free(storage);
}
#else
char *BLGetCStringDescription(CFTypeRef typeRef) {
return NULL;
}
#endif