@Override
	public String readString() throws DecoderException {
		byte header1 = curPos.getNextByte();
		if ((header1 & HEADEREXTEND_MASK) != 0) {
			curPos.getNextByte();
		}
		byte typeByte = curPos.getNextByte();
		int typeCode = typeByte >> TYPECODE_SHIFT;
		if (typeCode != TYPECODE_STRING) {
			skipAttributeRemaining(typeByte);
			throw new DecoderException("Expecting string attribute");
		}
		int length = typeByte & LENGTHCODE_MASK;
		length = (int) readInteger(length);

		attributeRead = true;
		int curLen = curPos.array.length - curPos.current;
		if (curLen >= length) {
			String res = new String(curPos.array, curPos.current, length);
			curPos.advancePosition(length);
			return res;
		}
		int size = curLen;
		byte[] buf = new byte[length];
		System.arraycopy(curPos.array, curPos.current, buf, 0, curLen);
		length -= curLen;
		curPos.advancePosition(curLen);
		while (length > 0) {
			curLen = curPos.array.length - curPos.current;
			if (curLen > length) {
				curLen = length;
			}
			System.arraycopy(curPos.array, curPos.current, buf, size, curLen);
			size += curLen;
			length -= curLen;
			curPos.advancePosition(curLen);
		}
		return new String(buf, 0, size);
	}
Close stream cached by the ingestStreamAsNeeded method.
@throws IOException for low-level problems with the stream
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PackedDecode.java