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