Make love::Exception safe(r).

Now allows exceptions of arbitrary length.
Now allows catching a non-reference, i.e. catch(love::Exception e).
This commit is contained in:
vrld
2011-11-12 21:11:41 +01:00
parent 03927f5207
commit 7a513e1434
4 changed files with 37 additions and 26 deletions
+29 -12
View File
@@ -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); int size_buffer = 256, size_out;
vsnprintf(buffer, BUFFER_SIZE, fmt, args); char * buffer;
va_end(args); while (true) {
} buffer = new char[size_buffer];
memset(buffer, 0, size_buffer);
Exception::Exception(int unparsed, const char * str) va_start(args, fmt);
{ size_out = vsnprintf(buffer, size_buffer, fmt, args);
LOVE_UNUSED(unparsed); va_end(args);
strncpy(buffer, str, BUFFER_SIZE);
}
const char * Exception::what() const throw() // see http://perfec.to/vsnprintf/pasprintf.c
{ // if size_out ...
return (const char *)buffer; // == -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
View File
@@ -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:
/** std::string message;
* The vsnprintf operates on a buffer this large.
**/
static const int BUFFER_SIZE = 256;
/**
* The buffer for vsnprintf.
**/
char buffer[BUFFER_SIZE];
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
View File
@@ -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;
@@ -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());