MetaTrader 5 / Библиотеки

TypeToBytes - библиотека для MetaTrader 5

5177
(40)

Эта кроссплатформенная библиотека позволяет удобно осуществлять побайтовую работу со структурами, массивами и стандартными типами данных.

Возможности:

  • Побайтовое сравнение (== и !=) между собой структур, массивов и стандартных типов данных (в MQL по умолчанию отсутствуют операторы сравнения структур) в любом сочетании.
  • Определение байтового смещения поля структуры по его имени.
  • Чтение значения любого стандартного типа по байтовому смещению в исходных данных.
  • Запись структур и стандартных типов (через оператор =) по байтовому смещению (через оператор []) в исходные данные.
  • Побайтовое присваивание (через оператор =) для структур и стандартных типов данных.
  • Преобразование структур, массивов и стандартных типов данных в байтовый массив.
  • Побайтовое копирование массива в массив.
  • Определение корректности оператора присваивания структур.
  • Кастинг произвольных структур.
Везде речь идет о простых структурах.

Для демонстрации возможностей библиотеки приложен скрипт с подробными комментариями
// MQL4&5-code #property strict #define PRINT(A) ::Print(#A + " = " + (string)(A)); #ifdef __MQL4__   template <typename T>   void ArrayPrint( const T &Array[] )   {     string Str = "";     const int Size = ArraySize(Array);     for (int i = 0; i < Size; i++)       Str += " " + (string)Array[i];     Print(Str);     return;   } #endif // Задали кастомную структуру struct STRUCT {   int i;   // Задали оператор присваивания   void operator =( const STRUCT& ) {} }; struct STRUCT2 {   MqlTick Tick; }; //#define TYPETOBYTES_FULL_SLOW #include <TypeToBytes.mqh> void OnStart( void ) {   MqlTick Tick;   SymbolInfoTick(Symbol(), Tick);   MqlTick CloneTick = Tick; // Работа со структурами   if (_R(Tick) == CloneTick)             // Теперь структуры можно сравнивать     ::Print("Equal"); // Получения значения требуемого типа по смещению   PRINT(_R(Tick)[(datetime)0])           // Смотрим значение datetime по нулевому смещению в объекте структуры MqlTick - Tick.time // Получение смещения поля структуры   const int Offset = _OFFSET(Tick, bid); // Нашли смещение в байтах поля bid в объекте структуры MqlTick   PRINT(Tick.bid)                        // Посмотрели значение Tick.bid   _W(Tick)[Offset] = 1.23456;            // Записали по найденному смещению значение (double)1.23456   PRINT(Tick.bid)                        // Убедились, что Tick.bid теперь равен 1.23456   PRINT(_R(Tick)[(double)Offset])        // Распечатали значение double, находящееся по смещению Offset - это снова Tick.bid   PRINT(_R(Tick).Bytes[8])               // Посмотрели значение байта со смещением 8 в объекте структуры MqlTick   PRINT(_R(Tick)[(uchar)8])              // То же самое, но другим способом   PRINT(CloneTick.bid)                   // Посмотрели значение CloneTick.bid   _W(CloneTick)[0] = Tick;               // Записали в CloneTick по нулевому смещению значение структурного объекта Tick   PRINT(CloneTick.bid)                   // Убедились, что CloneTick.bid == Tick.bid // Работа со стандартными типами   color Color = C'241,248,255';   PRINT(_R(Color)[(uchar)1])             // Green-составляющая цвета - 248   _W(Color)[2] = (uchar)230;             // Записали по смещению 2 значение (uchar)230.   PRINT(Color)                           // Убедились, что Color теперь C'241,248,230' // Одновременная работа со смешанными типами   PRINT((_R(Tick) != Color))             // Можно сравнивать даже структуры со стандартными типами // Побайтовый оператор присваивания   int i = 0;   _W(i) = (float)12.34;                  // Записали в int-переменную побайтовое представление числа (float)12.34   PRINT(i)                               // Посмотрели, что это 1095069860   float f = 0;   _W(f) = i;                             // Записали во float-переменную побайтовое представление ранее полученного числа (int)1095069860   PRINT(f)                               // Убедились, что теперь значение равно исходному - (float)12.34   ArrayPrint(_R(256).Bytes);             // Распечатали побайтовое представление числа (int)256 // Работа с массивами   short Array[] = {1, 2, 3};   ArrayPrint(_R(Array).Bytes);           // Распечатали побайтовое представление массива Array   PRINT((_R(Array) == _R(Array).Bytes))  // Убедились, что побайтовое сравнение массивов работает.   _W(Color) = Array;                     // Побайтово записали массив Array в Color   PRINT(Color)                           // Убедились, что Color теперь C'1,0,2'   ArrayPrint(_R(Color).Bytes);           // Распечатали побайтовое представления Color   uchar Array2[];   ArrayCopy(Array2, _R(Tick).Bytes);     // Записали в Array2 байтовое представление Tick   PRINT((_R(Tick) == Array2))            // Убедились, что Tick и Array2 побайтово совпадают   MqlTick Tick2 = {0};   _W(Tick2) = Array2;                    // Записали в Tick2 массив Array2   PRINT((_R(Tick) == Tick2))             // Убедились, что Tick и Tick2 совпадают   int Array3[] = {INT_MIN, INT_MAX};   ArrayPrint(_R(Array3).Bytes);          // Распечатали побайтовое представление массива Array3   ArrayPrint(_R(Array).Bytes);           // Распечатали побайтовое представление массива Array   _ArrayCopy(Array3, Array);             // Скопировали побайтово массив Array в массив Array3   ArrayPrint(_R(Array3).Bytes);          // Убедились, что побайтовое представление массив Array3 соответствует // Работа со строками   string Str = "abcd";   _W(i) = Str;                           // Записали в (int)i строку побайтово   PRINT((_R(i) == Str))                  // Сравнили побайтово int и sring   ArrayPrint(_R(i).Bytes);               // Посмотрели байты i   ArrayPrint(_R(Str).Bytes);             // Посмотрели байты Str   PRINT(_R(Str)[(short)1])               // Взяли short-значение по смешению 1 в строке Str   PRINT(Str)   _W(Str)[2] = "98765";                  // Побайтовая запись строки в строку со смещением 2   PRINT(Str)   string StrArray[] = {"123", "45", "6789"};   _W(Str) = StrArray;                    // Записали в строку строковый массив   PRINT(Str)   _W(Str)[3] = (uchar)0;                 // В байт со смещением 3 записали ноль, тем самым отбрезав строку (длина - 3 ANSI-символа (4 байта))   PRINT(Str); // Демонстрация результата обхода кастомного оператора присваивания структуры _R-функционалом библиотеки - нужен TYPETOBYTES_FULL_SLOW   STRUCT Struct;                         // Создали объект с кастомным оператором присваивания   Struct.i = 1;   ArrayPrint(_R(Struct).Bytes);          // Убедились, что оператор присваивания   PRINT(_R(Struct) == Struct)            // не влияет на _R-функционал библиотеки // Проверка "корректности" оператора присваивания типа   PRINT(_WRONG_ASSIGN_OPERATOR(int))     // Корректен   PRINT(_WRONG_ASSIGN_OPERATOR(MqlTick)) // Корректен   PRINT(_WRONG_ASSIGN_OPERATOR(STRUCT))  // Не корректен // Кастинг произвольных простых структур (если есть конструктор или кастомный оператор присваивания - нужен TYPETOBYTES_FULL_SLOW)   STRUCT2 Struct2 = _C(STRUCT2, Tick);   // Аналог классического кастинга STRUCT2 Struct2 = (STRUCT2)Tick;   PRINT(_R(Struct2) == Tick)             // Убедились, что Struct2 == Tick   Struct2.Tick.time = __DATETIME__;      // Изменили Struct2   PRINT(_R(Struct2) == Tick)             // Убедились, что Struct2 != Tick   _W(Struct2) = Tick;                    // Побайтово скопировали Tick в Struct2   PRINT(_R(Struct2) == Tick)             // Убедились, что Struct2 == Tick // Извлечение строк   int ArrayINT[];   string ArraySTR[] = {"123", "456", "789"};   _ArrayCopy(ArrayINT, ArraySTR);        // Скопировали побайтово массив ArraySTR в массив ArrayINT   ArrayPrint(_R(ArrayINT).Bytes);        // Посмотрели байты полученного массива   string ArraySTR2[];   _ArrayCopy(ArraySTR2, ArrayINT);       // Скопировали побайтово массив ArrayINT в массив ArraySTR2   ArrayPrint(ArraySTR2);                 // Распечатали полученный массив   PRINT(_R(ArraySTR) == ArraySTR2)       // Убедились, что ArraySTR == ArraySTR2   PRINT(_R(ArrayINT)[(string)1])         // Извлекли строку из ArrayINT, начинующуюся с байта 1 - "23"   return; }