/**
* Transforms PHP primitives, arrays, objects etc. to INI. Complex structures like arrays and objects
* can take multiple lines (every scalar value is on new line).
*
* @return array
*/
private static function parseSerializedString()
{
$type = self::$value[self::$index];
self::$index += 2;
// <type>:
switch ($type) {
case 's':
$length = intval(StringUtils::substringFromTo(self::$value, self::$index, strpos(self::$value, ':', self::$index)));
self::$index += strlen($length) + 2;
// :"
$str = substr(self::$value, self::$index, $length);
self::$index += strlen($str) + 2;
// ";
return ['type' => 'string', 'value' => $str];
case 'i':
$number = StringUtils::substringFromTo(self::$value, self::$index, strpos(self::$value, ';', self::$index));
self::$index += strlen($number) + 1;
// ;
return ['type' => 'int', 'value' => intval($number)];
case 'd':
$number = StringUtils::substringFromTo(self::$value, self::$index, strpos(self::$value, ';', self::$index));
self::$index += strlen($number) + 1;
// ;
return ['type' => 'double', 'value' => doubleval($number)];
case 'b':
$strVal = StringUtils::substringFromTo(self::$value, self::$index, strpos(self::$value, ';', self::$index));
self::$index += 2;
// <0|1>;
return ['type' => 'boolean', 'value' => $strVal === '1'];
case 'a':
$length = intval(StringUtils::substringFromTo(self::$value, self::$index, strpos(self::$value, ':', self::$index)));
self::$index += strlen($length) + 2;
// :{
$subItems = [];
for ($i = 0; $i < $length; $i++) {
$key = self::parseSerializedString()['value'];
$value = self::parseSerializedString();
$subItems[$key] = $value;
}
self::$index += 1;
// }
return ['type' => 'array', 'value' => $subItems];
case 'O':
$classNameLength = intval(StringUtils::substringFromTo(self::$value, self::$index, strpos(self::$value, ':', self::$index)));
self::$index += strlen($classNameLength) + 2;
// :"
$className = substr(self::$value, self::$index, $classNameLength);
self::$index += $classNameLength + 2;
// ":
$attributeCount = intval(StringUtils::substringFromTo(self::$value, self::$index, strpos(self::$value, ':', self::$index)));
self::$index += strlen($attributeCount) + 2;
// :{
$attribute = [];
for ($i = 0; $i < $attributeCount; $i++) {
$attributeName = self::parseSerializedString()['value'];
$attributeName = str_replace("*", '*', $attributeName);
$attributeName = str_replace("{$className}", '-', $attributeName);
$attributeValue = self::parseSerializedString();
$attribute[$attributeName] = $attributeValue;
}
self::$index += 1;
// }
return ['type' => 'object', 'class' => $className, 'value' => $attribute];
case 'N':
return ['type' => 'null'];
case 'r':
case 'R':
$number = StringUtils::substringFromTo(self::$value, self::$index, strpos(self::$value, ';', self::$index));
self::$index += strlen($number) + 1;
// ;
return ['type' => $type === 'r' ? '*pointer*' : '*reference*', 'value' => intval($number)];
default:
return [];
}
}