src/ets.php
function get_datatype($maskname, $carray, $incode, &$cindex, &$ckey, &$clast, &$datatree, &$datatype, &$direction, &$currentdata, $safemode)
	{
		// . from root
		if ($maskname == '//' && !$safemode) {
			$datatype = _ETS_COMPLEX;
			$currentdata = $this->datatree;
			if ($direction == _ETS_FORWARD) {
				if (is_array($currentdata)) {
					$currentdata['_parent'] = &$datatree;
				} elseif (is_object($currentdata)) {
					$currentdata->_parent = &$datatree;
				}
			}
		// . parent
		} elseif (($maskname == '..' || $maskname == '_parent') && !$safemode) {
			if (is_array($datatree)) {
				$datatype = _ETS_COMPLEX;
				$currentdata = $datatree['_parent'];
				$direction = _ETS_BACKWARD;
			} elseif (is_object($datatree)) {
				$datatype = _ETS_COMPLEX;
				$currentdata = $datatree->_parent;
				$direction = _ETS_BACKWARD;
			} else {
				$datatype = _ETS_MISSING;
				$currentdata = NULL;
				$direction = _ETS_FORWARD;
			}
		// . first sibling in an array
		} elseif ($maskname == '_start') {
			$direction = _ETS_FORWARD;
			$keys = array_keys($carray);
			$cindex = 0;
			if (isset($keys[$cindex]) && isset($carray[$keys[$cindex]])) {
				$ckey = $keys[$cindex];
				$clast = ($cindex == count($carray) - 2);
				$currentdata = $carray[$ckey];
				$datatype = _ETS_COMPLEX;
			} else {
				$currentdata = NULL;
				$datatype = _ETS_MISSING;
			}
		// . previous sibling in an array
		} elseif ($maskname == '_previous') {
			$direction = _ETS_FORWARD;
			$keys = array_keys($carray);
			--$cindex;
			if (isset($keys[$cindex]) && isset($carray[$keys[$cindex]])) {
				$ckey = $keys[$cindex];
				$clast = FALSE;
				$currentdata = $carray[$ckey];
				$datatype = _ETS_COMPLEX;
			} else {
				$currentdata = NULL;
				$datatype = _ETS_MISSING;
			}
		// . next sibling in an array
		} elseif ($maskname == '_next') {
			$direction = _ETS_FORWARD;
			$keys = array_keys($carray);
			++$cindex;
			if (isset($keys[$cindex]) && isset($carray[$keys[$cindex]]) && $keys[$cindex] != '_parent') {
				$ckey = $keys[$cindex];
				$clast = ($cindex == count($carray) - 2);
				$currentdata = $carray[$ckey];
				$datatype = _ETS_COMPLEX;
			} else {
				$currentdata = NULL;
				$datatype = _ETS_MISSING;
			}
		// . last sibling in an array
		} elseif ($maskname == '_end') {
			$direction = _ETS_FORWARD;
			$keys = array_keys($carray);
			$cindex = count($keys) - 2;
			if (isset($keys[$cindex]) && isset($carray[$keys[$cindex]])) {
				$ckey = $keys[$cindex];
				$clast = TRUE;
				$currentdata = $carray[$ckey];
				$datatype = _ETS_COMPLEX;
			} else {
				$currentdata = NULL;
				$datatype = _ETS_MISSING;
			}
		// . real data
		} else {
			// retrieve the value
			$currentdata = $this->get_value($datatree, $maskname);
			if (isset($currentdata)) {
				if (is_scalar($currentdata)) {
					$direction = _ETS_FORWARD;
					if ($currentdata === FALSE && !$incode) {
						$datatype = _ETS_MISSING;
					} elseif ($currentdata === '' && !$incode) {
						$datatype = _ETS_MISSING;
					} else {
						$datatype = _ETS_SCALAR;
					}
				} elseif (is_object($currentdata) && count(get_object_vars($currentdata)) > 0) {
					$datatype = _ETS_COMPLEX;
					if ($direction == _ETS_FORWARD && !$safemode) {
						$currentdata->_parent = &$datatree;
					}
				} elseif (is_array($currentdata) && count($currentdata) > 0) {
					$datatype = _ETS_COMPLEX;
					if ($direction == _ETS_FORWARD && !$safemode) {
						$currentdata['_parent'] = &$datatree;
					}
				} else {
					$direction = _ETS_FORWARD;
					$datatype = _ETS_MISSING;
				}
			} else {
				$direction = _ETS_FORWARD;
				$datatype = _ETS_MISSING;
			}
		}
	}
