sequencer
device_spec_reader.hpp
Go to the documentation of this file.
1 #pragma once
2 
4 
5 #include <fstream>
6 #include <iostream>
7 #include <regex>
8 #include <string>
9 #include <vector>
10 
11 namespace sequencer::midi
12 {
13  const auto key_sep = std::string( ":" );
14  const auto string_identifier_regex_str = std::string{"([a-zA-Z]+[\\sa-zA-Z0-9_]*)"};
15 
16  inline std::regex get_key_int_regex( const std::string& key )
17  {
18  return std::regex( key + "\\s*" + key_sep + "\\s*([\\-0-9]+)" );
19  }
20 
21 #define X( type, name, is_optional ) \
22  if ( std::regex_search( buffer, match, get_key_int_regex( #name ) ) ) \
23  { \
24  entry.name = decltype( entry.name )( std::stoi( match[ 1 ] ) ); \
25  } \
26  else \
27  { \
28  if constexpr ( !( is_optional ) ) \
29  { \
30  throw std::runtime_error( "Could not parse '" #name "' in line: " + buffer ); \
31  } \
32  }
33  inline void read_entry( device_entry_t& entry, const std::string& buffer )
34  {
35  const auto name_regex =
36  std::regex( "name\\s*" + key_sep + "\\s*" + string_identifier_regex_str );
37 
38  std::smatch match;
39  if ( std::regex_search( buffer, match, name_regex ) )
40  {
41  entry.name = match[ 1 ];
42  }
43  else
44  {
45  throw std::runtime_error( "Could not parse 'name' in line: " + buffer );
46  }
47 
49 
50  const auto sub_sep = ",";
51  const auto str_map_regex = std::regex( "str_map\\s*" + key_sep + "\\s*\\{.*\\}" );
52  if ( std::regex_search( buffer, str_map_regex ) )
53  {
54  entry.str_map.resize( entry.max - entry.min + 1 );
55  auto pos = buffer.find( "str_map" );
56  pos = 1 + buffer.find( key_sep, pos + 1 );
57  const auto entry_regex =
58  std::regex( "([\\-0-9]+)\\s*" + key_sep + "\\s*" + string_identifier_regex_str );
59  auto sub = buffer.substr( pos );
60  while ( std::regex_search( sub, match, entry_regex ) )
61  {
62  entry.str_map[ std::size_t( std::stoi( match[ 1 ] ) - entry.min ) ] = match[ 2 ];
63  pos = sub.find( sub_sep );
64  if ( pos == std::string::npos )
65  {
66  break;
67  }
68  sub = sub.substr( pos + 1 );
69  }
70  return;
71  }
72 
73  const auto map_regex = std::regex( "map\\s*" + key_sep + "\\s*\\{.*\\}" );
74  if ( std::regex_search( buffer, map_regex ) )
75  {
76  entry.map.resize( entry.max - entry.min + 1 );
77  auto pos = buffer.find( "map" );
78  pos = 1 + buffer.find( key_sep, pos + 1 );
79  const auto entry_regex = std::regex( "([\\-0-9]+)\\s*" + key_sep + "\\s*([\\-0-9]+)" );
80  auto sub = buffer.substr( pos );
81  while ( std::regex_search( sub, match, entry_regex ) )
82  {
83  entry.map[ std::size_t( std::stoi( match[ 1 ] ) - entry.min ) ] =
84  std::stoi( match[ 2 ] );
85  pos = sub.find( sub_sep );
86  if ( pos == std::string::npos )
87  {
88  break;
89  }
90  sub = sub.substr( pos + 1 );
91  }
92  }
93  }
94 #undef X
95 
96  inline std::vector< section_t > read_file( std::istream& file )
97  {
98  std::vector< section_t > sections;
99 
100  while ( !file.eof() )
101  {
102  std::string buffer;
103  std::getline( file, buffer );
104  if ( buffer.empty() )
105  {
106  continue;
107  }
108 
109  // new section
110  std::smatch match;
111  const auto section_regex = std::regex( "section: " + string_identifier_regex_str );
112  if ( std::regex_match( buffer, match, section_regex ) )
113  {
114  sections.emplace_back( match[ 1 ] );
115  continue;
116  }
117 
118  // entry in section
119  sections.back().entries.emplace_back();
120  try
121  {
122  read_entry( sections.back().entries.back(), buffer );
123  }
124  catch ( std::runtime_error& error )
125  {
126  std::cerr << error.what() << std::endl;
127  sections.back().entries.pop_back();
128  }
129  }
130 
131  return sections;
132  }
133 } // namespace sequencer::midi
Definition: device_spec.hpp:26
void read_entry(device_entry_t &entry, const std::string &buffer)
Definition: device_spec_reader.hpp:33
std::vector< section_t > read_file(std::istream &file)
Definition: device_spec_reader.hpp:96
#define SEQUENCER_DEVICE_CC_VALUES
Definition: device_spec.hpp:9
std::regex get_key_int_regex(const std::string &key)
Definition: device_spec_reader.hpp:16
const auto key_sep
Definition: device_spec_reader.hpp:13
const auto string_identifier_regex_str
Definition: device_spec_reader.hpp:14
Definition: clock.hpp:13