53std::string
DataMessageHeader::toJSON(std::map<uint16, std::string>* subtypes, std::map<uint16, std::string>* subcontexts, std::map<uint32, std::string>* compNames) {
55 if (!subtypes && !subcontexts && !compNames)
56 return utils::StringFormat(
"{ \"size\": %u, \"memid\": \"%llu\", \"time\": \"%llu\", \"time__desc\": \"%s\", \"sendtime\": \"%llu\", \"sendtime__desc\": \"%s\", \"recvtime\": \"%llu\", \"recvtime__desc\": \"%s\", "
57 "\"modulecputime\": %u, \"modulewalltime\": %u, \"chaincputime\": %u, \"chainwalltime\": %u, \"chaincount\": %u, "
58 "\"origin\": %u, \"destination\": %u, \"ttl\": \"%llu\", \"eol__desc\": \"%s\", \"priority\": %u, \"policy\": %u, \"from\": %u, \"to\": %u, \"type\": \"%s\", \"tag\": \"%u\", \"status\": %u, \"reference\": \"%llu\", \"serial\": \"%llu\", \"contextchange\": \"%s\", \"userdatacount\": %u, \"userdatasize\": %u }",
69 std::string typeStr, contextStr, fromStr, toStr;
70 typeStr =
type.toString(subtypes);
73 fromStr = (*compNames)[
from];
74 toStr = (*compNames)[
to];
76 if (!fromStr.length()) {
80 if (!toStr.length()) {
84 return utils::StringFormat(
"{ \"size\": %u, \"memid\": \"%llu\", \"time\": \"%llu\", \"time__desc\": \"%s\", \"sendtime\": \"%llu\", \"sendtime__desc\": \"%s\", \"recvtime\": \"%llu\", \"recvtime__desc\": \"%s\", "
85 "\"modulecputime\": %u, \"modulewalltime\": %u, \"chaincputime\": %u, \"chainwalltime\": %u, \"chaincount\": %u, "
86 "\"origin\": %u, \"destination\": %u, \"ttl\": \"%llu\", \"eol__desc\": \"%s\", \"priority\": %u, \"policy\": %u, \"from\": \"%s\", \"to\": \"%s\", \"type\": \"%s\", \"tag\": \"%u\", \"status\": %u, \"reference\": \"%llu\", \"serial\": \"%llu\", \"contextchange\": \"%s\", \"userdatacount\": %u, \"userdatasize\": %u }",
101std::string
DataMessageHeader::toXML(std::map<uint16, std::string>* subtypes, std::map<uint16, std::string>* subcontexts, std::map<uint32, std::string>* compNames) {
104 if (!subtypes && !subcontexts && !compNames)
105 return utils::StringFormat(
"<datamessage size=\"%u\" memid=\"%llu\" time=\"%llu\" timetext=\"%s\" sendtime=\"%llu\" sendtimetext=\"%s\" recvtime=\"%llu\" recvtimetext=\"%s\" "
106 "modulecputime=\"%u\" modulewalltime=\"%u\" chaincputime=\"%u\" chainwalltime=\"%u\" chaincount=\"%u\" "
107 "origin=\"%u\" destination=\"%u\" ttl=\"%llu\" eoltext=\"%s\" priority=\"%u\" policy=\"%u\" from=\"%u\" to=\"%u\" type=\"%s\" tag=\"%u\" status=\"%u\" reference=\"%llu\" serial=\"%llu\" contextchange=\"%s\" userdatacount=\"%u\" userdatasize=\"%u\" />\n",
113 origin,
destination,
ttl,
ttl ?
PrintTimeString(
time +
ttl).c_str() :
"",
priority,
policy,
from,
to,
type.toString().c_str(),
tag,
status,
reference,
serial,
contextchange.isValid() ?
contextchange.toString().c_str() :
"",
userCount,
userSize);
115 std::string typeStr, contextStr, fromStr, toStr;
116 typeStr =
type.toString(subtypes);
119 fromStr = (*compNames)[
from];
120 toStr = (*compNames)[
to];
122 if (!fromStr.length()) {
126 if (!toStr.length()) {
131 return utils::StringFormat(
"<datamessage size=\"%u\" memid=\"%llu\" time=\"%llu\" timetext=\"%s\" sendtime=\"%llu\" sendtimetext=\"%s\" recvtime=\"%llu\" recvtimetext=\"%s\" "
132 "modulecputime=\"%u\" modulewalltime=\"%u\" chaincputime=\"%u\" chainwalltime=\"%u\" chaincount=\"%u\" "
133 "origin=\"%u\" destination=\"%u\" ttl=\"%llu\" eoltext=\"%s\" priority=\"%u\" policy=\"%u\" from=\"%s\" to=\"%s\" type=\"%s\" tag=\"%u\" status=\"%u\" reference=\"%llu\" serial=\"%llu\" contextchange=\"%s\" userdatacount=\"%u\" userdatasize=\"%u\" />\n",
162 while (src < srcEnd) {
179 struct ArrayElem { int64 index;
char* entryPtr; uint32 cid; };
180 struct MapElem { std::string index;
char* entryPtr; uint32 cid; };
191 if (!
data->userCount)
194 std::map< std::string, std::list<ArrayElem> > userArrays;
195 std::map< std::string, std::list<MapElem> > userMaps;
199 const char* mapStart, *mapEnd;
200 std::string userData;
201 userData.reserve(
data->userSize +
data->userCount * 64);
203 char* srcEnd = (
char*)
data +
data->size;
204 while (src < srcEnd) {
208 if ((mapStart = strstr(key,
"_-|")) && (mapEnd = strstr(key,
"|-_"))) {
210 e.index =
utils::Ascii2Int64(std::string(mapStart + 3, mapEnd - mapStart - 3).c_str());
213 userArrays[std::string(key, mapStart - key)].push_back(e);
217 else if ((mapStart = strstr(key,
"_-[")) && (mapEnd = strstr(key,
"]-_"))) {
219 e.index = std::string(mapStart + 3, mapEnd - mapStart - 3);
222 userMaps[std::string(key, mapStart - key)].push_back(e);
257 if (userData.length()) userData +=
", ";
272 std::string subUserData;
274 std::list<ArrayElem>::iterator entryII, entryEE;
275 std::map< std::string, std::list<ArrayElem> >::iterator keyII = userArrays.begin(), keyEE = userArrays.end();
276 while (keyII != keyEE) {
278 entryII = keyII->second.begin();
279 entryEE = keyII->second.end();
280 while (entryII != entryEE) {
281 char* ep = entryII->entryPtr;
283 uint32 cid = entryII->cid;
300 if (subUserData.length()) subUserData +=
", ";
306 subUserData +=
utils::StringFormat(
"%lld : %lld (integer)\n", entryII->index, *(int64*)val);
312 subUserData +=
utils::StringFormat(
"%lld : (string of size %lld)\n", entryII->index, *(int64*)val);
315 subUserData +=
utils::StringFormat(
"%lld : (binary of size %lld)\n", entryII->index, *(int64*)val);
318 subUserData +=
utils::StringFormat(
"%lld : (message of size %lld)\n", entryII->index, *(int64*)val);
329 std::list<MapElem>::iterator entryI, entryE;
330 std::map< std::string, std::list<MapElem> >::iterator keyI = userMaps.begin(), keyE = userMaps.end();
331 while (keyI != keyE) {
333 entryI = keyI->second.begin();
334 entryE = keyI->second.end();
335 while (entryI != entryE) {
336 char* ep = entryI->entryPtr;
338 uint32 cid = entryI->cid;
345 entryI->index.c_str(),
355 if (subUserData.length()) subUserData +=
", ";
361 subUserData +=
utils::StringFormat(
"'%s' : %lld (integer)\n", entryI->index.c_str(), *(int64*)val);
364 subUserData +=
utils::StringFormat(
"'%s' : %f (float)\n", entryI->index.c_str(), *(float64*)val);
367 subUserData +=
utils::StringFormat(
"'%s' : (string of size %lld)\n", entryI->index.c_str(), *(int64*)val);
370 subUserData +=
utils::StringFormat(
"'%s' : (binary of size %lld)\n", entryI->index.c_str(), *(int64*)val);
373 subUserData +=
utils::StringFormat(
"'%s' : (message of size %lld)\n", entryI->index.c_str(), *(int64*)val);
395 if (!
data->userCount)
398 std::map< std::string, std::list<ArrayElem> > userArrays;
399 std::map< std::string, std::list<MapElem> > userMaps;
401 const char* oldData = NULL;
404 const char* mapStart, *mapEnd;
405 std::string userData;
406 userData.reserve(
data->userSize +
data->userCount * 64);
408 char* srcEnd = (
char*)
data +
data->size;
409 while (src < srcEnd) {
413 if ((mapStart = strstr(key,
"_-|")) && (mapEnd = strstr(key,
"|-_"))) {
415 e.index =
utils::Ascii2Int64(std::string(mapStart + 3, mapEnd - mapStart - 3).c_str());
418 userArrays[std::string(key, mapStart - key)].push_back(e);
422 else if ((mapStart = strstr(key,
"_-[")) && (mapEnd = strstr(key,
"]-_"))) {
424 e.index = std::string(mapStart + 3, mapEnd - mapStart - 3);
427 userMaps[std::string(key, mapStart - key)].push_back(e);
433 if (userData.length()) userData +=
", ";
440 if (userData.length()) userData +=
", ";
442 userData +=
utils::StringFormat(
"\"%s\": {\"type\": \"time\", \"value\": %llu, \"text\": \"%s\" }\n",
453 if (userData.length()) userData +=
", ";
458 if (userData.length()) userData +=
", ";
465 if (userData.length()) userData +=
", ";
479 if (userData.length()) userData +=
", ";
490 if (userData.length()) userData +=
", ";
496 if (userData.length()) userData +=
", ";
502 if (userData.length()) userData +=
", ";
519 std::string subUserData;
521 std::list<ArrayElem>::iterator entryII, entryEE;
522 std::map< std::string, std::list<ArrayElem> >::iterator keyII = userArrays.begin(), keyEE = userArrays.end();
523 while (keyII != keyEE) {
525 entryII = keyII->second.begin();
526 entryEE = keyII->second.end();
527 while (entryII != entryEE) {
528 char* ep = entryII->entryPtr;
530 uint32 cid = entryII->cid;
531 if (subUserData.length()) subUserData +=
", ";
535 subUserData +=
utils::StringFormat(
"%lld: {\"type\": \"text\", \"value\": \"%s\" }\n", entryII->index, val);
541 subUserData +=
utils::StringFormat(
"%lld: {\"type\": \"time\", \"value\": %llu, \"text\": \"%s\" }\n",
542 entryII->index, *(uint64*)val,
555 if (subUserData.length()) subUserData +=
", ";
557 subUserData +=
utils::StringFormat(
"%lld: {\"type\": \"message\", \"value\": %s }\n", entryII->index, msg->
toJSON().c_str());
565 subUserData +=
utils::StringFormat(
"%lld: {\"type\": \"integer\", \"value\": %lld }\n", entryII->index, *(int64*)val);
571 subUserData +=
utils::StringFormat(
"%lld: {\"type\": \"double\", \"value\": %f }\n", entryII->index, *(float64*)val);
577 subUserData +=
utils::StringFormat(
"%lld: {\"type\": \"textinfo\", \"size\": %lld }", entryII->index, *(int64*)val);
581 subUserData +=
utils::StringFormat(
"%lld: {\"type\": \"binary\", \"size\": %lld }", entryII->index, *(int64*)val);
585 subUserData +=
utils::StringFormat(
"%lld: {\"type\": \"messageinfo\", \"size\": %lld }", entryII->index, *(int64*)val);
592 if (userData.length()) userData +=
", ";
594 userData +=
utils::StringFormat(
"\"%s\": {\"type\": \"array\", \"value\":\n{%s} }\n", keyII->first.c_str(), subUserData.c_str());
596 userData +=
utils::StringFormat(
"\"%s\": {%s}\n", keyII->first.c_str(), subUserData.c_str());
601 std::list<MapElem>::iterator entryI, entryE;
602 std::map< std::string, std::list<MapElem> >::iterator keyI = userMaps.begin(), keyE = userMaps.end();
603 while (keyI != keyE) {
605 entryI = keyI->second.begin();
606 entryE = keyI->second.end();
607 while (entryI != entryE) {
608 char* ep = entryI->entryPtr;
610 uint32 cid = entryI->cid;
611 if (subUserData.length()) subUserData +=
", ";
615 subUserData +=
utils::StringFormat(
"\"%s\": {\"type\": \"text\", \"value\": \"%s\" }\n", entryI->index.c_str(), val);
621 subUserData +=
utils::StringFormat(
"\"%s\": {\"type\": \"time\", \"value\": %llu, \"text\": \"%s\" }\n",
622 entryI->index.c_str(), *(uint64*)val,
635 if (subUserData.length()) subUserData +=
", ";
637 subUserData +=
utils::StringFormat(
"\"%s\": {\"type\": \"message\", \"value\": %s }\n", entryI->index.c_str(), msg->
toJSON().c_str());
645 subUserData +=
utils::StringFormat(
"\"%s\": {\"type\": \"integer\", \"value\": %lld }\n", entryI->index.c_str(), *(int64*)val);
647 subUserData +=
utils::StringFormat(
"\"%s\": \"%lld\"\n", entryI->index.c_str(), *(int64*)val);
651 subUserData +=
utils::StringFormat(
"\"%s\": {\"type\": \"double\", \"value\": %f }\n", entryI->index.c_str(), *(float64*)val);
653 subUserData +=
utils::StringFormat(
"\"%s\": \"%f\" }\n", entryI->index.c_str(), *(float64*)val);
657 subUserData +=
utils::StringFormat(
"\"%s\": {\"type\": \"textinfo\", \"size\": %lld }", entryI->index.c_str(), *(int64*)val);
661 subUserData +=
utils::StringFormat(
"\"%s\": {\"type\": \"binary\", \"size\": %lld }", entryI->index.c_str(), *(int64*)val);
665 subUserData +=
utils::StringFormat(
"\"%s\": {\"type\": \"messageinfo\", \"size\": %lld }", entryI->index.c_str(), *(int64*)val);
672 if (userData.length()) userData +=
", ";
674 userData +=
utils::StringFormat(
"\"%s\": {\"type\": \"map\", \"value\":\n{%s} }\n", keyI->first.c_str(), subUserData.c_str());
676 userData +=
utils::StringFormat(
"\"%s\": {%s}\n", keyI->first.c_str(), subUserData.c_str());
684std::string
DataMessage::toJSON(std::map<uint16, std::string>* subtypes, std::map<uint16, std::string>* subcontexts, std::map<uint32, std::string>* compNames) {
687 if (!
data->userCount)
688 return data->toJSON(subtypes, subcontexts, compNames);
692 std::map< std::string, std::list<std::string> > userMaps;
693 std::map< std::string, std::list<int64> > userArrays;
695 uint32 draftSize = 0;
696 uint32 draftUserSize = 0;
697 uint32 draftUserCount = 0;
701 char* srcEnd = (
char*)
data +
data->size;
702 while (src < srcEnd) {
708 if (strcmp(key,
"OS") == 0)
710 else if (strcmp(key,
"US") == 0)
712 else if (strcmp(key,
"UC") == 0)
722 return utils::StringFormat(
"{ \"draft\":\"yes\", \"size\": %u, \"memid\": \"%llu\", \"time\": \"%llu\", \"time__text\": \"%s\", \"sendtime\": \"%llu\", \"sendtime__text\": \"%s\", \"recvtime\": \"%llu\", \"recvtime__text\": \"%s\", \"origin\": %u, \"destination\": %u, \"ttl\": \"%llu\", \"eol__text\": \"%s\", \"priority\": %u, \"policy\": %u, \"from\": %u, \"to\": %u, \"type\": \"%s\", \"tag\": \"%u\", \"status\": %u, \"reference\": \"%llu\", \"serial\": \"%llu\", \"contextchange\": \"%s\", \"userdatacount\": %u, \"userdatasize\": %u, \"userdata\":\n%s }\n",
723 draftSize,
data->memid,
729 data->contextchange.isValid() ?
data->contextchange.toString().c_str() :
"",
730 draftUserCount, draftUserSize, userData.c_str());
733 return utils::StringFormat(
"{ \"size\": %u, \"memid\": \"%llu\", \"time\": \"%llu\", \"time__text\": \"%s\", \"sendtime\": \"%llu\", \"sendtime__text\": \"%s\", \"recvtime\": \"%llu\", \"recvtime__text\": \"%s\", \"origin\": %u, \"destination\": %u, \"ttl\": \"%llu\", \"eol__text\": \"%s\", \"priority\": %u, \"policy\": %u, \"from\": %u, \"to\": %u, \"type\": \"%s\", \"tag\": \"%u\", \"status\": %u, \"reference\": \"%llu\", \"serial\": \"%llu\", \"contextchange\": \"%s\", \"userdatacount\": %u, \"userdatasize\": %u, \"userdata\":\n%s }\n",
740 data->contextchange.isValid() ?
data->contextchange.toString().c_str() :
"",
741 data->userCount,
data->userSize, userData.c_str());
745std::string
DataMessage::toCSV(
const char* separator,
const char* preample, std::map<uint16, std::string>* subtypes, std::map<uint16, std::string>* subcontexts, std::map<uint32, std::string>* compNames) {
750 if (separator && (len = (uint32)strlen(separator)))
751 memcpy(sep, separator, len+1);
755 std::string userData;
756 if (
data->userCount) {
762 std::string typeStr, contextStr, fromStr, toStr;
763 typeStr =
data->type.toString(subtypes);
764 contextStr =
data->contextchange.toString(subcontexts);
766 fromStr = (*compNames)[
data->from];
767 toStr = (*compNames)[
data->to];
769 if (!fromStr.length()) {
773 if (!toStr.length()) {
778 if (preample && strlen(preample)) {
779 return utils::StringFormat(
"%s%s%s%s%s%s%s%s%s%s%u%s%u%s%u%s%u%s%u%s%u%s%u%s%llu%s%s%s%s%s%u%s%llu%s%s%s%u%s%u%s%s\n",
781 typeStr.c_str(), sep,
785 data->cyclecputime, sep,
786 data->cyclewalltime, sep,
787 data->chaincputime, sep,
788 data->chainwalltime, sep,
789 data->chaincount, sep,
793 fromStr.c_str(), sep,
797 contextStr.c_str(), sep,
798 data->userCount, sep,
803 return utils::StringFormat(
"%s%s%s%s%s%s%s%s%u%s%u%s%u%s%u%s%u%s%u%s%u%s%llu%s%s%s%s%s%u%s%llu%s%s%s%u%s%u%s%s\n",
804 typeStr.c_str(), sep,
808 data->cyclecputime, sep,
809 data->cyclewalltime, sep,
810 data->chaincputime, sep,
811 data->chainwalltime, sep,
812 data->chaincount, sep,
816 fromStr.c_str(), sep,
820 contextStr.c_str(), sep,
821 data->userCount, sep,
832 if (separator && (len = (uint32)strlen(separator)))
833 memcpy(sep, separator, len + 1);
838 if (preample && strlen(preample))
839 header =
utils::StringFormat(
"%s,type,created,sent,received,modulecputime,modulewalltime,chaincputime,chainwalltime,chaincount,size,priority,ttl,from,to,tag,serial,contextchange,userdatacount,userdatasize,userdata\n", preample);
841 header =
"type,created,sent,received,modulecputime,modulewalltime,chaincputime,chainwalltime,chaincount,size,priority,ttl,from,to,tag,serial,contextchange,userdatacount,userdatasize,userdata\n";
850std::string
DataMessage::toXML(std::map<uint16, std::string>* subtypes, std::map<uint16, std::string>* subcontexts, std::map<uint32, std::string>* compNames) {
853 if (!
data->userCount)
854 return data->toXML(subtypes, subcontexts, compNames);
856 std::map< std::string, std::list<ArrayElem> > userArrays;
857 std::map< std::string, std::list<MapElem> > userMaps;
858 uint32 draftSize = 0;
859 uint32 draftUserSize = 0;
860 uint32 draftUserCount = 0;
862 const char* oldData = NULL;
865 const char* mapStart, *mapEnd;
866 std::string userData;
867 userData.reserve(
data->userSize +
data->userCount * 64);
869 char* srcEnd = (
char*)
data +
data->size;
870 while (src < srcEnd) {
874 if ((mapStart = strstr(key,
"_-|")) && (mapEnd = strstr(key,
"|-_"))) {
876 e.index =
utils::Ascii2Int64(std::string(mapStart + 3, mapEnd - mapStart - 3).c_str());
879 userArrays[std::string(key, mapStart - key)].push_back(e);
883 else if ((mapStart = strstr(key,
"_-[")) && (mapEnd = strstr(key,
"]-_"))) {
885 e.index = std::string(mapStart + 3, mapEnd - mapStart - 3);
888 userMaps[std::string(key, mapStart - key)].push_back(e);
897 userData +=
utils::StringFormat(
"<data name=\"%s\" type=\"time\" value=\"%llu\" text=\"%s\" />\n",
935 if (strcmp(key,
"OS") == 0)
937 else if (strcmp(key,
"US") == 0)
939 else if (strcmp(key,
"UC") == 0)
953 std::string subUserData;
955 std::list<ArrayElem>::iterator entryII, entryEE;
956 std::map< std::string, std::list<ArrayElem> >::iterator keyII = userArrays.begin(), keyEE = userArrays.end();
957 while (keyII != keyEE) {
959 entryII = keyII->second.begin();
960 entryEE = keyII->second.end();
961 while (entryII != entryEE) {
962 char* ep = entryII->entryPtr;
964 uint32 cid = entryII->cid;
967 subUserData +=
utils::StringFormat(
"<data name=\"%lld\" type=\"text\" value=\"%s\" />\n", entryII->index, val);
970 subUserData +=
utils::StringFormat(
"<data name=\"%lld\" type=\"time\" value=\"%llu\" text=\"%s\" />\n",
971 entryII->index, *(uint64*)val,
979 subUserData +=
utils::StringFormat(
"<data name=\"%lld\" type=\"integer\" value=\"%lld\" />\n", entryII->index, *(int64*)val);
982 subUserData +=
utils::StringFormat(
"<data name=\"%lld\" type=\"float\" value=\"%f\" />\n", entryII->index, *(float64*)val);
987 subUserData +=
utils::StringFormat(
"<data name=\"%lld\" type=\"datamessage\">\n%s</data>", entryII->index, msg->
toXML().c_str());
992 subUserData +=
utils::StringFormat(
"<data name=\"%lld\" type=\"textinfo\" size=\"%lld\" />\n", entryII->index, *(int64*)val);
995 subUserData +=
utils::StringFormat(
"<data name=\"%lld\" type=\"binary\" size=\"%lld\" />\n", entryII->index, *(int64*)val);
998 subUserData +=
utils::StringFormat(
"<data name=\"%lld\" type=\"messageinfo\" size=\"%lld\" />\n", entryII->index, *(int64*)val);
1005 userData +=
utils::StringFormat(
"<array name=\"%s\">\n%s</array>\n", keyII->first.c_str(), subUserData.c_str());
1009 std::list<MapElem>::iterator entryI, entryE;
1010 std::map< std::string, std::list<MapElem> >::iterator keyI = userMaps.begin(), keyE = userMaps.end();
1011 while (keyI != keyE) {
1012 subUserData.clear();
1013 entryI = keyI->second.begin();
1014 entryE = keyI->second.end();
1015 while (entryI != entryE) {
1016 char* ep = entryI->entryPtr;
1018 uint32 cid = entryI->cid;
1021 subUserData +=
utils::StringFormat(
"<data name=\"%s\" type=\"text\" value=\"%s\" />\n", entryI->index.c_str(), val);
1024 subUserData +=
utils::StringFormat(
"<data name=\"%s\" type=\"time\" value=\"%llu\" text=\"%s\" />\n",
1025 entryI->index.c_str(), *(uint64*)val,
1033 subUserData +=
utils::StringFormat(
"<data name=\"%s\" type=\"integer\" value=\"%lld\" />\n", entryI->index.c_str(), *(int64*)val);
1036 subUserData +=
utils::StringFormat(
"<data name=\"%s\" type=\"float\" value=\"%f\" />\n", entryI->index.c_str(), *(float64*)val);
1041 subUserData +=
utils::StringFormat(
"<data name=\"%s\" type=\"datamessage\">\n%s</data>", entryI->index.c_str(), msg->
toXML().c_str());
1046 subUserData +=
utils::StringFormat(
"<data name=\"%s\" type=\"textinfo\" size=\"%lld\" />\n", entryI->index.c_str(), *(int64*)val);
1049 subUserData +=
utils::StringFormat(
"<data name=\"%s\" type=\"binary\" size=\"%lld\" />\n", entryI->index.c_str(), *(int64*)val);
1052 subUserData +=
utils::StringFormat(
"<data name=\"%s\" type=\"messageinfo\" size=\"%lld\" />\n", entryI->index.c_str(), *(int64*)val);
1059 userData +=
utils::StringFormat(
"<map name=\"%s\">\n%s</map>\n", keyI->first.c_str(), subUserData.c_str());
1064 return utils::StringFormat(
"<datamessage draft=\"yes\" size=\"%u\" memid=\"%llu\" time=\"%llu\" timetext=\"%s\" sendtime=\"%llu\" sendtimetext=\"%s\" recvtime=\"%llu\" recvtimetext=\"%s\" origin=\"%u\" destination=\"%u\" ttl=\"%llu\" eoltext=\"%s\" priority=\"%u\" policy=\"%u\" from=\"%u\" to=\"%u\" type=\"%s\" tag=\"%u\" status=\"%u\" reference=\"%llu\" serial=\"%llu\" contextchange=\"%s\" userdatacount=\"%u\" userdatasize=\"%u\">\n%s</datamessage>\n",
1065 draftSize,
data->memid,
1070 data->priority,
data->policy,
data->from,
data->to,
data->type.toString().c_str(),
data->tag,
data->status,
data->reference,
data->serial,
data->contextchange.isValid() ?
data->contextchange.toString().c_str() :
"", draftUserCount, draftUserSize, userData.c_str());
1073 return utils::StringFormat(
"<datamessage size=\"%u\" memid=\"%llu\" time=\"%llu\" timetext=\"%s\" sendtime=\"%llu\" sendtimetext=\"%s\" recvtime=\"%llu\" recvtimetext=\"%s\" origin=\"%u\" destination=\"%u\" ttl=\"%llu\" eoltext=\"%s\" priority=\"%u\" policy=\"%u\" from=\"%u\" to=\"%u\" type=\"%s\" tag=\"%u\" status=\"%u\" reference=\"%llu\" serial=\"%llu\" contextchange=\"%s\" userdatacount=\"%u\" userdatasize=\"%u\">\n%s</datamessage>\n",
1079 data->priority,
data->policy,
data->from,
data->to,
data->type.toString().c_str(),
data->tag,
data->status,
data->reference,
data->serial,
data->contextchange.isValid() ?
data->contextchange.toString().c_str() :
"",
data->userCount,
data->userSize, userData.c_str());
1128 data->priority = priority;
1145 data->priority = priority;
1162 char* newData = NULL;
1184 uint32 size = *(uint32*)
data;
1186 memcpy(this->data,
data, size);
1217 char* newData = NULL;
1234 uint32 size = *(uint32*)
data;
1236 memcpy(this->data,
data, size);
1287 const char* newData = (
const char*)correctMsg->
data;
1288 uint32 size = *(uint32*)newData;
1289 if (size <= maxDraftSize) {
1291 memcpy(this->data, newData, size);
1312 uint32 size = *(uint32*)
data;
1313 if (size <= maxDraftSize) {
1315 memcpy(this->data,
data, size);
1336 uint32 size = *(uint32*)msg.
data;
1337 if (size <= maxDraftSize) {
1339 memcpy(this->
data, msg.
data, size);
1365 if (!
data->userCount)
1370 if (this->data->
size + (3 * draftInfoSize) > maxDraftSize)
1381 size =
data->userSize;
1383 size =
data->userCount;
1386 std::map< std::string, std::list<std::string> > userMaps;
1389 std::string userData;
1393 char* srcEnd = (
char*)
data +
data->size;
1394 while (src < srcEnd) {
1402 if (this->data->
size + itemSize < maxDraftSize) {
1412 if (this->data->
size + itemSize < maxDraftSize) {
1422 if (this->data->
size + itemSize < maxDraftSize) {
1433 if (this->data->
size + itemSize < maxDraftSize) {
1438 this->data->
userSize += itemSize -
sizeof(int64) + (uint32)size;
1444 if (this->data->
size + itemSize < maxDraftSize) {
1449 this->data->
userSize += itemSize -
sizeof(int64) + (uint32)size;
1456 if (this->data->
size + itemSize < maxDraftSize) {
1461 this->data->
userSize += itemSize -
sizeof(int64) + (uint32)size;
1467 if (this->data->
size + itemSize < maxDraftSize) {
1472 this->data->
userSize += itemSize -
sizeof(int64) + (uint32)size;
1478 if (this->data->
size + itemSize < maxDraftSize) {
1483 this->data->
userSize += itemSize -
sizeof(int64) + (uint32)size;
1498 while (src < srcEnd) {
1507 if (this->data->
size + itemSize + size < maxDraftSize) {
1511 else if (this->data->
size + itemSize +
sizeof(int64) < maxDraftSize) {
1516 this->data->
userSize += itemSize + (uint32)size;
1551 const char* oldData = (
const char*)this->data;
1609 return (*(uint64*)src != 0);
1613 return (*(int64*)src != 0);
1615 return (((int64)(*(float64*)src)) != 0);
1632 if (
stricmp(key,
"size") == 0)
1634 else if (
stricmp(key,
"cid") == 0)
1636 else if (
stricmp(key,
"memid") == 0)
1638 else if (
stricmp(key,
"time") == 0)
1640 else if (
stricmp(key,
"sendtime") == 0)
1642 else if (
stricmp(key,
"recvtime") == 0)
1644 else if (
stricmp(key,
"timetext") == 0)
1646 else if (
stricmp(key,
"sendtimetext") == 0)
1648 else if (
stricmp(key,
"recvtimetext") == 0)
1650 else if (
stricmp(key,
"origin") == 0)
1652 else if (
stricmp(key,
"destination") == 0)
1654 else if (
stricmp(key,
"ttl") == 0)
1656 else if (
stricmp(key,
"eol") == 0)
1658 else if (
stricmp(key,
"eoltext") == 0)
1660 else if (
stricmp(key,
"priority") == 0)
1662 else if (
stricmp(key,
"policy") == 0)
1664 else if (
stricmp(key,
"from") == 0)
1666 else if (
stricmp(key,
"to") == 0)
1668 else if (
stricmp(key,
"type") == 0)
1669 return data->type.toString();
1670 else if (
stricmp(key,
"tag") == 0)
1672 else if (
stricmp(key,
"status") == 0)
1674 else if (
stricmp(key,
"reference") == 0)
1676 else if (
stricmp(key,
"serial") == 0)
1678 else if (
stricmp(key,
"contextchange") == 0)
1679 return data->contextchange.isValid() ?
data->contextchange.toString() :
"";
1680 else if (
stricmp(key,
"userSize") == 0)
1682 else if (
stricmp(key,
"userCount") == 0)
1713 bool success =
false;
1718 bool success =
false;
1723 bool success =
false;
1728 bool success =
false;
1729 value =
getInt(key, success);
1734 bool success =
false;
1740 bool success =
false;
1746 bool success =
false;
1747 return getData(key, size, success);
1751 bool success =
false;
1756 bool success =
false;
1798 if (src == NULL)
return 0;
1804 if (src == NULL)
return 0;
1812 if (src == NULL)
return 0;
1825 if (src == NULL)
return 0;
1835 bool success =
false;
1836 return getInt(key, success);
1842 if (src == NULL)
return false;
1854 if (src == NULL)
return false;
1864 bool success =
false;
1869 bool success =
false;
1876 if (src == NULL)
return NULL;
1890 if (src == NULL)
return NULL;
1895 char*
data =
new char[size];
1906 if (src == NULL)
return NULL;
1942 float64 val = value;
1993 data->size = oldSize + fullSpaceReq;
1996 src = (
char*)
data + oldSize;
2008 data->userSize += fullSpaceReq;
2030 char* srcEnd = (
char*)
data +
data->size;
2031 while (src < srcEnd) {
2048 char* srcEnd = (
char*)
data +
data->size;
2049 while (src < srcEnd) {
2071 char* srcEnd = (
char*)
data +
data->size;
2072 while (src < srcEnd) {
2078 type =
ARRAY;
break; }
2081 type =
MAP;
break; }
2085 free(arrayKeyStart);
2094 std::map<std::string, KeyType> keys;
2097 char* srcEnd = (
char*)
data +
data->size;
2098 while (src < srcEnd) {
2102 if (k.size() > 6 && k.compare(k.size() - 3, 3,
"|-_") == 0 && (p = k.find(
"_-|")) != std::string::npos)
2103 keys[k.substr(0, p)] =
ARRAY;
2104 else if (k.size() > 6 && k.compare(k.size() - 3, 3,
"]-_") == 0 && (p = k.find(
"_-[")) != std::string::npos)
2105 keys[k.substr(0, p)] =
MAP;
2117 std::string arrayStart = std::string(key) +
"_-|";
2118 std::string mapStart = std::string(key) +
"_-[";
2121 char* srcEnd = (
char*)
data +
data->size;
2122 while (src < srcEnd) {
2146 if (src == NULL)
return 0;
2152 if (src == NULL)
return 0;
2158 if (src == NULL)
return 0;
2164 if (src == NULL)
return 0;
2170 if (src == NULL)
return 0;
2176 if (src == NULL)
return 0;
2187 int n = snprintf(buf,
sizeof(buf),
"%s_-|%lld|-_", key, i);
2188 if (n < 0 || (
size_t)n >=
sizeof(buf))
2239 return getInt(i, key, success);
2254 return getInt(idx, key, success);
2264 return getFloat(idx, key, success);
2313 int n = snprintf(buf,
sizeof(buf),
"%s_-[%s]-_", key, idx);
2314 if (n < 0 || (
size_t)n >=
sizeof(buf))
2412 std::map<int64, uint64> map;
2419 char* srcEnd = (
char*)
data +
data->size;
2420 while (src < srcEnd) {
2438 std::map<int64, int64> map;
2445 char* srcEnd = (
char*)
data +
data->size;
2446 while (src < srcEnd) {
2485 std::map<int64, float64> map;
2492 char* srcEnd = (
char*)
data +
data->size;
2493 while (src < srcEnd) {
2532 std::map<int64, std::string> map;
2539 char* srcEnd = (
char*)
data +
data->size;
2540 while (src < srcEnd) {
2579 std::map<int64, std::string> map;
2586 char* srcEnd = (
char*)
data +
data->size;
2587 while (src < srcEnd) {
2606 std::map<int64, int64> map;
2613 char* srcEnd = (
char*)
data +
data->size;
2614 while (src < srcEnd) {
2632 std::map<int64, double> map;
2639 char* srcEnd = (
char*)
data +
data->size;
2640 while (src < srcEnd) {
2658 std::map<int64, float64> map;
2665 char* srcEnd = (
char*)
data +
data->size;
2666 while (src < srcEnd) {
2684 std::map<int64, DataMessage*> map;
2691 char* srcEnd = (
char*)
data +
data->size;
2692 while (src < srcEnd) {
2710 std::map<int64, uint64>::iterator i = map.begin(), e = map.end();
2712 if (!
setTime(i->first, key, i->second))
2720 std::map<int64, std::string>::iterator i = map.begin(), e = map.end();
2722 if (!
setString(i->first, key, i->second.c_str()))
2730 std::map<int64, int64>::iterator i = map.begin(), e = map.end();
2732 if (!
setInt(i->first, key, i->second))
2740 std::map<int64, double>::iterator i = map.begin(), e = map.end();
2742 if (!
setDouble(i->first, key, i->second))
2750 std::map<int64, float64>::iterator i = map.begin(), e = map.end();
2752 if (!
setFloat(i->first, key, i->second))
2760 std::map<int64, DataMessage*>::iterator i = map.begin(), e = map.end();
2783 char* srcEnd = (
char*)
data +
data->size;
2784 while (src < srcEnd) {
2812 char* srcEnd = (
char*)
data +
data->size;
2813 while (src < srcEnd) {
2838 std::map<std::string, uint64> map;
2845 char* srcEnd = (
char*)
data +
data->size;
2846 while (src < srcEnd) {
2863 std::map<std::string, int64> map;
2870 char* srcEnd = (
char*)
data +
data->size;
2871 while (src < srcEnd) {
2907 std::map<std::string, float64> map;
2914 char* srcEnd = (
char*)
data +
data->size;
2915 while (src < srcEnd) {
2951 std::map<std::string, std::string> map;
2958 char* srcEnd = (
char*)
data +
data->size;
2959 while (src < srcEnd) {
2995 std::map<std::string, std::string> map;
3002 char* srcEnd = (
char*)
data +
data->size;
3003 while (src < srcEnd) {
3020 std::map<std::string, int64> map;
3027 char* srcEnd = (
char*)
data +
data->size;
3028 while (src < srcEnd) {
3045 std::map<std::string, double> map;
3052 char* srcEnd = (
char*)
data +
data->size;
3053 while (src < srcEnd) {
3070 std::map<std::string, float64> map;
3077 char* srcEnd = (
char*)
data +
data->size;
3078 while (src < srcEnd) {
3095 std::map<std::string, DataMessage*> map;
3102 char* srcEnd = (
char*)
data +
data->size;
3103 while (src < srcEnd) {
3120 std::map<std::string, uint64>::iterator i = map.begin(), e = map.end();
3122 if (!
setTime(i->first.c_str(), key, i->second))
3130 std::map<std::string, std::string>::iterator i = map.begin(), e = map.end();
3132 if (!
setString(i->first.c_str(), key, i->second.c_str()))
3140 std::map<std::string, int64>::iterator i = map.begin(), e = map.end();
3142 if (!
setInt(i->first.c_str(), key, i->second))
3150 std::map<std::string, double>::iterator i = map.begin(), e = map.end();
3152 if (!
setDouble(i->first.c_str(), key, i->second))
3160 std::map<std::string, float64>::iterator i = map.begin(), e = map.end();
3162 if (!
setFloat(i->first.c_str(), key, i->second))
3170 std::map<std::string, DataMessage*>::iterator i = map.begin(), e = map.end();
3181 uint64 bestCandidateDiff = 0, diff;
3183 std::map<uint64, DataMessage*>::reverse_iterator i = messages.rbegin(), e = messages.rend();
3185 if (!bestCandidate) {
3186 bestCandidate = i->second;
3187 bestCandidateDiff = (i->first > t) ? i->first - t : t - i->first;
3190 diff = (i->first > t) ? i->first - t : t - i->first;
3191 if (diff < bestCandidateDiff) {
3192 bestCandidate = i->second;
3193 bestCandidateDiff = diff;
3198 return bestCandidate;
3204 data->chaincputime = chainCPUTime + cycleCPUTime;
3205 data->chainwalltime = chainWallTime + cycleWallTime;
3206 data->chaincount = chainCount;
3208 data->cyclecputime = cycleCPUTime;
3209 data->cyclewalltime = cycleWallTime;
3216 if (!
data)
return false;
3232 *newData =
new char[newSize];
3234 memset(*newData, 0, newSize);
3268 *newData =
new char[header->
size];
3269 memcpy(*newData,
data, header->
size);
3272 switch (header->
cver) {
3274 *newData =
new char[header->
size];
3275 memcpy(*newData,
data, header->
size);
3292 unittest::fail(
"DataMessage test: default constructor invalid\n");
3302 unittest::fail(
"DataMessage test: DataMessage(type, from) invalid\n");
3308 unittest::fail(
"DataMessage test: DataMessage(type, from, to, ttl, priority) invalid\n");
3317 const uint64 t = 1234567890ULL;
3320 if (!msg.
setInt(
"I", -42)) {
unittest::fail(
"DataMessage test: setInt failed\n");
return false; }
3323 const char bin[] = {
'x',
'y',
'z' };
3324 if (!msg.
setData(
"B", bin, 3)) {
unittest::fail(
"DataMessage test: setData failed\n");
return false; }
3326 if (msg.
getTime(
"T") != t) {
unittest::fail(
"DataMessage test: getTime mismatch\n");
return false; }
3328 if (!s || strcmp(s,
"hello") != 0) {
unittest::fail(
"DataMessage test: getString mismatch\n");
return false; }
3330 if (!msg.
getInt(
"I", i) || i != -42) {
unittest::fail(
"DataMessage test: getInt mismatch\n");
return false; }
3332 if (!msg.
getDouble(
"D", d) || d < 3.13 || d > 3.15) {
unittest::fail(
"DataMessage test: getDouble mismatch\n");
return false; }
3334 if (!msg.
getFloat(
"F", f) || f < 2.4f || f > 2.6f) {
unittest::fail(
"DataMessage test: getFloat mismatch\n");
return false; }
3336 const char* b = msg.
getData(
"B", bsize);
3337 if (!b || bsize != 3 || b[0] !=
'x' || b[1] !=
'y' || b[2] !=
'z') {
3338 unittest::fail(
"DataMessage test: getData mismatch\n");
return false;
3347 unittest::fail(
"DataMessage test: hasKey/hasString etc failed\n");
return false;
3350 unittest::fail(
"DataMessage test: getKeyType/isSingleValue failed\n");
return false;
3358 if (!cpy || csize != 3) {
unittest::fail(
"DataMessage test: getDataCopy failed\n");
return false; }
3366 if (!got || got->
getUserCount() == 0) {
unittest::fail(
"DataMessage test: getAttachedMessageCopy failed\n");
delete got;
return false; }
3367 if (got->
getAsString(
"nested") !=
"value") {
unittest::fail(
"DataMessage test: attached message content mismatch\n");
delete got;
return false; }
3378 if (!msg.
setTime(
static_cast<int64
>(0),
"arr", 100ULL)) {
unittest::fail(
"DataMessage test: setTime array failed\n");
return false; }
3379 if (!msg.
setString(1,
"arr",
"one")) {
unittest::fail(
"DataMessage test: setString array failed\n");
return false; }
3380 if (!msg.
setInt(2,
"arr", 999)) {
unittest::fail(
"DataMessage test: setInt array failed\n");
return false; }
3381 if (msg.
getTime(
static_cast<int64
>(0),
"arr") != 100ULL) {
unittest::fail(
"DataMessage test: getTime array mismatch\n");
return false; }
3382 if (msg.
getAsString(1,
"arr") !=
"one") {
unittest::fail(
"DataMessage test: getAsString array mismatch\n");
return false; }
3384 if (!msg.
getInt(2,
"arr", vi) || vi != 999) {
unittest::fail(
"DataMessage test: getInt array mismatch\n");
return false; }
3386 unittest::fail(
"DataMessage test: array key type failed\n");
return false;
3390 unittest::fail(
"DataMessage test: getArraySize failed\n");
return false;
3393 std::map<int64, uint64> tmap; tmap[0] = 10; tmap[1] = 20;
3395 std::map<int64, std::string> smap; smap[0] =
"a"; smap[1] =
"b";
3397 std::map<int64, int64> imap; imap[0] = 1; imap[1] = 2;
3399 std::map<int64, double> dmap; dmap[0] = 1.1; dmap[1] = 2.2;
3401 std::map<int64, uint64> gotT = msg.
getTimeArray(
"tarr");
3402 if (gotT.size() != 2 || gotT[0] != 10 || gotT[1] != 20) {
unittest::fail(
"DataMessage test: getTimeArray mismatch\n");
return false; }
3404 if (gotS.size() != 2 || gotS[0] !=
"a" || gotS[1] !=
"b") {
unittest::fail(
"DataMessage test: getAsStringArray mismatch\n");
return false; }
3405 std::map<int64, int64> gotI = msg.
getIntArray(
"iarr");
3406 if (gotI.size() != 2 || gotI[0] != 1 || gotI[1] != 2) {
unittest::fail(
"DataMessage test: getIntArray mismatch\n");
return false; }
3408 if (gotD.size() != 2 || gotD[0] < 1.0 || gotD[0] > 1.2 || gotD[1] < 2.1 || gotD[1] > 2.3) {
unittest::fail(
"DataMessage test: getDoubleArray mismatch\n");
return false; }
3415 if (!msg.
setTime(
"x",
"m", 200ULL)) {
unittest::fail(
"DataMessage test: setTime map failed\n");
return false; }
3416 if (!msg.
setString(
"y",
"m",
"mapval")) {
unittest::fail(
"DataMessage test: setString map failed\n");
return false; }
3417 if (!msg.
setInt(
"z",
"m", -7)) {
unittest::fail(
"DataMessage test: setInt map failed\n");
return false; }
3418 if (msg.
getTime(
"x",
"m") != 200ULL) {
unittest::fail(
"DataMessage test: getTime map mismatch\n");
return false; }
3419 if (msg.
getAsString(
"y",
"m") !=
"mapval") {
unittest::fail(
"DataMessage test: getAsString map mismatch\n");
return false; }
3421 if (!msg.
getInt(
"z",
"m", vi) || vi != -7) {
unittest::fail(
"DataMessage test: getInt map mismatch\n");
return false; }
3423 unittest::fail(
"DataMessage test: map key type failed\n");
return false;
3427 unittest::fail(
"DataMessage test: getMapSize failed\n");
return false;
3430 std::map<std::string, uint64> tmap; tmap[
"a"] = 1; tmap[
"b"] = 2;
3432 std::map<std::string, std::string> smap; smap[
"k1"] =
"v1"; smap[
"k2"] =
"v2";
3434 std::map<std::string, int64> imap; imap[
"i1"] = 10; imap[
"i2"] = 20;
3436 std::map<std::string, uint64> gotT = msg.
getTimeMap(
"tm");
3437 if (gotT.size() != 2 || gotT[
"a"] != 1 || gotT[
"b"] != 2) {
unittest::fail(
"DataMessage test: getTimeMap mismatch\n");
return false; }
3438 std::map<std::string, std::string> gotS = msg.
getAsStringMap(
"sm");
3439 if (gotS.size() != 2 || gotS[
"k1"] !=
"v1" || gotS[
"k2"] !=
"v2") {
unittest::fail(
"DataMessage test: getAsStringMap mismatch\n");
return false; }
3440 std::map<std::string, int64> gotI = msg.
getIntMap(
"im");
3441 if (gotI.size() != 2 || gotI[
"i1"] != 10 || gotI[
"i2"] != 20) {
unittest::fail(
"DataMessage test: getIntMap mismatch\n");
return false; }
3451 std::map<int64, std::string> amap; amap[0] =
"elem0";
3453 std::map<std::string, int64> mmap; mmap[
"idx"] = 42;
3457 if (!raw || sz == 0) {
unittest::fail(
"DataMessage test: getRawData/getSize failed\n");
return false; }
3459 if (!decoded.
isValid()) {
unittest::fail(
"DataMessage test: decoded message invalid\n");
return false; }
3461 unittest::fail(
"DataMessage test: round-trip getUserCount mismatch\n");
return false;
3463 if (decoded.
getAsString(
"k") !=
"roundtrip") {
unittest::fail(
"DataMessage test: round-trip string mismatch\n");
return false; }
3465 if (!decoded.
getInt(
"n", nval) || nval != 77) {
unittest::fail(
"DataMessage test: round-trip int mismatch\n");
return false; }
3467 if (!decoded.
getDouble(
"x", xval) || xval < 1.4 || xval > 1.6) {
unittest::fail(
"DataMessage test: round-trip double mismatch\n");
return false; }
3469 if (decoded.
getIntMap(
"m")[
"idx"] != 42) {
unittest::fail(
"DataMessage test: round-trip map mismatch\n");
return false; }
3478 if (ustr.empty()) {
unittest::fail(
"DataMessage test: getUserEntriesAsString empty\n");
return false; }
3480 if (ujson.empty()) {
unittest::fail(
"DataMessage test: getUserEntriesAsJSON empty\n");
return false; }
3482 std::string json = msg.
toJSON();
3483 if (json.empty()) {
unittest::fail(
"DataMessage test: toJSON empty\n");
return false; }
3484 std::string xml = msg.
toXML();
3485 if (xml.empty()) {
unittest::fail(
"DataMessage test: toXML empty\n");
return false; }
3486 std::string csv = msg.
toCSV();
3487 if (csv.empty()) {
unittest::fail(
"DataMessage test: toCSV empty\n");
return false; }
3489 if (hdr.empty()) {
unittest::fail(
"DataMessage test: GetCSVHeader empty\n");
return false; }
3500 unittest::fail(
"DataMessage test: copyUserEntriesFromMessage count\n");
return false;
3503 unittest::fail(
"DataMessage test: copyUserEntriesFromMessage content\n");
return false;
3507 if (dst.
hasKey(
"a")) {
unittest::fail(
"DataMessage test: removeEntry key still present\n");
return false; }
3516 msg.
setTime(
"t", 123456789ULL);
3518 msg.
setInt((int64)0,
"arr", 10); msg.
setInt((int64)1,
"arr", 11);
3519 msg.
setTime(
"a",
"map", 1000ULL); msg.
setTime(
"b",
"map", 2000ULL);
3520 std::map<std::string, KeyType> keys = msg.
getAllKeys();
3521 if (keys.size() != 5) {
unittest::fail(
"DataMessage test: getAllKeys count %u != 5\n", (uint32)keys.size());
return false; }
3523 unittest::fail(
"DataMessage test: getAllKeys types\n");
return false;
3530 int64 iv = -1;
bool ok =
true;
3533 unittest::fail(
"DataMessage test: deleted key still readable\n");
return false;
3540 unittest::fail(
"DataMessage test: deleted array/map still readable\n");
return false;
3547 if (!m2.
setInt(
"k", 7) || !m2.
getInt(
"k", iv) || iv != 7) {
unittest::fail(
"DataMessage test: delete + re-add int (same slot)\n");
return false; }
3549 if (!m2.
setTime(
"k", 99ULL) || m2.
getTime(
"k") != 99ULL) {
unittest::fail(
"DataMessage test: delete + re-add as time (same slot)\n");
return false; }
3552 if (!m2.
setString(
"k",
"now a longer string") || m2.
getString(
"k") == NULL || strcmp(m2.
getString(
"k"),
"now a longer string") != 0) {
3553 unittest::fail(
"DataMessage test: delete + re-add as string\n");
return false;
3558 const char blob[3] = { 1, 2, 3 }; uint32 bsz = 0;
3559 if (!m2.
setData(
"k", blob, 3) || m2.
getData(
"k", bsz) == NULL || bsz != 3) {
unittest::fail(
"DataMessage test: delete + re-add as data\n");
return false; }
3563 if (m2.
getData(
"d", bsz) == NULL || bsz != 2) {
unittest::fail(
"DataMessage test: overwrite smaller data size %u\n", bsz);
return false; }
3567 m2.
setTime(
"c",
"trail", 3ULL);
3568 std::map<std::string, uint64> tm = m2.
getTimeMap(
"trail");
3569 if (tm.size() != 1 || tm[
"c"] != 3ULL) {
unittest::fail(
"DataMessage test: map replace\n");
return false; }
3572 if (
copy.getTimeMap(
"trail").size() != 1 ||
copy.getAllKeys().size() != 3 ||
copy.hasKey(
"i")) {
3573 unittest::fail(
"DataMessage test: round trip after delete/re-add\n");
return false;
3581 if (msg.
hasKey(
"nonexistent")) {
unittest::fail(
"DataMessage test: hasKey nonexistent true\n");
return false; }
3582 if (msg.
getString(
"nonexistent") != NULL) {
unittest::fail(
"DataMessage test: getString nonexistent non-NULL\n");
return false; }
3583 if (msg.
getTime(
"nonexistent") != 0) {
unittest::fail(
"DataMessage test: getTime nonexistent non-zero\n");
return false; }
3593 #define PKFAIL(what) { unittest::fail("DataMessage test: packed: " what "\n"); return false; }
3596 m.
setString(
"PsyDevice",
"phone-1234abcd");
3599 m.
setInt(
"big", (int64)0x7FFFFFFFFFFFFFFFLL);
3600 m.
setInt(
"min", (int64)(-0x7FFFFFFFFFFFFFFFLL - 1));
3602 m.
setTime(
"tcap", 63960700000123456ULL);
3604 for (
int i = 0; i < 80; i++) audio[i] = (
char)(i * 31);
3605 m.
setData(
"audio", audio, 80);
3615 if (!d)
PKFAIL(
"decode");
3621 const char* av = d->
getData(
"audio", sz);
3622 if (sz != 80 || memcmp(av, audio, 80) != 0 || d->
getInt(
"min") != (int64)(-0x7FFFFFFFFFFFFFFFLL - 1))
PKFAIL(
"values");
3630 if (!pk2 || n2 != n || memcmp(pk, pk2, n) != 0)
PKFAIL(
"re-encode differs");
3634 for (uint32 cut = 0; cut < n; cut++) {
3635 char* t = (
char*)malloc(n);
3640 if (bad) {
delete(bad);
PKFAIL(
"accepted a truncated message"); }
3642 pk[9] = (char)0xFF; pk[10] = (char)0xFF; pk[11] = (char)0xFF; pk[12] = (char)0xFF;
3644 if (bad2) {
delete(bad2);
PKFAIL(
"accepted a corrupt field mask"); }
3652 delete(d3); free(pk3);
3662 "Data message encode/decode, arrays, maps, serialisation",
"core");
3674 enum { PK_RAW = 0, PK_TEXT = 1, PK_INT = 2, PK_DOUBLE = 3, PK_TIME = 4, PK_DATA = 5, PK_MESSAGE = 6 };
3675 enum { PK_FIELDS = 24 };
3676 const uint32 PK_MAX_DEPTH = 16;
3678 void PkVarint(std::string& o, uint64 v) {
3679 while (v >= 0x80) { o += (char)((v & 0x7F) | 0x80); v >>= 7; }
3682 void PkBytes(std::string& o,
const char* d, uint32 n) { PkVarint(o, n); o.append(d, n); }
3683 void PkLevels(std::string& o,
const uint16* lv, uint32 n) {
3684 while (n && !lv[n - 1]) n--;
3686 for (uint32 i = 0; i < n; i++) PkVarint(o, lv[i]);
3690 f[0] = h->cenc & ~DATAMESSAGE_CENC_PACKED; f[1] = h->memid; f[2] = h->time; f[3] = h->sendtime;
3691 f[4] = h->recvtime; f[5] = h->origin; f[6] = h->destination; f[7] = h->ttl; f[8] = h->priority;
3692 f[9] = h->policy; f[10] = h->from; f[11] = h->to; f[12] = 0; f[13] = h->tag; f[14] = h->status;
3693 f[15] = h->reference; f[16] = h->serial; f[17] = 0; f[18] = h->cyclecputime; f[19] = h->cyclewalltime;
3694 f[20] = h->chaincputime; f[21] = h->chainwalltime; f[22] = h->chaincount; f[23] = h->systemid;
3700 size_t start = o.size();
3703 uint64 f[PK_FIELDS];
3705 bool hasType =
false, hasCtx =
false;
3706 for (uint32 i = 0; i <
PSYTYPELEVELS; i++) hasType |= (h->type.levels[i] != 0);
3707 for (uint32 i = 0; i <
PSYCONTEXTLEVELS; i++) hasCtx |= (h->contextchange.levels[i] != 0);
3709 for (uint32 i = 0; i < PK_FIELDS; i++)
3710 if (f[i] || (i == 12 && hasType) || (i == 17 && hasCtx)) mask |= (1ULL << i);
3712 for (uint32 i = 0; i < PK_FIELDS; i++) {
3713 if (!(mask & (1ULL << i)))
continue;
3716 else PkVarint(o, f[i]);
3719 const char* base = (
const char*)h;
3720 const char* end = base + h->size;
3731 const char* slotEnd = src + kh->
size;
3734 const char* k = key;
3735 while (k < slotEnd && *k) k++;
3736 if (k >= slotEnd)
return false;
3739 || (
const char*)vh + vh->size > slotEnd)
3743 PkBytes(o, key, (uint32)(k - key));
3748 while (n < vn && v[n]) n++;
3752 if (vn != 8)
return false;
3753 int64 x; memcpy(&x, v, 8);
3755 PkVarint(o, ((uint64)x << 1) ^ (uint64)(x >> 63));
3758 if (vn != 8)
return false;
3759 o += (char)PK_DOUBLE; o.append(v, 8);
3762 if (vn != 8)
return false;
3763 uint64 x; memcpy(&x, v, 8);
3764 o += (char)PK_TIME; PkVarint(o, x);
3767 o += (char)PK_DATA; PkBytes(o, v, vn);
3770 o += (char)PK_MESSAGE;
3773 PkBytes(o, nested.data(), (uint32)nested.size());
3776 o += (char)PK_RAW; PkVarint(o, vh->cid); PkBytes(o, v, vn);
3783 memcpy(&o[start], &size, 4);
3784 memcpy(&o[start + 4], &cid, 4);
3789 const uint8* p;
const uint8* e;
3791 PkReader(
const char* d, uint32 n) : p((const uint8*)d), e((const uint8*)d + n), ok(true) {}
3794 for (uint32 s = 0; s < 64; s += 7) {
3795 if (p >= e) { ok =
false;
return 0; }
3797 v |= (uint64)(b & 0x7F) << s;
3798 if (!(b & 0x80))
return v;
3803 uint8 byte() {
if (p >= e) { ok =
false;
return 0; }
return *p++; }
3804 const char* bytes(uint64 n) {
3805 if (!ok || n > (uint64)(e - p)) { ok =
false;
return NULL; }
3806 const char* r = (
const char*)p; p += n;
return r;
3808 bool levels(uint16* lv, uint32 max) {
3809 uint64 n = varint();
3810 if (!ok || n > max) { ok =
false;
return false; }
3811 for (uint32 i = 0; i < n; i++) { uint64 x = varint();
if (x > 0xFFFF) ok =
false; lv[i] = (uint16)x; }
3816 void PkEntry(std::string& o,
const char* key, uint32 kn, uint32 cid,
const char* v, uint32 vn,
bool nul) {
3822 o.append((
const char*)&kh,
sizeof(kh)); o.append(key, kn); o +=
'\0';
3823 o.append((
const char*)&vh,
sizeof(vh)); o.append(v, vn);
if (nul) o +=
'\0';
3827 bool PkDecode(
const char* d, uint32 n, std::string& o, uint32 depth) {
3828 if (n < 9 || depth > PK_MAX_DEPTH)
return false;
3830 memcpy(&size, d, 4); memcpy(&cid, d + 4, 4);
3832 PkReader r(d + 9, n - 9);
3834 memset(&h, 0,
sizeof(h));
3835 uint64 mask = r.varint();
3836 if (!r.ok || (mask >> PK_FIELDS))
return false;
3837 uint64 f[PK_FIELDS];
3838 memset(f, 0,
sizeof(f));
3839 for (uint32 i = 0; i < PK_FIELDS && r.ok; i++) {
3840 if (!(mask & (1ULL << i)))
continue;
3843 else f[i] = r.varint();
3845 if (!r.ok)
return false;
3847 h.cenc = (uint16)f[0]; h.memid = f[1]; h.time = f[2]; h.sendtime = f[3]; h.recvtime = f[4];
3848 h.origin = (uint16)f[5]; h.destination = (uint16)f[6]; h.ttl = f[7]; h.priority = (uint16)f[8];
3849 h.policy = (uint8)f[9]; h.from = (uint32)f[10]; h.to = (uint32)f[11]; h.tag = (uint32)f[13];
3850 h.status = (uint16)f[14]; h.reference = f[15]; h.serial = f[16]; h.cyclecputime = (uint32)f[18];
3851 h.cyclewalltime = (uint32)f[19]; h.chaincputime = (uint32)f[20]; h.chainwalltime = (uint32)f[21];
3852 h.chaincount = (uint32)f[22]; h.systemid = (uint32)f[23];
3853 size_t start = o.size();
3854 o.append((
const char*)&h,
sizeof(h));
3855 uint64 count = r.varint();
3856 if (!r.ok || count > n)
return false;
3857 for (uint64 i = 0; i < count; i++) {
3858 uint64 kn = r.varint();
3859 const char* key = r.bytes(kn);
3860 uint8 kind = r.byte();
3861 if (!r.ok || !kn || memchr(key, 0, (
size_t)kn))
return false;
3863 case PK_TEXT: { uint64 vn = r.varint();
const char* v = r.bytes(vn);
if (!r.ok)
return false;
3864 PkEntry(o, key, (uint32)kn,
CONSTCHARID, v, (uint32)vn,
true);
break; }
3865 case PK_INT: { uint64 z = r.varint();
if (!r.ok)
return false;
3866 int64 x = (int64)(z >> 1) ^ -(int64)(z & 1);
3867 PkEntry(o, key, (uint32)kn,
INTID, (
const char*)&x, 8,
false);
break; }
3868 case PK_DOUBLE: {
const char* v = r.bytes(8);
if (!r.ok)
return false;
3869 PkEntry(o, key, (uint32)kn,
DOUBLEID, v, 8,
false);
break; }
3870 case PK_TIME: { uint64 x = r.varint();
if (!r.ok)
return false;
3871 PkEntry(o, key, (uint32)kn,
TIMEID, (
const char*)&x, 8,
false);
break; }
3872 case PK_DATA: { uint64 vn = r.varint();
const char* v = r.bytes(vn);
if (!r.ok)
return false;
3873 PkEntry(o, key, (uint32)kn,
CHARDATAID, v, (uint32)vn,
false);
break; }
3874 case PK_MESSAGE: { uint64 vn = r.varint();
const char* v = r.bytes(vn);
if (!r.ok)
return false;
3876 if (!PkDecode(v, (uint32)vn, nested, depth + 1))
return false;
3877 PkEntry(o, key, (uint32)kn,
DATAMESSAGEID, nested.data(), (uint32)nested.size(),
false);
break; }
3878 case PK_RAW: { uint64 c = r.varint(); uint64 vn = r.varint();
const char* v = r.bytes(vn);
3880 PkEntry(o, key, (uint32)kn, (uint32)c, v, (uint32)vn,
false);
break; }
3885 if (r.p != r.e)
return false;
3887 out->
size = (uint32)(o.size() - start);
3889 out->userCount = (uint32)count;
3897 if (!
data || !PkEncode(
data, o, 0))
3899 char* buf = (
char*)malloc(o.size());
3902 memcpy(buf, o.data(), o.size());
3903 size = (uint32)o.size();
3908 if (!
data || size < 2 *
sizeof(uint32))
3911 memcpy(&cid,
data +
sizeof(uint32),
sizeof(uint32));
3920 char* buf = (
char*)malloc(o.size());
3923 memcpy(buf, o.data(), o.size());
The binary DataMessage container — the central data-exchange object of Psyclone/CMSDK.
#define DATAMESSAGE_CENC_PACKED
cenc flag: this message arrived in the packed wire form (DataMessage::FromPacked() sets it).
#define CURRENTDATAMESSAGEVERSION
#define DATAMESSAGEINFOID
#define PACKEDDATAMESSAGEID
Packed (compact) wire form of a DataMessage, see DataMessage::toPacked().
#define GetObjID(data)
Extract the cid field from a binary object block: the uint32 at byte offset 4 (after the leading size...
#define DATAMESSAGEDRAFTID
CMSDK time: µs-resolution 64-bit timestamps and the Time Mapping Constant (TMC).
#define PSYCONTEXTLEVELS
Number of hierarchy levels in a PsyContext.
#define PSYTYPELEVELS
Number of hierarchy levels in a PsyType.
Small, dependency-free unit test harness used by all CMSDK object tests.
bool setTime(const char *key, uint64 value)
setTime(const char* key, uint64 value)
std::map< int64, float64 > getAsFloatArray(const char *key)
getAsFloatArray(const char* key)
bool setFloatArray(const char *key, std::map< int64, float64 > &map)
setFloatArray(const char* key, std::map<int64, float64>& map) Sets the whole float array named key in...
static bool UnitTest()
Run the built-in self test for the DataMessage implementation.
DataMessage()
DataMessage() Creates an empty DataMessage.
bool getDouble(const char *key, double &value)
getDouble(const char* key, double& value)
~DataMessage()
~DataMessage() Message destructor
std::string toXML(std::map< uint16, std::string > *subtypes=NULL, std::map< uint16, std::string > *subcontexts=NULL, std::map< uint32, std::string > *compNames=NULL)
toXML()
bool deleteEntry(const char *key)
deleteEntry(const char* key)
uint32 removeCollectionEntries(const char *key)
removeEntry(const char* key)
static DataMessage * FindClosestMessage(uint64 t, std::map< uint64, DataMessage * > &messages)
FindClosestMessage(uint64 t, std::map<uint64, DataMessage*> &messages) In a map of time -> DataMessag...
bool setFloat(const char *key, float64 value)
setFloat(const char* key, float64 value)
std::map< int64, int64 > getIntArray(const char *key)
getIntArray(const char* key)
bool addTimeUsage(uint32 cycleCPUTime, uint32 cycleWallTime, uint32 chainCPUTime=0, uint32 chainWallTime=0, uint32 chainCount=0)
addTimeUsage()
std::map< std::string, double > getDoubleMap(const char *key)
returns the user double entry with this key
bool setString(const char *key, const char *value)
setString(const char* key, const char* value)
bool getInt(const char *key, int64 &value)
getInt(const char* key, int64& value)
bool setInt(const char *key, int64 value)
setInt(const char* key, int64 value)
bool isSingleValue(const char *key)
isSingleValue(const char* key)
bool hasData(const char *key)
Check if key variable exists and is a data entry.
uint32 getMapCount(const char *key)
getMapCount(const char* key) Returns the number of elements in map with name '<key>'
std::map< std::string, uint64 > getTimeMap(const char *key)
returns the user time entry with this key
std::map< std::string, int64 > getIntMap(const char *key)
returns the user integer entry with this key
uint32 getArraySize(const char *key)
getArraySize(const char* key) Returns the number of elements in array with name '<key>'
char * getDataCopy(const char *key, uint32 &size)
getDataCopy(const char* key, uint32& size)
bool setDoubleMap(const char *key, std::map< std::string, double > &map)
sets the user double entry with this key to the value provided
static bool IsPacked(const char *data, uint32 size)
True if data (at least 8 bytes) starts a packed message.
std::string getAsString(const char *key)
getAsString(const char* key)
DataMessageHeader * data
Pointer to the message's flat memory block (header + user entries).
std::string toJSON(std::map< uint16, std::string > *subtypes=NULL, std::map< uint16, std::string > *subcontexts=NULL, std::map< uint32, std::string > *compNames=NULL)
toJSON()
std::map< int64, float64 > getFloatArray(const char *key)
getFloatArray(const char* key)
std::string toCSV(const char *separator=NULL, const char *preample=NULL, std::map< uint16, std::string > *subtypes=NULL, std::map< uint16, std::string > *subcontexts=NULL, std::map< uint32, std::string > *compNames=NULL)
toCSV()
bool hasFloat(const char *key)
Check if key variable exists and is a float.
bool setIntMap(const char *key, std::map< std::string, int64 > &map)
sets the user integer entry with this key
char * findEntry(const char *key)
findEntry(const char* key)
const char * getData(const char *key, uint32 &size)
getData(const char* key, uint32& size)
bool getAsBool(const char *key)
getAsBool(const char* key)
uint32 getUserCount()
getUserCount()
uint32 getSize()
getSize() Get message size Many types of data of any size can be put into a message as user entries; ...
static bool ConvertDataFromOlderMessageFormat(const char *data, char **newData)
Convert a binary block in the legacy (pre-version-10, DATAMESSAGEOLDID) format to the current DataMes...
uint32 copyUserEntriesFromMessage(DataMessage *msg)
copyUserEntriesFromMessage(DataMessage* msg) Copies all user data from a message into this message,...
std::string getUserEntriesAsJSON(bool asText)
getUserEntriesAsJSON(bool asText) Returns the JSON representation of the full message including all u...
bool setAttachedMessage(const char *key, DataMessage *msg)
setAttachedMessage(const char* key, DataMessage* msg)
bool setTimeArray(const char *key, std::map< int64, uint64 > &map)
setTimeArray(const char* key, std::map<int64, uint64>& map) Sets the whole time array named key in on...
std::map< std::string, std::string > getStringMap(const char *key)
returns the user string entry with this key
std::map< std::string, KeyType > getAllKeys()
getAllKeys()
char * toPacked(uint32 &size) const
Encode this message in the packed wire form.
std::map< int64, std::string > getStringArray(const char *key)
getStringArray(const char* key)
bool setAttachedMessageArray(const char *key, std::map< int64, DataMessage * > &map)
setAttachedMessageArray(const char* key, std::map<int64, DataMessage*>& map) Sets the whole array of ...
bool removeEntry(const char *key)
bool hasTime(const char *key)
Check if key variable exists and is a time.
std::map< int64, std::string > getAsStringArray(const char *key)
getAsStringArray(const char* key)
bool setIntArray(const char *key, std::map< int64, int64 > &map)
setIntArray(const char* key, std::map<int64, int64>& map) Sets the whole integer array named key in o...
std::map< std::string, DataMessage * > getAttachedMessageMap(const char *key)
returns a copy of the user message entry with this key
bool setTimeMap(const char *key, std::map< std::string, uint64 > &map)
sets the user time entry with this key
uint32 getContentSize(const char *key)
getContentSize(const char* key)
void invalidateFindKeyCache()
Internal: clears the single-entry key-lookup cache.
uint32 getArrayCount(const char *key)
getArrayCount(const char* key) Returns the number of elements in array with name '<key>'
std::map< std::string, int64 > getAsIntMap(const char *key)
returns the user entry as an integer map regardless of what type it is
bool setFloatMap(const char *key, std::map< std::string, float64 > &map)
sets the user float entry with this key to the value provided
uint64 getAsTime(const char *key)
getAsTime(const char* key)
bool isMapContent(const char *key)
isMapContent(const char* key)
bool hasKey(const char *key)
Check if key variable exists.
uint64 getTime(const char *key)
getTime(const char* key)
bool getFloat(const char *key, float64 &value)
getFloat(const char* key, float64& value)
bool setRawData(const char *key, const char *value, uint32 size, uint32 datatype)
Internal: low-level entry writer used by all typed set...() overloads.
bool setDouble(const char *key, double value)
setDouble(const char* key, double value)
std::map< std::string, std::string > getAsStringMap(const char *key)
returns the user entry as a string regardless of what type it is
int64 getAsInt(const char *key)
getAsInt(const char* key)
bool setDoubleArray(const char *key, std::map< int64, double > &map)
setDoubleArray(const char* key, std::map<int64, double>& map) Sets the whole double array named key i...
bool setStringMap(const char *key, std::map< std::string, std::string > &map)
sets the user string entry with this key
bool isArrayContent(const char *key)
isArrayContent(const char* key)
DataMessage * getAttachedMessageCopy(const char *key)
getAttachedMessageCopy(const char* key)
bool isValid()
isValid() Checks that the message memory block exists and carries the current-format object id (DATAM...
bool hasMessage(const char *key)
Check if key variable exists and is a message.
char * getRawData()
getRawData() Retrieve a pointer to the raw binary block of the message (header + entries).
const char * swapMessageData(const char *data)
swapMessageData(const char* data)
std::map< int64, uint64 > getTimeArray(const char *key)
uint32 getMapSize(const char *key)
getMapSize(const char* key) Returns the number of elements in map with name '<key>'
std::map< int64, double > getDoubleArray(const char *key)
getDoubleArray(const char* key)
bool setData(const char *key, const char *value, uint32 size)
setData(const char* key, const char* value, uint32 size)
bool hasString(const char *key)
Check if key variable exists and is a string.
std::map< int64, DataMessage * > getAttachedMessageArray(const char *key)
getAttachedMessageArray(const char* key)
const char * getString(const char *key)
getString(const char* key)
char * findSpace(uint32 space)
findSpace(uint32 space)
static std::string GetCSVHeader(const char *separator=NULL, const char *preample=NULL)
toCSVHeader()
bool fillInDraftUserDataFrom(const char *data, uint32 maxDraftSize)
fillInDraftUserDataFrom(const char* data, uint32 maxDraftSize)
KeyType getKeyType(const char *key)
getKeyType(const char* key)
uint32 getContentType(const char *key)
getContentType(const char* key)
bool setSerial(uint64 serial)
setSerial(uint64 serial)
bool setStringArray(const char *key, std::map< int64, std::string > &map)
setStringArray(const char* key, std::map<int64, std::string>& map) Sets the whole string array named ...
DataMessage * copy()
copy() Creates a full deep copy of the message and returns it.
bool hasInteger(const char *key)
Check if key variable exists and is an integer.
std::map< int64, int64 > getAsIntArray(const char *key)
getAsIntArray(const char* key)
bool setAttachedMessageMap(const char *key, std::map< std::string, DataMessage * > &map)
sets the user message entry with this key to the provided message
static DataMessage * FromPacked(const char *data, uint32 size)
Decode a packed message (as written by toPacked() or the Kotlin codec).
std::string getUserEntriesAsString()
getUserEntriesAsString() Returns the textual representation of the full message including all user en...
float64 getAsFloat(const char *key)
getAsFloat(const char* key)
std::map< std::string, float64 > getFloatMap(const char *key)
returns the user float entry with this key
std::map< std::string, float64 > getAsFloatMap(const char *key)
returns the user entry as a float map regardless of what type it is
static UnitTestRunner & instance()
Access the singleton (created on first use).
void registerTest(const char *name, UnitTestFunc func, const char *description="", const char *category="", bool inDefaultRun=true)
Register a test with the runner.
std::string PrintTimeString(uint64 t, bool local=true, bool us=true, bool ms=true)
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
bool TextStartsWith(const char *str, const char *start, bool caseSensitive=true)
Test whether str starts with start.
bool TextEndsWith(const char *str, const char *end, bool caseSensitive=true)
Test whether str ends with end.
uint32 strcpyavail(char *dst, const char *src, uint32 maxlen, bool copyAvailable)
Bounded strcpy that always NUL-terminates.
void fail(const char *fmt,...)
Set an explanatory reason shown on the FAIL line.
void progress(int percent, const char *action)
Report progress with a short description of the current action.
std::string TextIndent(const char *text, const char *indent)
Prefix every line of text with indent.
uint32 StringSingleReplace(std::string &text, std::string key, std::string value, bool onlyFirst)
Replace occurrences of key with value in text.
std::string StringFormat(const char *format,...)
printf into a std::string.
uint64 Ascii2Uint64(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 64-bit decimal integer from a substring.
int64 Ascii2Int64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a signed 64-bit decimal integer from a substring.
float64 Ascii2Float64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a 64-bit float from a substring (decimal point, not locale dependent).
void Register_DataMessage_Tests()
static struct PsyType CTRL_TEST
Hierarchical message type identifier — the key used for publish/subscribe matching in Psyclone.