From 36014ad23f3fe1018371e66a0bbf9244ad34d721 Mon Sep 17 00:00:00 2001
From: Anatol Belski <ab@php.net>
Date: Fri, 6 Apr 2018 10:10:17 +0200
Subject: [PATCH] Replace the deprecated API by the newer one available with
 ICU 56+

---
 UPGRADING                                  |  1 +
 ext/intl/normalizer/normalizer.h           | 15 ++++
 ext/intl/normalizer/normalizer_normalize.c | 83 +++++++++++++++++++++-
 ext/intl/tests/normalizer_normalize.phpt   |  7 +-
 4 files changed, 104 insertions(+), 2 deletions(-)

diff --git ext/intl/normalizer/normalizer.h ext/intl/normalizer/normalizer.h
index c057a5188377..ddd2c38a946e 100644
--- ext/intl/normalizer/normalizer.h
+++ ext/intl/normalizer/normalizer.h
@@ -19,6 +19,7 @@
 
 #include <php.h>
 #include <unicode/utypes.h>
+#if U_ICU_VERSION_MAJOR_NUM < 56
 #include <unicode/unorm.h>
 
 #define NORMALIZER_NONE UNORM_NONE
@@ -31,6 +32,20 @@
 #define NORMALIZER_FORM_KC UNORM_NFKC
 #define NORMALIZER_NFKC UNORM_NFKC
 #define NORMALIZER_DEFAULT UNORM_DEFAULT
+#else
+#include <unicode/unorm2.h>
+
+#define NORMALIZER_NONE 0x2
+#define NORMALIZER_FORM_D 0x4
+#define NORMALIZER_NFD NORMALIZER_FORM_D
+#define NORMALIZER_FORM_KD 0x8
+#define NORMALIZER_NFKD NORMALIZER_FORM_KD
+#define NORMALIZER_FORM_C 0x10
+#define NORMALIZER_NFC NORMALIZER_FORM_C
+#define NORMALIZER_FORM_KC 0x20
+#define NORMALIZER_NFKC NORMALIZER_FORM_KC
+#define NORMALIZER_DEFAULT NORMALIZER_FORM_C
+#endif
 
 void normalizer_register_constants( INIT_FUNC_ARGS );
 
diff --git ext/intl/normalizer/normalizer_normalize.c ext/intl/normalizer/normalizer_normalize.c
index c0ab8341d415..e39b2ca73fc2 100644
--- ext/intl/normalizer/normalizer_normalize.c
+++ ext/intl/normalizer/normalizer_normalize.c
@@ -19,7 +19,12 @@
 #endif
 
 #include "php_intl.h"
+#if U_ICU_VERSION_MAJOR_NUM < 56
 #include "unicode/unorm.h"
+#endif
+#if U_ICU_VERSION_MAJOR_NUM >= 49
+#include <unicode/unorm2.h>
+#endif
 #include "normalizer.h"
 #include "normalizer_class.h"
 #include "normalizer_normalize.h"
@@ -28,6 +33,70 @@
 #include <unicode/utf8.h>
 #endif
 
