/* * © 2024 Vincent Hamp and Chris Harlow * All rights reserved. * * This file is part of CommandStation-EX * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * It is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ /* Reader be aware: This function implements the _hk data type so that a string keyword is hashed to the same value as the DCCEXParser uses to hash incoming keywords. Thus "MAIN"_hk generates exactly the same run time vakue as const int16_t HASH_KEYWORD_MAIN=11339 */ #ifndef KeywordHasher_h #define KeywordHasher_h #include constexpr uint16_t CompiletimeKeywordHasher(const char * sv, uint16_t running=0) { return (*sv==0) ? running : CompiletimeKeywordHasher(sv+1, (*sv >= '0' && *sv <= '9') ? (10*running+*sv-'0') // Numeric hash : ((running << 5) + running) ^ *sv ); // } constexpr int16_t operator""_hk(const char * keyword, size_t len) { return (int16_t) CompiletimeKeywordHasher(keyword,len*0); } /* Some historical values for testing: const int16_t HASH_KEYWORD_MAIN = 11339; const int16_t HASH_KEYWORD_SLOW = -17209; const int16_t HASH_KEYWORD_SPEED28 = -17064; const int16_t HASH_KEYWORD_SPEED128 = 25816; */ static_assert("MAIN"_hk == 11339,"Keyword hasher error"); static_assert("SLOW"_hk == -17209,"Keyword hasher error"); static_assert("SPEED28"_hk == -17064,"Keyword hasher error"); static_assert("SPEED128"_hk == 25816,"Keyword hasher error"); // Compile time converter from "abcd"_s7 to the 7 segment nearest equivalent constexpr uint8_t seg7Digits[]={ 0b00111111,0b00000110,0b01011011,0b01001111, // 0..3 0b01100110,0b01101101,0b01111101,0b00000111, // 4..7 0b01111111,0b01101111 // 8..9 }; constexpr uint8_t seg7Letters[]={ 0b01110111,0b01111100,0b00111001,0b01011110, // ABCD 0b01111001,0b01110001,0b00111101,0b01110110, // EFGH 0b00000100,0b00011110,0b01110010,0b00111000, //IJKL 0b01010101,0b01010100,0b01011100,0b01110011, // MNOP 0b10111111,0b01010000,0b01101101,0b01111000, // QRST 0b00111110,0b00011100,0b01101010,0b01001001, //UVWX 0b01100110,0b01011011 //YZ }; constexpr uint8_t seg7Space=0b00000000; constexpr uint8_t seg7Minus=0b01000000; constexpr uint8_t seg7Equals=0b01001000; constexpr uint32_t CompiletimeSeg7(const char * sv, uint32_t running, size_t rlen) { return (*sv==0 || rlen==0) ? running << (8*rlen) : CompiletimeSeg7(sv+1, (*sv >= '0' && *sv <= '9') ? (running<<8) | seg7Digits[*sv-'0'] : (*sv >= 'A' && *sv <= 'Z') ? (running<<8) | seg7Letters[*sv-'A'] : (*sv >= 'a' && *sv <= 'z') ? (running<<8) | seg7Letters[*sv-'a'] : (*sv == '-') ? (running<<8) | seg7Minus : (*sv == '=') ? (running<<8) | seg7Equals : (running<<8) | seg7Space, rlen-1 ); // } constexpr uint32_t operator""_s7(const char * keyword, size_t len) { return CompiletimeSeg7(keyword,0*len,4); } #endif