Browse Source

Make love::Exception safe(r).

Now allows exceptions of arbitrary length.
Now allows catching a non-reference, i.e. catch(love::Exception e).
vrld 13 years ago
parent
commit
7a513e1434

+ 29 - 12
src/common/Exception.cpp

@@ -20,26 +20,43 @@
 
 
 #include "Exception.h"
 #include "Exception.h"
 #include <common/config.h>
 #include <common/config.h>
+#include <iostream>
+using namespace std;
 
 
 namespace love
 namespace love
 {
 {
 	Exception::Exception(const char * fmt, ...)
 	Exception::Exception(const char * fmt, ...)
 	{
 	{
 		va_list args;
 		va_list args;
-		va_start(args, fmt);
-		vsnprintf(buffer, BUFFER_SIZE, fmt, args);
-		va_end(args);
-	}
+		int size_buffer = 256, size_out;
+		char * buffer;
+		while (true) {
+			buffer = new char[size_buffer];
+			memset(buffer, 0, size_buffer);
 
 
-	Exception::Exception(int unparsed, const char * str)
-	{
-		LOVE_UNUSED(unparsed);
-		strncpy(buffer, str, BUFFER_SIZE);
-	}
+			va_start(args, fmt);
+			size_out = vsnprintf(buffer, size_buffer, fmt, args);
+			va_end(args);
 
 
-	const char * Exception::what() const throw()
-	{
-		return (const char *)buffer;
+			// see http://perfec.to/vsnprintf/pasprintf.c
+			// if size_out ...
+			//      == -1             --> output was truncated
+			//      == size_buffer    --> output was truncated
+			//      == size_buffer-1  --> ambiguous, /may/ have been truncated
+			//       > size_buffer    --> output was truncated, and size_out
+			//                            bytes would have been written
+			if (size_out == size_buffer || size_out == -1 || size_out == size_buffer-1)
+				size_buffer *= 2;
+			else if (size_out > size_buffer)
+				size_buffer = size_out + 2; // to avoid the ambiguous case
+			else
+				break;
+
+			delete[] buffer;
+		}
+		message = std::string(buffer);
+		cerr << message << endl;
+		delete[] buffer;
 	}
 	}
 
 
 }
 }

+ 5 - 11
src/common/Exception.h

@@ -25,6 +25,7 @@
 #include <cstdarg> // vararg
 #include <cstdarg> // vararg
 #include <cstdio> // vsnprintf
 #include <cstdio> // vsnprintf
 #include <cstring> // strncpy
 #include <cstring> // strncpy
+#include <string>
 
 
 namespace love
 namespace love
 {
 {
@@ -35,15 +36,7 @@ namespace love
 	{
 	{
 	private:
 	private:
 
 
-		/**
-		* The vsnprintf operates on a buffer this large.
-		**/
-		static const int BUFFER_SIZE = 256;
-
-		/**
-		* The buffer for vsnprintf.
-		**/
-		char buffer[BUFFER_SIZE];
+		std::string message;
 
 
 	public:
 	public:
 
 
@@ -55,13 +48,14 @@ namespace love
 		* @param fmt The format string (see printf).
 		* @param fmt The format string (see printf).
 		**/
 		**/
 		Exception(const char * fmt, ...);
 		Exception(const char * fmt, ...);
-		Exception(int unparsed, const char * str);
+		virtual ~Exception() throw() {}
 
 
 		/**
 		/**
 		* Returns a string containing reason for the exception.
 		* Returns a string containing reason for the exception.
 		* @return A description of the exception.
 		* @return A description of the exception.
 		**/
 		**/
-		virtual const char * what() const throw();
+		inline virtual const char * what() const throw()
+		{ return message.c_str(); }
 
 
 	}; // class
 	}; // class
 
 

+ 2 - 2
src/modules/graphics/opengl/Font.cpp

@@ -177,7 +177,7 @@ namespace opengl
 		catch (utf8::exception & e)
 		catch (utf8::exception & e)
 		{
 		{
 			glPopMatrix();
 			glPopMatrix();
-			throw love::Exception(1, e.what());
+			throw love::Exception("%s", e.what());
 		}
 		}
 		glPopMatrix();
 		glPopMatrix();
 	}
 	}
@@ -212,7 +212,7 @@ namespace opengl
 		}
 		}
 		catch (utf8::exception & e)
 		catch (utf8::exception & e)
 		{
 		{
-			throw love::Exception(1, e.what());
+			throw love::Exception("%s", e.what());
 		}
 		}
 
 
 		return temp;
 		return temp;

+ 1 - 1
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -388,7 +388,7 @@ namespace opengl
 			const char* code = lua_tostring(L, -1);
 			const char* code = lua_tostring(L, -1);
 			PixelEffect * effect = instance->newPixelEffect(code);
 			PixelEffect * effect = instance->newPixelEffect(code);
 			luax_newtype(L, "PixelEffect", GRAPHICS_PIXELEFFECT_T, (void*)effect);
 			luax_newtype(L, "PixelEffect", GRAPHICS_PIXELEFFECT_T, (void*)effect);
-		} catch (love::Exception& e) {
+		} catch (const love::Exception& e) {
 			// memory is freed in Graphics::newPixelEffect
 			// memory is freed in Graphics::newPixelEffect
 			luax_getfunction(L, "graphics", "_transformGLSLErrorMessages");
 			luax_getfunction(L, "graphics", "_transformGLSLErrorMessages");
 			lua_pushstring(L, e.what());
 			lua_pushstring(L, e.what());