+
+#if U_ICU_VERSION_MAJOR_NUM >= 49
+static const UNormalizer2 *intl_get_normalizer(zend_long form, UErrorCode *err)
+{/*{{{*/
+	switch (form)
+	{
+		case NORMALIZER_FORM_C:
+			return unorm2_getNFCInstance(err);
+			break;
+		case NORMALIZER_FORM_D:
+			return unorm2_getNFDInstance(err);
+			break;
+		case NORMALIZER_FORM_KC:
+			return unorm2_getNFKCInstance(err);
+			break;
+		case NORMALIZER_FORM_KD:
+			return unorm2_getNFKDInstance(err);
+			break;
+	}
+
+	*err = U_ILLEGAL_ARGUMENT_ERROR;
+	return NULL;
+}/*}}}*/
+
+static int32_t intl_normalize(zend_long form, const UChar *src, int32_t src_len, UChar *dst, int32_t dst_len, UErrorCode *err)
+{/*{{{*/
+	const UNormalizer2 *norm;
+
+	/* Mimic the behavior of ICU < 56. */
+	if (UNEXPECTED(NORMALIZER_NONE == form)) {
+		/* FIXME This is a noop which should be removed somewhen after PHP 7.3.*/
+		zend_error(E_DEPRECATED, "Normalizer::NONE is obsolete with ICU 56 and above and will be removed in later PHP versions");
+
+		if (dst_len >= src_len) {
+			memmove(dst, src, sizeof(UChar) * src_len);
+			dst[src_len] = '\0';
+			*err = U_ZERO_ERROR;
+			return src_len;
+		}
+
+		*err = U_BUFFER_OVERFLOW_ERROR;
+		return -1;
+	}
+
+	norm = intl_get_normalizer(form, err);
+	if(U_FAILURE(*err)) {
+		return -1;
+	}
+
+	return unorm2_normalize(norm, src, src_len, dst, dst_len, err);
+}/*}}}*/
+
+static UBool intl_is_normalized(zend_long form, const UChar *uinput, int32_t uinput_len, UErrorCode *err)
+{/*{{{*/
+	const UNormalizer2 *norm = intl_get_normalizer(form, err);
+
+	if(U_FAILURE(*err)) {
+		return FALSE;
+	}
+
+	return unorm2_isNormalized(norm, uinput, uinput_len, err);
+}/*}}}*/
+#endif
+
 /* {{{ proto string Normalizer::normalize( string $input [, string $form = FORM_C] )
  * Normalize a string. }}} */
 /* {{{ proto string normalizer_normalize( string $input [, string $form = FORM_C] )
@@ -110,7 +179,11 @@ PHP_FUNCTION( normalizer_normalize )
 	uret_buf = eumalloc( uret_len + 1 );
 
 	/* normalize */
+#if U_ICU_VERSION_MAJOR_NUM < 56
 	size_needed = unorm_normalize( uinput, uinput_len, form, (int32_t) 0 /* options */, uret_buf, uret_len, &status);
+#else
+	size_needed = intl_normalize(form, uinput, uinput_len, uret_buf, uret_len, &status);
+#endif
 
 	/* Bail out if an unexpected error occurred.
 	 * (U_BUFFER_OVERFLOW_ERROR means that *target buffer is not large enough).
@@ -133,7 +206,11 @@ PHP_FUNCTION( normalizer_normalize )
 		status = U_ZERO_ERROR;
 
 		/* try normalize again */
+#if U_ICU_VERSION_MAJOR_NUM < 56
 		size_needed = unorm_normalize( uinput, uinput_len, form, (int32_t) 0 /* options */, uret_buf, uret_len, &status);
+#else
+		size_needed = intl_normalize(form, uinput, uinput_len, uret_buf, uret_len, &status);
+#endif
 
 		/* Bail out if an unexpected error occurred. */
 		if( U_FAILURE(status)  ) {
@@ -167,7 +244,7 @@ PHP_FUNCTION( normalizer_normalize )
 
 /* {{{ proto bool Normalizer::isNormalized( string $input [, string $form = FORM_C] )
  * Test if a string is in a given normalization form. }}} */
-/* {{{ proto bool normalizer_is_normalize( string $input [, string $form = FORM_C] )
+/* {{{ proto bool normalizer_is_normalized( string $input [, string $form = FORM_C] )
  * Test if a string is in a given normalization form.
  */
 PHP_FUNCTION( normalizer_is_normalized )
@@ -232,7 +309,11 @@ PHP_FUNCTION( normalizer_is_normalized )
 
 
 	/* test string */
+#if U_ICU_VERSION_MAJOR_NUM < 56
 	uret = unorm_isNormalizedWithOptions( uinput, uinput_len, form, (int32_t) 0 /* options */, &status);
+#else
+	uret = intl_is_normalized(form, uinput, uinput_len, &status);
+#endif
 
 	efree( uinput );
 
