/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkTLS.h"
#include "SkTypes.h"
#include "SkError.h"
#include "SkErrorInternals.h"
#include <stdio.h>
#include <stdarg.h>
namespace {
void *CreateThreadError() {
return SkNEW_ARGS(SkError, (kNoError_SkError));
}
void DeleteThreadError(void* v) {
SkDELETE(reinterpret_cast<SkError*>(v));
}
#define THREAD_ERROR \
(*reinterpret_cast<SkError*>(SkTLS::Get(CreateThreadError, DeleteThreadError)))
void *CreateThreadErrorCallback() {
return SkNEW_ARGS(SkErrorCallbackFunction, (SkErrorInternals::DefaultErrorCallback));
}
void DeleteThreadErrorCallback(void* v) {
SkDELETE(reinterpret_cast<SkErrorCallbackFunction *>(v));
}
#define THREAD_ERROR_CALLBACK \
*(reinterpret_cast<SkErrorCallbackFunction *>(SkTLS::Get(CreateThreadErrorCallback, \
DeleteThreadErrorCallback)))
void *CreateThreadErrorContext() {
return SkNEW_ARGS(void **, (NULL));
}
void DeleteThreadErrorContext(void* v) {
SkDELETE(reinterpret_cast<void **>(v));
}
#define THREAD_ERROR_CONTEXT \
(*reinterpret_cast<void **>(SkTLS::Get(CreateThreadErrorContext, DeleteThreadErrorContext)))
#define ERROR_STRING_LENGTH 2048
void *CreateThreadErrorString() {
return SkNEW_ARRAY(char, (ERROR_STRING_LENGTH));
}
void DeleteThreadErrorString(void* v) {
SkDELETE_ARRAY(reinterpret_cast<char *>(v));
}
#define THREAD_ERROR_STRING \
(reinterpret_cast<char *>(SkTLS::Get(CreateThreadErrorString, DeleteThreadErrorString)))
}
SkError SkGetLastError() {
return SkErrorInternals::GetLastError();
}
void SkClearLastError() {
SkErrorInternals::ClearError();
}
void SkSetErrorCallback(SkErrorCallbackFunction cb, void *context) {
SkErrorInternals::SetErrorCallback(cb, context);
}
const char *SkGetLastErrorString() {
return SkErrorInternals::GetLastErrorString();
}
// ------------ Private Error functions ---------
void SkErrorInternals::SetErrorCallback(SkErrorCallbackFunction cb, void *context) {
if (cb == NULL) {
THREAD_ERROR_CALLBACK = SkErrorInternals::DefaultErrorCallback;
} else {
THREAD_ERROR_CALLBACK = cb;
}
THREAD_ERROR_CONTEXT = context;
}
void SkErrorInternals::DefaultErrorCallback(SkError code, void *context) {
SkDebugf("Skia Error: %s\n", SkGetLastErrorString());
}
void SkErrorInternals::ClearError() {
SkErrorInternals::SetError( kNoError_SkError, "All is well" );
}
SkError SkErrorInternals::GetLastError() {
return THREAD_ERROR;
}
const char *SkErrorInternals::GetLastErrorString() {
return THREAD_ERROR_STRING;
}
void SkErrorInternals::SetError(SkError code, const char *fmt, ...) {
THREAD_ERROR = code;
va_list args;
char *str = THREAD_ERROR_STRING;
const char *error_name = NULL;
switch( code ) {
case kNoError_SkError:
error_name = "No Error";
break;
case kInvalidArgument_SkError:
error_name = "Invalid Argument";
break;
case kInvalidOperation_SkError:
error_name = "Invalid Operation";
break;
case kInvalidHandle_SkError:
error_name = "Invalid Handle";
break;
case kInvalidPaint_SkError:
error_name = "Invalid Paint";
break;
case kOutOfMemory_SkError:
error_name = "Out Of Memory";
break;
case kParseError_SkError:
error_name = "Parse Error";
break;
default:
error_name = "Unknown error";
break;
}
sprintf( str, "%s: ", error_name );
int string_left = SkToInt(ERROR_STRING_LENGTH - strlen(str));
str += strlen(str);
va_start( args, fmt );
vsnprintf( str, string_left, fmt, args );
va_end( args );
SkErrorCallbackFunction fn = THREAD_ERROR_CALLBACK;
if (fn && code != kNoError_SkError) {
fn(code, THREAD_ERROR_CONTEXT);
}
}