ArnLib  4.0.x
Active Registry Network
MQFlags.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2022 Michael Wiklund.
2 // All rights reserved.
3 // Contact: arnlib@wiklunden.se
4 //
5 // This file is part of the ArnLib - Active Registry Network.
6 // Parts of ArnLib depend on Qt and/or other libraries that have their own
7 // licenses. Usage of these other libraries is subject to their respective
8 // license agreements.
9 //
10 // The MIT License (MIT) Usage
11 // Permission is hereby granted, free of charge, to any person obtaining a
12 // copy of this file to deal in its contained Software without restriction,
13 // including without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to permit
15 // persons to whom the Software is furnished to do so, subject to the
16 // following conditions:
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software in this file.
19 //
20 // GNU Lesser General Public License Usage
21 // This file may be used under the terms of the GNU Lesser General Public
22 // License version 2.1 as published by the Free Software Foundation and
23 // appearing in the file LICENSE_LGPL.txt included in the packaging of this
24 // file. In addition, as a special exception, you may use the rights described
25 // in the Nokia Qt LGPL Exception version 1.1, included in the file
26 // LGPL_EXCEPTION.txt in this package.
27 //
28 // GNU General Public License Usage
29 // Alternatively, this file may be used under the terms of the GNU General Public
30 // License version 3.0 as published by the Free Software Foundation and appearing
31 // in the file LICENSE_GPL.txt included in the packaging of this file.
32 //
33 // Other Usage
34 // Alternatively, this file may be used in accordance with the terms and conditions
35 // contained in a signed written agreement between you and Michael Wiklund.
36 //
37 // This program is distributed in the hope that it will be useful, but WITHOUT ANY
38 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
39 // PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
40 //
41 
42 #include "ArnInc/MQFlags.hpp"
43 #include <ArnInc/XStringMap.hpp>
44 #include <ArnInc/Math.hpp>
45 #include <QMetaType>
46 #include <QMetaObject>
47 #include <QMetaEnum>
48 #include <QMapIterator>
49 #include <QDebug>
50 #include <limits.h>
51 
52 namespace Arn {
53 
54 EnumTxt::SubEnumEntry::SubEnumEntry( const EnumTxt& subEnum, uint bitMask, uint factor, bool isLocalOwn)
55 {
56  _subEnum = &subEnum;
57  _bitMask = bitMask;
58  _bitPos = log2( factor | 1);
59  _isLocalOwn = isLocalOwn;
60 }
61 
62 
63 EnumTxt::EnumTxt( const QMetaObject* metaObj, bool isFlag, const _InitEnumTxt* initTxt, const _InitSubEnum* initSubEnum,
64  const char* name)
65 {
66  _metaObj = metaObj;
67  _txtStore = arnNullptr;
68  _subEnumTab = arnNullptr;
69  _isFlag = isFlag;
70  _name = name;
71  setupFromMetaObject();
72  setupTxt( initTxt);
73  setupSubEnum( initSubEnum);
74 }
75 
76 
77 EnumTxt::EnumTxt( bool isFlag, const QString& name)
78 {
79  _metaObj = arnNullptr;
80  _txtStore = arnNullptr;
81  _subEnumTab = arnNullptr;
82  _isFlag = isFlag;
83  _name = name.toUtf8();
84 }
85 
86 
88 {
89  // Q_ASSERT(!_metaObj);
90  clear();
91 }
92 
93 
94 void EnumTxt::setTxtRefAny( const char* txt, int enumVal, quint16 nameSpace)
95 {
96  _enumTxtTab.insert( EnumTxtKey( enumVal, nameSpace, _isFlag), txt);
97 }
98 
99 
100 void EnumTxt::setTxtRef( const char *txt, int enumVal, quint16 nameSpace)
101 {
102  if (_metaObj && nameSpace > 0)
103  setTxtRefAny( txt, enumVal, nameSpace);
104 }
105 
106 
107 void EnumTxt::setTxt( const char* txt, int enumVal, quint16 nameSpace)
108 {
109  if (_metaObj && nameSpace == 0) return; // Not allowed to change original enum texts
110 
111  if (!_txtStore)
112  _txtStore = new QList<QByteArray>;
113 
114  int idx = _txtStore->size();
115  *_txtStore += QByteArray( txt);
116 
117  setTxtRefAny( _txtStore->at( idx).constData(), enumVal, nameSpace);
118 }
119 
120 
121 const char* EnumTxt::getTxt( int enumVal, quint16 nameSpace, bool* isFound) const
122 {
123  const char* txt = _enumTxtTab.value( EnumTxtKey( enumVal, nameSpace, _isFlag), arnNullptr);
124  if (isFound)
125  *isFound = (txt != arnNullptr);
126  return txt ? txt : "";
127 }
128 
129 
130 void EnumTxt::setTxtString( const QString& txt, int enumVal, quint16 nameSpace)
131 {
132  setTxt( txt.toUtf8().constData(), enumVal, nameSpace);
133 }
134 
135 
136 QString EnumTxt::getTxtString( int enumVal, quint16 nameSpace, bool* isFound) const
137 {
138  return QString::fromUtf8( getTxt( enumVal, nameSpace, isFound));
139 }
140 
141 
142 int EnumTxt::getEnumVal( const char* txt, int defaultVal, quint16 nameSpace, bool* isFound) const
143 {
144  EnumTxtKey keyStart( _isFlag ? 1 : uint(INT_MIN), nameSpace, _isFlag);
145  EnumTxtKey keyStop( _isFlag ? UINT_MAX : uint(INT_MAX), nameSpace, _isFlag);
146 
147  QMap<EnumTxtKey,const char*>::const_iterator i = _enumTxtTab.lowerBound( keyStart);
148  for (; i != _enumTxtTab.end(); ++i) {
149  const EnumTxtKey& keyStored = i.key();
150  if (keyStop < keyStored) break;
151 
152  if (qstrcmp( i.value(), txt) == 0) {
153  if (isFound) *isFound = true;
154  return int(keyStored._enumVal); // Matching txt
155  }
156  }
157 
158  if (isFound) *isFound = false;
159  return defaultVal; // Not found
160 }
161 
162 
163 int EnumTxt::getEnumVal( const QString& txt, int defaultVal, quint16 nameSpace, bool* isFound) const
164 {
165  return getEnumVal( txt.toUtf8().constData(), defaultVal, nameSpace, isFound);
166 }
167 
168 
169 bool EnumTxt::getSubEnumVal( const char* txt, int& subEnumVal, uint& bitMask, quint16 nameSpace) const
170 {
171  if (_subEnumTab) {
172  foreach (const SubEnumEntry& entry, *_subEnumTab) {
173  bool isFound = false;
174  int enumVal = entry._subEnum->getEnumVal( txt, -1, nameSpace, &isFound);
175  if (isFound) {
176  subEnumVal = enumVal << entry._bitPos;
177  bitMask = entry._bitMask;
178  return true;
179  }
180  }
181  }
182 
183  return false; // Not found
184 }
185 
186 
187 bool EnumTxt::getSubEnumVal( const QString& txt, int& subEnumVal, uint& bitMask, quint16 nameSpace) const
188 {
189  return getSubEnumVal( txt.toUtf8().constData(), subEnumVal, bitMask, nameSpace);
190 }
191 
192 
193 void EnumTxt::addFlagsTo( XStringMap& xsm, const IncludeMode& incMode, quint16 nameSpace, bool neverHumanize) const
194 {
195  if (!_isFlag) return; // Only for flags
196 
197  EnumTxtKey keyStart( 1, nameSpace, _isFlag);
198  EnumTxtKey keyStop( UINT_MAX, nameSpace, _isFlag);
199  uint bitNum = 0;
200 
201  QMap<EnumTxtKey,const char*>::const_iterator i = _enumTxtTab.lowerBound( keyStart);
202  for (; i != _enumTxtTab.end(); ++i) {
203  const EnumTxtKey& keyStored = i.key();
204  if (keyStop < keyStored) break;
205 
206  uint enumValStored = keyStored._enumVal;
207  bool isSubEnum = (_subEnumMask & enumValStored) != 0;
208  if ((incMode != IncludeMode::Any) && (isSubEnum != (incMode == IncludeMode::OnlySubEnumBits))) {
209  continue;
210  }
211 
212  QByteArray enumValTxt;
213  if (keyStored._isSingleBit) {
214  if (incMode == IncludeMode::OnlyMulti1Bits) continue;
215  bitNum = log2( enumValStored);
216  enumValTxt = "B" + QByteArray::number( bitNum);
217  }
218  else {
219  if (incMode == IncludeMode::OnlySingle1Bits) continue;
220  enumValTxt = numToStr( enumValStored);
221  }
222 
223  QByteArray enumTxt;
224  if ((nameSpace > 0) || neverHumanize) { // Enum name is used as is
225  enumTxt = i.value();
226  }
227  else { // Enum name is humanized (Leading capital and separated words)
228  enumTxt = humanize( QString::fromUtf8( i.value())).toUtf8();
229  }
230 
231  xsm.add( enumValTxt, enumTxt);
232  }
233 }
234 
235 
236 void EnumTxt::addSubEnumTo( XStringMap& xsm, quint16 nameSpace, bool neverHumanize) const
237 {
238  if (!_subEnumTab) return;
239 
240  XStringMap xsmSub;
241  foreach (const SubEnumEntry& entry, *_subEnumTab) {
242  uint bitMask = entry._bitMask;
243  uchar bitPos = entry._bitPos;
244  QByteArray enumValTxt = "SE" + numToStr( bitMask);
245  if (bitPos)
246  enumValTxt += ":B" + QByteArray::number( bitPos);
247  QByteArray subEnumName = getTxt( bitMask, nameSpace);
248  xsm.add( enumValTxt, subEnumName);
249 
250  xsmSub.clear();
251  entry._subEnum->addEnumSetTo( xsmSub, nameSpace, neverHumanize);
252  for (int i = 0; i < xsmSub.size(); ++i) {
253  int enumVal = xsmSub.keyRef( i).toInt();
254  uint enumValMasked = enumVal & (bitMask >> bitPos);
255  enumValTxt = "E" + numToStr( enumValMasked) + (enumVal < 0 ? "-" : "");
256  xsm.add( enumValTxt, xsmSub.valueRef( i));
257  }
258  }
259 }
260 
261 
262 void EnumTxt::addBitSetTo( XStringMap& xsm, quint16 nameSpace, bool neverHumanize) const
263 {
264  if (!_isFlag) return; // Only for flags
265 
266  addFlagsTo( xsm, IncludeMode::AnyButSubEnumBits, nameSpace, neverHumanize);
267  addSubEnumTo( xsm, nameSpace, neverHumanize);
268 }
269 
270 
271 QString EnumTxt::getBitSet( quint16 nameSpace, bool neverHumanize) const
272 {
273  if (!_isFlag) return QString(); // Only for flags
274 
275  XStringMap xsm;
276  addBitSetTo( xsm, nameSpace, neverHumanize);
277  return QString::fromUtf8( xsm.toXString());
278 }
279 
280 
281 void EnumTxt::addSubEnumPlainTo( XStringMap& xsm, quint16 nameSpace, bool neverHumanize) const
282 {
283  if (!_subEnumTab) return;
284 
285  XStringMap xsmSub;
286  foreach (const SubEnumEntry& entry, *_subEnumTab) {
287  uint bitMask = entry._bitMask;
288  uchar bitPos = entry._bitPos;
289  QByteArray enumValTxt = numToStr( bitMask);
290  QByteArray subEnumName = getTxt( bitMask, nameSpace);
291  xsm.add( enumValTxt, subEnumName);
292 
293  xsmSub.clear();
294  entry._subEnum->addEnumSetTo( xsmSub, nameSpace, neverHumanize);
295  for (int i = 0; i < xsmSub.size(); ++i) {
296  int enumVal = xsmSub.keyRef( i).toInt();
297  uint subEnumVal = (enumVal << bitPos) & bitMask;
298  enumValTxt = numToStr( subEnumVal);
299  xsm.add( enumValTxt, xsmSub.valueRef( i));
300  }
301  }
302 }
303 
304 
305 QString EnumTxt::flagsToString( int val, quint16 nameSpace) const
306 {
307  if (!_isFlag) return QString(); // Only for flags
308 
309  return flagsToStringList( val, nameSpace).join(" | ");
310 }
311 
312 
313 QStringList EnumTxt::flagsToStringList( int val, quint16 nameSpace) const
314 {
315  if (!_isFlag) return QStringList(); // Only for flags
316 
317  uint maxBitVal = (UINT_MAX >> 1) + 1;
318  EnumTxtKey keyStart( 1, nameSpace, _isFlag); // Zero is skipped
319  EnumTxtKey keyStop( maxBitVal, nameSpace, _isFlag); // Combined bits are skipped
320  QStringList retVal;
321 
322  QMap<EnumTxtKey,const char*>::const_iterator i = _enumTxtTab.lowerBound( keyStart);
323  for (; i != _enumTxtTab.end(); ++i) {
324  const EnumTxtKey& keyStored = i.key();
325  if (keyStop < keyStored) break;
326 
327  uint enumValStored = keyStored._enumVal;
328  if (_subEnumMask & enumValStored)
329  continue;
330 
331  if (uint( val) & enumValStored) {
332  retVal += QString::fromUtf8( i.value());
333  }
334  }
335  if (_subEnumTab) {
336  foreach (const SubEnumEntry& entry, *_subEnumTab) {
337  int subEnum = (uint( val) & entry._bitMask) >> entry._bitPos;
338  QString etxt = entry._subEnum->getTxtString( subEnum, nameSpace);
339  if (etxt.isEmpty()) { // Positive enum not found, try negative version
340  subEnum |= -1 & ~(entry._bitMask >> entry._bitPos); // Do kind of sign extension
341  etxt = entry._subEnum->getTxtString( subEnum, nameSpace);
342  if (etxt.isEmpty()) { // Negative enum not found, skip this invalid subEnum
343  continue;
344  }
345  }
346  retVal += etxt;
347  }
348  }
349 
350  return retVal;
351 }
352 
353 
354 int EnumTxt::flagsFromString( const QString& flagString, quint16 nameSpace)
355 {
356  if (!_isFlag) return 0; // Only for flags
357 
358  return flagsFromStringList( flagString.split(" | "), nameSpace);
359 }
360 
361 
362 int EnumTxt::flagsFromStringList( const QStringList& flagStrings, quint16 nameSpace)
363 {
364  if (!_isFlag) return 0; // Only for flags
365 
366  uint maxBitVal = (UINT_MAX >> 1) + 1;
367  EnumTxtKey keyStart( 1, nameSpace, _isFlag);
368  EnumTxtKey keyStop( maxBitVal, nameSpace, _isFlag);
369  int retVal = 0;
370 
371  QMap<EnumTxtKey,const char*>::iterator i = _enumTxtTab.lowerBound( keyStart);
372  for (; i != _enumTxtTab.end(); ++i) {
373  const EnumTxtKey& keyStored = i.key();
374  if (keyStop < keyStored) break;
375 
376  uint enumValStored = keyStored._enumVal;
377  if (_subEnumMask & enumValStored)
378  continue;
379 
380  if (flagStrings.contains( QString::fromUtf8( i.value())))
381  retVal |= enumValStored;
382  }
383  if (_subEnumTab) {
384  foreach (const SubEnumEntry& entry, *_subEnumTab) {
385  EnumTxtKey keyStart( uint(INT_MIN), nameSpace, false);
386  EnumTxtKey keyStop( uint(INT_MAX), nameSpace, false);
387  QMap<EnumTxtKey,const char*>::const_iterator j = entry._subEnum->_enumTxtTab.lowerBound( keyStart);
388  for (; j != entry._subEnum->_enumTxtTab.end(); ++j) {
389  const EnumTxtKey& keyStored = j.key();
390  if (keyStop < keyStored) break;
391 
392  QString enumTxtStr = QString::fromUtf8( j.value());
393  if (flagStrings.contains( enumTxtStr)) {
394  retVal &= ~entry._bitMask;
395  retVal |= (keyStored._enumVal << entry._bitPos) & entry._bitMask;
396  break;
397  }
398  }
399  }
400  }
401 
402  return retVal;
403 }
404 
405 
406 void EnumTxt::addEnumSetTo( XStringMap& xsm, quint16 nameSpace, bool neverHumanize) const
407 {
408  EnumTxtKey keyStart( _isFlag ? 1 : uint(INT_MIN), nameSpace, _isFlag);
409  EnumTxtKey keyStop( _isFlag ? UINT_MAX : uint(INT_MAX), nameSpace, _isFlag);
410 
411  QMap<EnumTxtKey,const char*>::const_iterator i = _enumTxtTab.lowerBound( keyStart);
412  for (; i != _enumTxtTab.end(); ++i) {
413  const EnumTxtKey& keyStored = i.key();
414  if (keyStop < keyStored) break;
415 
416  int enumValStored = int(keyStored._enumVal);
417  QByteArray enumTxt;
418  if ((nameSpace > 0) || neverHumanize) { // Enum name is used as is
419  enumTxt = i.value();
420  }
421  else { // Enum name is humanized (Leading capital and separated words)
422  enumTxt = humanize( QString::fromUtf8( i.value())).toUtf8();
423  }
424  xsm.add(QByteArray::number( enumValStored), enumTxt);
425  }
426 }
427 
428 
429 QString EnumTxt::getEnumSet( quint16 nameSpace, bool neverHumanize) const
430 {
431  XStringMap xsm;
432  addEnumSetTo( xsm, nameSpace, neverHumanize);
433  return QString::fromUtf8( xsm.toXString());
434 }
435 
436 
437 QStringList EnumTxt::getBasicTextList( quint16 nameSpace, bool neverHumanize) const
438 {
439  XStringMap xsm;
440  if (_isFlag) {
441  addFlagsTo( xsm, IncludeMode::OnlySingle1Bits, nameSpace, neverHumanize);
442  }
443  else {
444  addEnumSet( xsm, nameSpace, neverHumanize);
445  }
446 
447  return xsm.values();
448 }
449 
450 
451 void EnumTxt::addSubEnum( const EnumTxt& subEnum, uint bitMask, uint factor)
452 {
453  addSubEnumAny( subEnum, bitMask, factor, false);
454 }
455 
456 
457 void EnumTxt::addSubEnumAny( const EnumTxt& subEnum, uint bitMask, uint factor, bool isLocalOwn)
458 {
459  if (subEnum.isFlag()) return; // Not allowed with flags as subEnum
460 
461  if (!_subEnumTab)
462  _subEnumTab = new QList<SubEnumEntry>;
463  SubEnumEntry entry( subEnum, bitMask, factor, isLocalOwn);
464  *_subEnumTab += entry;
465  _subEnumMask |= bitMask;
466 }
467 
468 
469 void EnumTxt::setMissingTxt( quint16 toNameSpace, quint16 fromNameSpace, bool neverHumanize)
470 {
471  if (toNameSpace == 0) return; // Not allowed to change original enum texts
472  if (toNameSpace == fromNameSpace) return;
473 
474  XStringMap xsmFrom;
475  XStringMap xsmTo;
476  addEnumSetTo( xsmFrom, fromNameSpace);
477  addEnumSetTo( xsmTo, toNameSpace);
478 
479  for (int i = 0; i < xsmFrom.size(); ++i) {
480  const QByteArray& enumValKey = xsmFrom.keyRef( i);
481  if (xsmTo.indexOf( enumValKey) < 0) { // Missing enumval in target
482  int enumVal = enumValKey.toInt();
483  const char* enumTxt = getTxt( enumVal, fromNameSpace); // Get the original txt ptr
484 
485  if ((fromNameSpace > 0) || neverHumanize) { // Enum name is used as is
486  setTxtRefAny( enumTxt, enumVal, toNameSpace);
487  }
488  else { // Enum name is humanized (Leading capital and separated words)
489  QByteArray enumTxtHuman = humanize( QString::fromUtf8( enumTxt)).toUtf8();
490  setTxt( enumTxtHuman.constData(), enumVal, toNameSpace);
491  }
492  }
493  }
494 }
495 
496 
497 QString EnumTxt::humanize( const QString& txt)
498 {
499  QString retVal;
500  bool wasDigit = false;
501  bool wasUpper = false;
502  bool wasLower = false;
503  bool wasWantSpace = false;
504  bool wasSpace = false;
505 
506  for (int i = 0; i < txt.size(); ++i) {
507  QChar c = txt.at(i);
508  bool isDigit = c.isDigit();
509  bool isUpper = c.isUpper();
510  bool isLower = c.isLower();
511  bool wantSpace = false;
512 
513  if (i > 0)
514  c = c.toLower();
515 
516  if (i == 0)
517  c = c.toUpper();
518  else if (c == '_')
519  c = ' ';
520  else if ((i >= 2) && wasUpper && isLower && !wasWantSpace)
521  retVal.insert( retVal.size() - 1, ' ');
522  else if (wasLower && isUpper)
523  wantSpace = true;
524  else if (!wasDigit && isDigit && !wasSpace)
525  wantSpace = true;
526  else if (wasDigit && !isDigit)
527  wantSpace = true;
528 
529  if (wantSpace)
530  retVal += ' ';
531 
532  retVal += c;
533 
534  wasSpace = c.isSpace();
535  wasDigit = isDigit;
536  wasUpper = isUpper;
537  wasLower = isLower;
538  wasWantSpace = wantSpace;
539  }
540 
541  return retVal;
542 }
543 
544 
545 void EnumTxt::setupTxt( const _InitEnumTxt* initTxt)
546 {
547  if (!initTxt) return; // Nothing to setup
548 
549  for (int i = 0; (initTxt[i].enumTxt || initTxt[i].enumVal || initTxt[i].ns); ++i) {
550  if (initTxt[i].enumTxt)
551  setTxtRef( initTxt[i].enumTxt, initTxt[i].enumVal, initTxt[i].ns);
552  else
553  setMissingTxt( initTxt[i].ns, initTxt[i].enumVal);
554  }
555 }
556 
557 
558 void EnumTxt::setupSubEnum( const _InitSubEnum* initSubEnum)
559 {
560  if (!initSubEnum) return; // Nothing to setup
561 
562  for (int i = 0; initSubEnum[i].enumTxtClass; ++i) {
563  addSubEnum( *initSubEnum[i].enumTxtClass, initSubEnum[i].mask, initSubEnum[i].factor);
564  }
565 }
566 
567 
568 bool EnumTxt::isFlag() const
569 {
570  return _isFlag;
571 }
572 
573 
575 {
576  if (_metaObj) return; // Not allowed to clear when setup via metaobj
577 
578  if (_txtStore) {
579  delete _txtStore;
580  _txtStore = arnNullptr;
581  }
582  if (_subEnumTab) {
583  for (int i = 0; i < _subEnumTab->size(); ++i) {
584  const SubEnumEntry& entry =_subEnumTab->at( i);
585  if (entry._isLocalOwn) {
586  delete entry._subEnum;
587  }
588  }
589  delete _subEnumTab;
590  _subEnumTab = arnNullptr;
591  }
592  _enumTxtTab.clear();
593  _name.clear();
594  _isFlag = false;
595  _subEnumMask = 0;
596 }
597 
598 
599 bool EnumTxt::loadEnumSet( const XStringMap& xsm, const QString& name)
600 {
601  if (_metaObj) return false; // Not allowed to load when setup via metaobj
602  bool retVal = true; // Assusme ok
603 
604  clear();
605  _isFlag = false;
606  _name = name.toUtf8();
607  int nKeys = xsm.size();
608  for (int i = 0; i < nKeys; ++i) {
609  const char* txt = xsm.valueRef( i).constData();
610  bool isOk = true;
611  int enumVal = strToNum( xsm.keyRef( i), &isOk);
612  retVal &= isOk;
613  setTxt( txt, enumVal, 0);
614  }
615  return retVal;
616 }
617 
618 
619 bool EnumTxt::loadEnumSet( const QString& xstr, const QString& name)
620 {
621  return loadEnumSet( XStringMap( xstr.toUtf8()), name);
622 }
623 
624 
625 bool EnumTxt::loadBitSet( const XStringMap& xsm, const QString& name)
626 {
627  if (_metaObj) return false; // Not allowed to load when setup via metaobj
628  bool retVal = true; // Assusme ok
629  bool isOk = true;
630 
631  clear();
632  _isFlag = true;
633  _name = name.toUtf8();
634 
635  EnumTxt* subEnumTxt = arnNullptr;
636  uint subeMask = 0;
637  uchar subePos = 0;
638  int nLoop = xsm.size() + 1; // 1 extra
639  for (int i = 0; i < nLoop; ++i) {
640  QByteArray key = xsm.keyRef( i);
641  QByteArray itemTxt = xsm.valueRef( i);
642  QChar c = key.isEmpty() ? ' ' : key.at( 0);
643 
644  if (subEnumTxt) {
645  if (c == 'E') {
646  int numLen = key.size() - 1;
647  bool isNeg = key.endsWith( '-');
648  numLen -= isNeg;
649  int enumVal = strToNum( key.mid( 1, numLen), &isOk);
650  retVal &= isOk;
651  enumVal |= isNeg ? (-1 & ~(subeMask >> subePos)) : 0;
652  subEnumTxt->setTxt( itemTxt.constData(), enumVal, 0);
653  }
654  else {
655  addSubEnumAny( *subEnumTxt, subeMask, 1 << subePos, true);
656  subEnumTxt = arnNullptr;
657  }
658  }
659 
660  if (c == 'B' ) {
661  uint enumValue = 1 << strToBitpos( key, &isOk);
662  retVal &= isOk;
663  setTxt( itemTxt.constData(), enumValue, 0);
664  }
665  else if (c.isDigit()) {
666  uint enumValue = strToNum( key, &isOk);
667  retVal &= isOk;
668  setTxt( itemTxt.constData(), enumValue, 0);
669  }
670  else if (key.startsWith( "SE")) {
671  QList<QByteArray> seParts = key.mid( 2).split( ':');
672  subeMask = strToNum( seParts.at( 0), &isOk);
673  retVal &= isOk;
674  subePos = seParts.size() > 1 ? strToBitpos( seParts.at( 1), &isOk) : 0;
675  retVal &= isOk;
676  setTxt( itemTxt.constData(), subeMask, 0);
677  QString subEnumName = QString::fromUtf8( itemTxt.constData(), itemTxt.size());
678  subEnumTxt = new EnumTxt( false, subEnumName);
679  }
680  else {
681  retVal = false;
682  }
683  }
684 
685  return retVal;
686 }
687 
688 
689 bool EnumTxt::loadBitSet( const QString& xstr, const QString& name)
690 {
691  return loadBitSet( XStringMap( xstr.toUtf8()), name);
692 }
693 
694 
696 {
697  if (!_subEnumTab) return 0;
698  return _subEnumTab->size();
699 }
700 
701 
702 QString EnumTxt::subEnumNameAt( int idx, quint16 nameSpace) const
703 {
704  if (idx >= subEnumCount()) return QString();
705 
706  uint bitMask = _subEnumTab->at( idx)._bitMask;
707  return getTxtString( bitMask, nameSpace);
708 }
709 
710 
711 bool EnumTxt::subEnumPropAt( int idx, uint& bitMask, uchar& bitPos) const
712 {
713  if (idx >= subEnumCount()) return false;
714 
715  const SubEnumEntry& entry = _subEnumTab->at( idx);
716  bitMask = entry._bitMask;
717  bitPos = entry._bitPos;
718  return true;
719 }
720 
721 
722 const EnumTxt* EnumTxt::subEnumAt( int idx) const
723 {
724  if (idx >= subEnumCount()) return arnNullptr;
725 
726  return _subEnumTab->at( idx)._subEnum;
727 }
728 
729 
730 const char* EnumTxt::name() const
731 {
732  return _name.constData();
733 }
734 
735 
737 {
738  if (!_metaObj || _metaObj->enumeratorCount() < 1) return 0;
739 
740  QMetaEnum metaEnum = _metaObj->enumerator(0);
741  return metaEnum.keyCount();
742 }
743 
744 
745 QByteArray EnumTxt::numToStr( uint num)
746 {
747  if (num < 10)
748  return QByteArray::number( num);
749  else
750  return "0x" + QByteArray::number( num, 16);
751 }
752 
753 
754 uint EnumTxt::strToNum( const QByteArray& str, bool* isOk)
755 {
756  if (str.startsWith( "0x")) {
757  return str.mid( 2).toInt( isOk, 16);
758  }
759  else {
760  return str.toInt( isOk);
761  }
762 }
763 
764 
765 uchar EnumTxt::strToBitpos( const QByteArray& str, bool* isOk)
766 {
767  if (str.startsWith( "B")) {
768  return str.mid( 1).toInt( isOk);
769  }
770  if (isOk) *isOk = false;
771  return 0;
772 }
773 
774 
775 void EnumTxt::setupFromMetaObject()
776 {
777  if (!_metaObj || _metaObj->enumeratorCount() < 1) return;
778 
779  QMetaEnum metaEnum = _metaObj->enumerator(0);
780  int nKeys = metaEnum.keyCount();
781  for (int i = 0; i < nKeys; ++i) {
782  int enumVal = metaEnum.value(i);
783  setTxtRefAny( metaEnum.key(i), enumVal, 0);
784  }
785 }
786 
787 
788 EnumTxt::EnumTxtKey::EnumTxtKey( uint enumVal, quint16 nameSpace, bool isFlag)
789 {
790  _enumVal = enumVal;
791  _nameSpace = nameSpace;
792  _isFlag = isFlag;
793  _isSingleBit = isFlag ? isPower2( enumVal ) : false;
794 }
795 
796 
797 bool EnumTxt::EnumTxtKey::operator <( const EnumTxt::EnumTxtKey& other) const
798 {
799  if (_isFlag != other._isFlag) qWarning() << "ERROR EnumKey isFlag diff !!!";
800  if (_nameSpace < other._nameSpace) return true;
801  if (_nameSpace > other._nameSpace) return false;
802  if (_isFlag) { // Flags sorted: 1, 2, 4, 8 .. 0, 3, 5, 6, 7, 9 .. (i.e. Singlebits .. Others)
803  if (_isSingleBit != other._isSingleBit) return _isSingleBit;
804  return _enumVal < other._enumVal; // Flag: unsigned compare
805  }
806  else { // Enums sorted: as signed integers
807  return int(_enumVal) < int(other._enumVal);
808  }
809 }
810 
811 }
QStringList flagsToStringList(int val, quint16 nameSpace=0) const
returns string list for enum flags
Definition: MQFlags.cpp:313
QString getEnumSet(quint16 nameSpace=0, bool neverHumanize=false) const
returns the enum set string
Definition: MQFlags.cpp:429
int indexOf(const char *key, int from=0) const
static uchar strToBitpos(const QByteArray &str, bool *isOk=arnNullptr)
Definition: MQFlags.cpp:765
void addSubEnumPlainTo(Arn::XStringMap &xsm, quint16 nameSpace=0, bool neverHumanize=false) const
Adds all sub enum plain and shifted to a XStringMap.
Definition: MQFlags.cpp:281
void setTxt(const char *txt, int enumVal, quint16 nameSpace)
Set an additional text for an enum val in a namespace.
Definition: MQFlags.cpp:107
QStringList values(const char *keyPrefix=arnNullptr) const
void addEnumSetTo(Arn::XStringMap &xsm, quint16 nameSpace=0, bool neverHumanize=false) const
Adds enum set to a XStringMap.
Definition: MQFlags.cpp:406
int flagsFromStringList(const QStringList &flagStrings, quint16 nameSpace=0)
returns enum flags from string list
Definition: MQFlags.cpp:362
QStringList getBasicTextList(quint16 nameSpace=0, bool neverHumanize=false) const
returns a string list containing the most basic texts
Definition: MQFlags.cpp:437
Class Enum text.
Definition: MQFlags.hpp:212
QString flagsToString(int val, quint16 nameSpace=0) const
returns text string for enum flags
Definition: MQFlags.cpp:305
bool isFlag() const
Returns true if this is a flag usage.
Definition: MQFlags.cpp:568
QString getBitSet(quint16 nameSpace=0, bool neverHumanize=false) const
returns the bit set string for enum flags
Definition: MQFlags.cpp:271
Container class with string representation for serialized data.
Definition: XStringMap.hpp:107
bool getSubEnumVal(const char *txt, int &subEnumVal, uint &bitMask, quint16 nameSpace=0) const
Returns the shifted enum value and the mask for a subEnum text in a namespace.
Definition: MQFlags.cpp:169
void addEnumSet(Arn::XStringMap &xsm, quint16 nameSpace=0, bool neverHumanize=false) const
Definition: MQFlags.hpp:503
const char * enumTxt
Definition: MQFlags.hpp:134
bool isPower2(T x)
Definition: Math.hpp:69
void addBitSetTo(Arn::XStringMap &xsm, quint16 nameSpace=0, bool neverHumanize=false) const
Adds bit set for enum flags to a XStringMap.
Definition: MQFlags.cpp:262
int enumCount() const
returns number of enumerators in the enum (class)
Definition: MQFlags.cpp:736
void addFlagsTo(Arn::XStringMap &xsm, const IncludeMode &incMode, quint16 nameSpace=0, bool neverHumanize=false) const
Adds enum flags to a XStringMap.
Definition: MQFlags.cpp:193
static QByteArray numToStr(uint num)
Definition: MQFlags.cpp:745
void addSubEnum(const EnumTxt &subEnum, uint bitMask, uint factor)
Adds an other EnumTxt as a subEnum to this flag EnumTxt.
Definition: MQFlags.cpp:451
const QByteArray & keyRef(int i) const
int subEnumCount() const
Returns number of subEnums in this bitSet (class)
Definition: MQFlags.cpp:695
void setTxtString(const QString &txt, int enumVal, quint16 nameSpace)
Set an additional text for an enum val in a namespace.
Definition: MQFlags.cpp:130
const QByteArray & valueRef(int i) const
void clear(bool freeMem=false)
const EnumTxt * subEnumAt(int idx) const
Returns a pointer to a SubEnum.
Definition: MQFlags.cpp:722
void setTxtRef(const char *txt, int enumVal, quint16 nameSpace)
Definition: MQFlags.cpp:100
QByteArray toXString() const
Definition: Arn.cpp:43
bool loadBitSet(const Arn::XStringMap &xsm, const QString &name=QString())
Loads the instance by an bit set (flags) XStringMap.
Definition: MQFlags.cpp:625
void addSubEnumTo(Arn::XStringMap &xsm, quint16 nameSpace=0, bool neverHumanize=false) const
Adds sub enum flags to a XStringMap.
Definition: MQFlags.cpp:236
int getEnumVal(const char *txt, int defaultVal=0, quint16 nameSpace=0, bool *isFound=arnNullptr) const
Returns the enum value for a text in a namespace.
Definition: MQFlags.cpp:142
const char * name() const
returns the name of the enum (class)
Definition: MQFlags.cpp:730
void clear()
Clear this dynamic instance to its starting state.
Definition: MQFlags.cpp:574
QString getTxtString(int enumVal, quint16 nameSpace=0, bool *isFound=arnNullptr) const
Returns the text for a enum value in a namespace.
Definition: MQFlags.cpp:136
bool subEnumPropAt(int idx, uint &bitMask, uchar &bitPos) const
Returns the properties of a SubEnum.
Definition: MQFlags.cpp:711
QString subEnumNameAt(int idx, quint16 nameSpace=0) const
Returns the name of a SubEnum.
Definition: MQFlags.cpp:702
const char * getTxt(int enumVal, quint16 nameSpace=0, bool *isFound=arnNullptr) const
Returns the text for a enum value in a namespace.
Definition: MQFlags.cpp:121
XStringMap & add(const char *key, const QByteArray &val)
static uint strToNum(const QByteArray &str, bool *isOk=arnNullptr)
Definition: MQFlags.cpp:754
int log2(T x)
Definition: Math.hpp:75
static QString humanize(const QString &txt)
returns the humanized text
Definition: MQFlags.cpp:497
int flagsFromString(const QString &flagString, quint16 nameSpace=0)
returns enum flags from string
Definition: MQFlags.cpp:354
int size() const
Definition: XStringMap.hpp:121
EnumTxt(const QMetaObject *metaObj, bool isFlag, const _InitEnumTxt *initTxt, const _InitSubEnum *initSubEnum, const char *name)
Definition: MQFlags.cpp:63
bool loadEnumSet(const Arn::XStringMap &xsm, const QString &name=QString())
Loads the instance by an enum set XStringMap.
Definition: MQFlags.cpp:599
void setMissingTxt(quint16 toNameSpace, quint16 fromNameSpace=0, bool neverHumanize=false)
Copies missing enum texts from one namespace to another.
Definition: MQFlags.cpp:469