private function addCidr( $cidr ) {
		// v4 or v6 check
		if ( strpos( $cidr, ':' ) === false ) {
			$node =& $this->root4;
			$defMask = '32';
		} else {
			$node =& $this->root6;
			$defMask = '128';
		}

		// Default to all-1's mask if no netmask in the input
		if ( strpos( $cidr, '/' ) === false ) {
			$net = $cidr;
			$mask = $defMask;
		} else {
			list( $net, $mask ) = explode( '/', $cidr, 2 );
			if ( !ctype_digit( $mask ) || intval( $mask ) > $defMask ) {
				trigger_error( "IPSet: Bad mask '$mask' from '$cidr', ignored", E_USER_WARNING );
				return false;
			}
		}
		$mask = intval( $mask ); // explicit integer convert, checked above

		// convert $net to an array of integer bytes, length 4 or 16:
		$raw = AtEase::quietCall( 'inet_pton', $net );
		if ( $raw === false ) {
			return false;
		}
		$rawOrd = array_map( 'ord', str_split( $raw ) );

		// iterate the bits of the address while walking the tree structure for inserts
		// at the end, $snode will point to the highest node that could only lead to a
		// successful match (and thus can be set to true)
		$snode =& $node;
		$curBit = 0;
		while ( 1 ) {
			if ( $node === true ) {
				// already added a larger supernet, no need to go deeper
				return;
			} elseif ( $curBit == $mask ) {
				// this may wipe out deeper subnets from earlier
				$snode = true;
				return;
			} elseif ( $node === false ) {
				// create new subarray to go deeper
				if ( !( $curBit & 7 ) && $curBit <= $mask - 8 ) {
					$node = [ 'comp' => $rawOrd[$curBit >> 3], 'next' => false ];
				} else {
					$node = [ false, false ];
				}
			}

			if ( isset( $node['comp'] ) ) {
				$comp = $node['comp'];
				if ( $rawOrd[$curBit >> 3] == $comp && $curBit <= $mask - 8 ) {
					// whole byte matches, skip over the compressed node
					$node =& $node['next'];
					$snode =& $node;
					$curBit += 8;
					continue;
				} else {
					// have to decompress the node and check individual bits
					$unode = $node['next'];
					for ( $i = 0; $i < 8; ++$i ) {
						$unode = ( $comp & ( 1 << $i ) )
							? [ false, $unode ]
							: [ $unode, false ];
					}
					$node = $unode;
				}
			}

			$maskShift = 7 - ( $curBit & 7 );
			$index = ( $rawOrd[$curBit >> 3] & ( 1 << $maskShift ) ) >> $maskShift;
			if ( $node[$index ^ 1] !== true ) {
				// no adjacent subnet, can't form a supernet at this level
				$snode =& $node[$index];
			}
			$node =& $node[$index];
			++$curBit;
		} // Unreachable outside 'while'
	}