Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1431738
ConversionSpec.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
ConversionSpec.php
View Options
<?php
declare
(
strict_types
=
1
);
namespace
Phan\Library
;
/**
* An object representing a conversion specifier of a format string, such as "%1$d".
* @phan-pure
*/
class
ConversionSpec
{
/** @var string Original text of the directive */
public
$directive
;
/** @var ?int Which argument this refers to, starting from 1 */
public
$position
;
/** @var string Character used for padding (commonly confused with $position) */
public
$padding_char
;
/** @var string indicates which side is used for alignment */
public
$alignment
;
/** @var string minimum width of output */
public
$width
;
/** @var string precision of output */
public
$precision
;
/** @var string Type to print (s,d,f,etc.) */
public
$arg_type
;
/**
* Create a conversion specifier from a match.
* @param array{0:string,1:string,2:string,3:string,4:string,5:string,6:string} $match groups in a match.
*/
protected
function
__construct
(
array
$match
)
{
[
$this
->
directive
,
$position_str
,
$this
->
padding_char
,
$this
->
alignment
,
$this
->
width
,
$this
->
precision
,
$this
->
arg_type
]
=
$match
;
if
(
$position_str
!==
""
)
{
$this
->
position
=
\intval
(
\substr
(
$position_str
,
0
,
-
1
));
}
}
// A padding string regex may be a space or 0.
// Alternate padding specifiers may be specified by prefixing it with a single quote.
public
const
PADDING_STRING_REGEX_PART
=
'[0 ]?|
\'
.'
;
/**
* Based on https://secure.php.net/manual/en/function.sprintf.php
*/
public
const
FORMAT_STRING_INNER_REGEX_PART
=
'%'
// Every format string begins with a percent
.
'(
\d
+
\$
)?'
// Optional n$ position specifier must go immediately after percent
.
'('
.
self
::
PADDING_STRING_REGEX_PART
.
')'
// optional padding specifier
.
'([+-]?)'
// optional alignment specifier
.
'(
\d
*)'
// optional width specifier
.
'(
\.\d
*)?'
// Optional precision specifier in the form of a period followed by an optional decimal digit string
.
'(?:l)?'
// Optional length specifier (ignored)
.
'([bcdeEfFgGosuxX])'
;
// A type specifier
public
const
FORMAT_STRING_REGEX
=
'/%%|'
.
self
::
FORMAT_STRING_INNER_REGEX_PART
.
'/'
;
/**
* Compute the number of additional arguments expected when sprintf is called
* with a format string of $fmt_str.
* @param string $fmt_str
*/
public
static
function
computeExpectedArgumentCount
(
string
$fmt_str
):
int
{
$result
=
0
;
foreach
(
self
::
extractAll
(
$fmt_str
)
as
$i
=>
$_
)
{
$result
=
\max
(
$result
,
$i
);
}
return
$result
;
}
/**
* Extract a list of directives from a format string.
* @param string $fmt_str a format string to extract directives from.
* @return associative-array<int,non-empty-list<ConversionSpec>> array(int position => array of ConversionSpec referring to arg at that position)
*/
public
static
function
extractAll
(
string
$fmt_str
):
array
{
// echo "format is $fmt_str\n";
$directives
=
[];
\preg_match_all
(
self
::
FORMAT_STRING_REGEX
,
$fmt_str
,
$matches
,
\PREG_SET_ORDER
);
$unnamed_count
=
0
;
foreach
(
$matches
as
$match
)
{
if
(
$match
[
0
]
===
'%%'
)
{
continue
;
}
$directive
=
new
self
(
$match
);
if
(!
isset
(
$directive
->
position
))
{
// @phan-suppress-next-line PhanAccessReadOnlyProperty
$directive
->
position
=
++
$unnamed_count
;
}
$directives
[
$directive
->
position
][]
=
$directive
;
}
\ksort
(
$directives
);
return
$directives
;
}
/**
* @return string an unambiguous way of referring to this conversion spec.
*/
public
function
toCanonicalString
():
string
{
if
(
$this
->
width
!==
''
)
{
$padding_char
=
$this
->
padding_char
;
$alignment
=
$this
->
alignment
;
}
else
{
$padding_char
=
''
;
$alignment
=
''
;
}
return
'%'
.
$this
->
position
.
'$'
.
$padding_char
.
$alignment
.
$this
->
width
.
$this
->
precision
.
$this
->
arg_type
;
}
/**
* @return string the conversion spec if the width was used as a position instead.
*/
public
function
toCanonicalStringWithWidthAsPosition
():
string
{
return
'%'
.
$this
->
width
.
'$'
.
$this
->
padding_char
.
$this
->
alignment
.
$this
->
precision
.
$this
->
arg_type
;
}
public
const
ARG_TYPE_LOOKUP
=
[
'b'
=>
'int'
,
'c'
=>
'int'
,
'd'
=>
'int'
,
'e'
=>
'float'
,
'E'
=>
'float'
,
'f'
=>
'float'
,
'F'
=>
'float'
,
'g'
=>
'float'
,
'G'
=>
'float'
,
'o'
=>
'int'
,
's'
=>
'string'
,
'u'
=>
'int'
,
'x'
=>
'int'
,
'X'
=>
'int'
,
];
/**
* @return string the name of the union type expected for the arg for this conversion spec
*/
public
function
getExpectedUnionTypeName
():
string
{
return
self
::
ARG_TYPE_LOOKUP
[
$this
->
arg_type
]
??
'string'
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 21:01 (1 d, 15 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
96/71/2015c2079638466b4b9061c6613f
Default Alt Text
ConversionSpec.php (4 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment