private boolean containsStringDataType(DataType dt) {
		if (StringDataInstance.isStringDataType(dt)) {
			return true;
		}
		else if (dt instanceof Array arrayDT) {
			DataType elementDT = arrayDT.getDataType();
			return arrayDT.getNumElements() != 0 && containsStringDataType(elementDT);
		}
		else if (dt instanceof Structure struct) {
			// handle Structures and general Composite's separately so
			// we can focus on just the defined elements of a structure
			for (DataTypeComponent dtc : struct.getDefinedComponents()) {
				if (dtc.getLength() != 0 && containsStringDataType(dtc.getDataType())) {
					return true;
				}
			}
			return false;
		}
		else if (dt instanceof Composite comp) {
			for (DataTypeComponent dtc : comp.getComponents()) {
				if (containsStringDataType(dtc.getDataType())) {
					return true;
				}
			}
			return false;
		}
		else if (dt instanceof TypeDef tdDT) {
			return containsStringDataType(tdDT.getBaseDataType());
		}
		return false;
	}
LIFO stack of iterators.  Newly found iterators of sub-components are
pushed onto the end and become the current iterator.  When an iterator is exhausted, 
it is popped of the end and the uncovered iterator is now the current.
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/DefinedStringIterator.java