public static void convertHexStringToMaskedValue(AtomicLong msk, AtomicLong val, String hex,
			int n, int spaceevery, String spacer) {
		long lmsk = 0;
		long lval = 0;
		int pos = 0;
		int i = 0;
		while (pos < hex.length() && i < n) {
			lmsk <<= 4;
			lval <<= 4;
			if (i != 0 && spaceevery != 0 && i % spaceevery == 0) {
				boolean matchspacer = hex.regionMatches(pos, spacer, 0, spacer.length());
				if (!matchspacer) {
					throw new NumberFormatException("Missing spacer at " + pos);
				}
				pos += spacer.length();
				continue;
			}
			char c = hex.charAt(pos);
			if (Character.isLetterOrDigit(c)) { // a hex digit, defined or not
				if (c == 'X') { // undefined
					// Write to neither. Just shift.
					i++;
					pos++;
					continue;
				}
				// Try defined
				long nibble = Long.parseLong(hex.substring(pos, pos + 1), 16);
				lmsk |= 0x0fL;
				lval |= nibble;
				i++;
				pos++;
				continue;
			}
			if (c == '[') { // A partially-defined nibble. Parse bits
				lmsk >>= 4; // EW
				lval >>= 4; // EW
				for (int j = 0; j < 4; j++) {
					pos++;
					lmsk <<= 1;
					lval <<= 1;
					if (pos > hex.length()) {
						throw new NumberFormatException("Missing one or more bits at " + pos);
					}
					c = hex.charAt(pos);
					if (c == 'x') { // undefined. Just let it shift.
						continue;
					}
					lmsk |= 1; // defined, so write the mask
					if (c == '0') {
						continue; // Mask already written
					}
					if (c == '1') {
						lval |= 1;
						continue;
					}
					throw new NumberFormatException("Illegal character '" + c + "' at " + pos);
				}
				pos++;
				if (pos > hex.length() || hex.charAt(pos) != ']') {
					throw new NumberFormatException("Missing closing bracket after bits at " + pos);
				}
				pos++;
				i++;
				continue;
			}
			throw new NumberFormatException("Illegal character '" + c + "' at " + pos);
		}
		if (pos < hex.length()) {
			throw new NumberFormatException("Gratuitous characters starting at " + pos);
		}
		if (i < n) {
			throw new NumberFormatException("Too few characters for " + n + " nibbles. Got " + i);
		}
		msk.set(lmsk);
		val.set(lval);
	}
The reverse of {@link #convertMaskedValueToHexString(long, long, int, boolean, int, String)}

@param msk an object to receive the resulting mask
@param val an object to receive the resulting value
@param hex the input string to parse
@param n the number of nibbles to parse (they are stored right aligned in the result)
@param spaceevery how many nibbles are expected between spacers
@param spacer the spacer

@see #convertMaskedValueToHexString(long, long, int, boolean, int, String)
@see #convertMaskToHexString(long, int, boolean, int, String)
Ghidra/Framework/Generic/src/main/java/ghidra/util/NumericUtilities.java