ICU-21035 Update locale implementation to use ulocimp_getKeywordValue().
diff --git a/icu4c/source/common/locdispnames.cpp b/icu4c/source/common/locdispnames.cpp
index 655c32b..47c0667 100644
--- a/icu4c/source/common/locdispnames.cpp
+++ b/icu4c/source/common/locdispnames.cpp
@@ -26,6 +26,8 @@
 #include "unicode/uloc.h"
 #include "unicode/ures.h"
 #include "unicode/ustring.h"
+#include "bytesinkutil.h"
+#include "charstr.h"
 #include "cmemory.h"
 #include "cstring.h"
 #include "putilimp.h"
@@ -811,10 +813,6 @@
                                UErrorCode* status){
 
 
-    char keywordValue[ULOC_FULLNAME_CAPACITY*4];
-    int32_t capacity = ULOC_FULLNAME_CAPACITY*4;
-    int32_t keywordValueLen =0;
-
     /* argument checking */
     if(status==NULL || U_FAILURE(*status)) {
         return 0;
@@ -826,10 +824,11 @@
     }
 
     /* get the keyword value */
-    keywordValue[0]=0;
-    keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue, capacity, status);
-    if (*status == U_STRING_NOT_TERMINATED_WARNING)
-      *status = U_BUFFER_OVERFLOW_ERROR;
+    CharString keywordValue;
+    {
+        CharStringByteSink sink(&keywordValue);
+        ulocimp_getKeywordValue(locale, keyword, sink, status);
+    }
 
     /* 
      * if the keyword is equal to currency .. then to get the display name 
@@ -845,7 +844,7 @@
         icu::LocalUResourceBundlePointer currencies(
                 ures_getByKey(bundle.getAlias(), _kCurrencies, NULL, status));
         icu::LocalUResourceBundlePointer currency(
-                ures_getByKeyWithFallback(currencies.getAlias(), keywordValue, NULL, status));
+                ures_getByKeyWithFallback(currencies.getAlias(), keywordValue.data(), NULL, status));
 
         dispName = ures_getStringByIndex(currency.getAlias(), UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status);
 
@@ -869,12 +868,12 @@
             }
         }else{
             /* we have not found the display name for the value .. just copy over */
-            if(keywordValueLen <= destCapacity){
-                u_charsToUChars(keywordValue, dest, keywordValueLen);
-                return u_terminateUChars(dest, destCapacity, keywordValueLen, status);
+            if(keywordValue.length() <= destCapacity){
+                u_charsToUChars(keywordValue.data(), dest, keywordValue.length());
+                return u_terminateUChars(dest, destCapacity, keywordValue.length(), status);
             }else{
                  *status = U_BUFFER_OVERFLOW_ERROR;
-                return keywordValueLen;
+                return keywordValue.length();
             }
         }
 
@@ -883,8 +882,8 @@
 
         return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale,
                                    _kTypes, keyword, 
-                                   keywordValue,
-                                   keywordValue,
+                                   keywordValue.data(),
+                                   keywordValue.data(),
                                    dest, destCapacity,
                                    status);
     }
diff --git a/icu4c/source/common/locmap.cpp b/icu4c/source/common/locmap.cpp
index a631134..29a5646 100644
--- a/icu4c/source/common/locmap.cpp
+++ b/icu4c/source/common/locmap.cpp
@@ -28,8 +28,11 @@
  */
 
 #include "locmap.h"
+#include "bytesinkutil.h"
+#include "charstr.h"
 #include "cstring.h"
 #include "cmemory.h"
+#include "ulocimp.h"
 #include "unicode/uloc.h"
 
 #if U_PLATFORM_HAS_WIN32_API && UCONFIG_USE_WINDOWS_LCID_MAPPING_API
@@ -1167,15 +1170,18 @@
     // conversion functionality when available.
 #if U_PLATFORM_HAS_WIN32_API && UCONFIG_USE_WINDOWS_LCID_MAPPING_API
     int32_t len;