function get_datatype($maskname, $carray, $incode, &$cindex, &$ckey, &$clast, &$datatree, &$datatype, &$direction, &$currentdata, $safemode)
	{
		// . from root
		if ($maskname == '//' && !$safemode) {
			$datatype = _ETS_COMPLEX;
			$currentdata = $this->datatree;
			if ($direction == _ETS_FORWARD) {
				if (is_array($currentdata)) {
					$currentdata['_parent'] = &$datatree;
				} elseif (is_object($currentdata)) {
					$currentdata->_parent = &$datatree;
				}
			}
		// . parent
		} elseif (($maskname == '..' || $maskname == '_parent') && !$safemode) {
			if (is_array($datatree)) {
				$datatype = _ETS_COMPLEX;
				$currentdata = $datatree['_parent'];
				$direction = _ETS_BACKWARD;
			} elseif (is_object($datatree)) {
				$datatype = _ETS_COMPLEX;
				$currentdata = $datatree->_parent;
				$direction = _ETS_BACKWARD;
			} else {
				$datatype = _ETS_MISSING;
				$currentdata = NULL;
				$direction = _ETS_FORWARD;
			}
		// . first sibling in an array
		} elseif ($maskname == '_start') {
			$direction = _ETS_FORWARD;
			$keys = array_keys($carray);
			$cindex = 0;
			if (isset($keys[$cindex]) && isset($carray[$keys[$cindex]])) {
				$ckey = $keys[$cindex];
				$clast = ($cindex == count($carray) - 2);
				$currentdata = $carray[$ckey];
				$datatype = _ETS_COMPLEX;
			} else {
				$currentdata = NULL;
				$datatype = _ETS_MISSING;
			}
		// . previous sibling in an array
		} elseif ($maskname == '_previous') {
			$direction = _ETS_FORWARD;
			$keys = array_keys($carray);
			--$cindex;
			if (isset($keys[$cindex]) && isset($carray[$keys[$cindex]])) {
				$ckey = $keys[$cindex];
				$clast = FALSE;
				$currentdata = $carray[$ckey];
				$datatype = _ETS_COMPLEX;
			} else {
				$currentdata = NULL;
				$datatype = _ETS_MISSING;
			}
		// . next sibling in an array
		} elseif ($maskname == '_next') {
			$direction = _ETS_FORWARD;
			$keys = array_keys($carray);
			++$cindex;
			if (isset($keys[$cindex]) && isset($carray[$keys[$cindex]]) && $keys[$cindex] != '_parent') {
				$ckey = $keys[$cindex];
				$clast = ($cindex == count($carray) - 2);
				$currentdata = $carray[$ckey];
				$datatype = _ETS_COMPLEX;
			} else {
				$currentdata = NULL;
				$datatype = _ETS_MISSING;
			}
		// . last sibling in an array
		} elseif ($maskname == '_end') {
			$direction = _ETS_FORWARD;
			$keys = array_keys($carray);
			$cindex = count($keys) - 2;
			if (isset($keys[$cindex]) && isset($carray[$keys[$cindex]])) {
				$ckey = $keys[$cindex];
				$clast = TRUE;
				$currentdata = $carray[$ckey];
				$datatype = _ETS_COMPLEX;
			} else {
				$currentdata = NULL;
				$datatype = _ETS_MISSING;
			}
		// . real data
		} else {
			// retrieve the value
			$currentdata = $this->get_value($datatree, $maskname);
			if (isset($currentdata)) {
				if (is_scalar($currentdata)) {
					$direction = _ETS_FORWARD;
					if ($currentdata === FALSE && !$incode) {
						$datatype = _ETS_MISSING;
					} elseif ($currentdata === '' && !$incode) {
						$datatype = _ETS_MISSING;
					} else {
						$datatype = _ETS_SCALAR;
					}
				} elseif (is_object($currentdata) && count(get_object_vars($currentdata)) > 0) {
					$datatype = _ETS_COMPLEX;
					if ($direction == _ETS_FORWARD && !$safemode) {
						$currentdata->_parent = &$datatree;
					}
				} elseif (is_array($currentdata) && count($currentdata) > 0) {
					$datatype = _ETS_COMPLEX;
					if ($direction == _ETS_FORWARD && !$safemode) {
						$currentdata['_parent'] = &$datatree;
					}
				} else {
					$direction = _ETS_FORWARD;
					$datatype = _ETS_MISSING;
				}
			} else {
				$direction = _ETS_FORWARD;
				$datatype = _ETS_MISSING;
			}
		}
	}
Define the type of the current data, the direction and parent property