// get value as string // might contain '\n' if list or compound std::string Tag::asString() const { if (isIntType(type)) return std::to_string(payload->tagInt); else if (isFloatType(type)) return std::to_string(payload->tagFloat); else if (type == tagTypeString) return *payload->tagString; else if (isListType(type) || type == tagTypeCompound) { std::string str = std::to_string(getListSize()) + " entries\n{\n"; for (int32_t i = 0; i < getListSize(); i++) { // limit output to 10-15 lines if (isListType(type) && i >= 10 && getListSize() > 15) { str += " ... and " + std::to_string(getListSize()-10) + " more\n"; break; } Tag * tag = getListItemAsTag(i); if (tag != NULL) { std::string content = " " + tag->toString(); // indent content for (size_t pos = content.find_first_of('\n'); pos != std::string::npos; pos = content.find_first_of('\n', pos+1)) { content = content.replace(pos, 1, "\n "); } str += content + "\n"; } else str += " ERROR\n"; } str += "}"; return str; } return ""; }
void Tag::safeRemovePayload(Payload * payload, TagType type) { DEBUG printf("Deleting payload of '%s' ...\n", name.c_str()); if (payload != NULL) { if (type == tagTypeString && payloadToBeDeleted) { delete payload->tagString; } else if (type == tagTypeCompound && payloadToBeDeleted) { DEBUG printf("Deleting tagCompound, size=%i\n", payload->tagCompound->size()); for (int i = 0; i < payload->tagCompound->size(); i++) delete payload->tagCompound->at(i); delete payload->tagCompound; } else if (isListType(type) && payloadToBeDeleted) { DEBUG printf("Deleting list type, size=%i\n", payload->tagList.values->size()); for (int i = 0; i < payload->tagList.values->size(); i++) { DEBUG printf("Here goes entry %i ...\n", i); safeRemovePayload(payload->tagList.values->at(i), payload->tagList.type); //delete payload->tagList.values->at(i); } delete payload->tagList.values; } else DEBUG printf("Deleting primitive type, type=%s\n", tagTypeToString(type).c_str()); delete payload; } else DEBUG printf("Not deleting, payload == NULL\n"); }
// gets child at the given path if type is compound or list // returns 0 on error // format: "list.42.intHolder..myInt." // (multiple dots are like one dot, dots at the end are ignored) Tag * Tag::getSubTag(std::string path) { size_t dotPos = path.find_first_of('.'); std::string first = path.substr(0, dotPos); std::string rest = ""; if (dotPos < path.length()) rest = path.substr(dotPos+1); DEBUG printf("getSubTag: path='%s', first='%s', rest='%s' at tag '%s'\n", path.c_str(), first.c_str(), rest.c_str(), name.c_str()); if (path.length() <= 0) return this; // recursion anchor if (first.length() <= 0) return getSubTag(rest); // allows "foo..bar." == "foo.bar" Tag * tag = NULL; if (isListType(type) || type == tagTypeCompound) { for (int32_t i = 0; i < getListSize(); i++) { tag = getListItemAsTag(i); if (tag == NULL) continue; // didn't get a tag ... why? if (first.compare(tag->getName()) == 0) break; else tag = NULL; // do not remember incorrect tags } } // we still found no matching tag, try interpreting first as number and getting n-th tag if (tag == NULL) { try { tag = getListItemAsTag(stoi(first)); DEBUG printf("getting tag #%i\n", stoi(first)); } catch (const std::invalid_argument& ia) { tag = NULL; } } // still no luck? we're out of ideas, return nothing if (tag == NULL) return NULL; return tag->getSubTag(rest); }
// get the size of the list or compound // 0 if no list or compound int32_t Tag::getListSize() const { if (isListType(type)) { return payload->tagList.values->size(); } if (type == tagTypeCompound) { return payload->tagCompound->size(); } return 0; }
/* ========================================================================== */ int sci_bug_11106(char *fname) { int* piAddr = NULL; char pstRet[64]; getVarAddressFromPosition(pvApiCtx, 1, &piAddr); if (isStringType(pvApiCtx, piAddr)) { //named check char* pstVar = NULL; getAllocatedSingleString(pvApiCtx, piAddr, &pstVar); if (isNamedListType(pvApiCtx, pstVar)) { sprintf(pstRet, "%s", "isNamedList"); } else if (isNamedTListType(pvApiCtx, pstVar)) { sprintf(pstRet, "%s", "isNamedTList"); } else if (isNamedMListType(pvApiCtx, pstVar)) { sprintf(pstRet, "%s", "isNamedMList"); } else { sprintf(pstRet, "%s", "unmanaged named type"); } FREE(pstVar); } else { if (isListType(pvApiCtx, piAddr)) { sprintf(pstRet, "%s", "isList"); } else if (isTListType(pvApiCtx, piAddr)) { sprintf(pstRet, "%s", "isTList"); } else if (isMListType(pvApiCtx, piAddr)) { sprintf(pstRet, "%s", "isMList"); } else { sprintf(pstRet, "%s", "unmanaged type"); } } createSingleString(pvApiCtx, Rhs + 1, pstRet); LhsVar(1) = Rhs + 1; return 0; }
// gets the ith item of a list or compound // NULL if out of bounds or no list or compound Tag * Tag::getListItemAsTag(int32_t i) const { if (i < 0 || i >= getListSize()) return NULL; if (isListType(type)) { return createTagFromPayload(std::to_string(i), payload->tagList.type, payload->tagList.values->at(i)); } if (type == tagTypeCompound) { return payload->tagCompound->at(i); } return NULL; }
// creates a tag from the supplied payload // returns NULL if invalid type or payload Tag * Tag::createTagFromPayload(std::string name, TagType type, Payload * payload) { if (payload == NULL) return NULL; if (type == tagTypeByte || type == tagTypeShort || type == tagTypeInt || type == tagTypeLong) { return new Tag(name, type, payload->tagInt); } else if (type == tagTypeFloat || type == tagTypeDouble) { return new Tag(name, type, payload->tagFloat); } else if (type == tagTypeString) { return new Tag(name, type, *payload->tagString); } else if (isListType(type)) { return new Tag(name, type, payload->tagList.type, payload->tagList.values); } else if (type == tagTypeCompound) { return new Tag(name, type, payload->tagCompound); } return NULL; }
const core::TypePtr getElementType(const core::TypePtr& listType) { assert_true(isListType(listType)) << "Not applicable to non-list type!"; return static_pointer_cast<const core::GenericType>(listType)->getTypeParameter()->getElement(0); }
// reads the payload from the Bytestream and returns it Payload * Tag::readPayload(TagType type, Bytestream * data) { Payload * payload = new Payload; payload->tagInt = 0; if (type == tagTypeByte) { payload->tagInt = data->get(); DEBUG printf("tagByte=%i\n", payload->tagInt); } // integers else if (type == tagTypeShort) { int16_t value = 0; data->getInverseEndian(&value, 2); payload->tagInt = value; DEBUG printf("tagShort=%i\n", payload->tagInt); } else if (type == tagTypeInt) { int32_t value = 0; data->getInverseEndian(&value, 4); payload->tagInt = value; DEBUG printf("tagInt=%i\n", payload->tagInt); } else if (type == tagTypeLong) { int64_t value = 0; data->getInverseEndian(&value, 8); payload->tagInt = value; DEBUG printf("tagLong=%lld\n", payload->tagInt); } // floating point numbers else if (type == tagTypeFloat) { float value = 0; data->getInverseEndian(&value, 4); payload->tagFloat = value; DEBUG printf("tagFloat=%.2f\n", payload->tagFloat); } else if (type == tagTypeDouble) { double value = 0; data->getInverseEndian(&value, 8); payload->tagFloat = value; DEBUG printf("tagDouble=%.2f\n", payload->tagFloat); } // string type else if (type == tagTypeString) { int strLen = (uint16_t(data->get()) << 8) + data->get(); payload->tagString = new std::string(""); for (int i = 0; i < strLen; i++) *payload->tagString += data->get(); DEBUG printf("tagString=%s\n", payload->tagString->c_str()); } // tag holding types else if (isListType(type)) { DEBUG printf("tagTypeList...\n"); TagType listType = tagTypeInvalid; if (type == tagTypeByteArray) listType = tagTypeByte; else if (type == tagTypeIntArray) listType = tagTypeInt; else if (type == tagTypeList) { // read type listType = static_cast<TagType>(data->get()); DEBUG printf("listType=%i\n", listType); } // read size int32_t size = 0; data->getInverseEndian(&size, 4); // read values payload->tagList.type = listType; payload->tagList.values = new std::vector<Payload *>; DEBUG printf("type=%i, size=%i\n", listType, size); for (int32_t i = 0; i < size; i++) payload->tagList.values->push_back(readPayload(listType, data)); DEBUG printf("tagTypeList end\n"); } else if (type == tagTypeCompound) { DEBUG printf("tagCompound...\n"); TagType tagType; payload->tagCompound = new std::vector<Tag*>; while (1) { // breaks on TAG_End or error Tag *subTag = (new Tag)->loadFromBytestream(data); tagType = subTag->getType(); if (tagType == tagTypeEnd) { delete subTag; break; } if (tagType < 0 || tagType > 11) { printf("ERROR: unknown type %i %#x\n", (int) tagType, (int) tagType); delete subTag; break; } payload->tagCompound->push_back(subTag); } DEBUG printf("tagCompound end\n"); } else { printf("ERROR: unknown type %i %#x\n", (int) type, (int) type); } return payload; }