13/8/10

Desempaquetar una cadena con un listado de subcadenas

Esto puede ser útil por ejemplo para extraer los elementos de un enum en PHP usando un SHOW COLUMNS. En ese caso el decode_list_json podría ser el más apropiado ya que, generalmente, los elementos de un enum o un set no contendrán comillas.




// Lenta pero segura y sin efectos colaterales (en principio).
function decode_list_preg($list_string) {
preg_match_all("@(?:,|^)('|\")((?:\\\\'|\\\\\\\\|[^'])*)\\1@Umsi", $list_string, $matches);
return array_map('stripslashes', $matches[2]);
}


// Rápida pero insegura con posibilidad de inyección de código con una entrada inválida.
function decode_list_eval($list_string) {
eval('$list = array(' . $list_string . ');');
return $list;
}


// Rápida pero con efectos colaterales: cambia comillas simples por dobles para que sea un json válido.
function decode_list_json($list_string) {
return json_decode('[' . str_replace("'", '"', $list_string) . ']');
}


// Lenta y segura usando el tokenizer de php.


function decode_list_php($list_string) {
$tokens = array_slice(token_get_all(' $expect_comma = false;
$list = array();
//print_r($tokens);
foreach ($tokens as $token) {
if (!is_array($token)) $token = array(0, $token, -1);
if ($expect_comma) {
if ($token[1] !== ',') throw(new Exception("Invalid input (" . token_name($token[0]) . ")"));
} else {
if ($token[0] !== T_CONSTANT_ENCAPSED_STRING) throw(new Exception("Invalid input (" . token_name($token[0]) . ")"));
$list[] = stripslashes(substr($token[1], 1, -1));
}
$expect_comma = !$expect_comma;
}
return $list;
}

function util_rand_string($len) {
$str = '';
while ($len-- > 0) $str .= chr(mt_rand(0x20, 0x7e));
return $str;
}

$str_list = array();
for ($n = 0, $len = mt_rand(1000, 2000); $n < $len; $n++) $str_list[] = var_export(util_rand_string(mt_rand(40, 80)), true);
$list_string = implode(',', $str_list);


//echo $list_string; exit;

//$list_string = "'ho\'la',\"esto\",'es','una','prueba'";

//print_r(decode_list_preg($list_string));
//print_r(decode_list_eval($list_string));
//print_r(decode_list_json($list_string));
print_r(decode_list_php($list_string));

No hay comentarios:

Publicar un comentario