phpstringstrposstring-searchordinals

What if the 'needle' parameter of strpos() function contains a converted integer value that can not be applied as the ordinal value of any character?


I'm using PHP 7.2.8 on my machine running on Windows 10 Operating System.

I come across the following text from the description of 'needle' parameter in strpos() function given in the PHP Manual :

needle
If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.

From the above statement about the 'needle' parameter I don't understand how does the function strpos(); work when the 'needle' parameter of strpos() function contains a converted integer value that can not be applied as the ordinal value of any character.

Can someone please explain the actual meaning of the statement from the manual when the 'needle' parameter of strpos() function contains a converted integer value that can not be applied as the ordinal value of any character in an easy to understand, simple and lucid language?

It would be better for me and other learning people if you could provide couple of suitable working code examples of strpos() function where the 'needle' parameter of strpos() function contains a converted integer value that can not be applied as the ordinal value of any character.

Thank You.


Solution

  • Any value (within reason) given as needle will be converted to char (the datatype internally in C, which is one byte in size). The relevant code from the current strpos implementation:

    /* {{{ php_needle_char
     */
    static int php_needle_char(zval *needle, char *target)
    {
        switch (Z_TYPE_P(needle)) {
            case IS_LONG:
                *target = (char)Z_LVAL_P(needle);
                return SUCCESS;
            case IS_NULL:
            case IS_FALSE:
                *target = '\0';
                return SUCCESS;
            case IS_TRUE:
                *target = '\1';
                return SUCCESS;
            case IS_DOUBLE:
                *target = (char)(int)Z_DVAL_P(needle);
                return SUCCESS;
            case IS_OBJECT:
                *target = (char) zval_get_long(needle);
                return SUCCESS;
            default:
                php_error_docref(NULL, E_WARNING, "needle is not a string or an integer");
                return FAILURE;
        }
    }
    /* }}} */
    

    That (char) cast will wrap around (i.e. only the 8 least significant bits will be kept), meaning that var_dump(strpos('foo', ord('o') + 256)); will give 1 as the answer, the same as var_dump(strpos('foo', ord('o')));.

    Be aware that any of the old str* functions in PHP is not multi byte encoding aware - they only work on single bytes. A string in PHP is a collection of bytes (and not characters), and calling strpos will result in only a single byte value being matched. So if you give it a string with a multibyte encoding, your results will not make much sense.

    If you're using a multibyte encoding, such as utf-8, the mbstring module provides copies of most of the internal string functions while handling multibyte encoding. For strpos that function is named mb_strpos.

    PHP also supported functionality to override the internal function names with their mb_* counterparts, but that behavior has been deprecated as far as I remember - and should not be relied on in any manner, since it breaks code in non-apparent ways.