// Copyright (C) 2007 EQ2EMulator Development Team, GPL v3+ #pragma once #include #include #include "../log.hpp" #include "../types.hpp" #include "../misc_functions.hpp" #define DATA_STRUCT_NONE 0 #define DATA_STRUCT_INT8 1 #define DATA_STRUCT_INT16 2 #define DATA_STRUCT_INT32 3 #define DATA_STRUCT_INT64 4 #define DATA_STRUCT_FLOAT 5 #define DATA_STRUCT_DOUBLE 6 #define DATA_STRUCT_COLOR 7 #define DATA_STRUCT_SINT8 8 #define DATA_STRUCT_SINT16 9 #define DATA_STRUCT_SINT32 10 #define DATA_STRUCT_CHAR 11 #define DATA_STRUCT_EQ2_8BIT_STRING 12 #define DATA_STRUCT_EQ2_16BIT_STRING 13 #define DATA_STRUCT_EQ2_32BIT_STRING 14 #define DATA_STRUCT_EQUIPMENT 15 #define DATA_STRUCT_ARRAY 16 #define DATA_STRUCT_ITEM 17 #define DATA_STRUCT_SINT64 18 class DataStruct { public: // Default constructor - initializes all member variables to default values DataStruct() { item_size = 0; type = 0; type2 = 0; length = 1; if_flag_set = false; if_flag_not_set = false; if_set = false; if_not_set = false; if_not_equals = false; if_equals = false; is_set = false; optional = false; oversized = 0; oversized_byte = 0; add = false; addType = 0; maxArraySize = 0; default_value = 0; } // Copy constructor - creates new DataStruct from existing one DataStruct(DataStruct* data_struct) { type = data_struct->GetType(); type2 = data_struct->GetType2(); length = data_struct->GetLength(); name = data_struct->GetName(); array_size_variable = data_struct->array_size_variable; default_value = data_struct->default_value; add = true; addType = type; oversized = data_struct->GetOversized(); oversized_byte = data_struct->GetOversizedByte(); maxArraySize = data_struct->GetMaxArraySize(); if_flag_set = false; if_flag_not_set = false; if_set = false; if_not_set = false; if_not_equals = false; if_equals = false; optional = false; if (data_struct->GetIfSet()) SetIfSetVariable(data_struct->GetIfSetVariable()); if (data_struct->GetIfNotSet()) SetIfNotSetVariable(data_struct->GetIfNotSetVariable()); if (data_struct->GetIfNotEquals()) SetIfNotEqualsVariable(data_struct->GetIfNotEqualsVariable()); if (data_struct->GetIfEquals()) SetIfEqualsVariable(data_struct->GetIfEqualsVariable()); if (data_struct->GetIfFlagSet()) SetIfFlagSetVariable(data_struct->GetIfFlagSetVariable()); if (data_struct->GetIfFlagNotSet()) SetIfFlagNotSetVariable(data_struct->GetIfFlagNotSetVariable()); item_size = 0; is_set = false; } // Constructor with name and type strings DataStruct(const char* new_name, const char* new_type, int32 new_length, const char* new_type2) { name = std::string(new_name); type = 0; type2 = 0; SetType(new_type, &type); if (new_type2) SetType(new_type2, &type2); length = new_length; add = true; addType = type; if_set = false; if_not_set = false; is_set = false; if_not_equals = false; item_size = 0; } // Constructor with name and length only DataStruct(const char* new_name, int32 new_length) { name = std::string(new_name); length = new_length; if_set = false; if_not_set = false; is_set = false; item_size = 0; } // Constructor with name, type integers, and length DataStruct(const char* new_name, int8 new_type, int32 new_length, int8 new_type2) { name = std::string(new_name); type = new_type; length = new_length; type2 = new_type2; addType = type; if_set = false; if_not_set = false; is_set = false; item_size = 0; } // Converts type string to numeric type constant void SetType(const char* new_type, int8* output_type) { if (strlen(new_type) > 3 && strncasecmp("int", new_type, 3) == 0) { if (strncasecmp("int8", new_type, 4) == 0) *output_type = DATA_STRUCT_INT8; else if (strncasecmp("int16", new_type, 5) == 0) *output_type = DATA_STRUCT_INT16; else if (strncasecmp("int32", new_type, 5) == 0) *output_type = DATA_STRUCT_INT32; else if (strncasecmp("int64", new_type, 5) == 0) *output_type = DATA_STRUCT_INT64; } else if (strlen(new_type) > 4 && strncasecmp("sint", new_type, 4) == 0) { if (strncasecmp("sint8", new_type, 5) == 0) *output_type = DATA_STRUCT_SINT8; else if (strncasecmp("sint16", new_type, 6) == 0) *output_type = DATA_STRUCT_SINT16; else if (strncasecmp("sint32", new_type, 6) == 0) *output_type = DATA_STRUCT_SINT32; else if (strncasecmp("sint64", new_type, 6) == 0) *output_type = DATA_STRUCT_SINT64; } else if (strlen(new_type) == 4 && strncasecmp("char", new_type, 4) == 0) *output_type = DATA_STRUCT_CHAR; else if (strlen(new_type) == 5 && strncasecmp("float", new_type, 5) == 0) *output_type = DATA_STRUCT_FLOAT; else if (strlen(new_type) == 6 && strncasecmp("double", new_type, 6) == 0) *output_type = DATA_STRUCT_DOUBLE; else if (strlen(new_type) >= 5 && strncasecmp("EQ2_", new_type, 4) == 0) { if (strncasecmp("EQ2_8", new_type, 5) == 0) *output_type = DATA_STRUCT_EQ2_8BIT_STRING; else if (strncasecmp("EQ2_16", new_type, 6) == 0) *output_type = DATA_STRUCT_EQ2_16BIT_STRING; else if (strncasecmp("EQ2_32", new_type, 6) == 0) *output_type = DATA_STRUCT_EQ2_32BIT_STRING; else if (strncasecmp("EQ2_E", new_type, 5) == 0) *output_type = DATA_STRUCT_EQUIPMENT; else if (strncasecmp("EQ2_C", new_type, 5) == 0) *output_type = DATA_STRUCT_COLOR; else if (strncasecmp("EQ2_I", new_type, 5) == 0) *output_type = DATA_STRUCT_ITEM; } else if (strlen(new_type) >= 5) { if (strncasecmp("Array", new_type, 5) == 0) *output_type = DATA_STRUCT_ARRAY; } else LogWrite(PACKET__ERROR, 0, "Packet", "Invalid Type: %s", new_type); } // Setter methods void SetType(int8 new_type) { type = new_type; addType = type; } void SetMaxArraySize(int8 size) { maxArraySize = size; } void SetOversized(int8 val) { oversized = val; } void SetDefaultValue(int8 new_val) { default_value = new_val; } void SetName(const char* new_name) { name = std::string(new_name); } void SetLength(int32 new_length) { length = new_length; } void SetOversizedByte(int8 val) { oversized_byte = val; } void SetAddToStruct(bool val) { add = val; } void SetAddType(int8 new_type) { addType = new_type; } void SetArraySizeVariable(const char* new_name) { array_size_variable = std::string(new_name); } void SetIsSet(bool val) { is_set = val; } void SetIsOptional(bool val) { optional = val; } // Sets item size in bytes and marks as set if size > 0 void SetItemSize(int32 val) { item_size = val; if (item_size) is_set = true; else is_set = false; } // Conditional variable setters void SetIfEqualsVariable(const char* variable) { if (variable) { if_equals = true; if_equals_variable = std::string(variable); } else if_equals = false; } void SetIfNotEqualsVariable(const char* variable) { if (variable) { if_not_equals = true; if_not_equals_variable = std::string(variable); } else if_not_equals = false; } void SetIfFlagNotSetVariable(const char* variable) { if (variable) { if_flag_not_set = true; if_flag_not_set_variable = std::string(variable); } else if_flag_not_set = false; } void SetIfFlagSetVariable(const char* variable) { if (variable) { if_flag_set = true; if_flag_set_variable = std::string(variable); } else if_flag_set = false; } void SetIfSetVariable(const char* variable) { if (variable) { if_set = true; if_set_variable = std::string(variable); } else if_set = false; } void SetIfNotSetVariable(const char* variable) { if (variable) { if_not_set = true; if_not_set_variable = std::string(variable); } else if_not_set = false; } // Getter methods const char* GetArraySizeVariable() { return array_size_variable.c_str(); } int32 GetItemSize() { return item_size; } bool GetIfSet() { return if_set; } bool GetIfNotSet() { return if_not_set; } bool GetIfEquals() { return if_equals; } bool GetIfNotEquals() { return if_not_equals; } bool GetIfFlagSet() { return if_flag_set; } bool GetIfFlagNotSet() { return if_flag_not_set; } bool IsSet() { return is_set; } bool IsOptional() { return optional; } bool AddToStruct() { return add; } int8 GetDefaultValue() { return default_value; } int8 GetType() { return type; } int8 GetType2() { return type2; } int8 GetOversized() { return oversized; } int8 GetOversizedByte() { return oversized_byte; } int8 GetMaxArraySize() { return maxArraySize; } int8 GetAddType() { return addType; } int32 GetLength() { return length; } const char* GetName() { return name.c_str(); } std::string GetStringName() { return name; } // Conditional variable getters const char* GetIfSetVariable() { if (if_set_variable.length() > 0) return if_set_variable.c_str(); return 0; } const char* GetIfNotSetVariable() { if (if_not_set_variable.length() > 0) return if_not_set_variable.c_str(); return 0; } const char* GetIfEqualsVariable() { if (if_equals_variable.length() > 0) return if_equals_variable.c_str(); return 0; } const char* GetIfNotEqualsVariable() { if (if_not_equals_variable.length() > 0) return if_not_equals_variable.c_str(); return 0; } const char* GetIfFlagSetVariable() { if (if_flag_set_variable.length() > 0) return if_flag_set_variable.c_str(); return 0; } const char* GetIfFlagNotSetVariable() { if (if_flag_not_set_variable.length() > 0) return if_flag_not_set_variable.c_str(); return 0; } // Appends variable name to existing variable list, avoiding duplicates std::string AppendVariable(std::string orig, const char* val) { if (!val) return orig; if (orig.length() == 0) return std::string(val); if (orig.find(",") < 0xFFFFFFFF) { // has more than one already std::string valstr = std::string(val); std::vector* varnames = SplitString(orig, ','); if (varnames) { for (int32 i = 0; i < varnames->size(); i++) { if (valstr.compare(varnames->at(i)) == 0) { return orig; // already in the variable, no need to append } } safe_delete(varnames); } } return orig.append(",").append(val); } // Calculates total data size in bytes based on type and length int32 GetDataSizeInBytes() { int32 ret = 0; switch (type) { case DATA_STRUCT_INT8: ret = length * sizeof(int8); break; case DATA_STRUCT_INT16: ret = length * sizeof(int16); break; case DATA_STRUCT_INT32: ret = length * sizeof(int32); break; case DATA_STRUCT_INT64: ret = length * sizeof(int64); break; case DATA_STRUCT_SINT8: ret = length * sizeof(sint8); break; case DATA_STRUCT_SINT16: ret = length * sizeof(sint16); break; case DATA_STRUCT_SINT32: ret = length * sizeof(sint32); break; case DATA_STRUCT_SINT64: ret = length * sizeof(sint64); break; case DATA_STRUCT_FLOAT: ret = length * sizeof(float); break; case DATA_STRUCT_DOUBLE: ret = length * sizeof(double); break; case DATA_STRUCT_ARRAY: // Array elements won't have a size so get out now to avoid the warning. break; default: LogWrite(PACKET__WARNING, 0, "DataStruct", "Tried retrieving a data size from an unsupported data struct type in GetDataSizeInBytes()"); break; } return ret; } // Adds variable to if-set condition list void AddIfSetVariable(const char* val) { if (val) { if_set_variable = AppendVariable(if_set_variable, val); is_set = true; } } // Adds variable to if-not-set condition list void AddIfNotSetVariable(const char* val) { if (val) { if_not_set_variable = AppendVariable(if_not_set_variable, val); if_not_set = true; } } private: bool is_set; // Whether this data structure contains data bool if_not_set; // Conditional inclusion based on variable not set bool optional; // Whether this field is optional bool if_set; // Conditional inclusion based on variable set bool if_not_equals; // Conditional inclusion based on variable not equals bool if_equals; // Conditional inclusion based on variable equals bool if_flag_set; // Conditional inclusion based on flag set bool if_flag_not_set; // Conditional inclusion based on flag not set std::string if_flag_not_set_variable; // Variable name for flag not set condition std::string if_flag_set_variable; // Variable name for flag set condition std::string if_not_equals_variable; // Variable name for not equals condition std::string if_equals_variable; // Variable name for equals condition std::string if_not_set_variable; // Variable name for not set condition std::string if_set_variable; // Variable name for set condition int8 oversized; // Threshold for oversized data handling int8 oversized_byte; // Byte marker for oversized data bool add; // Whether to include in packet structure int8 addType; // Type to use when adding to packet int8 maxArraySize; // Maximum allowed array size std::string array_size_variable; // Variable name containing array size std::string name; // Name identifier of this data structure int8 type; // Primary data type int8 default_value; // Default value for initialization int8 type2; // Secondary data type (for special cases) int32 length; // Number of elements/length int32 item_size; // Size in bytes for item data };