← index
acidcamGL/midi-cfg/Config.Tool/midi_cfg.hpp
Source: acidcamGL/midi-cfg/Config.Tool/midi_cfg.hpp
#include <vector>
#include <unordered_map>
#include <string>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <iostream>

namespace std {
    template <>
    struct hash<std::pair<int, int>> {
        size_t operator()(const std::pair<int, int>& p) const {
            return hash<int>()(p.first) ^ hash<int>()(p.second);
        }
    };
}

namespace midi {


    struct Key {
        std::vector<unsigned char> bytes;

        Key() = default;
        Key(unsigned char byte1, unsigned char byte2, unsigned char byte3) {
            bytes.push_back(byte1);
            bytes.push_back(byte2);
            bytes.push_back(byte3);
        }
    };

    class MIDI_Config {
    public:
        void addCode(std::pair<int, int> keys, const Key& k) {
            codes.insert({ keys, k });
        }

        void write(const std::string& filename) {
            std::fstream file;
            file.open(filename, std::ios::out);
            if (!file.is_open()) {
                throw std::runtime_error("Could not open file");
            }
            for (auto it = codes.begin(); it != codes.end(); ++it) {
                file << it->first.first << ":" << it->first.second << " {";
                for (size_t j = 0; j < it->second.bytes.size() - 1; ++j) {
                    file << static_cast<int>(it->second.bytes[j]) << " ";
                }
                file << static_cast<int>(it->second.bytes[it->second.bytes.size() - 1]) << "}\n";
            }
            file.close();
        }

        void read(const std::string& filename) {
            std::fstream file;
            file.open(filename, std::ios::in);
            if (!file.is_open()) {
                throw std::runtime_error("Could not open file for reading");
            }

            std::string line;
            while (std::getline(file, line)) {
                std::istringstream iss(line);
                std::string keyPair;
                if (!(iss >> keyPair)) {
                    continue;
                }

                size_t colonPos = keyPair.find(':');
                if (colonPos == std::string::npos) {
                    continue;
                }

                int key1 = std::stoi(keyPair.substr(0, colonPos));
                int key2 = std::stoi(keyPair.substr(colonPos + 1));

                char brace;
                if (!(iss >> brace) || brace != '{') {
                    continue;
                }

                std::vector<unsigned char> bytes;
                int byteValue;
                while (iss >> byteValue) {
                    bytes.push_back(static_cast<unsigned char>(byteValue));
                }

                if (!bytes.empty() && bytes.back() == '}') {
                    bytes.pop_back(); 
                }
                addCode({ key1, key2 }, Key(bytes[0], bytes[1], bytes[2]));
            }
            file.close();
            print(std::cout);
        }

        std::pair<int, int> lookup(const Key& k) {
            for (auto it = codes.begin(); it != codes.end(); ++it) {
                if (it->second.bytes.size() >= k.bytes.size()) {
                    if (k.bytes.at(0) == it->second.bytes.at(0) && k.bytes.at(1) == it->second.bytes.at(1) && k.bytes.at(2) == it->second.bytes.at(2)) {
                        return it->first;
                    }
                }
            }
            return { -1, -1 };
        }

        std::pair<int, int> lookup_nov(const Key& k) {
            for (auto it = codes.begin(); it != codes.end(); ++it) {
                if (it->second.bytes.size() >= k.bytes.size()) {
                    if (k.bytes.at(0) == it->second.bytes.at(0) && k.bytes.at(1) == it->second.bytes.at(1)) {
                        return it->first;
                    }
                }
            }
            return { -1, -1 };
        }

        void print(std::ostream& out) {
            for (auto it = codes.begin(); it != codes.end(); ++it) {
                out << "acidcam: Mapped Function Keys: " << it->first.first << ":" << it->first.second << " Bytes: ";
                for (size_t j = 0; j < it->second.bytes.size(); ++j) {
                    out << static_cast<int>(it->second.bytes[j]) << " ";
                }
                out << "\n";
            }
        }

    protected:
        std::unordered_multimap<std::pair<int, int>, Key, std::hash<std::pair<int, int>>> codes;
    };
}