Maison développement back-end Problème PHP PHP implémente des fonctions similaires à la bibliothèque Construct en Python (1) Idées de conception de base

PHP implémente des fonctions similaires à la bibliothèque Construct en Python (1) Idées de conception de base

Aug 19, 2019 pm 05:12 PM

Introduction

Il existe une bibliothèque Construct en python, qui peut être utilisée pour analyser des données binaires. Il est très pratique d'utiliser cet outil pour analyser des paquets réseau, des fichiers de données formatés, etc.

Si j'avais utilisé cet outil lors de l'analyse du format de fichier de la base de données SQLite il y a quelque temps, cela m'aurait évité bien des ennuis.

Cependant, Construct 2.9 a beaucoup changé par rapport aux versions précédentes. Le code python original écrit en Construct doit essentiellement être réécrit. En visualisant le code source de Construct, j'ai découvert que l'idée de base de l'implémentation de​​Construct est la méthode d'analyse de descente récursive. Utilisez la méthode de construction de l'objet pour définir dynamiquement la structure des données et implémentez l'analyse des données binaires dans la méthode d'analyse.

Je prévois d'utiliser php pour analyser les données binaires, mais l'idée d'implémentation est complètement différente de celle de Construct de Python.

Tutoriel vidéo PHP recommandé : https://www.php.cn/course/list/29/type/2.html

Idées de base

Étant donné que Construct de Python utilise la syntaxe objet de Python pour implémenter la définition et l'analyse des structures hiérarchiques dynamiques, certaines définitions de structure semblent obscures en raison de la limitation de la syntaxe objet de Python.

Mon idée est de définir un petit langage spécifiquement utilisé pour décrire des structures hiérarchiques dynamiques, afin qu'il puisse prendre en charge autant que possible les habitudes d'expression communes des gens.

Pour ce petit projet, il s'appuie sur la syntaxe de définition de structure en langage C, et sur cette base, la conditionnalisation et la définition de structure de boucle sont ajoutées.

Il existe une structure commune dans les données binaires. Les premiers octets stockent la longueur du bloc de données suivant, suivi du bloc de données. Il n’est pas pratique d’exprimer ce type de structure avec la définition de structure du langage C. La longueur de l'ensemble du bloc de données varie et ne peut pas être déterminée au moment de la compilation, mais ne peut être déterminée que lors de l'analyse. Il est donc nécessaire d’étendre la syntaxe de définition de structure du langage C.

La première étape consiste à mettre en œuvre l'analyse de la structure du langage C

Dans cette étape, nous ne considérons pas la définition de la structure hiérarchique dynamique, mais implémentons ce petit Le partie essentielle du langage, il doit au moins être capable de comprendre la définition de la structure du langage C et d'analyser les données binaires sur la base de cette définition de la structure. Une fois cette étape terminée, la définition et l’analyse de la structure dynamique seront mises en œuvre.

Ce projet est basé sur le moteur de langage de script ADOS brièvement présenté dans le document précédent.

Jetons d'abord un coup d'œil à notre tâche

Voici un fichier de définition de structure qui est entièrement une spécification du langage C

blockStruct.h

struct student
{
  char name[2];
  int num;
  int age;
  char addr[3];
};

struct teacher
{
  char name[2];
  int num;  
  char addr[3];
};
Copier après la connexion
Copier après la connexion

à être bloc de données binaires analysé

"\x41\x42\x01\x00\x00\x00\x02\x00\x00\x00\x41\x42\x43\x41\x42\x01\x00\x00\x00\x41\x42\x43"
Copier après la connexion

J'espère obtenir le résultat de l'analyse

[value] => Array
        (
            [name] => AB
            [num] => 1
            [age] => 2
            [addr] => ABC
        )
[value] => Array
        (
            [name] => AB
            [num] => 1
            [addr] => ABC
        )
Copier après la connexion

Les amis intéressés peuvent prêter attention à la relation entre les trois

Mais seulement le C Le fichier de règles lexicales pour compilation des structures de langage

<?php
/*!
 * struckwkr的词法规则
 * 45022300@qq.com
 * Version 0.9.0
 *
 * Copyright 2019, Zhu Hui
 * Released under the MIT license
 */

