+Implemented as a macro in utf8.h
+
+=for apidoc A|bool|is_utf8_string_loc|const U8 *s|STRLEN len|const U8 **ep
+
+Like is_utf8_string() but stores the location of the failure (in the
+case of "utf8ness failure") or the location s+len (in the case of
+"utf8ness success") in the C<ep>.
+
+See also is_utf8_string_loclen() and is_utf8_string().
+
+=for apidoc A|bool|is_utf8_string_loclen|const U8 *s|STRLEN len|const U8 **ep|const STRLEN *el
+
+Like is_utf8_string() but stores the location of the failure (in the
+case of "utf8ness failure") or the location s+len (in the case of
+"utf8ness success") in the C<ep>, and the number of UTF-8
+encoded characters in the C<el>.
+
+See also is_utf8_string_loc() and is_utf8_string().
+
+=cut
+*/
+
+bool
+Perl_is_utf8_string_loclen(pTHX_ const U8 *s, STRLEN len, const U8 **ep, STRLEN *el)
+{
+ const U8* x = s;
+ const U8* send;
+ STRLEN c;
+
+ if (!len)
+ len = strlen((const char *)s);
+ send = s + len;
+ if (el)
+ *el = 0;
+
+ while (x < send) {
+ /* Inline the easy bits of is_utf8_char() here for speed... */
+ if (UTF8_IS_INVARIANT(*x))
+ c = 1;
+ else if (!UTF8_IS_START(*x))
+ goto out;
+ else {
+ /* ... and call is_utf8_char() only if really needed. */
+#ifdef IS_UTF8_CHAR
+ c = UTF8SKIP(x);
+ if (IS_UTF8_CHAR_FAST(c)) {
+ if (!IS_UTF8_CHAR(x, c))
+ c = 0;
+ } else
+ c = is_utf8_char_slow(x, c);
+#else
+ c = is_utf8_char(x);
+#endif /* #ifdef IS_UTF8_CHAR */
+ if (!c)
+ goto out;
+ }
+ x += c;
+ if (el)
+ (*el)++;
+ }
+
+ out:
+ if (ep)
+ *ep = x;
+ if (x != send)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+
+=for apidoc A|UV|utf8n_to_uvuni|const U8 *s|STRLEN curlen|STRLEN *retlen|U32 flags