1 #ifndef UTILITY_H 2 #define UTILITY_H 3 4 #include <Qt> 5 #include <stdint.h> 6 #include <QByteArray> 7 #include <QDateTime> 8 #include <QDebug> 9 #include <QApplication> 10 #include <QRect> 11 #include <QDesktopWidget> 12 13 class Utility 14 { 15 public: 16 17 static bool decimalMode; 18 static bool secondsMode; 19 static bool sysTimeMode; 20 static QString timeFormat; 21 22 //determines whether the window position is within any available screens. If it is not we default 23 //back to 0,0 which is going to be on screen. This fixes a problem where some operating systems would 24 //otherwise let you put windows on a second monitor, disconnect that monitor, and still put windows on it. constrainedWindowPos(QPoint originalPos)25 static QPoint constrainedWindowPos(QPoint originalPos) 26 { 27 QScreen *screen = QGuiApplication::screenAt(originalPos); 28 if (!screen) 29 { 30 return QPoint(0,0); 31 } 32 return originalPos; 33 } 34 unQuote(QString inStr)35 static QString unQuote(QString inStr) 36 { 37 QStringList temp; 38 temp = inStr.split('\"'); 39 if (temp.length() >= 3) 40 return temp[1]; 41 return inStr; 42 } 43 ParseStringToNum(QByteArray input)44 static uint64_t ParseStringToNum(QByteArray input) 45 { 46 uint64_t temp = 0; 47 48 input = input.toUpper(); 49 if (input.startsWith("0X") || input.startsWith("X")) //hex number 50 { 51 if (input.length() < 3) temp = 0; 52 else temp = input.right(input.size() - 2).toLongLong(nullptr, 16); 53 } 54 else if (input.startsWith("0B") || input.startsWith("B")) //binary number 55 { 56 input = input.right(input.size() - 1); //remove the B 57 for (int i = 0; i < input.length(); i++) 58 { 59 if (input[i] == '1') temp += (uint64_t)1 << (input.length() - i - 1); 60 } 61 } 62 else //decimal number 63 { 64 temp = input.toLongLong(); 65 } 66 67 return temp; 68 } 69 ParseStringToNum(QString input)70 static uint64_t ParseStringToNum(QString input) 71 { 72 return ParseStringToNum(input.toUtf8()); 73 } 74 75 static uint ParseStringToNum2(QString pInput, bool* pOk_p = nullptr) 76 { 77 if(pInput.startsWith("0b")) 78 { 79 pInput.remove(0, 2); 80 return pInput.toUInt(pOk_p, 2); 81 } 82 83 return pInput.toUInt(pOk_p, 0); 84 } 85 GetTimeMS()86 static uint64_t GetTimeMS() 87 { 88 QDateTime stamp = QDateTime::currentDateTime(); 89 return (((static_cast<uint64_t>(stamp.time().hour()) * 3600ull) + (static_cast<uint64_t>(stamp.time().minute()) * 60ull) 90 + (static_cast<uint64_t>(stamp.time().second())) * 1000ull) + static_cast<uint64_t>(stamp.time().msec())); 91 } 92 93 //prints hex numbers in uppercase with 0's filling out the number depending 94 //on the size needed. Promotes hex numbers to either 2, 4, or 8 digits formatHexNum(uint64_t input)95 static QString formatHexNum(uint64_t input) 96 { 97 if (input < 256) 98 return "0x" + QString::number(input, 16).toUpper().rightJustified(2,'0'); 99 if (input < 65536) 100 return "0x" + QString::number(input, 16).toUpper().rightJustified(4,'0'); 101 if (input < 4294967296) 102 return "0x" + QString::number(input, 16).toUpper().rightJustified(8,'0'); 103 return "0x" + QString::number(input, 16).toUpper().rightJustified(16,'0'); 104 } 105 106 //uses decimalMode to see if it should show value as decimal or hex formatNumber(uint64_t value)107 static QString formatNumber(uint64_t value) 108 { 109 if (decimalMode) 110 { 111 return QString::number(value, 10); 112 } 113 else return formatHexNum(value); 114 } 115 formatCANID(uint64_t id,bool extended)116 static QString formatCANID(uint64_t id, bool extended) 117 { 118 if (decimalMode) return QString::number(id, 10); 119 120 if (extended) 121 { 122 return "0x" + QString::number(id, 16).toUpper().rightJustified(8,'0'); 123 } 124 else 125 { 126 id = id & 0x7FF; 127 return "0x" + QString::number(id, 16).toUpper().rightJustified(3,'0'); 128 } 129 } 130 formatCANID(uint64_t id)131 static QString formatCANID(uint64_t id) 132 { 133 if (id < 0x800) return formatCANID(id, false); 134 return formatCANID(id, true); 135 } 136 formatByteAsBinary(uint8_t value)137 static QString formatByteAsBinary(uint8_t value) 138 { 139 QString output; 140 for (int b = 7; b >= 0; b--) 141 { 142 if (value & (1 << b)) output += "1"; 143 else output += "0"; 144 } 145 return output; 146 } 147 formatTimestamp(uint64_t timestamp)148 static QVariant formatTimestamp(uint64_t timestamp) 149 { 150 if (!sysTimeMode) { 151 if (!secondsMode) return (unsigned long long)(timestamp); 152 else return (double)timestamp / 1000000.0; 153 } 154 else return QDateTime::fromMSecsSinceEpoch(timestamp / 1000); 155 } 156 157 //parses the input string to grab as much of it as possible while staying alpha numeric grabAlphaNumeric(QString & input)158 static QString grabAlphaNumeric(QString &input) 159 { 160 QString builder; 161 QChar thisChar; 162 for (int i = 0; i < input.length(); i++) 163 { 164 thisChar = input[i]; 165 if (thisChar.isLetterOrNumber() || thisChar == ':' || thisChar == '~') builder.append(input[i]); 166 else 167 { 168 //qDebug() << "i: "<< i << " len: " << input.length(); 169 if (i < (input.length() - 1)) input = input.right(input.length() - i); 170 else input = ""; 171 return builder; 172 } 173 } 174 //qDebug() << "Reached end of string in grabAlphaNumeric"; 175 input = ""; 176 return builder; 177 } 178 grabOperation(QString & input)179 static QString grabOperation(QString &input) 180 { 181 QString builder; 182 QChar thisChar = input[0]; 183 184 if (thisChar == '+' || thisChar == '-' || thisChar == '*' || thisChar == '/' || thisChar == '^' || thisChar == '&' || thisChar == '|' || thisChar == '=' || thisChar == '%') 185 { 186 input = input.right(input.length() - 1); 187 builder = thisChar; 188 } 189 return builder; 190 } 191 192 //simple linear interpolation between value1 and value2. sample point is 0.0 to 1.0 Lerp(double value1,double value2,double samplePoint)193 static double Lerp(double value1, double value2, double samplePoint) 194 { 195 return (value1 * (1.0 - samplePoint)) + (value2 * samplePoint); 196 } 197 processIntegerSignal(const QByteArray data,int startBit,int sigSize,bool littleEndian,bool isSigned)198 static int64_t processIntegerSignal(const QByteArray data, int startBit, int sigSize, bool littleEndian, bool isSigned) 199 { 200 201 int64_t result = 0; 202 int bit; 203 204 int maxBytes = (startBit + sigSize) / 8; 205 if (data.size() < maxBytes) return 0; 206 207 if (littleEndian) 208 { 209 bit = startBit; 210 for (int bitpos = 0; bitpos < sigSize; bitpos++) 211 { 212 if (bit < 64) { 213 int bytePos = bit / 8; 214 if (bytePos >= data.count()) return 0; //error! 215 if (data[bit / 8] & (1 << (bit % 8))) 216 result += (1ULL << bitpos); 217 } 218 bit++; 219 } 220 } 221 else //motorola / big endian mode 222 { 223 bit = startBit; 224 for (int bitpos = 0; bitpos < sigSize; bitpos++) 225 { 226 if (bit < 64) { 227 int bytePos = bit / 8; 228 if (bytePos >= data.count()) return 0; //error! 229 if (data[bit / 8] & (1 << (bit % 8))) 230 result += (1ULL << (sigSize - bitpos - 1)); 231 } 232 233 if ((bit % 8) == 0) 234 bit += 15; 235 else bit--; 236 237 } 238 } 239 240 if (isSigned) 241 { 242 int64_t mask = (1ULL << (sigSize - 1)); 243 if ((result & mask) == mask) //is the highest bit possible for this signal size set? 244 { 245 /* 246 * if so we need to also set every bit higher in the result int too. 247 * This leads to the below two lines that are nasty. Here's the theory behind that... 248 * If the value is signed and the highest bit is set then it is negative. To create 249 * a negative value out of this even though the variable result is 64 bit we have to 250 * run 1's all of the way up to bit 63 in result. -1 is all ones for whatever size integer 251 * you have. So, it's 64 1's in this case. 252 * signedMask is done this way: 253 * first you take the signal size and shift 1 up that far. Then subtract one. Lets 254 * see that for a 16 bit signal: 255 * (1 << 16) - 1 = the first 16 bits set as 1's. So far so good. We then negate the whole 256 * thing which flips all bits. Thus signedMask ends up with 1's everwhere that the signal 257 * doesn't take up in the 64 bit signed integer result. Then, result has an OR operation on 258 * it with the old value and -1 masked so that the the 1 bits from -1 don't overwrite bits from the 259 * actual signal. This extends the sign bits out so that the integer result reads as the proper negative 260 * value. We dont need to do any of this if the sign bit wasn't set. 261 */ 262 uint64_t signedMask = ~((1ULL << sigSize) - 1); 263 result = (-1LL & signedMask) | result; 264 } 265 } 266 267 return result; 268 } 269 }; 270 271 #endif // UTILITY_H 272