/* * 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); } }