1 #ifndef devatlas_priv_h 2 #define devatlas_priv_h 3 #include <mtld/devatlas.h> 4 #include <mtld/common_priv.h> 7 namespace Mobi {
namespace Mtld {
namespace Da {
15 static constexpr
size_t LOCAL_PROP_COUNT=16;
39 typedef unsigned int I;
41 static const int mask =
sizeof (I) * 8 - 1;
43 static unsigned idxOf(
unsigned item) {
44 return item /
sizeof(I);
48 propset(
size_t maxcount = 200) {
49 size_t count = idxOf(maxcount | mask) + 1;
51 memset(vals, 0,
sizeof (I) * count);
57 bool find(
size_t v)
const {
58 return vals[idxOf(v)] & (1 << (v & mask));
65 void insert(
unsigned v) {
66 vals[idxOf(v)] |= 1 << (v & mask);
96 std::shared_ptr<NodeData> data;
99 template <
typename T>
void visitR(T &t,
char key)
const;
102 bool isLeaf()
const {
return children.empty(); }
110 unsigned int nextTree;
111 unsigned int matchedDevices;
114 std::unique_ptr<std::vector<size_t> > replacementStrings;
115 std::unique_ptr<std::vector<size_t> > excls;
116 NodeData() : nextTree(0), matchedDevices(0), resetWalkId(-1) {}
117 const attrvec &getAttrs()
const {
return attrs; }
118 attrvec &getAttrs() {
return attrs; }
119 const propset &getConflicts()
const {
return conflicts; }
120 propset &getConflicts() {
return conflicts; }
121 unsigned getMatchedDeviceCount()
const {
return matchedDevices; }
122 unsigned getNextTreeMatchCount()
const {
return nextTree; }
123 int getResetWalkId()
const {
return resetWalkId; }
132 template <
typename T>
void 133 Node::visitR(T &t,
char key)
const 135 if (!t.pre(key,
this))
137 for (childmap::const_iterator it = children.begin(); it != children.end(); ++it)
139 (*it).second->visitR(t, (*it).first);
159 template <
typename T,
typename Allocator>
size_t 160 dafind(
const DeviceAtlas &atlas, T &t, TreeID tree, Allocator &a,
const char *rostr,
char **matched,
char **unmatched)
162 const Node *n = atlas.roots[tree];
163 size_t len = strlen(rostr);
165 a.allocate(str, len + 1);
166 strlcpy(str, rostr, len + 1);
169 a.allocate(*matched, atlas.maxDepth + 1);
171 Node::childmap::const_iterator it;
174 char *pathp = matched ? *matched : 0;
176 for (offset=0;;++offset) {
177 NodeData *data = n->data.get();
180 if (data->getResetWalkId() > -1) {
182 std::string resetWalk = atlas.getResetWalkString((
size_t)data->getResetWalkId());
183 const char *resetWalkString = resetWalk.c_str();
184 size_t resetWalkStringLen = resetWalk.size();
185 size_t ostrlen = strlen(str + offset);
186 size_t pcount = atlas.getPropertyCount();
187 a.allocate(pstr, resetWalkStringLen + ostrlen + 1);
188 memcpy(pstr, resetWalkString, resetWalkStringLen);
189 memcpy(pstr + resetWalkStringLen, str + offset, ostrlen + 1);
196 for (
size_t i = 0; i < pcount; i ++)
199 return dafind(atlas, t, tree, a, pstr, matched, unmatched);
202 if (atlas.getpropId()) {
203 if (t.rfskp && data->getAttrs().find(atlas.getpropId()->index) != data->getAttrs().end())
206 t.rfskp = data->excls.get();
208 if (!t(*n, str, offset) || str[offset] == 0)
210 if ((atlas.flags & DeviceAtlas::NoREFold) == 0) {
211 const auto repls = data->replacementStrings.get();
213 atlas.doReplacements(repls, str, offset);
217 *pathp++ = str[offset];
218 it = n->children.find(str[offset]);
219 if (it == n->children.end())
226 (*matched)[dataoff] = 0;
228 *unmatched = str + dataoff;
233 template <
typename T>
void 234 visit(
const DeviceAtlas &atlas, T &t, TreeID tree)
236 atlas.roots[tree]->visitR(t,
'.');
264 std::vector<Rule *> rules;
272 std::unordered_map<int, int> selectionCriteria;
273 std::vector<RuleSet *> ruleSets;
276 const RuleSet *findSet(
const UAR *,
int,
const char *text)
const;
282 TaggedRegexMap allRegexes;
283 const std::vector<REInfo *> *langRegexes;
284 const std::vector<REInfo *> *defaultRegexes;
285 std::vector<int> skipProps;
286 std::vector<RuleGroup *> groups;
287 const REInfo *getRE(
size_t re)
const;
297 template <
typename T>
bool 298 testop(Operator op,
const T &lhs,
const T &rhs)
301 case Equal:
return lhs == rhs;
302 case NotEqual:
return lhs != rhs;
303 default: {
Exception err; err <<
"\"unknown\"";
throw err; }
314 const Property &p = da.getPropertyDescr(property);
316 case Bool:
return testop<bool>(op, *value, *candidate);
317 case Integer:
return testop<long>(op, *value, *candidate);
318 case String:
return testop<std::string>(op, *value, *candidate);
319 default:
throw Exception(
"unhandled property type");
326 typedef std::vector<CPRule> Rules;
331 void setProperty(
size_t,
const Value *) {}
332 bool hasProperty(
const Property &) {
return false; }
334 bool operator() (
const Node &node,
const char *,
size_t);
335 std::vector<size_t> *rfskp;
338 std::ostream &operator<<(std::ostream &os,
const CPRuleGroup &);
339 std::ostream &operator<<(std::ostream &os,
const CPRule &);
340 std::ostream &operator<<(std::ostream &os,
const Operator &);
344 std::vector<const Value *> props;
347 void operator () (PropertyType type,
const char *,
const char *);
367 decodeLanguage(
char *language,
size_t *minuspos) {
369 if (*language ==
'*')
374 if ((m = strchr(language,
'-')) == NULL)
375 m = strchr(language,
'_');
379 if (mlen == 1 || mlen > 3)
388 if (strlen(language) > 2)
392 for(; *p; p++, mp++) {
393 if ((*p !=
'-' && !isalpha(*p) && !isspace(*p)))
395 if (*minuspos > 0 && mp > *minuspos)
406 template <
typename Allocator>
408 stripQlanguage(
const char *language,
size_t *minuspos, Allocator &a) {
410 size_t plen = strlen(language);
411 a.allocate(cp, plen + 1);
412 strlcpy(cp, language, plen + 1);
415 AcceptLanguagePreference apmax = {0};
417 while((token = strtok_r(cp,
",", &ptr)) != NULL) {
421 while (isspace(*token) && token ++);
427 if ((qstr = strstr(token,
";")) != NULL) {
428 codelen = (qstr - token);
431 while (isspace(*qstr) && qstr ++);
432 if (strncmp(qstr,
"q=", 2) == 0) {
434 while (isspace(*qstr) && qstr ++);
436 float qtmp = strtod(qstr, 0);
447 size_t tminuspos = 0;
449 if ((codelen = decodeLanguage(token, &tminuspos)) > 0) {
450 a.allocate(code, codelen + 1);
451 strlcpy(code, token, codelen + 1);
456 apmax.minuspos = tminuspos;
458 }
else if (q == apmax.q) {
459 if (apmax.code && tminuspos > 0 &&
460 strncmp(apmax.code, code, tminuspos) == 0 &&
461 codelen > apmax.len) {
463 apmax.minuspos = tminuspos;
470 const char *finallanguage = (apmax.code ? (*apmax.code ==
'*' ? 0 : apmax.code) : 0);
471 *minuspos = (apmax.code ? apmax.minuspos : 0);
473 return finallanguage;
476 template <
typename T,
typename Allocator>
477 void decodeHeuristic(
const char *p, T &cprec, Allocator &a)
482 size_t plen = strlen(p);
483 a.allocate(cp, plen + 1);
484 strlcpy(cp, p, plen + 1);
490 while ((token = strtok_r(cp,
"|", &ptr)) != NULL) {
493 char key[124], *kp = key;
494 char escapedvalue[124], *ep = escapedvalue;
495 switch ((c = nextchar((
const char *&)token, Util::SKIPQUOTE | Util::NULLOK))) {
496 case 'b': type = Bool;
break;
497 case 'i': type = Integer;
break;
498 case 's': type = String;
break;
500 default: cprec.props.clear();
return;
503 char *sptr, *tmpkp, *tmpvp;
504 tmpkp = strtok_r(token,
":", &sptr);
505 tmpvp = strtok_r(NULL,
":", &sptr);
511 for (
char *p = tmpkp; m++ < (
sizeof(key)) - 1 && *p; ++p)
516 for (
const char *p = tmpvp; m++ < (
sizeof(escapedvalue) - 1) && *p; ++p) {
518 case '\"': ep += snprintf(ep,
sizeof(
""e;") + 1,
""e;");
break;
519 case '&': ep += snprintf(ep,
sizeof(
"&") + 1,
"&");
break;
520 case '<': ep += snprintf(ep,
sizeof(
"<") + 1,
"<");
break;
521 case '>': ep += snprintf(ep,
sizeof(
">") + 1,
">");
break;
522 default: *ep++ = *p;
break;
528 for (i = kp; *i && (isalnum(*i) || *i ==
'.'); ++i);
530 if (*i == 0 && i != kp)
531 cprec(type, kp, escapedvalue);
535 template<
typename T,
typename Allocator>
537 dafindDesktopOsVer(T &t, Allocator &a,
const char *oname,
const char *plt,
const char *oversion) {
538 const char *ovname = 0;
539 Value *ptroversion, *ptroname, *ptrovname;
540 auto olen = strlen(oversion);
541 if (strcmp(plt,
"Windows") == 0) {
544 foversion = t.strdup(oversion);
545 while (foversion && *foversion ==
'0') foversion++;
548 auto v = strtol(foversion, &e, 0);
549 if (*e !=
'\0' && *e !=
'.')
589 oname =
"Windows 11";
591 oname =
"Windows 10";
592 }
else if (strcmp(oversion,
"0.3.0") == 0) {
593 oname =
"Windows 8.1";
595 }
else if (strcmp(oversion,
"0.2.0") == 0) {
598 }
else if (strcmp(oversion,
"0.1.0") == 0) {
602 }
else if (strcmp(plt,
"macOS") == 0) {
604 if (strncmp(oversion,
"11", 2) == 0) {
606 }
else if (strncmp(oversion,
"12", 2) == 0) {
608 }
else if (strncmp(oversion,
"13", 2) == 0) {
610 }
else if (strncmp(oversion,
"10.12", 5) == 0) {
612 }
else if (strncmp(oversion,
"10.13", 5) == 0) {
613 ovname =
"High Sierra";
614 }
else if (strncmp(oversion,
"10.14", 5) == 0) {
616 }
else if (strncmp(oversion,
"10.15", 5) == 0) {
618 }
else if (strncmp(oversion,
"10.11", 5) == 0) {
619 ovname =
"El Capitan";
624 a.allocate(ptroname);
625 ptroname->u.strval = t.strdup(oname);
626 ptroname->type = String;
627 t.setProperty(t.getAtlas().getpropOname()->index, ptroname);
629 a.allocate(ptrovname);
630 ptrovname->u.strval = t.strdup(ovname);
631 ptrovname->type = String;
632 t.setProperty(t.getAtlas().getpropOversionNm()->index, ptrovname);
635 a.allocate(ptroversion);
636 ptroversion->u.strval = t.strdup(oversion);
637 ptroversion->type = String;
638 t.setProperty(t.getAtlas().getpropOversion()->index, ptroversion);
644 typedef std::vector<CPRuleGroup> RuleGroups;
645 RuleGroups ruleGroups;
651 #endif // devatlas_priv_h Definition: devatlas_priv.h:308
Definition: devatlas.h:108
Definition: devatlas_priv.h:642
Definition: exception.h:16
Definition: devatlas_priv.h:38
Definition: dajson.cpp:244
Definition: dajson.cpp:187
Definition: devatlas_priv.h:343
Definition: devatlas_priv.h:85
Definition: devatlas_priv.h:105
Definition: devatlas_priv.h:240
Definition: devatlas_priv.h:10
Definition: devatlas_priv.h:16
Definition: devatlas_priv.h:261
Definition: devatlas_priv.h:280
Definition: devatlas_priv.h:355
Definition: devatlas.h:229
Definition: devatlas_priv.h:269
Definition: devatlas_priv.h:324