Переглянути джерело

Added enum cast support. Requires bcc 0.108+

woollybah 6 роки тому
батько
коміт
9197f71b49
4 змінених файлів з 95 додано та 0 видалено
  1. 14 0
      blitz.mod/blitz.bmx
  2. 4 0
      blitz.mod/blitz.h
  3. 57 0
      blitz.mod/blitz_enum.c
  4. 20 0
      blitz.mod/blitz_enum.h

+ 14 - 0
blitz.mod/blitz.bmx

@@ -237,6 +237,16 @@ Type TRuntimeException Extends TBlitzException
 	End Function
 	End Function
 End Type
 End Type
 
 
+Rem
+bbdoc: Invalid enum exception
+about: Thrown when attempting to cast an invalid value to an #Enum. (only in debug mode)
+End Rem
+Type TInvalidEnumException Extends TBlitzException
+	Method ToString$() Override
+		Return "Attempt to cast invalid value to Enum"
+	End Method
+End Type
+
 Function NullObjectError()
 Function NullObjectError()
 	Throw New TNullObjectException
 	Throw New TNullObjectException
 End Function
 End Function
@@ -257,6 +267,10 @@ Function OutOfDataError()
 	Throw New TOutOfDataException
 	Throw New TOutOfDataException
 End Function
 End Function
 
 
+Function InvalidEnumError()
+	Throw New TInvalidEnumException
+End Function
+
 Rem
 Rem
 bbdoc: Generate a runtime error
 bbdoc: Generate a runtime error
 about: Throws a #TRuntimeException.
 about: Throws a #TRuntimeException.

+ 4 - 0
blitz.mod/blitz.h

@@ -50,6 +50,7 @@ extern void brl_blitz_NullFunctionError();
 extern void brl_blitz_ArrayBoundsError();
 extern void brl_blitz_ArrayBoundsError();
 extern void brl_blitz_OutOfDataError();
 extern void brl_blitz_OutOfDataError();
 extern void brl_blitz_RuntimeError( BBString *error );
 extern void brl_blitz_RuntimeError( BBString *error );
+extern void brl_blitz_InvalidEnumError();
 
 
 // BaH
 // BaH
 struct BBClass_brl_blitz_TBlitzException;
 struct BBClass_brl_blitz_TBlitzException;
@@ -73,6 +74,9 @@ extern struct BBClass_brl_blitz_TOutOfDataException brl_blitz_TOutOfDataExceptio
 struct BBClass_brl_blitz_TRuntimeException;
 struct BBClass_brl_blitz_TRuntimeException;
 extern struct BBClass_brl_blitz_TRuntimeException brl_blitz_TRuntimeExeption;
 extern struct BBClass_brl_blitz_TRuntimeException brl_blitz_TRuntimeExeption;
 
 
+struct BBClass_brl_blitz_TInvalidEnumException;
+extern struct BBClass_brl_blitz_TInvalidEnumException brl_blitz_TInvalidEnumException;
+
 
 
 #if 0
 #if 0
 extern BBClass brl_blitz_TBlitzException;
 extern BBClass brl_blitz_TBlitzException;

+ 57 - 0
blitz.mod/blitz_enum.c

@@ -65,6 +65,63 @@ ENUM_TO_STRING(BBLONG,l)
 ENUM_TO_STRING(BBULONG,y)
 ENUM_TO_STRING(BBULONG,y)
 ENUM_TO_STRING(BBSIZET,t)
 ENUM_TO_STRING(BBSIZET,t)
 
 
