public function validate($type, $val, &$return) { $return = false; if (self::_isBasicType($type)) { $def = array('base' => $type); } else { $def = @$this->struct_def[$type]; } if (!is_array($def)) { Ak_Log::warning("type[{$type}] not exists"); return null; } //check if value is null if (is_null($val)) { if (isset($def['default'])) { $val = $def['default']; } elseif (@$def['optional']) { $return = true; return null; } else { Ak_Log::warning("value is null"); return null; } } //check if value matches the type switch ($def['base']) { case 'bool': if (!is_bool($val)) { Ak_Log::warning("value[{$val}] is not bool"); return null; } break; case 'int': if (!is_int($val)) { Ak_Log::warning("value[{$val}] is not int"); return null; } break; case 'float': if (!is_float($val)) { Ak_Log::warning("value[{$val}] is not float"); return null; } break; case 'string': if (!is_string($val)) { Ak_Log::warning("value[{$val}] is not string"); return null; } break; case 'array': if (!is_array($val)) { Ak_Log::warning("value[{$val}] is not array"); return null; } break; case 'dict': if (!is_array($val)) { Ak_Log::warning("value[{$val}] is not dict"); return null; } break; case 'object': if (!is_array($val)) { Ak_Log::warning("value[{$val}] is not object"); return null; } break; case 'any': break; case 'multi': $ret_all = false; Ak_Log::beginSub(); foreach ($def['types'] as $t) { $temp_val = $this->validate($t, $val, $ret); if ($ret != true) { Ak_Log::warning("value[{$val}] is not type[{$t}]"); } else { $val = $temp_val; $ret_all = true; break; } } if ($ret_all == true) { Ak_Log::endSub(false); } else { Ak_Log::endSub(true); return null; } break; default: Ak_Log::warning("unknown type[{$def['base']}]"); return null; } //check if value in the array if (is_array(@$def['in'])) { $ret = in_array($val, $def['in']); if ($ret != true) { Ak_Log::warning("value[{$val}] not in array"); return null; } } //check if the value in range switch ($def['base']) { case 'int': case 'float': if (!self::_checkRange(@$def['min'], @$def['max'], $val)) { Ak_Log::warning("value[{$val}] is not valid"); return null; } break; case 'string': $len = strlen($val); if (!self::_checkRange(@$def['min_size'], @$def['max_size'], $len)) { Ak_Log::warning("string len[{$len}] is not valid"); return null; } if (isset($def['regex']) && !preg_match($def['regex'], $val)) { Ak_Log::warning("value[{$val}] not match regex[{$def['regex']}]"); return null; } break; case 'array': case 'dict': $len = count($val); if (!self::_checkRange(@$def['min_size'], @$def['max_size'], $len)) { Ak_Log::warning("item count[{$len}] is not valid"); return null; } break; } //check children switch ($def['base']) { case 'array': $i = 0; foreach ($val as $k => &$v) { if (!is_int($k) || $k != $i) { Ak_Log::warning("array index[{$i}] != key[{$k}]"); return null; } $v = $this->validate($def['item_type'], $v, $ret); if (!$ret) { Ak_Log::warning("item[{$k}] not valid"); return null; } $i++; } break; case 'dict': foreach ($val as $k => &$v) { $this->validate($def['key_type'], $k, $ret); if (!$ret) { Ak_Log::warning("key[{$k}] is not type[{$def['key_type']}]"); return null; } $v = $this->validate($def['value_type'], $v, $ret); if (!$ret) { Ak_Log::warning("value of key[{$k}] is not type[{$def['value_type']}]"); return null; } } break; case 'object': if (!is_array(@$def['alias'])) { $def['alias'] = array(); } foreach ($def['alias'] as $k1 => $k2) { if (!isset($val[$k2])) { $val[$k2] = @$val[$k1]; unset($val[$k1]); } } foreach ($def['members'] as $k => $t) { $val[$k] = $this->validate($t, @$val[$k], $ret); if (!$ret) { Ak_Log::warning("key[{$k}] is not type[{$t}]"); return null; } } break; } //user defined check $func = @$def['user_def']; if (is_callable($func)) { $val = $func($val, $ret); if ($ret != true) { Ak_Log::warning("user check[{$func}] failed"); return null; } } $return = true; return $val; }