-    char collVal[ULOC_KEYWORDS_CAPACITY] = {};
     char baseName[ULOC_FULLNAME_CAPACITY] = {};
     const char * mylocaleID = localeID;
 
     // Check any for keywords.
     if (uprv_strchr(localeID, '@'))
     {
-        len = uloc_getKeywordValue(localeID, "collation", collVal, UPRV_LENGTHOF(collVal) - 1, status);
-        if (U_SUCCESS(*status) && len > 0)
+        icu::CharString collVal;
+        {
+            icu::CharStringByteSink sink(&collVal);
+            ulocimp_getKeywordValue(localeID, "collation", sink, status);
+        }
+        if (U_SUCCESS(*status) && !collVal.isEmpty())
         {
             // If it contains the keyword collation, return 0 so that the LCID lookup table will be used.
             return 0;
diff --git a/icu4c/source/common/uloc.cpp b/icu4c/source/common/uloc.cpp
index 07660d7..42cbe4b 100644
--- a/icu4c/source/common/uloc.cpp
+++ b/icu4c/source/common/uloc.cpp
@@ -1995,22 +1995,22 @@
         // uprv_convertToLCID does not support keywords other than collation.
         // Remove all keywords except collation.
         int32_t len;
-        char collVal[ULOC_KEYWORDS_CAPACITY];
         char tmpLocaleID[ULOC_FULLNAME_CAPACITY];
 
-        len = uloc_getKeywordValue(localeID, "collation", collVal,
-            UPRV_LENGTHOF(collVal) - 1, &status);
+        CharString collVal;
+        {
+            CharStringByteSink sink(&collVal);
+            ulocimp_getKeywordValue(localeID, "collation", sink, &status);
+        }
 
-        if (U_SUCCESS(status) && len > 0) {
-            collVal[len] = 0;
-
+        if (U_SUCCESS(status) && !collVal.isEmpty()) {
             len = uloc_getBaseName(localeID, tmpLocaleID,
                 UPRV_LENGTHOF(tmpLocaleID) - 1, &status);
 
             if (U_SUCCESS(status) && len > 0) {
                 tmpLocaleID[len] = 0;
 
-                len = uloc_setKeywordValue("collation", collVal, tmpLocaleID,
+                len = uloc_setKeywordValue("collation", collVal.data(), tmpLocaleID,
                     UPRV_LENGTHOF(tmpLocaleID) - len - 1, &status);
 
                 if (U_SUCCESS(status) && len > 0) {
diff --git a/icu4c/source/common/uloc_tag.cpp b/icu4c/source/common/uloc_tag.cpp
index 9e93650..b4e3c92 100644
--- a/icu4c/source/common/uloc_tag.cpp
+++ b/icu4c/source/common/uloc_tag.cpp
@@ -15,6 +15,7 @@
 #include "unicode/uenum.h"
 #include "unicode/uloc.h"
 #include "ustr_imp.h"
+#include "bytesinkutil.h"
 #include "charstr.h"
 #include "cmemory.h"
 #include "cstring.h"
@@ -1269,35 +1270,17 @@
         UBool isBcpUExt;
 
         while (TRUE) {
-            icu::CharString buf;
             key = uenum_next(keywordEnum.getAlias(), NULL, status);
             if (key == NULL) {
                 break;
             }
-            char* buffer;
-            int32_t resultCapacity = ULOC_KEYWORD_AND_VALUES_CAPACITY;
 
-            for (;;) {
-                buffer = buf.getAppendBuffer(
-                        /*minCapacity=*/resultCapacity,
-                        /*desiredCapacityHint=*/resultCapacity,
-                        resultCapacity,
-                        tmpStatus);
-
-                if (U_FAILURE(tmpStatus)) {
-                    break;
-                }
-
-                len = uloc_getKeywordValue(
-                        localeID, key, buffer, resultCapacity, &tmpStatus);
-
-                if (tmpStatus != U_BUFFER_OVERFLOW_ERROR) {
-                    break;
-                }
-
-                resultCapacity = len;
-                tmpStatus = U_ZERO_ERROR;
+            icu::CharString buf;
+            {
+                icu::CharStringByteSink sink(&buf);
+                ulocimp_getKeywordValue(localeID, key, sink, &tmpStatus);
             }
+            len = buf.length();
 
             if (U_FAILURE(tmpStatus)) {
                 if (tmpStatus == U_MEMORY_ALLOCATION_ERROR) {
@@ -1313,11 +1296,6 @@
                 continue;
             }
 
-            buf.append(buffer, len, tmpStatus);
-            if (tmpStatus == U_STRING_NOT_TERMINATED_WARNING) {
-                tmpStatus = U_ZERO_ERROR;  // Terminators provided by CharString.
-            }
-
             keylen = (int32_t)uprv_strlen(key);
             isBcpUExt = (keylen > 1);
 
@@ -2707,14 +2685,17 @@
 
                 key = uenum_next(kwdEnum.getAlias(), &len, &tmpStatus);
                 if (len == 1 && *key == PRIVATEUSE) {
-                    char buf[ULOC_KEYWORD_AND_VALUES_CAPACITY];
-                    buf[0] = PRIVATEUSE;
-                    buf[1] = SEP;
-                    len = uloc_getKeywordValue(localeID, key, &buf[2], sizeof(buf) - 2, &tmpStatus);
+                    icu::CharString buf;
+                    {
+                        icu::CharStringByteSink sink(&buf);
+                        ulocimp_getKeywordValue(localeID, key, sink, &tmpStatus);
+                    }
                     if (U_SUCCESS(tmpStatus)) {
-                        if (ultag_isPrivateuseValueSubtags(&buf[2], len)) {
+                        if (ultag_isPrivateuseValueSubtags(buf.data(), buf.length())) {
                             /* return private use only tag */
-                            sink.Append(buf, len + 2);
+                            static const char PREFIX[] = { PRIVATEUSE, SEP };
+                            sink.Append(PREFIX, sizeof(PREFIX));
+                            sink.Append(buf.data(), buf.length());
                             done = TRUE;
                         } else if (strict) {
                             *status = U_ILLEGAL_ARGUMENT_ERROR;