На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Парсим байтовый массив в динамическую структуру , byte[] в СТРУКТУРА
    Уважаемые форумчане подскажите такой вопрос ,
    как создать структуру во время выполнения программы не зная заранее ни количества не тип полей ,
    и после этого загнать в эту структуру байтовый массив

    типа псевдо код
    ExpandedWrap disabled
        byte[] BytBuf ; // уже заполненный байтовый массив
       
        infCol[]  // уже заполненный массив структур "информация о колонках "
       
        СТРУКТУРА  структ = new СТРУКТУРА() // объявили пустую структуру-приемник
       
        for(int n=0; n<Кол-воКолонок ; n++)
        {
          структ.ДобавитьНовоеПоле.Тип =  infCol[n].type ;
        }
       
         структ =  BytBuf  ; //  вот как то так сразу в массив
      Использовать контейнеры, ну например vector<char>, а этот вектор состоящий из количества байт снова можно положить в контейнер
      vector< vector<char> >
        например
        ExpandedWrap disabled
          std::map<std::string, std::variant>
          Да просто делаете:
          ExpandedWrap disabled
            class СТРУКТУРА
            {
              char **data;
              int *длина;
            };


          Сначала узнаёте кол-во полей:
          ExpandedWrap disabled
            длина = new int[кол_во];

          А после - столько данных и создаёте:
          ExpandedWrap disabled
            data = new char*[кол_во];

          Ну а дальше уже выделяете под каждое поле столько байт, сколько надо:
          ExpandedWrap disabled
            data[i] = new char[длина[i]];
            Цитата ter_nk_ @
            Использовать контейнеры, ну например vector<char>,

            но массив и так находится в byte[] BytBuf, т.е. еще раз переложить в char[] , а потом еще раз ,
            по моему то немного не то ,

            Добавлено
            Цитата ter_nk_ @
            а этот вектор состоящий из количества байт снова можно положить в контейнер
            vector< vector<char> >

            такая упаковка наврят ли поможет разобрать массив , или возможно я ошибаюсь , давайте попробуем ,
            вот например вот такой у меня массив уже заполненый байтоми

            byte[] BytBuf ; // уже заполненный байтовый массив

            как мне его загнать в vector< vector<char> > с учетом infCol[n].type - "иформация о колонках"

            Добавлено
            Цитата Алексей_Л @

            например

            std::map<std::string, std::variant>

            разверните хоть чуть чуть, подробней , потому что контейнер map я плохо знаю

            возможно там как то можно сделать , но разве он сам сможет определить тип ,
            контейнеру map я так думаю надо самому указывать строку и тип , и тогда он уже ищет я правильно понимаю ?
            или нет ?

            Добавлено
            Славян ок Ваш вариант сейчас пробую
              Славян помоги пожалуйста , вот примерно накидал насколько хватило ума ,
              ExpandedWrap disabled
                ...
                   //  pCol    - кол-во колонок в результате
                   // pRecSize - длина строки , одной записи в байтах , в результате
                   // pStr     - коли
                 
                 int  *dlina  = new int[pCol];       // Сначала узнаёте кол-во полей:
                 
                     char **data = new char*[pRecSize];  // А после - столько данных и создаёте :
                    
                      for (long i = 0; i < pStr; i++)    //проход как бы по строкам
                      {
                          for (int j = 0; j < pCol; j++) //каждую строку перебираем по количеству полей
                          {
                              data[j] = new char[dlina[i]]; //  Ну а дальше уже выделяете под каждое поле столько байт, сколько надо
                              std::cout << data[j] <<  " ";
                          }
                          std::cout <<   std::endl;
                      }
                kms а откуда этот массив? я что-то уже позабыл что откуда берётся :)
                  Цитата Cfon @
                  а откуда этот массив?

                  из леса вестимо , слышишь батя рубит а отважу :)

                  из HyTech конечно же вот до сих пор верчу по всякому
                    ExpandedWrap disabled
                      struct CField
                      {
                         int m_type;
                         std::vector<char> m_data;
                      };
                       
                      struct CRecord
                      {
                         std::vector<CField> m_fields;
                      }
                       
                      ..............................................
                      std::list<CRecord> records;
                      for (....) //Пробегаем по всем строкам
                      {
                         const auto err = hcSqlReadResults(pOper, i, bufOut, sizeof(bufOut), &cntOut);// Чтение результатов
                         char *p = bufOut;
                         CRecord rec;
                         rec.m_fields.reserve(Количство колонок);
                         for (....) //По всем колонкам
                         {
                            CField field;
                            field.m_type = infCol[n].type;
                            field.m_data.insert(field.m_data.end(), p, p + infCol[j].len);
                            rec.m_fields.emplace_back(std::move(field));    
                       
                            p += infCol[j].len;
                         }
                         record.emplace_back(std::move(rec));
                       
                      }
                      Цитата Алексей_Л @
                      например

                      Думаю std::vector<std::any> будет получше, поменьше оверхеда.
                        kms, а можно уточняющий вопрос? Как именно описываются поля структуры, и как содержимое байтового массива соотносится с этими полями? Так то очень сильно смахивает на почти типовую задачу десериализации данных на базе дескрипторов.

                        Добавлено
                        Должно получиться что-то вроде этого:

                        ExpandedWrap disabled
                          #include <iostream>
                          #include <cstdlib>
                          #include <sstream>
                          #include <boost/property_tree/ptree.hpp>
                          #include <boost/property_tree/json_parser.hpp>
                           
                          namespace pt = boost::property_tree;
                           
                          enum class ColTypes
                          {
                              Int32,
                              String
                          };
                           
                          class ColInfo
                          {
                          public:
                              ColInfo(const std::string& colName, ColTypes colType)
                                  : m_name(colName)
                                  , m_type(colType)
                              {
                              }
                              
                              void ReadFromStream(std::istream& is, pt::ptree& data)
                              {
                                  switch (m_type)
                                  {
                                  case ColTypes::Int32:
                                      ReadInt32Col(is, data);
                                      break;
                                  case ColTypes::String:
                                      ReadStringCol(is, data);
                                      break;
                                  }
                              }
                              
                          private:
                              void ReadInt32Col(std::istream& is, pt::ptree& data)
                              {
                                  union
                                  {
                                      uint8_t buff[sizeof(int32_t)];
                                      int32_t value;
                                  };
                                  
                                  is.read((char*)buff, sizeof(buff));
                                  data.add(m_name, value);
                              }
                              
                              void ReadStringCol(std::istream& is, pt::ptree& data)
                              {
                                  union
                                  {
                                      uint8_t sizeBuff[sizeof(int32_t)];
                                      int32_t size;
                                  };
                                  
                                  is.read((char*)sizeBuff, sizeof(sizeBuff));
                                  std::string value(size, '\0');
                                  is.read(&value[0], size);
                                  data.add(m_name, value);
                              }
                              
                          private:
                              std::string m_name;
                              ColTypes m_type;
                          };
                           
                          int main()
                          {
                              pt::ptree props1;
                              pt::ptree props2;
                              
                              props1.put("Col1", 10);
                              props1.put("Col2", "Hello, Wandbox!");
                              
                              ColInfo colsInfo[] = {{"Col1", ColTypes::Int32}, {"Col2", ColTypes::String}};
                              
                              std::string bin = {'\x0a', 0, 0, 0, '\x0f', 0, 0, 0, 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'a', 'n', 'd', 'b', 'o', 'x', '!'};
                              std::istringstream raw(bin);
                              
                              for (auto& colInfo : colsInfo)
                                  colInfo.ReadFromStream(raw, props2);
                           
                              pt::write_json(std::cout, props1);
                              pt::write_json(std::cout, props2);
                              // std::cout << jsonRes << std::endl;
                          }
                          Цитата kms @
                          такая упаковка наврят ли поможет разобрать массив , или возможно я ошибаюсь , давайте попробуем ,
                          вот например вот такой у меня массив уже заполненый байтоми

                          byte[] BytBuf ; // уже заполненный байтовый массив

                          как мне его загнать в vector< vector<char> > с учетом infCol[n].type - "иформация о колонках"


                          Не очень понимаю. Если у тебя vector< vector<char> > то это массив массивов для тебя

                          0 1 6 0 5 3 2
                          3 5 7 4 5
                          2 4 5 6

                          Ты можешь добавлять удалять вставлять элементы в любом из них, если информацию о них кранить типа это массив о сем, о том, т.е.

                          0 1 6 0 5 3 2 это массив о том
                          3 5 7 4 5 это массив о сем
                          2 4 5 6 это массив не знаю где

                          то тебе написали

                          ExpandedWrap disabled
                            struct OneArray
                            {
                            std::string sArrInfo; (ну или идинтификатор, что надо)
                            vector<char> arr;
                            }
                             
                            vector<OneArray> myExample;
                             
                            Сюда добавляй удаляй.
                            Олег М спасибо , сделал как Вы написали , компилируется ,
                            в конце пытаюсь добавить вывод на экран вот так
                            ExpandedWrap disabled
                              std::copy(records.begin(), records.end(), std::ostream_iterator<std::string>(std::cout, " "));

                            но пишет ошибку
                            ExpandedWrap disabled
                              СерьезностьКодОписаниеПроектФайлСтрока
                              ОшибкаC2679бинарный "=": не найден оператор, принимающий правый операнд типа "CRecord" (или приемлемое преобразование отсутствует)AdmHyTechc:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility2148


                            Добавлено
                            Цитата Flex Ferrum @
                            а можно уточняющий вопрос? Как именно описываются поля структуры, и как содержимое байтового массива соотносится с этими полями?

                            если будет удобней и не затруднит http://hytechdb.ru/index.php?s=docs&ru=V25...SqlDstInfoT.htm
                            вот так выглядит у меня на сегодняшний день
                            ExpandedWrap disabled
                              #define HYCFG_WIN32
                              #include "hscli.h"
                              #include <iostream>
                              #include <memory>
                              #include <vector>
                              #include <list>
                              #include <string>
                              #include <algorithm>
                              #include <iterator>
                               
                              using namespace std;
                               
                              #define SIZE_HCSQLDSTINFOT      128
                               
                              int main() {
                                  //setlocale(LC_ALL, "RUS"); //  рус локаль
                                  hcERR     err ; // Код ошибки
                                  hcHDB     pdb ; // Адрес памяти, куда будет записан идентификатор   соединения.
                                  hcHSTMT pOper ; // Адрес памяти, куда будет записан идентификатор   оператора.
                                  hcSqlParmT Init = { sizeof(Init) }; // Адрес структуры с параметрами инициализации
                                  int      pCol     = 0 ; // количество колонок
                                  hcRECNO  pStr     = 0 ; // количество строк  
                                  unsigned cntOp    = 0 ; // Размер считанной информации в байтах, в ф-ции "Получить информацию об операторе".
                                  unsigned pRecSize = 0 ; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" .
                                  unsigned cntOut   = 0 ; // для ф-ции "Чтение результатов" Адрес, куда функция запишет количество байтов данных, помещённых в буфер пользователя. Если это количество разделить на длину записи, то получим количество считанных записей. Неполные записи не присылаются.
                               
                                  if (err = hcSqlInit(&Init) != 0) {/* Инициализация клиентской части */ std::cout << "Ошибка с параметрами инициализации \n" ; return 0; }
                                  if (hcSqlCheckInit()  < 0) {  /* Проверка завершения инициализации */ std::cout << "Ошибка завершения инициализации \n" ; return 0; }
                                  err = hcSqlAllocConnect(&pdb);                                // Создать соединение
                                  err = hcSqlConnect(pdb, "tcpip:/localhost:13000", "HTADMIN", "PASSWORD");//Установить связь с СУБД
                                  err = hcSqlAllocStmt(pdb, &pOper);                            // Создать оператор
                                  err = hcSqlExecDirect(pOper, "fix all; select * from CITY;"); // Выполняем SQLзапрос GROUP TAB TABLES USERSPEC UGROUPS
                                  err = hcSqlNumResultCols(pOper, &pCol) ;                      // Получить количество колонок результата
                                  err = hcSqlRowCount(pOper, &pStr)      ;                      // Получить количество строк результата
                                  
                                  hcSqlDstInfoT *infCol = new hcSqlDstInfoT[pCol];//  Структура   "Информация о колонках результата"
                                  
                                  err = hcSqlOpenResults(pOper, &pRecSize);    // Открытие результатов для чтения
                                  
                                  err = hcSqlGetStmtAttr(pOper, HSCLI_STMT_DST_INFO, 0, infCol, pCol * SIZE_HCSQLDSTINFOT, &cntOp);// Получить информацию об операторе
                               
                                  char *bufOut = new char[pRecSize * pStr]; // Адрес буфера для присылаемых записей.
                                  
                                  err = hcSqlReadResults(pOper, 0, bufOut, pRecSize * pStr, &cntOut); // Чтение результатов
                               
                                  char *p = bufOut; //  делаем указатель на массив
                                
                                  for (long i = 0; i <  pStr; i++)//идем по строкам
                                  {
                                  
                                   for (int j = 0; j < pCol; j++ ) // идем по колонкам
                                   {
                                     switch (infCol[j].type)
                                     {
                                      case HSCLI_ET_CHAR: { // 0 Массив символов длиной не более заданной
                                          std::string s(p, infCol[j].len) ;      std::cout   << s.c_str() << "  " ; }
                                          break;
                                                
                                      case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины
                                          std::cout << *reinterpret_cast<unsigned char *>(p) << "  ";
                                          break;
                               
                                      case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое)  short
                                          std::cout << *reinterpret_cast<unsigned char *>(p) << "  ";
                                          break;
                               
                                      case HSCLI_ET_INTR: // 3 Элемент - signed short  
                                          std::cout << *reinterpret_cast<signed short *>(p) << "  " ;
                                          break;
                                              
                                      case HSCLI_ET_WORD: // 4 Элемент - unsigned short  
                                                 std::cout   << *reinterpret_cast<unsigned short *>(p) << "  " ;
                                           break;
                               
                                      case HSCLI_ET_DATE: // 5 Дата    - unsigned short  
                                                   std::cout << *reinterpret_cast<unsigned short *>(p) << "  " ;
                                           break;
                               
                                      case HSCLI_ET_NMBR: //6  Номер   - 3-х байтовое целое без знака  
                                                  // std::cout << *reinterpret_cast<  *>(p);
                                           break;
                               
                                      case HSCLI_ET_LONG: //7 Элемент - long int
                                           std::cout << *reinterpret_cast<long int *>(p) << "  " ;
                                           break;
                               
                                      case  HSCLI_ET_DWRD: // 8 Элемент - unsigned long int  в БД это dword          
                                           std::cout <<  *reinterpret_cast<unsigned long int *>(p) << "  ";
                                           break;
                               
                                      case HSCLI_ET_FLOA: //  9  Элемент - float
                                           std::cout << *reinterpret_cast<float *>(p) << "  ";
                                           break;
                               
                                      case HSCLI_ET_CURR: //  10 Деньги (double)  
                                           std::cout << *reinterpret_cast<double *>(p) << "  ";
                                           break;
                               
                                      case HSCLI_ET_DFLT: // 11 Элемент - double  
                                           std::cout   << *reinterpret_cast<double *>(p) << "  ";
                                           break;
                               
                                      case HSCLI_ET_QINT: //  12 Элемент - signed __int64
                                           std::cout << *reinterpret_cast<signed __int64 *>(p) << "  ";
                                           break;
                                      
                                      case HSCLI_ET_QWRD: //  13 Элемент - unsigned __int64
                                           std::cout << *reinterpret_cast<unsigned __int64 *>(p) << "  ";
                                           break;
                                      }
                                    
                                      p += infCol[j].len;
                                      
                                   }
                                   std::cout << std::endl ;
                                  }
                                  
                                  hcSqlCloseResults(pOper); // Закрытие доступа к результатам
                                  hcSqlFreeConnect(pdb);    // Освободить соединение
                                  hcSqlDone();              // Завершение работы
                                  std::system("pause");
                              }

                            это работает , но мне хочется изучить этот вопрос полностью, т.е. знать как делается в других СУБД , или вообще возможные варианты

                            Добавлено
                            Цитата Flex Ferrum @
                            Должно получиться что-то вроде этого:

                            да что то в этом есть , пробую , я так понял надо class ColTypes из этого примера сделать не на дватипа а у меня 13 типов поетому мне надо делать класс с 13 полями на каждый тип
                              Олег М
                              вот так сделал
                              ExpandedWrap disabled
                                for (int i = 0; i < pStr; i++) //Пробегаем по всем строкам
                                                      {
                                                        CRecord rec;
                                                        rec.m_fields.reserve(pCol);
                                 
                                                        for (int j = 0; j < pCol; j++) //По всем колонкам
                                                        {
                                                            CField field;
                                                            field.m_type = infCol[j].type;
                                                            field.m_data.insert(field.m_data.end(), p, p + infCol[j].len);
                                                            rec.m_fields.emplace_back(std::move(field));
                                                            field.m_data.insert(field.m_data.end(), p, p + infCol[j].len);
                                                            p += infCol[j].len;
                                 
                                                            for (int n = 0; n < infCol[j].len; n++)// вывожу на экран
                                                                cout << field.m_data[n] << " ";    
                                 
                                                        }
                                                        records.emplace_back(std::move(rec));
                                                        
                                                        cout <<   "\r\n ";
                                                      }


                              вот такой результат
                              Прикреплённая картинка
                              Прикреплённая картинка
                                Цитата kms @
                                но пишет ошибку

                                Надо добавить операторы вывода в поток

                                ExpandedWrap disabled
                                  struct CField
                                  {
                                      int m_type;
                                      std::vector<char> m_data;
                                      friend std::ostream &operator<<(std::ostream &out, const CField &field);
                                  };
                                   
                                   
                                  struct CRecord
                                  {
                                     std::vector<CField> m_fields;
                                     friend std::ostream &operator<<(std::ostream &out, const CRecord &rec);
                                  };
                                   
                                  std::ostream &operator<<(std::ostream &out, const CField &field)
                                  {
                                       switch (field.m_type)
                                         {
                                          case HSCLI_ET_CHAR: // 0 Массив символов длиной не более заданной
                                              out << std::string(field.m_data.begin(), field.m_data.end());
                                              break;
                                   
                                          case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины
                                              //out << *reinterpret_cast<unsigned char *>(field.m_data.data());
                                              break;
                                   
                                          case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое)  short
                                              out << *reinterpret_cast<unsigned char *>(field.m_data.data());
                                              break;
                                   
                                          case HSCLI_ET_INTR: // 3 Элемент - signed short
                                              out << *reinterpret_cast<signed short *>(field.m_data.data());
                                              break;
                                   
                                          case HSCLI_ET_WORD: // 4 Элемент - unsigned short
                                              out << *reinterpret_cast<unsigned short *>(field.m_data.data());
                                              break;
                                   
                                  .........................................................
                                      }
                                      return out;
                                  }
                                   
                                  std::ostream &operator<<(std::ostream &out, const CRecord &rec)
                                  {
                                      for (auto it = rec.m_fields.begin(), end = rec.m_fields.end(); it != end; ++it)
                                          out << *it << ", ";
                                      return out;
                                  }


                                ExpandedWrap disabled
                                  std::list<CRecord> records;
                                  for (int i = 0; i < pStr; i++) //Пробегаем по всем строкам
                                  {
                                  ...................
                                  }
                                   
                                  for (auto it = records.begin(), end = records.end(); it != end; ++it)
                                      std::cout << *it << std::endl;
                                Сообщение отредактировано: Олег М -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0746 ]   [ 19 queries used ]   [ Generated: 28.03.24, 11:17 GMT ]