Gebruiker van FPC wilde PHP arrays accessen vanuit FPC/Delphi, (gepost vanuit webapps) en dat heb ik ff uitgezocht. Het bleek redelijk eenvoudig te zijn, omdat de basis PHP types die zin hebben om via webinterfaces door te geven prima op variants mappen.
Met behulp van de volgende code kan je geserialiseerde php arrays naar variant (vararray) serialiseren (met phpunserialize) en weer terug. (phpserialize)
Code:
{$ifdef FPC}{$mode delphi}{$else}{$apptype console}{$endif}
Uses Variants,SysUtils;
function phpdeserialize (const s : string):variant;
var i,l:integer;
function consumefield:variant; forward;
function consumearray:variant;
var j,k,fields : integer;
begin
inc(i,2);
j:=i;
while (j<l) and (s[j] in ['0'..'9']) do inc(j);
fields:=strtointdef(copy(s,i,j-i),0);
i:=j+2;
result:=vararraycreate([0,fields-1],varvariant);
for j:=0 to fields-1 do
begin
inc(i,2);
k:=i;
while (k<l) and (s[k] in ['0'..'9']) do
inc(k);
i:=k+1;
result[j]:=consumefield;
end;
end;
function consumestring:variant;
var j,len : integer;
s2 : string;
begin
inc(i,2);
j:=i;
while (j<l) and (s[j] in ['0'..'9']) do inc(j);
len:=strtointdef(copy(s,i,j-i),0);
i:=j;
s2:=copy(s,i+2,len);
result:=s2;
inc(i,len+4); // +2 are the quotes, + two :
end;
function consumeinteger:variant;
var j,len : integer;
begin
inc(i,2);
j:=i;
while (j<l) and (s[j] in ['0'..'9']) do inc(j);
result:=strtointdef(copy(s,i,j-i),0);
i:=j+1;
end;
function consumefield:variant;
begin
case s[i] of
'a' : result:=consumearray;
's' : result:=consumestring;
'i' : result:=consumeinteger;
// 'd' : result:=consumedouble; // t.b.d.
'n' : begin
result:=varnull;
inc(i,2); // ; also
end;
end;
end;
begin
i:=1; l:=length(s);
if i<l then // tokens are >1
result:=consumefield;
end;
function phpserialize(v:variant):String;
function servariant(v:variant):string; forward;
function servarray(v:variant):string;
var i : integer;
begin
result:='a:' +inttostr(vararrayhighbound(v,1)-vararraylowbound(v,1)+1)+':{';;
for i:=VarArrayLowBound(v,1) to vararrayhighbound(v,1) do
result:=result+'i:'+inttostr(i)+':'+servariant(v[i])+';';
result:=result+'}';
end;
function servariant(v:variant):string;
var i : integer;
begin
result:='';
i:=VarType(v);
if (i and vararray)=vararray then
i:=vararray;
case i of
varinteger : result:='i:'+vartostr(v);
// was inttostr(vr)
varolestr,
varstring : result:='s:'+inttostr(length(v))+':"'+v+'"';
vararray : result:=servarray(v);
varnull : result:='N';
// vardouble : t.b.d.
end;
end;
begin
result:=servariant(v);
end;
procedure dotest;
const phparr ='a:4:{i:0;s:5:"Tuple";i:1;s:4:"With";i:2;i:4;i:3;s:6:"Values";}';
var v : Variant;
serobj : string;
begin
Writeln(phparr);
// deserialize a serialized a PHP array to an vararray
v:=phpdeserialize(phparr);
serobj:=phpserialize(v);
writeln(serobj);
end;
begin
dotest;
end.
Overigens werkt de code nog niet met FPC, er zit ergens een refcounting issue. Dit zou echter ook een probleem met Kylix kunnen veroorzaken. (strings worden als olestr opgeslagen)
Bookmarks