protected function _propToFunctionCase(
        $propName)
    {
        // To translate a property name to FunctionCase, we must simply convert
        // any leading lowercase (a-z) character to uppercase, as well as any
        // (a-z) that comes after an underscore. In the latter case, the
        // underscore must be removed during the conversion.
        // For example: "example_property" = "ExampleProperty".
        // (If multiple underscores, still just remove ONE: "a__b"="A_B").
        //
        // However, there is a special case: All LEADING underscores must be
        // preserved exactly as-is: "__messages" = "__Messages" (still 2).
        //
        // As for camelCasePropertyNames? They're already perfect, except that
        // the first letter must be made uppercase. And IF they have any inner
        // "_[a-z]" (lowercase) chunks, those should be translated as they would
        // for a snake_case string. But any "_[A-Z]" should not be touched.
        // In other words, the algorithm is exactly the same for camelCase.

        // Begin by removing and counting all leading underscores (important!).
        // NOTE: The reason why we have to do this is because otherwise a
        // property named "_messages" would be translated to just "Messages",
        // which then becomes incredibly hard to guess whether it means
        // "messages" or "_messages". So by preserving any leading underscores,
        // we remove that ambiguity. It also make the function names more
        // logical (they match the property's amount of leading underscores) and
        // it removes clashes. For example if the user defines both "messages"
        // and "_messages", they can safely use their "getMessages()" and
        // "get_Messages()" without any ambiguity about what they refer to.
        $result = ltrim($propName, '_');
        $leadingUnderscores = strlen($propName) - strlen($result);

        // Now simply uppercase any lowercase (a-z) character that is either at
        // the start of the string or appears immediately after an underscore.
        //
        // ----------------------------------------
        // TODO: If someone is using Unicode in their JSON data, we should
        // simply extend this (and also the FunctionTranslation class) to run
        // with PHP's slower mb_* multibyte functions and "//u" UTF-8 flags,
        // so that we can support functions like "getÅngbåt()", for a property
        // named '{"ångbåt":1}'. But honestly, I doubt that even international
        // users name their JSON data in anything but pure, highly-compressible
        // ASCII, such as "angbat" and "getAngbat()" in the example above. So
        // for now, we can have the efficient ASCII algorithms here. In the
        // future we may want to provide a class-constant to override the
        // parsers to enable UTF-8 mode, so that the user can have that slower
        // parsing behavior in certain classes only. And in that case, the magic
        // function translations can still be stored in the same global cache
        // together with all the ASCII entries, since they'd use their UTF-8
        // names as key and thus never clash with anything from this algorithm.
        // ----------------------------------------
        $result = preg_replace_callback('/(?:^|_)([a-z])/', function ($matches) {
            return ucfirst($matches[1]); // Always contains just 1 character.
        }, $result);

        // Now just prepend any leading underscores that we removed earlier.
        if ($leadingUnderscores > 0) {
            $result = str_repeat('_', $leadingUnderscores).$result;
        }

        // Lastly, we must now translate special PHP operators to an encoded
        // representation, just in case their property name has illegal chars.
        $result = SpecialOperators::encodeOperators($result);

        return $result;
    }