$GLOBALS[&#39;structwkr_lexRules&#39;] =	[
		[&#39;/^\"(.*?)\"/&#39;,&#39;_cons&#39;	,&#39;"&#39;],
		[&#39;/^\(/&#39;,&#39;_lp&#39;			,&#39;(&#39;],
		[&#39;/^\)/&#39;,&#39;_rp&#39;			,&#39;)&#39;],
		[&#39;/^\[/&#39;,&#39;_lb&#39;			,&#39;[&#39;],
		[&#39;/^\]/&#39;,&#39;_rb&#39;			,&#39;]&#39;],
		[&#39;/^\{/&#39;,&#39;_lcb&#39;			,&#39;{&#39;],
		[&#39;/^\}/&#39;,&#39;_rcb&#39;			,&#39;}&#39;],
		[&#39;/^;/&#39;,&#39;_semi&#39;			,&#39;;&#39;],
		[&#39;/^,/&#39;,&#39;_comma&#39;		,&#39;,&#39;],
		[&#39;/^==/&#39;,&#39;_bieq&#39;		,&#39;=&#39;],
		[&#39;/^!=/&#39;,&#39;_uneq&#39;		,&#39;!&#39;],		
		[&#39;/^\>=/&#39;,&#39;_greq&#39;		,&#39;>&#39;],		
		[&#39;/^\<=/&#39;,&#39;_leeq&#39;		,&#39;<&#39;],		
		[&#39;/^=/&#39;,&#39;_equa&#39;			,&#39;=&#39;],		
		[&#39;/^\>/&#39;,&#39;_grea&#39;		,&#39;>&#39;],
		[&#39;/^\</&#39;,&#39;_less&#39;		,&#39;<&#39;],	
		[&#39;/^\+/&#39;,&#39;_add&#39;			,&#39;+&#39;],
		[&#39;/^-/&#39;,&#39;_sub&#39;			,&#39;-&#39;],
		[&#39;/^\*/&#39;,&#39;_mul&#39;			,&#39;*&#39;],
		[&#39;/^\//&#39;,&#39;_div&#39;			,&#39;/&#39;],	
		[&#39;/^%/&#39;,&#39;_mod&#39;			,&#39;$&#39;],
		[&#39;/^&&/&#39;,&#39;_and&#39;			,&#39;&&#39;],	
		[&#39;/^\|\|/&#39;,&#39;_or&#39;		,&#39;|&#39;],	
		[&#39;/^!/&#39;,&#39;_not&#39;			,&#39;!&#39;],	
		[&#39;/^struct/&#39;,&#39;_strukey&#39;	,&#39;s&#39;],
		[&#39;/^char/&#39;,&#39;_char&#39;		,&#39;c&#39;],
		[&#39;/^int/&#39;,&#39;_int&#39;		,&#39;i&#39;],
		[&#39;/^float/&#39;,&#39;_float&#39;	,&#39;f&#39;],
		[&#39;/^double/&#39;,&#39;_double&#39;	,&#39;d&#39;],
		[&#39;/^[0-9]+([.]{1}[0-9]+){0,1}/&#39;,&#39;_num&#39;,&#39;&#39;],
		[&#39;/^\./&#39;,&#39;_dot&#39;			,&#39;.&#39;],
		[&#39;/^[\x{4e00}-\x{9fa5}A-Za-z_][\x{4e00}-\x{9fa5}A-Za-z0-9_]*\b/u&#39;,&#39;_iden&#39;,&#39;&#39;],
		[&#39;/^\s*/&#39;,&#39;_null&#39;,&#39;&#39;]
		];
Copier après la connexion

Ce qui suit est le fichier de règles grammaticales qui implémente uniquement la compilation des structures de langage C

<?php
/*!
 * structwkr的语法规则处理器
 * 45022300@qq.com
 * Version 0.9.0
 *
 * Copyright 2019, Zhu Hui
 * Released under the MIT license
 */

namespace Ados;

require_once &#39;const.php&#39;;
require_once __SCRIPTCORE__.&#39;syntax_rule/base_rules_handler.php&#39;;

class StructwkrRulesHandler extends BaseRulesHandler{

//语法分析的起始记号,归约到最后得到就是若干个结构体定义的列表
function startToken(){
	return &#39;_structList&#39;;
}

//附加类型
function extraType($extraArray){
	if(count($extraArray)>0){
		return $extraArray[0];
	}else{
		return &#39;&#39;;
	}
}

//求出放在附加信息中的数组长度
function elementSize($extraArray){
	if(count($extraArray)>0){
		return intval($extraArray[0]);
	}else{
		return 0;
	}
}

//处理源代码中的多条声明语句
function handleStatementList($stack,$coder,$listIndex,$statementIndex){
	
	$t1= $this->topItem($stack,$statementIndex);	

	if($listIndex>0){
		$t2= $this->topItem($stack,$listIndex);
		//将元素名所在项的附加信息数组找出来
		$extraArray=$t2[TokenExtraIndex];
	}else{ //$listIndex=0表示,statementList是上级节点,附加信息数组应该是空数组
		$extraArray=[];
	}
	//将statement中的附加信息添加到statementList的附加信息中去
	$extraArray[]=$t1[TokenExtraIndex];

	return [&#39;#&#39;,$extraArray];
}

//处理源代码中的一条声明语句
function handleStatement($stack,$coder,$typeItemIndex,$idenItemIndex){
	
	$t1= $this->topItem($stack,$typeItemIndex);
	$elementType = 	$t1[TokenValueIndex];

	$t2= $this->topItem($stack,$idenItemIndex);
	$elementName = 	$t2[TokenValueIndex];
	
	//将元素名所在项的附加信息数组找出来
	$extraArray=$t2[TokenExtraIndex];
	$valLen =$extraArray[0];
	//附加信息中包含 元素名称,元素类型,数据长度
	return [$elementName,[$elementName,$elementType,$valLen]];
}


//语法规则处理函数名由规则右边部分与规则左边部分拼接而成
//语法规则定义的先后决定了归约时匹配的顺序,要根据实际的语法安排
//如果不熟悉语法,随意调整语法规则的先后次序将有可能导致语法错误

// struct list  {{{

function _structList_0_structList_struct($stack,$coder){

	$coder->pushBlockTail();
	return [&#39;#&#39;,[]];
	
	
}

function _structList_0_struct($stack,$coder){	
	$coder->pushBlockTail();
	return [&#39;#&#39;,[]];
}

// struct list  }}}


// struct   {{{

function _struct_0_structName_blockStatement_semi($stack,$coder){

	$t1= $this->topItem($stack,3);
	$structName = 	$t1[TokenValueIndex];

	$t2= $this->topItem($stack,2);
	$extraArray=$t2[TokenExtraIndex];
	
	return [$structName,$extraArray];
}

// struct   }}}

// struct name     {{{

function _structName_0_strukey_iden($stack,$coder){  

	$t1= $this->topItem($stack,1);
	$structName = 	$t1[TokenValueIndex];

	$coder->pushBlockHeader($structName);	
	return $this->pass($stack,1);
}

// struct name     }}}

// blockStatement    {{{

function _blockStatement_0_lcb_statementList_rcb($stack,$coder){

	return $this->pass($stack,2);

}

// blockStatement    }}}

// statement list  {{{

function _statementList_0_statementList_statement($stack,$coder){
	
	return $this->handleStatementList($stack,$coder,2,1);
}

function _statementList_0_statement($stack,$coder){
	//此处0表示statementList是上一级节点,要做特殊处理
	return $this->handleStatementList($stack,$coder,0,1);	
}

// statement list  }}}


// statement       {{{

function _statement_0_double_term_semi($stack,$coder){	

	$t1= $this->topItem($stack,2);
	$elementName = 	$t1[TokenValueIndex];
	$parseFuncName = &#39;parseDouble&#39;;	
	$coder->pushBlockBody($parseFuncName,$elementName);	
	
	return $this->handleStatement($stack,$coder,3,2);
}

function _statement_0_float_term_semi($stack,$coder){	

	$t1= $this->topItem($stack,2);
	$elementName = 	$t1[TokenValueIndex];
	$parseFuncName = &#39;parseFloat&#39;;	
	$coder->pushBlockBody($parseFuncName,$elementName);	
	
	return $this->handleStatement($stack,$coder,3,2);
}


function _statement_0_char_term_semi($stack,$coder){

	$t1= $this->topItem($stack,2);
	$elementName = 	$t1[TokenValueIndex];
	$size = $this->elementSize($t1[TokenExtraIndex]);
	$parseFuncName = &#39;parseFixStr&#39;;	
	$coder->pushBlockBody($parseFuncName,$elementName,$size);		
	
	return $this->handleStatement($stack,$coder,3,2);
}

function _statement_0_int_term_semi($stack,$coder){	

	$t1= $this->topItem($stack,2);
	$elementName = 	$t1[TokenValueIndex];
	$parseFuncName = &#39;parseInt&#39;;	
	$coder->pushBlockBody($parseFuncName,$elementName,4);	
	
	return $this->handleStatement($stack,$coder,3,2);
}

// statement        }}}


//   term    {{{

function _term_0_term_array($stack,$coder){

	$t1= $this->topItem($stack,1);
	$valLen = 	$t1[TokenValueIndex];
	//将数据长度放入附加信息 
	$t2= $this->topItem($stack,2);
	return [$t2[TokenValueIndex],[$valLen]];
	
	
}

function _term_0_iden($stack,$coder){
	$t1= $this->topItem($stack,1);
	//未指定数据长度时将长度值设为0 
	$valLen = 	&#39;0&#39;;	
	$t2= $this->topItem($stack,2);
	return [$t1[TokenValueIndex],[$valLen]];	
}

//   term     }}}


// array 	  {{{

function _array_0_lb_num_rb($stack,$coder){

	return $this->pass($stack,2);	
}

// array 	   }}}


} // end of class
Copier après la connexion

Ce qui suit est le type de données de base, entier, chaîne La fonction d'analyse (remarque, utilisé pour les expériences, ne couvre pas tous les types de données de base)

<?php

//用于解析基本数据类型的内置函数

namespace Ados;

//解析一个字节,得到无符号整数值
function parseByte($context,$size = 0){
	$pos=$context[&#39;pos&#39;];
	$data = substr($context[&#39;data&#39;], $pos);
	if(strlen($data)>0){
		$raw = substr($data, 0,1);
		$value = unpack("C1",$raw)[1];
		return [&#39;value&#39;=>$value,&#39;size&#39;=>1,&#39;error&#39;=>0,&#39;msg&#39;=>&#39;ok&#39;];
	}else{
		return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>1,&#39;msg&#39;=>&#39;not enough for parseByte&#39;];
	}
	
}

//解析一个有符号整数
function parseInt($context,$size = 4){
	if(!($size == 2 or $size == 4 or $size == 8 )){
		return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>2,&#39;msg&#39;=>&#39;not a valid size&#39;];
	}
	if($size == 2) $format = "s1";
	if($size == 4) $format = "l1";
	if($size == 8) $format = "q1";

	$pos=$context[&#39;pos&#39;];
	$data = substr($context[&#39;data&#39;], $pos);
	if(strlen($data)>=$size){
		$raw = substr($data, 0,$size);
		$value = unpack($format,$raw)[1];
		return [&#39;value&#39;=>$value,&#39;size&#39;=>$size,&#39;error&#39;=>0,&#39;msg&#39;=>&#39;ok&#39;];
	}else{
		return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>1,&#39;msg&#39;=>&#39;no data for parseInt&#39;];
	}
	
}

//解析一个大端无符号整数
function parseBUInt($context,$size = 4){
	if(!($size == 2 or $size == 4 or $size == 8 )){
		return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>2,&#39;msg&#39;=>&#39;not a valid size&#39;];
	}
	if($size == 2) $format = "n1";
	if($size == 4) $format = "N1";
	if($size == 8) $format = "J1";

	$pos=$context[&#39;pos&#39;];
	$data = substr($context[&#39;data&#39;], $pos);
	if(strlen($data)>=$size){
		$raw = substr($data, 0,$size);
		$value = unpack($format,$raw)[1];
		return [&#39;value&#39;=>$value,&#39;size&#39;=>$size,&#39;error&#39;=>0,&#39;msg&#39;=>&#39;ok&#39;];
	}else{
		return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>1,&#39;msg&#39;=>&#39;no data for parseBUInt&#39;];
	}
	
}

//解析一个小端无符号整数
function parseLUInt($context,$size = 4){
	if(!($size == 2 or $size == 4 or $size == 8 )){
		return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>2,&#39;msg&#39;=>&#39;not a valid size&#39;];
	}
	if($size == 2) $format = "v1";
	if($size == 4) $format = "NL";
	if($size == 8) $format = "P1";

	$pos=$context[&#39;pos&#39;];
	$data = substr($context[&#39;data&#39;], $pos);
	if(strlen($data)>=$size){
		$raw = substr($data, 0,$size);
		$value = unpack($format,$raw)[1];
		return [&#39;value&#39;=>$value,&#39;size&#39;=>$size,&#39;error&#39;=>0,&#39;msg&#39;=>&#39;ok&#39;];
	}else{
		return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>1,&#39;msg&#39;=>&#39;no data for parseLUInt&#39;];
	}
	
}

//解析一个null结束的字符串
function parseString($context,$size=0){
	$pos=$context[&#39;pos&#39;];
	$data = substr($context[&#39;data&#39;], $pos);

	$p=0;
	$raw = substr($data, $p,1);
	$byte = unpack("C1",$raw)[1];	
	$result =&#39;&#39;;
	while($byte){
		$result.=$raw;
		$p++;
		if($p>=strlen($data)){
			return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>1,&#39;msg&#39;=>&#39;not find null end for parseString&#39;];
		}
		$raw = substr($data, $p,1);
		$byte = unpack("C1",$raw)[1];		
	}
	return [&#39;value&#39;=>$result,&#39;size&#39;=>$p,&#39;error&#39;=>0,&#39;msg&#39;=>&#39;ok&#39;];
}

//解析一个定长字符串
function parseFixStr($context,$size=0){
	$pos=$context[&#39;pos&#39;];
	$data = substr($context[&#39;data&#39;], $pos);
	//var_dump($data);	
	if(strlen($data)>=$size){
		$result =&#39;&#39;;
		for($i=0;$i<$size;$i++){
			$raw = substr($data, $i,1);
			$value = unpack("a1",$raw)[1];
			$result.=$value;			
		}
		return [&#39;value&#39;=>$result,&#39;size&#39;=>$size,&#39;error&#39;=>0,&#39;msg&#39;=>&#39;ok&#39;]; 
	}
	return [&#39;value&#39;=>False,&#39;size&#39;=>0,&#39;error&#39;=>1,&#39;msg&#39;=>&#39;not enough for parseFixedString&#39;];
}
Copier après la connexion

Ce qui suit est la fonction de travail pour le remplacement du modèle

<?php

//用于进行模板替换的工作函数

namespace Ados;

defined(&#39;__STRUCT_PARSE_TEMP__&#39;) or define(&#39;__STRUCT_PARSE_TEMP__&#39;, &#39;./&#39;);
define(&#39;_blockParsTempFile_&#39;,__STRUCT_PARSE_TEMP__.&#39;parseFunc.template.php&#39;);

//取出两个记号串之间的内容
function strBetweenToke($src,$toke1,$toke2){
	$p1 = strpos($src,$toke1);
	$p2 = strpos($src,$toke2);
	return substr($src,$p1+strlen($toke1),$p2-$p1-strlen($toke1));
}

//取得块分析函数的header
function blockHeaderStr(){
	$src = file_get_contents(_blockParsTempFile_);
	return strBetweenToke($src,&#39;/*blockHeader{{*/&#39;,&#39;/*blockHeader}}*/&#39;);
}

//取得块分析函数的body
function blockBodyStr(){
	$src = file_get_contents(_blockParsTempFile_);
	return strBetweenToke($src,&#39;/*blockBody{{*/&#39;,&#39;/*blockBody}}*/&#39;);
}

//取得块分析函数的tail
function blockTailStr(){
	$src = file_get_contents(_blockParsTempFile_);
	return strBetweenToke($src,&#39;/*blockTail{{*/&#39;,&#39;/*blockTail}}*/&#39;);
}

define(&#39;_blockHeaderStr_&#39;,blockHeaderStr());
define(&#39;_blockBodyStr_&#39;,blockBodyStr());
define(&#39;_blockTailStr_&#39;,blockTailStr());

function makeBlockHeader($blockName){
	return str_replace(&#39;parseBlock_Temp&#39;, &#39;parse&#39;.$blockName, _blockHeaderStr_);
}

function makeblockBody($parseFuncName,$filedName=&#39;&#39;,$filedSize=0){
	$tmp = str_replace(&#39;parseByte&#39;, $parseFuncName, _blockBodyStr_);
	$tmp = str_replace(&#39;$filedName&#39;, $filedName, $tmp);
	$tmp = str_replace(&#39;$filedSize&#39;, $filedSize, $tmp);
	return $tmp;
}

function makeblockTail(){
	return _blockTailStr_ ;
}


/*
echo blockHeaderStr();
echo blockBodyStr();
echo blockTailStr();

echo makeBlockHeader(&#39;Test1&#39;);
echo makeblockBody(&#39;parseInt&#39;);
echo makeblockBody(&#39;parseStr&#39;);
echo makeblockTail();
*/
Copier après la connexion

Avec ces préparations, un encodeur guidé par la grammaire peut être implémenté pour générer le fonction d'analyse finale.
Ce qui suit est un encodeur simple qui génère un code de script qui peut être utilisé pour analyser des données binaires lors de l'analyse syntaxique de la définition de la structure

<?php
/*!
 * structwkr编码器,
 *
 * 45022300@qq.com
 * Version 0.9.0
 *
 * Copyright 2019, Zhu Hui
 * Released under the MIT license
 */

namespace Ados;

require_once __SCRIPTCORE__.&#39;coder/base_coder.php&#39;;
require_once __STRUCT_PARSE_TEMP__.&#39;templateReplaceFuncs.php&#39;;


class StructwkrCoder extends BaseCoder{

	public function __construct($engine)
	{
		if($engine){ 
			$this->engine = $engine;
		}else{ 
			exit(&#39;the engine is not valid in StructwkrCoder construct.&#39;);
		}
	}

	//编译得到的最终结果
	public function codeLines(){
		if(count($this->codeLines)<1){
			return &#39;&#39;;
		}
		$script=&#39;&#39;;		
		for ($i=0;$i< count($this->codeLines);$i+=1) {
			$script.=$this->codeLines[$i];
		}	
		return $script;
	}	

	//输出编译后的结果
	public function printCodeLines(){
		echo $this->codeLines();	
	}

	//添加一个块解析函数头
	public function pushBlockHeader($structName){
		$structName=ucfirst($structName);
		$content = makeBlockHeader($structName);
		array_push($this->codeLines, $content);
		$lineIndex=$this->lineIndex;
		$this->lineIndex+=1;
		return $lineIndex;		
	}

	//添加一个块解析函数体
	public function pushBlockBody($parseFuncName,$filedName=&#39;&#39;,$filedSize=0){
		$content = makeblockBody($parseFuncName,$filedName,$filedSize);
		array_push($this->codeLines, $content);
		$lineIndex=$this->lineIndex;
		$this->lineIndex+=1;
		return $lineIndex;		
	}

	//添加一个块解析函数尾
	public function pushBlockTail(){
		$content = makeblockTail();
		array_push($this->codeLines, $content);
		$lineIndex=$this->lineIndex;
		$this->lineIndex+=1;
		return $lineIndex;		
	}

}
Copier après la connexion

Fichier de script généré automatiquement pour l'analyse

Compilez la structure du langage C et obtenez enfin une série de fonctions qui peuvent être utilisées pour analyser des données binaires. Par exemple, le fichier de définition de structure ci-dessus définit deux structures

struct student
{
  char name[2];
  int num;
  int age;
  char addr[3];
};

struct teacher
{
  char name[2];
  int num;  
  char addr[3];
};
Copier après la connexion
Copier après la connexion

Puis les fonctions analytiques parseStudent et. Des parseTeacher correspondant à ces deux structures seront générés.

Ce qui suit est le script de test généré automatiquement

False,'size'=>0,'error'=>$expRes['error'],'msg'=>$expRes['msg']];
	}

	$expRes = parseInt($context,4);
	if($expRes['error']==0){
		$filed = 'num';
		if($filed){
			$valueArray[$filed]=$expRes['value'];
		}else{
			$valueArray[]=$expRes['value'];
		}		
		$context['pos']+=$expRes['size'];
		$totalSize+= $expRes['size'];
	}else{
		return ['value'=>False,'size'=>0,'error'=>$expRes['error'],'msg'=>$expRes['msg']];
	}

	$expRes = parseInt($context,4);
	if($expRes['error']==0){
		$filed = 'age';
		if($filed){
			$valueArray[$filed]=$expRes['value'];
		}else{
			$valueArray[]=$expRes['value'];
		}		
		$context['pos']+=$expRes['size'];
		$totalSize+= $expRes['size'];
	}else{
		return ['value'=>False,'size'=>0,'error'=>$expRes['error'],'msg'=>$expRes['msg']];
	}

	$expRes = parseFixStr($context,3);
	if($expRes['error']==0){
		$filed = 'addr';
		if($filed){
			$valueArray[$filed]=$expRes['value'];
		}else{
			$valueArray[]=$expRes['value'];
		}		
		$context['pos']+=$expRes['size'];
		$totalSize+= $expRes['size'];
	}else{
		return ['value'=>False,'size'=>0,'error'=>$expRes['error'],'msg'=>$expRes['msg']];
	}

	return ['value'=>$valueArray,'size'=>$totalSize,'error'=>0,'msg'=>'ok'];
}

function parseTeacher($context,$size=0){
	$valueArray=[];
	$totalSize = 0;

	$expRes = parseFixStr($context,2);
	if($expRes['error']==0){
		$filed = 'name';
		if($filed){
			$valueArray[$filed]=$expRes['value'];
		}else{
			$valueArray[]=$expRes['value'];
		}		
		$context['pos']+=$expRes['size'];
		$totalSize+= $expRes['size'];
	}else{
		return ['value'=>False,'size'=>0,'error'=>$expRes['error'],'msg'=>$expRes['msg']];
	}

	$expRes = parseInt($context,4);
	if($expRes['error']==0){
		$filed = 'num';
		if($filed){
			$valueArray[$filed]=$expRes['value'];
		}else{
			$valueArray[]=$expRes['value'];
		}		
		$context['pos']+=$expRes['size'];
		$totalSize+= $expRes['size'];
	}else{
		return ['value'=>False,'size'=>0,'error'=>$expRes['error'],'msg'=>$expRes['msg']];
	}

	$expRes = parseFixStr($context,3);
	if($expRes['error']==0){
		$filed = 'addr';
		if($filed){
			$valueArray[$filed]=$expRes['value'];
		}else{
			$valueArray[]=$expRes['value'];
		}		
		$context['pos']+=$expRes['size'];
		$totalSize+= $expRes['size'];
	}else{
		return ['value'=>False,'size'=>0,'error'=>$expRes['error'],'msg'=>$expRes['msg']];
	}

	return ['value'=>$valueArray,'size'=>$totalSize,'error'=>0,'msg'=>'ok'];
}
Copier après la connexion

Exécutez ce script de test et les résultats sont les suivants :

Array
(
    [value] => Array
        (
            [name] => AB
            [num] => 1
            [age] => 2
            [addr] => ABC
        )

    [size] => 13
    [error] => 0
    [msg] => ok
)
Array
(
    [value] => Array
        (
            [name] => AB
            [num] => 1
            [addr] => ABC
        )

    [size] => 9
    [error] => 0
    [msg] => ok
)
Copier après la connexion

OK La première étape de la tâche est terminée ! . Ensuite, envisagez de l'implémenter. Analyse d'une structure avec jugement conditionnel.

Pour plus de questions connexes, veuillez visiter le site Web PHP chinois : https://www.php.cn/

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Repo: Comment relancer ses coéquipiers
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Quelles sont les meilleures pratiques pour la déduplication des tableaux PHP Quelles sont les meilleures pratiques pour la déduplication des tableaux PHP Mar 03, 2025 pm 04:41 PM

Cet article explore la déduplication efficace du tableau PHP. Il compare les fonctions intégrées comme Array_Unique () avec les approches de hashmap personnalisées, mettant en évidence les compromis de performances en fonction de la taille du tableau et du type de données. La méthode optimale dépend de Profili

La déduplication PHP Array peut-elle profiter de l'unicité du nom clé? La déduplication PHP Array peut-elle profiter de l'unicité du nom clé? Mar 03, 2025 pm 04:51 PM

Cet article explore la déduplication du tableau PHP en utilisant l'unicité clé. Bien qu'il ne s'agisse pas d'une méthode de suppression en double directe, la mise à profit de l'unicité clé permet de créer un nouveau tableau avec des valeurs uniques en mappant des valeurs aux clés, en écrasant des doublons. Ce AP

La déduplication du tableau PHP doit-elle être prise en compte pour les pertes de performance? La déduplication du tableau PHP doit-elle être prise en compte pour les pertes de performance? Mar 03, 2025 pm 04:47 PM

Cet article analyse la déduplication du tableau PHP, mettant en évidence les goulots d'étranglement des performances des approches naïves (O (n²)). Il explore des alternatives efficaces à l'aide d'Array_Unique () avec des fonctions personnalisées, des implémentations SplobjectStorage et HashSet, réalisant

Comment implémenter les files d'attente de messages (Rabbitmq, Redis) dans PHP? Comment implémenter les files d'attente de messages (Rabbitmq, Redis) dans PHP? Mar 10, 2025 pm 06:15 PM

Cet article détaille la mise en œuvre des files d'attente de messages en PHP à l'aide de RabbitMQ et Redis. Il compare leurs architectures (AMQP vs en mémoire), les fonctionnalités et les mécanismes de fiabilité (confirmations, transactions, persistance). Meilleures pratiques de conception, erreur

Quelles sont les dernières normes de codage PHP et les meilleures pratiques? Quelles sont les dernières normes de codage PHP et les meilleures pratiques? Mar 10, 2025 pm 06:16 PM

Cet article examine les normes de codage PHP actuelles et les meilleures pratiques, en se concentrant sur les recommandations PSR (PSR-1, PSR-2, PSR-4, PSR-12). Il met l'accent

Quelles sont les techniques d'optimisation pour la déduplication des tableaux PHP Quelles sont les techniques d'optimisation pour la déduplication des tableaux PHP Mar 03, 2025 pm 04:50 PM

Cet article explore l'optimisation de la déduplication du tableau PHP pour les grands ensembles de données. Il examine des techniques comme Array_Unique (), Array_flip (), SploBjectStorage et Pre-Sorting, en comparant leur efficacité. Pour les ensembles de données massifs, il suggère de secouer, datab

Comment puis-je travailler avec les extensions de PHP et PECL? Comment puis-je travailler avec les extensions de PHP et PECL? Mar 10, 2025 pm 06:12 PM

Cet article détaille l'installation et le dépannage des extensions de PHP, en se concentrant sur PECL. Il couvre les étapes d'installation (trouver, télécharger / compilation, activer, redémarrer le serveur), dépannage des techniques (vérification des journaux, vérification de l'installation,

Comment utiliser la réflexion pour analyser et manipuler le code PHP? Comment utiliser la réflexion pour analyser et manipuler le code PHP? Mar 10, 2025 pm 06:12 PM

Cet article explique l'API de réflexion de PHP, permettant l'inspection d'exécution et la manipulation des classes, des méthodes et des propriétés. Il détaille les cas d'utilisation courants (génération de documentation, ORMS, injection de dépendance) et prévient contre la performance Overhea

See all articles