private static function readValue($data, &$offset, &$type = null)
{
$value = "";
$type = null;
$inQuotes = false;
$len = strlen($data);
for (; $offset < $len; ++$offset) {
$c = $data[$offset];
if (!$inQuotes and ($c === " " or $c === "\r" or $c === "\n" or $c === "\t" or $c === "," or $c === "}" or $c === "]")) {
if ($c === "," or $c === "}" or $c === "]") {
break;
}
} elseif ($c === '"') {
$inQuotes = !$inQuotes;
if ($type === null) {
$type = self::TAG_String;
} elseif ($inQuotes) {
throw new \Exception("Syntax error: invalid quote at offset {$offset}");
}
} elseif ($c === "\\") {
$value .= isset($data[$offset + 1]) ? $data[$offset + 1] : "";
++$offset;
} elseif ($c === "{" and !$inQuotes) {
if ($value !== "") {
throw new \Exception("Syntax error: invalid compound start at offset {$offset}");
}
++$offset;
$value = self::parseCompound($data, $offset);
$type = self::TAG_Compound;
break;
} elseif ($c === "[" and !$inQuotes) {
if ($value !== "") {
throw new \Exception("Syntax error: invalid list start at offset {$offset}");
}
++$offset;
$value = self::parseList($data, $offset);
$type = self::TAG_List;
break;
} else {
$value .= $c;
}
}
if ($value === "") {
throw new \Exception("Syntax error: invalid empty value at offset {$offset}");
}
if ($type === null and strlen($value) > 0) {
$value = trim($value);
$last = strtolower(substr($value, -1));
$part = substr($value, 0, -1);
if ($last !== "b" and $last !== "s" and $last !== "l" and $last !== "f" and $last !== "d") {
$part = $value;
$last = null;
}
if ($last !== "f" and $last !== "d" and (string) (int) $part === $part) {
if ($last === "b") {
$type = self::TAG_Byte;
} elseif ($last === "s") {
$type = self::TAG_Short;
} elseif ($last === "l") {
$type = self::TAG_Long;
} else {
$type = self::TAG_Int;
}
$value = (int) $part;
} elseif (is_numeric($part)) {
if ($last === "f" or $last === "d" or strpos($part, ".") !== false) {
if ($last === "f") {
$type = self::TAG_Float;
} elseif ($last === "d") {
$type = self::TAG_Double;
} else {
$type = self::TAG_Float;
}
$value = (double) $part;
} else {
if ($last === "l") {
$type = self::TAG_Long;
} else {
$type = self::TAG_Int;
}
$value = $part;
}
} else {
$type = self::TAG_String;
}
}
return $value;
}