@Override
	public DataTypeComponent replace(int ordinal, DataType dataType, int length,
			String componentName, String comment)
			throws IndexOutOfBoundsException, IllegalArgumentException {
		if (ordinal < 0 || ordinal >= numComponents) {
			throw new IndexOutOfBoundsException(ordinal);
		}

		dataType = validateDataType(dataType);

		dataType = dataType.clone(dataMgr);
		checkAncestry(dataType);

		length = getPreferredComponentLength(dataType, length);

		LinkedList<DataTypeComponentImpl> replacedComponents = new LinkedList<>();
		int offset;

		int index = ordinal;
		if (!isPackingEnabled()) {
			index = Collections.binarySearch(components, Integer.valueOf(ordinal),
				OrdinalComparator.INSTANCE);
		}
		if (index >= 0) {
			// defined component
			DataTypeComponentImpl origDtc = components.get(index);
			offset = origDtc.getOffset();

			if (isPackingEnabled() || length == 0) {
				// case 1: packed structure or zero-length replacement - do 1-for-1 replacement
				replacedComponents.add(origDtc);
			}
			else if (origDtc.getLength() == 0) {
				// case 2: replaced component is zero-length (like-for-like replacement handled by case 1 above
				throw new IllegalArgumentException(
					"Zero-length component may only be replaced with another zero-length component");
			}
			else if (origDtc.isBitFieldComponent()) {
				// case 3: replacing bit-field (must replace all bit-fields which overlap)
				int minOffset = origDtc.getOffset();
				int maxOffset = origDtc.getEndOffset();

				replacedComponents.add(origDtc);

				// consume bit-field overlaps before
				for (int i = index - 1; i >= 0; i--) {
					origDtc = components.get(i);
					if (origDtc.getLength() == 0 || !origDtc.containsOffset(minOffset)) {
						break;
					}
					replacedComponents.add(0, origDtc);
				}

				// consume bit-field overlaps after
				for (int i = index + 1; i < components.size(); i++) {
					origDtc = components.get(i);
					if (origDtc.getLength() == 0 || !origDtc.containsOffset(maxOffset)) {
						break;
					}
					replacedComponents.add(origDtc);
				}
			}
			else {
				// case 4: sized component replacemnt - do 1-for-1 replacement 
				replacedComponents.add(origDtc);
			}
		}
		else {
			// case 5: undefined component replaced (non-packed only)
			index = -index - 1;
			offset = ordinal;
			if (index > 0) {
				// use previous defined component to compute undefined offset
				DataTypeComponent dtc = components.get(index - 1);
				offset = dtc.getEndOffset() + ordinal - dtc.getOrdinal();
				if (dtc.getLength() == 0) {
					--offset;
				}
			}
			DataTypeComponentImpl origDtc =
				new DataTypeComponentImpl(DataType.DEFAULT, this, 1, ordinal, offset);
			if (dataType == DataType.DEFAULT) {
				return origDtc; // no change
			}
			replacedComponents.add(origDtc);
		}

		DataTypeComponent replaceComponent = doComponentReplacement(replacedComponents, offset,
			dataType, length, componentName, comment);

		return replaceComponent != null ? replaceComponent : getComponent(ordinal);
	}
Perform component replacement(s)
@param replacedComponents ordered list of components to be replaced
@param offset offset of component replacement
@param dataType datatype of component replacement
@param length length of component replacement
@param componentName name of component replacement (may be null)
@param comment comment for component replacement (may be null)
@return new/updated component (may be null if replacement is not a defined component)
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java