Olivier Smeesters
/
DtmfKit
A DTMF sequence editor and player for HAM radio equipment command & control.
KeyboardManager/KeyboardState.cpp
- Committer:
- osmeest
- Date:
- 2011-03-07
- Revision:
- 0:1324e7d9d471
File content as of revision 0:1324e7d9d471:
#include "kbd_mgr/KeyboardState.h" #include <algorithm> #include <iomanip> namespace kbd_mgr { KeyboardState::KeyboardState() : numRows(0), numKeysPerRow(0), rowMask(0), numRowsPerWord(0), numKeysPerWord(0), numWords(0), data(0) { } KeyboardState::KeyboardState(std::size_t numRows, std::size_t numKeysPerRow) : numRows(numRows), numKeysPerRow(numKeysPerRow), rowMask((1 << numKeysPerRow) -1), numRowsPerWord((sizeof(int) * 8) / numKeysPerRow), numKeysPerWord(numRowsPerWord * numKeysPerRow), numWords((numRows + (numRowsPerWord-1)) / numRowsPerWord), data(numWords, 0) { } void KeyboardState::clear() { std::fill(this->data.begin(), this->data.end(), 0); } int KeyboardState::getRowInfo(std::size_t row, std::size_t &wordIndex, std::size_t &rowShift, int &rowMask) const { std::size_t rowInWord = row % numRowsPerWord; wordIndex = row / numRowsPerWord; rowShift = numKeysPerRow * rowInWord; rowMask = this->rowMask << rowShift; return this->data[wordIndex]; } void KeyboardState::setRowState(std::size_t row, int rowState) { std::size_t wordIndex; std::size_t rowShift; int rowMask; int v = getRowInfo(row, wordIndex, rowShift, rowMask); v = (v & ~rowMask) | ((rowState & this->rowMask) << rowShift); this->data[wordIndex] = v; } int KeyboardState::getRowState(std::size_t row) const { std::size_t wordIndex; std::size_t rowShift; int rowMask; int v = getRowInfo(row, wordIndex, rowShift, rowMask); return (v & rowMask) >> rowShift; } bool KeyboardState::getKeyState(std::size_t key) const { std::size_t row = key / this->numKeysPerRow; std::size_t keyInRow = key % this->numKeysPerRow; int keyMask = 1 << keyInRow; return (getRowState(row) & keyMask) != 0; } KeyboardState KeyboardState::operator&(const KeyboardState &other) const { KeyboardState result(this->numRows, this->numKeysPerRow); typedef Data::const_iterator SourceIterator; typedef Data::iterator TargetIterator; SourceIterator a = this->data.begin(); SourceIterator b = other.data.begin(); TargetIterator t = result.data.begin(); while (a != this->data.end() && b != other.data.end() && t != result.data.end()) { *t = *a & *b; ++a; ++b; ++t; } return result; } bool KeyboardState::operator==(const KeyboardState &other) const { if (this == &other) { return true; } if (this->numRows != other.numRows || this->numKeysPerRow != other.numKeysPerRow) return false; Data::const_iterator p = this->data.begin(); Data::const_iterator q = other.data.begin(); while (p != this->data.end() && q != other.data.end()) { if (*p != *q) { return false; } ++p; ++q; } return true; } bool KeyboardState::empty() const { for(Data::const_iterator p = this->data.begin(); p != this->data.end(); ++p) { if (*p != 0) { return false; } } return true; } namespace { int getBitNumber(int v) { if (v == 0) { return -1; } int key = 0; while (v != 1) { key++; v >>= 1; } return key; } } KeyboardState::KeyPressType KeyboardState::getKeyPressType(int *key) const { if (key) { *key = -1; } Data::const_iterator p = this->data.begin(); std::size_t wordIndex = 0; while (p != this->data.end() && *p == 0) { ++p; ++wordIndex; } if (p != this->data.end()) { int v = *p; if (v != (v & -v)) { return MultiKeyPress; } int k = getBitNumber(v) + wordIndex * this->numKeysPerWord; ++p; while (p != this->data.end() && *p == 0) { ++p; } if (p == this->data.end()) { if (key) { *key = k; } return SingleKeyPress; } else { return MultiKeyPress; } } else { return Idle; } } void KeyboardState::streamTo(std::ostream &out) const { using namespace std; std::size_t width = (this->numKeysPerWord + 3) / 4; ios_base::fmtflags f = out.flags(); for(Data::const_reverse_iterator p = this->data.rbegin(); p != this->data.rend(); ++p) { out << hex << setw(width) << setfill('0') << *p; } out.flags(f); } } // kbd_mgr