+#define TRY_ENUM_CONVERT(type,chr)\
+int bbEnumTryConvert_##chr(BBEnum * bbEnum, type ordinalValue, type * ordinalResult) {\
+	type * value = (type*)bbEnum->values;\
+	if (bbEnum->flags) {\
+		int result;\
+		for (int i = 0; i < bbEnum->length; i++) {\
+			if (ordinalValue & *value) {\
+				result |= *value++;\
+			}\
+		}\
+		if (result == ordinalValue) {\
+			*ordinalResult = ordinalValue;\
+			return 1;\
+		}\
+	} else {\
+		if (ordinalValue < *value || ordinalValue > ((type*)bbEnum->values)[bbEnum->length - 1]) {\
+			return 0;\
+		}\
+		for (int i = 0; i < bbEnum->length; i++) {\
+			if (*value++ == ordinalValue) {\
+				*ordinalResult = ordinalValue;\
+				return 1;\
+			}\
+		}\
+	}\
+	return 0;\
+}
+
+TRY_ENUM_CONVERT(BBBYTE,b)
+TRY_ENUM_CONVERT(BBSHORT,s)
+TRY_ENUM_CONVERT(BBINT,i)
+TRY_ENUM_CONVERT(BBUINT,u)
+TRY_ENUM_CONVERT(BBLONG,l)
+TRY_ENUM_CONVERT(BBULONG,y)
+TRY_ENUM_CONVERT(BBSIZET,t)
+
+#ifndef NDEBUG
+
+#define ENUM_CAST(type,chr)\
+type bbEnumCast_##chr(BBEnum * bbEnum, type ordinalValue) {\
+	type result;\
+	if (!bbEnumTryConvert_##chr(bbEnum, ordinalValue, &result)) {\
+		brl_blitz_InvalidEnumError();\
+	}\
+	return result;\
+}
+
+ENUM_CAST(BBBYTE,b)
+ENUM_CAST(BBSHORT,s)
+ENUM_CAST(BBINT,i)
+ENUM_CAST(BBUINT,u)
+ENUM_CAST(BBLONG,l)
+ENUM_CAST(BBULONG,y)
+ENUM_CAST(BBSIZET,t)
+
+#endif
+
 struct enum_info_node {
 struct enum_info_node {
 	struct avl_root link;
 	struct avl_root link;
 	BBEnum * bbEnum;
 	BBEnum * bbEnum;

+ 20 - 0
blitz.mod/blitz_enum.h

@@ -27,6 +27,26 @@ BBString * bbEnumToString_l(BBEnum * bbEnum, BBLONG ordinal);
 BBString * bbEnumToString_y(BBEnum * bbEnum, BBULONG ordinal);
 BBString * bbEnumToString_y(BBEnum * bbEnum, BBULONG ordinal);
 BBString * bbEnumToString_t(BBEnum * bbEnum, BBSIZET ordinal);
 BBString * bbEnumToString_t(BBEnum * bbEnum, BBSIZET ordinal);
 
 
+int bbEnumTryConvert_b(BBEnum * bbEnum, BBBYTE ordinalValue, BBBYTE * ordinalResult);
+int bbEnumTryConvert_s(BBEnum * bbEnum, BBSHORT ordinalValue, BBSHORT * ordinalResult);
+int bbEnumTryConvert_i(BBEnum * bbEnum, BBINT ordinalValue, BBINT * ordinalResult);
+int bbEnumTryConvert_u(BBEnum * bbEnum, BBUINT ordinalValue, BBUINT * ordinalResult);
+int bbEnumTryConvert_l(BBEnum * bbEnum, BBLONG ordinalValue, BBLONG * ordinalResult);
+int bbEnumTryConvert_y(BBEnum * bbEnum, BBULONG ordinalValue, BBULONG * ordinalResult);
+int bbEnumTryConvert_t(BBEnum * bbEnum, BBSIZET ordinalValue, BBSIZET * ordinalResult);
+
+#ifndef NDEBUG
+
+BBBYTE bbEnumCast_b(BBEnum * bbEnum, BBBYTE ordinalValue);
+BBSHORT bbEnumCast_s(BBEnum * bbEnum, BBSHORT ordinalValue);
+BBINT bbEnumCast_i(BBEnum * bbEnum, BBINT ordinalValue);
+BBUINT bbEnumCast_u(BBEnum * bbEnum, BBUINT ordinalValue);
+BBLONG bbEnumCast_l(BBEnum * bbEnum, BBLONG ordinalValue);
+BBULONG bbEnumCast_y(BBEnum * bbEnum, BBULONG ordinalValue);
+BBSIZET bbEnumCast_t(BBEnum * bbEnum, BBSIZET ordinalValue);
+
+#endif
+
 void bbEnumRegister(BBEnum * bbEnum, BBDebugScope *p);
 void bbEnumRegister(BBEnum * bbEnum, BBDebugScope *p);
 BBEnum * bbEnumGetInfo( char * name );
 BBEnum * bbEnumGetInfo( char * name );