genericopenlibs/cppstdlib/src/stdcpp_support.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/cppstdlib/src/stdcpp_support.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,213 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name        : stdcpp_support.cpp
+// Part of     : standard c++ library.
+// 
+//
+
+#include <new>
+#include <stdcpp_support.h>
+#include <typeinfo>
+#include <string>
+#include <stdexcept>
+
+
+EXPORT_C void TranslateSymErrorToCppException(TInt aError)
+{
+	switch(aError)
+	{
+	case KErrNoMemory:
+		// This is about to use the emergency buffer!
+		__THROW(std::bad_alloc());
+	case KErrArgument:
+		__THROW(std::invalid_argument("Invalid argument"));
+	case KErrOverflow :
+		__THROW(std::overflow_error("Overflow error"));
+	case KErrUnderflow:
+		__THROW(std::underflow_error("Underflow error"));
+	default:
+		__THROW(Symbian_error(KErrGeneral));
+	}
+}
+
+EXPORT_C TInt TranslateCppExceptionToSymError(const std::exception& aThrow)
+{
+#ifndef __GCCXML__
+	const std::type_info& atype = typeid(aThrow);
+
+	if(atype == typeid (std::bad_alloc))
+		return KErrNoMemory;
+	else if(atype == typeid(std::invalid_argument))
+		return KErrArgument;
+	else if(atype == typeid(std::out_of_range))
+		// std::out_of_range is of type logic_error which by definition means that it is
+		// "presumably detectable before the program executes".
+		// std::out_of_range is used to report an argument is not within the expected range.
+		// The description of KErrArgument says an argument is out of range. Hence the mapping.
+		return KErrArgument;
+	else if(atype == typeid(std::overflow_error))
+		return KErrOverflow;
+	else if(atype == typeid(std::underflow_error))
+		return KErrUnderflow;
+	else
+		return KErrGeneral;
+#else
+	return KErrGeneral;
+#endif
+}
+
+#ifdef __WINSCW__
+/*
+ * The StdC++ global new and delete operators defined here. They are done only for the emulator
+ * as for EABI platforms, it is part of the runtime support(i.e., stdnew.dll).
+ */
+#include <e32std.h>
+
+EXPORT_C const std::nothrow_t std::nothrow;
+
+EXPORT_C void* operator new(std::size_t a_size) __THROW(std::bad_alloc)
+	{
+	for (;;)
+		{
+		void* p = User::Alloc(a_size);
+
+		if (p)
+			{
+			return p;
+			}
+		std::new_handler nh_func ;
+		std::new_handler *ptr = reinterpret_cast<std::new_handler*>(Dll::Tls());
+		nh_func = (ptr)?(*ptr):NULL;
+
+		if (nh_func)
+			{
+			nh_func();
+			}
+		else
+			{
+			__THROW(std::bad_alloc());
+			}
+		}
+	}
+
+EXPORT_C void* operator new[](std::size_t a_size) __THROW(std::bad_alloc)
+	{
+    return ::operator new(a_size);
+	}
+
+EXPORT_C void* operator new(std::size_t a_size, const std::nothrow_t&) __NO_THROW
+	{
+	for (;;)
+		{
+		void* p = User::Alloc(a_size);
+
+		if (p)
+			{
+			return p;
+			}
+
+		std::new_handler nh_func ;
+		std::new_handler *ptr = reinterpret_cast<std::new_handler*>(Dll::Tls());
+		nh_func = (ptr)?(*ptr):NULL;
+
+		if (nh_func)
+			{
+			try
+				{
+				nh_func();
+				}
+			catch (...)
+				{
+				return 0;
+				}
+			}
+		else
+			{
+			return 0;
+			}
+		}
+	}
+
+EXPORT_C void* operator new[](std::size_t a_size, const std::nothrow_t) __NO_THROW
+	{
+    return ::operator new(a_size, std::nothrow);
+	}
+
+// Symbian-specific addition.
+EXPORT_C void* operator new(std::size_t a_size, std::size_t a_extra_size) __NO_THROW
+	{
+    return ::operator new(a_size + a_extra_size, std::nothrow);
+	}
+
+EXPORT_C void operator delete(void* p) __NO_THROW
+	{
+	User::Free(p);
+	}
+
+EXPORT_C void operator delete(void* p, const std::nothrow_t&) __NO_THROW
+	{
+	User::Free(p);
+	}
+
+EXPORT_C void operator delete[](void* p) __NO_THROW
+	{
+	User::Free(p);
+	}
+
+EXPORT_C void operator delete[](void* p, const std::nothrow_t&) __NO_THROW
+	{
+	User::Free(p);
+	}
+
+// Symbian-specific addition.
+EXPORT_C void operator delete(void* p, std::size_t) __NO_THROW
+	{
+	User::Free(p);
+	}
+_LIT(K,"set_new_handler");
+
+
+using std::new_handler;
+
+EXPORT_C new_handler std::set_new_handler(new_handler a_new_nh) __NO_THROW
+	{
+	new_handler current_nh;
+	TAny* tls_word_p = Dll::Tls();
+
+	if (!tls_word_p)
+		{
+		// This is the first time we're called, so we need to set up the TLS.
+
+		tls_word_p = User::Alloc( sizeof(new_handler) );
+		if ( !tls_word_p )
+			{
+			User::Panic(K, KErrNoMemory);
+			}
+
+		Dll::SetTls(tls_word_p);
+		current_nh = 0;
+		}
+	else
+		{
+		// Get the currently installed new_handler function.
+		current_nh = *reinterpret_cast<new_handler*>(tls_word_p);
+		}
+	
+	// Set the new new_handler.
+	*reinterpret_cast<new_handler*>(tls_word_p) = a_new_nh;
+
+	return current_nh;
+	}
+
+#endif //__WINSCW__