ICU-13778 DataTimePatternGenerator code refactor. Handle Out-of-Memory (OOM) errors, use LocalPointer to prevent memory leaks when OOM occurs, use an internal error code to better report errors during clone and copy construction, mark helper methods and parameters as const, use nullptr instead of NULL, minor spelling and formatting changes. (Note: All tests pass on Windows and Linux).

X-SVN-Rev: 41552
diff --git a/icu4c/source/i18n/dtptngen.cpp b/icu4c/source/i18n/dtptngen.cpp
index aefd704..16e64d7 100644
--- a/icu4c/source/i18n/dtptngen.cpp
+++ b/icu4c/source/i18n/dtptngen.cpp
@@ -18,6 +18,7 @@
 #include "unicode/decimfmt.h"
 #include "unicode/dtfmtsym.h"
 #include "unicode/dtptngen.h"
+#include "unicode/localpointer.h"
 #include "unicode/simpleformatter.h"
 #include "unicode/smpdtfmt.h"
 #include "unicode/udat.h"
@@ -88,17 +89,17 @@
     aiter->num = ures_getSize(aiter->bund);
     aiter->cursor = 0;
 #if !defined(U_SORT_ASCII_BUNDLE_ITERATOR)
-    aiter->entries = NULL;
+    aiter->entries = nullptr;
 #else
     aiter->entries = (UResAEntry*)uprv_malloc(sizeof(UResAEntry)*aiter->num);
     for(int i=0;i<aiter->num;i++) {
-        aiter->entries[i].item = ures_getByIndex(aiter->bund, i, NULL, status);
+        aiter->entries[i].item = ures_getByIndex(aiter->bund, i, nullptr, status);
         const char *akey = ures_getKey(aiter->entries[i].item);
         int32_t len = uprv_strlen(akey)+1;
         aiter->entries[i].key = (UChar*)uprv_malloc(len*sizeof(UChar));
         u_charsToUChars(akey, aiter->entries[i].key, len);
     }
-    uprv_sortArray(aiter->entries, aiter->num, sizeof(UResAEntry), ures_a_codepointSort, NULL, TRUE, status);
+    uprv_sortArray(aiter->entries, aiter->num, sizeof(UResAEntry), ures_a_codepointSort, nullptr, TRUE, status);
 #endif
 }
 
@@ -115,7 +116,7 @@
 #if !defined(U_SORT_ASCII_BUNDLE_ITERATOR)
     return ures_getNextString(aiter->bund, len, key, err);
 #else
-    if(U_FAILURE(*err)) return NULL;
+    if(U_FAILURE(*err)) return nullptr;
     UResourceBundle *item = aiter->entries[aiter->cursor].item;
     const UChar* ret = ures_getString(item, len, err);
     *key = ures_getKey(item);
@@ -302,49 +303,48 @@
 DateTimePatternGenerator* U_EXPORT2
 DateTimePatternGenerator::createInstance(const Locale& locale, UErrorCode& status) {
     if (U_FAILURE(status)) {
-        return NULL;
+        return nullptr;
     }
     LocalPointer<DateTimePatternGenerator> result(
             new DateTimePatternGenerator(locale, status), status);
-    return U_SUCCESS(status) ? result.orphan() : NULL;
+    return U_SUCCESS(status) ? result.orphan() : nullptr;
 }
 
 DateTimePatternGenerator*  U_EXPORT2
 DateTimePatternGenerator::createEmptyInstance(UErrorCode& status) {
-    DateTimePatternGenerator *result = new DateTimePatternGenerator(status);
-    if (result == NULL) {
-        status = U_MEMORY_ALLOCATION_ERROR;
-    }
     if (U_FAILURE(status)) {
-        delete result;
-        result = NULL;
+        return nullptr;
     }
-    return result;
+    LocalPointer<DateTimePatternGenerator> result(
+            new DateTimePatternGenerator(status), status);
+    return U_SUCCESS(status) ? result.orphan() : nullptr;
 }
 
 DateTimePatternGenerator::DateTimePatternGenerator(UErrorCode &status) :
-    skipMatcher(NULL),
-    fAvailableFormatKeyHash(NULL)
+    skipMatcher(nullptr),
+    fAvailableFormatKeyHash(nullptr),
+    internalErrorCode(U_ZERO_ERROR)
 {
     fp = new FormatParser();
     dtMatcher = new DateTimeMatcher();
     distanceInfo = new DistanceInfo();
     patternMap = new PatternMap();
-    if (fp == NULL || dtMatcher == NULL || distanceInfo == NULL || patternMap == NULL) {
-        status = U_MEMORY_ALLOCATION_ERROR;
+    if (fp == nullptr || dtMatcher == nullptr || distanceInfo == nullptr || patternMap == nullptr) {
+        internalErrorCode = status = U_MEMORY_ALLOCATION_ERROR;
     }
 }
 
 DateTimePatternGenerator::DateTimePatternGenerator(const Locale& locale, UErrorCode &status) :
-    skipMatcher(NULL),
-    fAvailableFormatKeyHash(NULL)
+    skipMatcher(nullptr),
+    fAvailableFormatKeyHash(nullptr),
+    internalErrorCode(U_ZERO_ERROR)
 {
     fp = new FormatParser();
     dtMatcher = new DateTimeMatcher();
     distanceInfo = new DistanceInfo();
     patternMap = new PatternMap();
-    if (fp == NULL || dtMatcher == NULL || distanceInfo == NULL || patternMap == NULL) {
-        status = U_MEMORY_ALLOCATION_ERROR;
+    if (fp == nullptr || dtMatcher == nullptr || distanceInfo == nullptr || patternMap == nullptr) {
+        internalErrorCode = status = U_MEMORY_ALLOCATION_ERROR;
     }
     else {
         initData(locale, status);
@@ -353,13 +353,17 @@
 
 DateTimePatternGenerator::DateTimePatternGenerator(const DateTimePatternGenerator& other) :
     UObject(),
-    skipMatcher(NULL),
-    fAvailableFormatKeyHash(NULL)
+    skipMatcher(nullptr),
+    fAvailableFormatKeyHash(nullptr),
+    internalErrorCode(U_ZERO_ERROR)
 {
     fp = new FormatParser();
     dtMatcher = new DateTimeMatcher();
     distanceInfo = new DistanceInfo();
     patternMap = new PatternMap();
+    if (fp == nullptr || dtMatcher == nullptr || distanceInfo == nullptr || patternMap == nullptr) {
+        internalErrorCode = U_MEMORY_ALLOCATION_ERROR;
+    }
     *this=other;
 }
 
@@ -369,6 +373,7 @@
     if (&other == this) {
         return *this;
     }
+    internalErrorCode = other.internalErrorCode;
     pLocale = other.pLocale;
     fDefaultHourFormatChar = other.fDefaultHourFormatChar;
     *fp = *(other.fp);
@@ -380,11 +385,16 @@
     dateTimeFormat.getTerminatedBuffer();
     decimal.getTerminatedBuffer();
     delete skipMatcher;
-    if ( other.skipMatcher == NULL ) {
-        skipMatcher = NULL;
+    if ( other.skipMatcher == nullptr ) {
+        skipMatcher = nullptr;
     }
     else {
         skipMatcher = new DateTimeMatcher(*other.skipMatcher);
+        if (skipMatcher == nullptr)
+        {
+            internalErrorCode = U_MEMORY_ALLOCATION_ERROR;
+            return *this;
+        }
     }
     for (int32_t i=0; i< UDATPG_FIELD_COUNT; ++i ) {
         appendItemFormats[i] = other.appendItemFormats[i];
@@ -394,9 +404,8 @@
             fieldDisplayNames[i][j].getTerminatedBuffer(); // NUL-terminate for the C API.
         }
     }
-    UErrorCode status = U_ZERO_ERROR;
-    patternMap->copyFrom(*other.patternMap, status);
-    copyHashtable(other.fAvailableFormatKeyHash, status);
+    patternMap->copyFrom(*other.patternMap, internalErrorCode);
+    copyHashtable(other.fAvailableFormatKeyHash, internalErrorCode);
     return *this;
 }
 
@@ -431,21 +440,21 @@
 }
 
 DateTimePatternGenerator::~DateTimePatternGenerator() {
-    if (fAvailableFormatKeyHash!=NULL) {
+    if (fAvailableFormatKeyHash!=nullptr) {
         delete fAvailableFormatKeyHash;
     }
 
-    if (fp != NULL) delete fp;
-    if (dtMatcher != NULL) delete dtMatcher;
-    if (distanceInfo != NULL) delete distanceInfo;
-    if (patternMap != NULL) delete patternMap;
-    if (skipMatcher != NULL) delete skipMatcher;
+    if (fp != nullptr) delete fp;
+    if (dtMatcher != nullptr) delete dtMatcher;
+    if (distanceInfo != nullptr) delete distanceInfo;
+    if (patternMap != nullptr) delete patternMap;
+    if (skipMatcher != nullptr) delete skipMatcher;
 }
 
 namespace {
 
 UInitOnce initOnce = U_INITONCE_INITIALIZER;
-UHashtable *localeToAllowedHourFormatsMap = NULL;
+UHashtable *localeToAllowedHourFormatsMap = nullptr;
 
 // Value deleter for hashmap.
 U_CFUNC void U_CALLCONV deleteAllowedHourFormats(void *ptr) {
@@ -474,8 +483,8 @@
 DateTimePatternGenerator::initData(const Locale& locale, UErrorCode &status) {
     //const char *baseLangName = locale.getBaseName(); // unused
 
-    skipMatcher = NULL;
-    fAvailableFormatKeyHash=NULL;
+    skipMatcher = nullptr;
+    fAvailableFormatKeyHash=nullptr;
     addCanonicalItems(status);
     addICUPatterns(locale, status);
     addCLDRData(locale, status);
@@ -483,6 +492,8 @@
     setDecimalSymbols(locale, status);
     umtx_initOnce(initOnce, loadAllowedHourFormatsData, status);
     getAllowedHourFormats(locale, status);
+    // If any of the above methods failed then the object is in an invalid state.
+    internalErrorCode = status;
 } // DateTimePatternGenerator::initData
 
 namespace {
@@ -505,7 +516,7 @@
                     LocalMemory<int32_t> list;
                     int32_t length;
                     if (value.getType() == URES_STRING) {
-                        if (list.allocateInsteadAndReset(2) == NULL) {
+                        if (list.allocateInsteadAndReset(2) == nullptr) {
                             errorCode = U_MEMORY_ALLOCATION_ERROR;
                             return;
                         }
@@ -515,7 +526,7 @@
                     else {
                         ResourceArray allowedFormats = value.getArray(errorCode);
                         length = allowedFormats.getSize();
-                        if (list.allocateInsteadAndReset(length + 1) == NULL) {
+                        if (list.allocateInsteadAndReset(length + 1) == nullptr) {
                             errorCode = U_MEMORY_ALLOCATION_ERROR;
                             return;
                         }
@@ -555,9 +566,14 @@
 U_CFUNC void U_CALLCONV DateTimePatternGenerator::loadAllowedHourFormatsData(UErrorCode &status) {
     if (U_FAILURE(status)) { return; }
     localeToAllowedHourFormatsMap = uhash_open(
-        uhash_hashChars, uhash_compareChars, NULL, &status);
+        uhash_hashChars, uhash_compareChars, nullptr, &status);
+    if (U_FAILURE(status)) { return; }
+
     uhash_setValueDeleter(localeToAllowedHourFormatsMap, deleteAllowedHourFormats);
-    LocalUResourceBundlePointer rb(ures_openDirect(NULL, "supplementalData", &status));
+    ucln_i18n_registerCleanup(UCLN_I18N_ALLOWED_HOUR_FORMATS, allowedHourFormatsCleanup);
+
+    LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "supplementalData", &status));
+    if (U_FAILURE(status)) { return; }
 
     AllowedHourFormatsSink sink;
     // TODO: Currently in the enumeration each table allocates a new array.
@@ -566,9 +582,7 @@
     // into the hashmap, store 6 single-value sub-arrays right at the beginning of the
     // vector (at index enum*2) for easy data sharing, copy sub-arrays into runtime
     // object. Remember to clean up the vector, too.
-    ures_getAllItemsWithFallback(rb.getAlias(), "timeData", sink, status);
-
-    ucln_i18n_registerCleanup(UCLN_I18N_ALLOWED_HOUR_FORMATS, allowedHourFormatsCleanup);
+    ures_getAllItemsWithFallback(rb.getAlias(), "timeData", sink, status);    
 }
 
 void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErrorCode &status) {
@@ -589,17 +603,17 @@
     const char *language = maxLocale.getLanguage();
 
     CharString langCountry;
-    langCountry.append(language, uprv_strlen(language), status);
+    langCountry.append(language, static_cast<int32_t>(uprv_strlen(language)), status);
     langCountry.append('_', status);
-    langCountry.append(country, uprv_strlen(country), status);
+    langCountry.append(country, static_cast<int32_t>(uprv_strlen(country)), status);
 
     int32_t *allowedFormats;
     allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, langCountry.data());
-    if (allowedFormats == NULL) {
+    if (allowedFormats == nullptr) {
         allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, const_cast<char *>(country));
     }
 
-    if (allowedFormats != NULL) {  // Lookup is successful
+    if (allowedFormats != nullptr) {  // Lookup is successful
         for (int32_t i = 0; i < UPRV_LENGTHOF(fAllowedHourFormats); ++i) {
             fAllowedHourFormats[i] = allowedFormats[i];
             if (allowedFormats[i] == ALLOWED_HOUR_FORMAT_UNKNOWN) {
@@ -663,7 +677,7 @@
         DateFormat::EStyle style = (DateFormat::EStyle)i;
         df = DateFormat::createDateInstance(style, locale);
         SimpleDateFormat* sdf;
-        if (df != NULL && (sdf = dynamic_cast<SimpleDateFormat*>(df)) != NULL) {
+        if (df != nullptr && (sdf = dynamic_cast<SimpleDateFormat*>(df)) != nullptr) {
             sdf->toPattern(dfPattern);
             addPattern(dfPattern, FALSE, conflictingString, status);
         }
@@ -672,7 +686,7 @@
         if (U_FAILURE(status)) { return; }
 
         df = DateFormat::createTimeInstance(style, locale);
-        if (df != NULL && (sdf = dynamic_cast<SimpleDateFormat*>(df)) != NULL) {
+        if (df != nullptr && (sdf = dynamic_cast<SimpleDateFormat*>(df)) != nullptr) {
             sdf->toPattern(dfPattern);
             addPattern(dfPattern, FALSE, conflictingString, status);
 
@@ -747,13 +761,14 @@
         ures_getFunctionalEquivalent(
             localeWithCalendarKey,
             ULOC_LOCALE_IDENTIFIER_CAPACITY,
-            NULL,
+            nullptr,
             "calendar",
             "calendar",
             locale.getName(),
-            NULL,
+            nullptr,
             FALSE,
             &err);
+        if (U_FAILURE(err)) { return; }
         localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
         // now get the calendar key value from that locale
         char calendarType[ULOC_KEYWORDS_CAPACITY];
@@ -763,7 +778,8 @@
             calendarType,
             ULOC_KEYWORDS_CAPACITY,
             &err);
-        if (U_SUCCESS(err) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
+        if (U_FAILURE(err)) { return; }
+        if (calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
             destination.clear().append(calendarType, -1, err);
             if (U_FAILURE(err)) { return; }
         }
@@ -774,7 +790,7 @@
 void
 DateTimePatternGenerator::consumeShortTimePattern(const UnicodeString& shortTimePattern,
         UErrorCode& status) {
-
+    if (U_FAILURE(status)) { return; }
     // set fDefaultHourFormatChar to the hour format character from this pattern
     int32_t tfIdx, tfLen = shortTimePattern.length();
     UBool ignoreChars = FALSE;
@@ -782,7 +798,7 @@
         UChar tfChar = shortTimePattern.charAt(tfIdx);
         if ( tfChar == SINGLE_QUOTE ) {
             ignoreChars = !ignoreChars; // toggle (handle quoted literals & '' for single quote)
-        } else if ( !ignoreChars && u_strchr(hourFormatChars, tfChar) != NULL ) {
+        } else if ( !ignoreChars && u_strchr(hourFormatChars, tfChar) != nullptr ) {
             fDefaultHourFormatChar = tfChar;
             break;
         }
@@ -921,7 +937,7 @@
     UnicodeString rbPattern, value, field;
     CharString path;
 
-    LocalUResourceBundlePointer rb(ures_open(NULL, locale.getName(), &errorCode));
+    LocalUResourceBundlePointer rb(ures_open(nullptr, locale.getName(), &errorCode));
     if (U_FAILURE(errorCode)) { return; }
 
     CharString calendarTypeToUse; // to be filled in with the type to use, if all goes well
@@ -966,12 +982,13 @@
 
 void
 DateTimePatternGenerator::initHashtable(UErrorCode& err) {
-    if (fAvailableFormatKeyHash!=NULL) {
+    if (U_FAILURE(err)) { return; }
+    if (fAvailableFormatKeyHash!=nullptr) {
         return;
     }
-    if ((fAvailableFormatKeyHash = new Hashtable(FALSE, err))==NULL) {
-        err=U_MEMORY_ALLOCATION_ERROR;
-        return;
+    LocalPointer<Hashtable> hash(new Hashtable(FALSE, err), err);
+    if (U_SUCCESS(err)) {
+        fAvailableFormatKeyHash = hash.orphan();
     }
 }
 
@@ -1028,7 +1045,14 @@
 
 UnicodeString
 DateTimePatternGenerator::getBestPattern(const UnicodeString& patternForm, UDateTimePatternMatchOptions options, UErrorCode& status) {
-    const UnicodeString *bestPattern=NULL;
+    if (U_FAILURE(status)) {
+        return UnicodeString();
+    }
+    if (U_FAILURE(internalErrorCode)) {
+        status = internalErrorCode;
+        return UnicodeString();
+    }
+    const UnicodeString *bestPattern = nullptr;
     UnicodeString dtFormat;
     UnicodeString resultPattern;
     int32_t flags = kDTPGNoFlags;
@@ -1044,16 +1068,23 @@
 
     resultPattern.remove();
     dtMatcher->set(patternFormMapped, fp);
-    const PtnSkeleton* specifiedSkeleton=NULL;
-    bestPattern=getBestRaw(*dtMatcher, -1, distanceInfo, &specifiedSkeleton);
+    const PtnSkeleton* specifiedSkeleton = nullptr;
+    bestPattern=getBestRaw(*dtMatcher, -1, distanceInfo, status, &specifiedSkeleton);
+    if (U_FAILURE(status)) {
+        return UnicodeString();
+    }
+
     if ( distanceInfo->missingFieldMask==0 && distanceInfo->extraFieldMask==0 ) {
         resultPattern = adjustFieldTypes(*bestPattern, specifiedSkeleton, flags, options);
 
         return resultPattern;
     }
     int32_t neededFields = dtMatcher->getFieldMask();
-    UnicodeString datePattern=getBestAppending(neededFields & dateMask, flags, options);
-    UnicodeString timePattern=getBestAppending(neededFields & timeMask, flags, options);
+    UnicodeString datePattern=getBestAppending(neededFields & dateMask, flags, status, options);
+    UnicodeString timePattern=getBestAppending(neededFields & timeMask, flags, status, options);
+    if (U_FAILURE(status)) {
+        return UnicodeString();
+    }
     if (datePattern.length()==0) {
         if (timePattern.length()==0) {
             resultPattern.remove();
@@ -1074,7 +1105,7 @@
 
 /*
  * Map a skeleton that may have metacharacters jJC to one without, by replacing
- * the metacharacters with locale-appropriate fields of of h/H/k/K and of a/b/B
+ * the metacharacters with locale-appropriate fields of h/H/k/K and of a/b/B
  * (depends on fDefaultHourFormatChar and fAllowedHourFormats being set, which in
  * turn depends on initData having been run). This method also updates the flags
  * as necessary. Returns the updated skeleton.
@@ -1159,9 +1190,16 @@
 DateTimePatternGenerator::replaceFieldTypes(const UnicodeString& pattern,
                                             const UnicodeString& skeleton,
                                             UDateTimePatternMatchOptions options,
-                                            UErrorCode& /*status*/) {
+                                            UErrorCode& status) {
+    if (U_FAILURE(status)) {
+        return UnicodeString();
+    }
+    if (U_FAILURE(internalErrorCode)) {
+        status = internalErrorCode;
+        return UnicodeString();
+    }
     dtMatcher->set(skeleton, fp);
-    UnicodeString result = adjustFieldTypes(pattern, NULL, kDTPGNoFlags, options);
+    UnicodeString result = adjustFieldTypes(pattern, nullptr, kDTPGNoFlags, options);
     return result;
 }
 
@@ -1204,20 +1242,24 @@
 
 void
 DateTimePatternGenerator::setDateTimeFromCalendar(const Locale& locale, UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
+
     const UChar *resStr;
     int32_t resStrLen = 0;
 
-    Calendar* fCalendar = Calendar::createInstance(locale, status);
+    LocalPointer<Calendar> fCalendar(Calendar::createInstance(locale, status), status);
     if (U_FAILURE(status)) { return; }
 
-    LocalUResourceBundlePointer calData(ures_open(NULL, locale.getBaseName(), &status));
+    LocalUResourceBundlePointer calData(ures_open(nullptr, locale.getBaseName(), &status));
+    if (U_FAILURE(status)) { return; }
     ures_getByKey(calData.getAlias(), DT_DateTimeCalendarTag, calData.getAlias(), &status);
+    if (U_FAILURE(status)) { return; }
 
     LocalUResourceBundlePointer dateTimePatterns;
-    if (fCalendar != NULL && fCalendar->getType() != NULL && *fCalendar->getType() != '\0'
+    if (fCalendar->getType() != nullptr && *fCalendar->getType() != '\0'
             && uprv_strcmp(fCalendar->getType(), DT_DateTimeGregorianTag) != 0) {
         dateTimePatterns.adoptInstead(ures_getByKeyWithFallback(calData.getAlias(), fCalendar->getType(),
-                                                                NULL, &status));
+                                                                nullptr, &status));
         ures_getByKeyWithFallback(dateTimePatterns.getAlias(), DT_DateTimePatternsTag,
                                   dateTimePatterns.getAlias(), &status);
     }
@@ -1238,8 +1280,6 @@
     }
     resStr = ures_getStringByIndex(dateTimePatterns.getAlias(), (int32_t)DateFormat::kDateTime, &resStrLen, &status);
     setDateTimeFormat(UnicodeString(TRUE, resStr, resStrLen));
-
-    delete fCalendar;
 }
 
 void
@@ -1259,7 +1299,12 @@
     UnicodeString &conflictingPattern,
     UErrorCode& status)
 {
-    return addPatternWithSkeleton(pattern, NULL, override, conflictingPattern, status);
+    if (U_FAILURE(internalErrorCode)) {
+        status = internalErrorCode;
+        return UDATPG_NO_CONFLICT;
+    }
+
+    return addPatternWithSkeleton(pattern, nullptr, override, conflictingPattern, status);
 }
 
 // For DateTimePatternGenerator::addPatternWithSkeleton -
@@ -1280,13 +1325,17 @@
     UnicodeString& conflictingPattern,
     UErrorCode& status)
 {
+    if (U_FAILURE(internalErrorCode)) {
+        status = internalErrorCode;
+        return UDATPG_NO_CONFLICT;
+    }
 
     UnicodeString basePattern;
     PtnSkeleton   skeleton;
     UDateTimePatternConflict conflictingStatus = UDATPG_NO_CONFLICT;
 
     DateTimeMatcher matcher;
-    if ( skeletonToUse == NULL ) {
+    if ( skeletonToUse == nullptr ) {
         matcher.set(pattern, fp, skeleton);
         matcher.getBasePattern(basePattern);
     } else {
@@ -1302,7 +1351,7 @@
     // availableFormats items from root, which should not override any previous entry with the same base.
     UBool entryHadSpecifiedSkeleton;
     const UnicodeString *duplicatePattern = patternMap->getPatternFromBasePattern(basePattern, entryHadSpecifiedSkeleton);
-    if (duplicatePattern != NULL && (!entryHadSpecifiedSkeleton || (skeletonToUse != NULL && !override))) {
+    if (duplicatePattern != nullptr && (!entryHadSpecifiedSkeleton || (skeletonToUse != nullptr && !override))) {
         conflictingStatus = UDATPG_BASE_CONFLICT;
         conflictingPattern = *duplicatePattern;
         if (!override) {
@@ -1313,16 +1362,16 @@
     // items from CLDR data. In that case, we don't want an item from a parent locale to replace an item with
     // same skeleton from the specified locale, so skip the current item if skeletonWasSpecified is true for
     // the previously-specified conflicting item.
-    const PtnSkeleton* entrySpecifiedSkeleton = NULL;
+    const PtnSkeleton* entrySpecifiedSkeleton = nullptr;
     duplicatePattern = patternMap->getPatternFromSkeleton(skeleton, &entrySpecifiedSkeleton);
-    if (duplicatePattern != NULL ) {
+    if (duplicatePattern != nullptr ) {
         conflictingStatus = UDATPG_CONFLICT;
         conflictingPattern = *duplicatePattern;
-        if (!override || (skeletonToUse != NULL && entrySpecifiedSkeleton != NULL)) {
+        if (!override || (skeletonToUse != nullptr && entrySpecifiedSkeleton != nullptr)) {
             return conflictingStatus;
         }
     }
-    patternMap->add(basePattern, skeleton, pattern, skeletonToUse != NULL, status);
+    patternMap->add(basePattern, skeleton, pattern, skeletonToUse != nullptr, status);
     if(U_FAILURE(status)) {
         return conflictingStatus;
     }
@@ -1369,13 +1418,16 @@
 DateTimePatternGenerator::getBestRaw(DateTimeMatcher& source,
                                      int32_t includeMask,
                                      DistanceInfo* missingFields,
+                                     UErrorCode &status,
                                      const PtnSkeleton** specifiedSkeletonPtr) {
     int32_t bestDistance = 0x7fffffff;
     DistanceInfo tempInfo;
-    const UnicodeString *bestPattern=NULL;
-    const PtnSkeleton* specifiedSkeleton=NULL;
+    const UnicodeString *bestPattern=nullptr;
+    const PtnSkeleton* specifiedSkeleton=nullptr;
 
-    PatternMapIterator it;
+    PatternMapIterator it(status);
+    if (U_FAILURE(status)) { return nullptr; }
+
     for (it.set(*patternMap); it.hasNext(); ) {
         DateTimeMatcher trial = it.next();
         if (trial.equals(skipMatcher)) {
@@ -1485,8 +1537,8 @@
                         c = fDefaultHourFormatChar;
                     }
                     field.remove();
-                    for (int32_t i=adjFieldLen; i>0; --i) {
-                        field+=c;
+                    for (int32_t j=adjFieldLen; j>0; --j) {
+                        field += c;
                     }
             }
             newPattern+=field;
@@ -1496,14 +1548,21 @@
 }
 
 UnicodeString
-DateTimePatternGenerator::getBestAppending(int32_t missingFields, int32_t flags, UDateTimePatternMatchOptions options) {
+DateTimePatternGenerator::getBestAppending(int32_t missingFields, int32_t flags, UErrorCode &status, UDateTimePatternMatchOptions options) {
+    if (U_FAILURE(status)) {
+        return UnicodeString();
+    }
     UnicodeString  resultPattern, tempPattern;
-    UErrorCode err=U_ZERO_ERROR;
+    const UnicodeString* tempPatternPtr;
     int32_t lastMissingFieldMask=0;
     if (missingFields!=0) {
         resultPattern=UnicodeString();
-        const PtnSkeleton* specifiedSkeleton=NULL;
-        tempPattern = *getBestRaw(*dtMatcher, missingFields, distanceInfo, &specifiedSkeleton);
+        const PtnSkeleton* specifiedSkeleton=nullptr;
+        tempPatternPtr = getBestRaw(*dtMatcher, missingFields, distanceInfo, status, &specifiedSkeleton);
+        if (U_FAILURE(status)) {
+            return UnicodeString();
+        }
+        tempPattern = *tempPatternPtr;
         resultPattern = adjustFieldTypes(tempPattern, specifiedSkeleton, flags, options);
         if ( distanceInfo->missingFieldMask==0 ) {
             return resultPattern;
@@ -1519,19 +1578,26 @@
                 continue;
             }
             int32_t startingMask = distanceInfo->missingFieldMask;
-            tempPattern = *getBestRaw(*dtMatcher, distanceInfo->missingFieldMask, distanceInfo, &specifiedSkeleton);
+            tempPatternPtr = getBestRaw(*dtMatcher, distanceInfo->missingFieldMask, distanceInfo, status, &specifiedSkeleton);
+            if (U_FAILURE(status)) {
+                return UnicodeString();
+            }
+            tempPattern = *tempPatternPtr;
             tempPattern = adjustFieldTypes(tempPattern, specifiedSkeleton, flags, options);
             int32_t foundMask=startingMask& ~distanceInfo->missingFieldMask;
             int32_t topField=getTopBitNumber(foundMask);
-            UnicodeString appendName;
-            getAppendName((UDateTimePatternField)topField, appendName);
-            const UnicodeString *values[3] = {
-                &resultPattern,
-                &tempPattern,
-                &appendName
-            };
-            SimpleFormatter(appendItemFormats[topField], 2, 3, err).
-                    formatAndReplace(values, 3, resultPattern, NULL, 0, err);
+
+            if (appendItemFormats[topField].length() != 0) {
+                UnicodeString appendName;
+                getAppendName((UDateTimePatternField)topField, appendName);
+                const UnicodeString *values[3] = {
+                    &resultPattern,
+                    &tempPattern,
+                    &appendName
+                };
+                SimpleFormatter(appendItemFormats[topField], 2, 3, status).
+                    formatAndReplace(values, 3, resultPattern, nullptr, 0, status);
+            }
             lastMissingFieldMask = distanceInfo->missingFieldMask;
         }
     }
@@ -1539,7 +1605,7 @@
 }
 
 int32_t
-DateTimePatternGenerator::getTopBitNumber(int32_t foundMask) {
+DateTimePatternGenerator::getTopBitNumber(int32_t foundMask) const {
     if ( foundMask==0 ) {
         return 0;
     }
@@ -1568,22 +1634,21 @@
 
 void
 DateTimePatternGenerator::copyHashtable(Hashtable *other, UErrorCode &status) {
-
-    if (other == NULL) {
+    if (other == nullptr || U_FAILURE(status)) {
         return;
     }
-    if (fAvailableFormatKeyHash != NULL) {
+    if (fAvailableFormatKeyHash != nullptr) {
         delete fAvailableFormatKeyHash;
-        fAvailableFormatKeyHash = NULL;
+        fAvailableFormatKeyHash = nullptr;
     }
     initHashtable(status);
     if(U_FAILURE(status)){
         return;
     }
     int32_t pos = UHASH_FIRST;
-    const UHashElement* elem = NULL;
+    const UHashElement* elem = nullptr;
     // walk through the hash table and create a deep clone
-    while((elem = other->nextElement(pos))!= NULL){
+    while((elem = other->nextElement(pos))!= nullptr){
         const UHashTok otherKeyTok = elem->key;
         UnicodeString* otherKey = (UnicodeString*)otherKeyTok.pointer;
         fAvailableFormatKeyHash->puti(*otherKey, 1, status);
@@ -1595,8 +1660,17 @@
 
 StringEnumeration*
 DateTimePatternGenerator::getSkeletons(UErrorCode& status) const {
-    StringEnumeration* skeletonEnumerator = new DTSkeletonEnumeration(*patternMap, DT_SKELETON, status);
-    return skeletonEnumerator;
+    if (U_FAILURE(status)) {
+        return nullptr;
+    }
+    if (U_FAILURE(internalErrorCode)) {
+        status = internalErrorCode;
+        return nullptr;
+    }
+    LocalPointer<StringEnumeration> skeletonEnumerator(
+        new DTSkeletonEnumeration(*patternMap, DT_SKELETON, status), status);
+
+    return U_SUCCESS(status) ? skeletonEnumerator.orphan() : nullptr;
 }
 
 const UnicodeString&
@@ -1607,47 +1681,70 @@
         return emptyString;
     }
     curElem = patternMap->getHeader(skeleton.charAt(0));
-    while ( curElem != NULL ) {
+    while ( curElem != nullptr ) {
         if ( curElem->skeleton->getSkeleton()==skeleton ) {
             return curElem->pattern;
         }
-        curElem=curElem->next;
+        curElem = curElem->next.getAlias();
     }
     return emptyString;
 }
 
 StringEnumeration*
 DateTimePatternGenerator::getBaseSkeletons(UErrorCode& status) const {
-    StringEnumeration* baseSkeletonEnumerator = new DTSkeletonEnumeration(*patternMap, DT_BASESKELETON, status);
-    return baseSkeletonEnumerator;
+    if (U_FAILURE(status)) {
+        return nullptr;
+    }
+    if (U_FAILURE(internalErrorCode)) {
+        status = internalErrorCode;
+        return nullptr;
+    }
+    LocalPointer<StringEnumeration> baseSkeletonEnumerator(
+        new DTSkeletonEnumeration(*patternMap, DT_BASESKELETON, status), status);
+
+    return U_SUCCESS(status) ? baseSkeletonEnumerator.orphan() : nullptr;
 }
 
 StringEnumeration*
 DateTimePatternGenerator::getRedundants(UErrorCode& status) {
-    StringEnumeration* output = new DTRedundantEnumeration();
+    if (U_FAILURE(status)) { return nullptr; }
+    if (U_FAILURE(internalErrorCode)) {
+        status = internalErrorCode;
+        return nullptr;
+    }
+    LocalPointer<StringEnumeration> output(new DTRedundantEnumeration(), status);
+    if (U_FAILURE(status)) { return nullptr; }
     const UnicodeString *pattern;
-    PatternMapIterator it;
+    PatternMapIterator it(status);
+    if (U_FAILURE(status)) { return nullptr; }
+
     for (it.set(*patternMap); it.hasNext(); ) {
         DateTimeMatcher current = it.next();
         pattern = patternMap->getPatternFromSkeleton(*(it.getSkeleton()));
         if ( isCanonicalItem(*pattern) ) {
             continue;
         }
-        if ( skipMatcher == NULL ) {
+        if ( skipMatcher == nullptr ) {
             skipMatcher = new DateTimeMatcher(current);
+            if (skipMatcher == nullptr) {
+                status = U_MEMORY_ALLOCATION_ERROR;
+                return nullptr;
+            }
         }
         else {
             *skipMatcher = current;
         }
         UnicodeString trial = getBestPattern(current.getPattern(), status);
+        if (U_FAILURE(status)) { return nullptr; }
         if (trial == *pattern) {
-            ((DTRedundantEnumeration *)output)->add(*pattern, status);
+            ((DTRedundantEnumeration *)output.getAlias())->add(*pattern, status);
+            if (U_FAILURE(status)) { return nullptr; }
         }
         if (current.equals(skipMatcher)) {
             continue;
         }
     }
-    return output;
+    return output.orphan();
 }
 
 UBool
@@ -1671,45 +1768,54 @@
 
 PatternMap::PatternMap() {
    for (int32_t i=0; i < MAX_PATTERN_ENTRIES; ++i ) {
-      boot[i]=NULL;
+       boot[i] = nullptr;
    }
    isDupAllowed = TRUE;
 }
 
 void
 PatternMap::copyFrom(const PatternMap& other, UErrorCode& status) {
+    if (U_FAILURE(status)) {
+        return;
+    }
     this->isDupAllowed = other.isDupAllowed;
-    for (int32_t bootIndex=0; bootIndex<MAX_PATTERN_ENTRIES; ++bootIndex ) {
-        PtnElem *curElem, *otherElem, *prevElem=NULL;
+    for (int32_t bootIndex = 0; bootIndex < MAX_PATTERN_ENTRIES; ++bootIndex) {
+        PtnElem *curElem, *otherElem, *prevElem=nullptr;
         otherElem = other.boot[bootIndex];
-        while (otherElem!=NULL) {
-            if ((curElem = new PtnElem(otherElem->basePattern, otherElem->pattern))==NULL) {
-                // out of memory
-                status = U_MEMORY_ALLOCATION_ERROR;
-                return;
+        while (otherElem != nullptr) {
+            LocalPointer<PtnElem> newElem(new PtnElem(otherElem->basePattern, otherElem->pattern), status);
+            if (U_FAILURE(status)) {
+                return; // out of memory
             }
-            if ( this->boot[bootIndex]== NULL ) {
+            newElem->skeleton.adoptInsteadAndCheckErrorCode(new PtnSkeleton(*(otherElem->skeleton)), status);
+            if (U_FAILURE(status)) {
+                return; // out of memory
+            }
+            newElem->skeletonWasSpecified = otherElem->skeletonWasSpecified;
+
+            // Release ownership from the LocalPointer of the PtnElem object.
+            // The PtnElem will now be owned by either the boot (for the first entry in the linked-list)
+            // or owned by the previous PtnElem object in the linked-list.
+            curElem = newElem.orphan();
+
+            if (this->boot[bootIndex] == nullptr) {
                 this->boot[bootIndex] = curElem;
+            } else {
+                if (prevElem != nullptr) {
+                    prevElem->next.adoptInstead(curElem);
+                } else {
+                    U_ASSERT(false);
+                }
             }
-            if ((curElem->skeleton=new PtnSkeleton(*(otherElem->skeleton))) == NULL ) {
-                // out of memory
-                status = U_MEMORY_ALLOCATION_ERROR;
-                return;
-            }
-            curElem->skeletonWasSpecified = otherElem->skeletonWasSpecified;
-            if (prevElem!=NULL) {
-                prevElem->next=curElem;
-            }
-            curElem->next=NULL;
             prevElem = curElem;
-            otherElem = otherElem->next;
+            otherElem = otherElem->next.getAlias();
         }
 
     }
 }
 
 PtnElem*
-PatternMap::getHeader(UChar baseChar) {
+PatternMap::getHeader(UChar baseChar) const {
     PtnElem* curElem;
 
     if ( (baseChar >= CAP_A) && (baseChar <= CAP_Z) ) {
@@ -1720,7 +1826,7 @@
             curElem = boot[26+baseChar-LOW_A];
         }
         else {
-            return NULL;
+            return nullptr;
         }
     }
     return curElem;
@@ -1728,9 +1834,9 @@
 
 PatternMap::~PatternMap() {
    for (int32_t i=0; i < MAX_PATTERN_ENTRIES; ++i ) {
-       if (boot[i]!=NULL ) {
+       if (boot[i] != nullptr ) {
            delete boot[i];
-           boot[i]=NULL;
+           boot[i] = nullptr;
        }
    }
 }  // PatternMap destructor
@@ -1759,39 +1865,45 @@
          }
     }
 
-    if (baseElem == NULL) {
-        if ((curElem = new PtnElem(basePattern, value)) == NULL ) {
-            // out of memory
-            status = U_MEMORY_ALLOCATION_ERROR;
-            return;
+    if (baseElem == nullptr) {
+        LocalPointer<PtnElem> newElem(new PtnElem(basePattern, value), status);
+        if (U_FAILURE(status)) {
+            return; // out of memory
         }
+        newElem->skeleton.adoptInsteadAndCheckErrorCode(new PtnSkeleton(skeleton), status);
+        if (U_FAILURE(status)) {
+            return; // out of memory
+        }
+        newElem->skeletonWasSpecified = skeletonWasSpecified;
         if (baseChar >= LOW_A) {
-            boot[26 + (baseChar-LOW_A)] = curElem;
+            boot[26 + (baseChar - LOW_A)] = newElem.orphan(); // the boot array now owns the PtnElem.
         }
         else {
-            boot[baseChar-CAP_A] = curElem;
+            boot[baseChar - CAP_A] = newElem.orphan(); // the boot array now owns the PtnElem.
         }
-        curElem->skeleton = new PtnSkeleton(skeleton);
-        curElem->skeletonWasSpecified = skeletonWasSpecified;
     }
-    if ( baseElem != NULL ) {
+    if ( baseElem != nullptr ) {
         curElem = getDuplicateElem(basePattern, skeleton, baseElem);
 
-        if (curElem == NULL) {
+        if (curElem == nullptr) {
             // add new element to the list.
             curElem = baseElem;
-            while( curElem -> next != NULL )
+            while( curElem -> next != nullptr )
             {
-                curElem = curElem->next;
+                curElem = curElem->next.getAlias();
             }
-            if ((curElem->next = new PtnElem(basePattern, value)) == NULL ) {
-                // out of memory
-                status = U_MEMORY_ALLOCATION_ERROR;
-                return;
+
+            LocalPointer<PtnElem> newElem(new PtnElem(basePattern, value), status);
+            if (U_FAILURE(status)) {
+                return; // out of memory
             }
-            curElem=curElem->next;
-            curElem->skeleton = new PtnSkeleton(skeleton);
-            curElem->skeletonWasSpecified = skeletonWasSpecified;
+            newElem->skeleton.adoptInsteadAndCheckErrorCode(new PtnSkeleton(skeleton), status);
+            if (U_FAILURE(status)) {
+                return; // out of memory
+            }
+            newElem->skeletonWasSpecified = skeletonWasSpecified;
+            curElem->next.adoptInstead(newElem.orphan());
+            curElem = curElem->next.getAlias();
         }
         else {
             // Pattern exists in the list already.
@@ -1809,11 +1921,11 @@
 
 // Find the pattern from the given basePattern string.
 const UnicodeString *
-PatternMap::getPatternFromBasePattern(UnicodeString& basePattern, UBool& skeletonWasSpecified) { // key to search for
+PatternMap::getPatternFromBasePattern(const UnicodeString& basePattern, UBool& skeletonWasSpecified) const { // key to search for
    PtnElem *curElem;
 
-   if ((curElem=getHeader(basePattern.charAt(0)))==NULL) {
-       return NULL;  // no match
+   if ((curElem=getHeader(basePattern.charAt(0)))==nullptr) {
+       return nullptr;  // no match
    }
 
    do  {
@@ -1821,10 +1933,10 @@
           skeletonWasSpecified = curElem->skeletonWasSpecified;
           return &(curElem->pattern);
        }
-       curElem=curElem->next;
-   }while (curElem != NULL);
+       curElem = curElem->next.getAlias();
+   } while (curElem != nullptr);
 
-   return NULL;
+   return nullptr;
 }  // PatternMap::getFromBasePattern
 
 
@@ -1835,69 +1947,69 @@
 // optimum distance value in getBestRaw. When this is called from public getRedundants (specifiedSkeletonPtr is NULL),
 // for now it will continue to compare based on baseOriginal so as not to change the behavior unnecessarily.
 const UnicodeString *
-PatternMap::getPatternFromSkeleton(PtnSkeleton& skeleton, const PtnSkeleton** specifiedSkeletonPtr) { // key to search for
+PatternMap::getPatternFromSkeleton(const PtnSkeleton& skeleton, const PtnSkeleton** specifiedSkeletonPtr) const { // key to search for
    PtnElem *curElem;
 
    if (specifiedSkeletonPtr) {
-       *specifiedSkeletonPtr = NULL;
+       *specifiedSkeletonPtr = nullptr;
    }
 
    // find boot entry
    UChar baseChar = skeleton.getFirstChar();
-   if ((curElem=getHeader(baseChar))==NULL) {
-       return NULL;  // no match
+   if ((curElem=getHeader(baseChar))==nullptr) {
+       return nullptr;  // no match
    }
 
    do  {
        UBool equal;
-       if (specifiedSkeletonPtr != NULL) { // called from DateTimePatternGenerator::getBestRaw or addPattern, use original
+       if (specifiedSkeletonPtr != nullptr) { // called from DateTimePatternGenerator::getBestRaw or addPattern, use original
            equal = curElem->skeleton->original == skeleton.original;
        } else { // called from DateTimePatternGenerator::getRedundants, use baseOriginal
            equal = curElem->skeleton->baseOriginal == skeleton.baseOriginal;
        }
        if (equal) {
            if (specifiedSkeletonPtr && curElem->skeletonWasSpecified) {
-               *specifiedSkeletonPtr = curElem->skeleton;
+               *specifiedSkeletonPtr = curElem->skeleton.getAlias();
            }
            return &(curElem->pattern);
        }
-       curElem=curElem->next;
-   }while (curElem != NULL);
+       curElem = curElem->next.getAlias();
+   } while (curElem != nullptr);
 
-   return NULL;
+   return nullptr;
 }
 
 UBool
-PatternMap::equals(const PatternMap& other) {
+PatternMap::equals(const PatternMap& other) const {
     if ( this==&other ) {
         return TRUE;
     }
-    for (int32_t bootIndex=0; bootIndex<MAX_PATTERN_ENTRIES; ++bootIndex ) {
-        if ( boot[bootIndex]==other.boot[bootIndex] ) {
+    for (int32_t bootIndex = 0; bootIndex < MAX_PATTERN_ENTRIES; ++bootIndex) {
+        if (boot[bootIndex] == other.boot[bootIndex]) {
             continue;
         }
-        if ( (boot[bootIndex]==NULL)||(other.boot[bootIndex]==NULL) ) {
+        if ((boot[bootIndex] == nullptr) || (other.boot[bootIndex] == nullptr)) {
             return FALSE;
         }
         PtnElem *otherElem = other.boot[bootIndex];
         PtnElem *myElem = boot[bootIndex];
-        while ((otherElem!=NULL) || (myElem!=NULL)) {
+        while ((otherElem != nullptr) || (myElem != nullptr)) {
             if ( myElem == otherElem ) {
                 break;
             }
-            if ((otherElem==NULL) || (myElem==NULL)) {
+            if ((otherElem == nullptr) || (myElem == nullptr)) {
                 return FALSE;
             }
             if ( (myElem->basePattern != otherElem->basePattern) ||
                  (myElem->pattern != otherElem->pattern) ) {
                 return FALSE;
             }
-            if ((myElem->skeleton!=otherElem->skeleton)&&
+            if ((myElem->skeleton.getAlias() != otherElem->skeleton.getAlias()) &&
                 !myElem->skeleton->equals(*(otherElem->skeleton))) {
                 return FALSE;
             }
-            myElem = myElem->next;
-            otherElem=otherElem->next;
+            myElem = myElem->next.getAlias();
+            otherElem = otherElem->next.getAlias();
         }
     }
     return TRUE;
@@ -1909,21 +2021,21 @@
 PatternMap::getDuplicateElem(
             const UnicodeString &basePattern,
             const PtnSkeleton &skeleton,
-            PtnElem *baseElem)  {
+            PtnElem *baseElem) {
    PtnElem *curElem;
 
-   if ( baseElem == (PtnElem *)NULL )  {
-         return (PtnElem*)NULL;
+   if ( baseElem == nullptr ) {
+         return nullptr;
    }
    else {
          curElem = baseElem;
    }
    do {
      if ( basePattern.compare(curElem->basePattern)==0 ) {
-        UBool isEqual=TRUE;
-        for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
+         UBool isEqual = TRUE;
+         for (int32_t i = 0; i < UDATPG_FIELD_COUNT; ++i) {
             if (curElem->skeleton->type[i] != skeleton.type[i] ) {
-                isEqual=FALSE;
+                isEqual = FALSE;
                 break;
             }
         }
@@ -1931,11 +2043,11 @@
             return curElem;
         }
      }
-     curElem = curElem->next;
-   } while( curElem != (PtnElem *)NULL );
+     curElem = curElem->next.getAlias();
+   } while( curElem != nullptr );
 
    // end of the list
-   return (PtnElem*)NULL;
+   return nullptr;
 
 }  // PatternMap::getDuplicateElem
 
@@ -1976,7 +2088,7 @@
             continue;
         }
         int32_t canonicalIndex = fp->getCanonicalIndex(value);
-        if (canonicalIndex < 0 ) {
+        if (canonicalIndex < 0) {
             continue;
         }
         const dtTypeElem *row = &dtTypes[canonicalIndex];
@@ -1986,8 +2098,9 @@
         int32_t repeatCount = row->minLen;
         skeletonResult.baseOriginal.populate(field, repeatChar, repeatCount);
         int16_t subField = row->type;
-        if ( row->type > 0) {
-            subField += value.length();
+        if (row->type > 0) {
+            U_ASSERT(value.length() < INT16_MAX);
+            subField += static_cast<int16_t>(value.length());
         }
         skeletonResult.type[field] = subField;
     }
@@ -2031,8 +2144,8 @@
 }
 
 int32_t
-DateTimeMatcher::getDistance(const DateTimeMatcher& other, int32_t includeMask, DistanceInfo& distanceInfo) {
-    int32_t result=0;
+DateTimeMatcher::getDistance(const DateTimeMatcher& other, int32_t includeMask, DistanceInfo& distanceInfo) const {
+    int32_t result = 0;
     distanceInfo.clear();
     for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i ) {
         int32_t myType = (includeMask&(1<<i))==0 ? 0 : skeleton.type[i];
@@ -2071,13 +2184,13 @@
 
 UBool
 DateTimeMatcher::equals(const DateTimeMatcher* other) const {
-    if (other==NULL) { return FALSE; }
+    if (other==nullptr) { return FALSE; }
     return skeleton.original == other->skeleton.original;
 }
 
 int32_t
-DateTimeMatcher::getFieldMask() {
-    int32_t result=0;
+DateTimeMatcher::getFieldMask() const {
+    int32_t result = 0;
 
     for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
         if (skeleton.type[i]!=0) {
@@ -2094,7 +2207,7 @@
 
 FormatParser::FormatParser () {
     status = START;
-    itemNumber=0;
+    itemNumber = 0;
 }
 
 
@@ -2106,7 +2219,7 @@
 // Note: the startPos may
 FormatParser::TokenStatus
 FormatParser::setTokens(const UnicodeString& pattern, int32_t startPos, int32_t *len) {
-    int32_t  curLoc = startPos;
+    int32_t curLoc = startPos;
     if ( curLoc >= pattern.length()) {
         return DONE;
     }
@@ -2132,10 +2245,10 @@
 
 void
 FormatParser::set(const UnicodeString& pattern) {
-    int32_t startPos=0;
-    TokenStatus result=START;
-    int32_t len=0;
-    itemNumber =0;
+    int32_t startPos = 0;
+    TokenStatus result = START;
+    int32_t len = 0;
+    itemNumber = 0;
 
     do {
         result = setTokens( pattern, startPos, &len );
@@ -2186,14 +2299,14 @@
 
 UBool
 FormatParser::isQuoteLiteral(const UnicodeString& s) {
-    return (UBool)(s.charAt(0)==SINGLE_QUOTE);
+    return (UBool)(s.charAt(0) == SINGLE_QUOTE);
 }
 
-// This function aussumes the current itemIndex points to the quote literal.
+// This function assumes the current itemIndex points to the quote literal.
 // Please call isQuoteLiteral prior to this function.
 void
 FormatParser::getQuoteLiteral(UnicodeString& quote, int32_t *itemIndex) {
-    int32_t i=*itemIndex;
+    int32_t i = *itemIndex;
 
     quote.remove();
     if (items[i].charAt(0)==SINGLE_QUOTE) {
@@ -2222,7 +2335,7 @@
 }
 
 UBool
-FormatParser::isPatternSeparator(UnicodeString& field) {
+FormatParser::isPatternSeparator(const UnicodeString& field) const {
     for (int32_t i=0; i<field.length(); ++i ) {
         UChar c= field.charAt(i);
         if ( (c==SINGLE_QUOTE) || (c==BACKSLASH) || (c==SPACE) || (c==COLON) ||
@@ -2239,21 +2352,19 @@
 DistanceInfo::~DistanceInfo() {}
 
 void
-DistanceInfo::setTo(DistanceInfo &other) {
+DistanceInfo::setTo(const DistanceInfo& other) {
     missingFieldMask = other.missingFieldMask;
     extraFieldMask= other.extraFieldMask;
 }
 
-PatternMapIterator::PatternMapIterator() {
-    bootIndex = 0;
-    nodePtr = NULL;
-    patternMap=NULL;
-    matcher= new DateTimeMatcher();
+PatternMapIterator::PatternMapIterator(UErrorCode& status) :
+    bootIndex(0), nodePtr(nullptr), matcher(nullptr), patternMap(nullptr)
+{
+    if (U_FAILURE(status)) { return; }
+    matcher.adoptInsteadAndCheckErrorCode(new DateTimeMatcher(), status);
 }
 
-
 PatternMapIterator::~PatternMapIterator() {
-    delete matcher;
 }
 
 void
@@ -2262,36 +2373,36 @@
 }
 
 PtnSkeleton*
-PatternMapIterator::getSkeleton() {
-    if ( nodePtr == NULL ) {
-        return NULL;
+PatternMapIterator::getSkeleton() const {
+    if ( nodePtr == nullptr ) {
+        return nullptr;
     }
     else {
-        return nodePtr->skeleton;
+        return nodePtr->skeleton.getAlias();
     }
 }
 
 UBool
-PatternMapIterator::hasNext() {
-    int32_t headIndex=bootIndex;
-    PtnElem *curPtr=nodePtr;
+PatternMapIterator::hasNext() const {
+    int32_t headIndex = bootIndex;
+    PtnElem *curPtr = nodePtr;
 
-    if (patternMap==NULL) {
+    if (patternMap==nullptr) {
         return FALSE;
     }
     while ( headIndex < MAX_PATTERN_ENTRIES ) {
-        if ( curPtr != NULL ) {
-            if ( curPtr->next != NULL ) {
+        if ( curPtr != nullptr ) {
+            if ( curPtr->next != nullptr ) {
                 return TRUE;
             }
             else {
                 headIndex++;
-                curPtr=NULL;
+                curPtr=nullptr;
                 continue;
             }
         }
         else {
-            if ( patternMap->boot[headIndex] != NULL ) {
+            if ( patternMap->boot[headIndex] != nullptr ) {
                 return TRUE;
             }
             else {
@@ -2299,7 +2410,6 @@
                 continue;
             }
         }
-
     }
     return FALSE;
 }
@@ -2307,19 +2417,19 @@
 DateTimeMatcher&
 PatternMapIterator::next() {
     while ( bootIndex < MAX_PATTERN_ENTRIES ) {
-        if ( nodePtr != NULL ) {
-            if ( nodePtr->next != NULL ) {
-                nodePtr = nodePtr->next;
+        if ( nodePtr != nullptr ) {
+            if ( nodePtr->next != nullptr ) {
+                nodePtr = nodePtr->next.getAlias();
                 break;
             }
             else {
                 bootIndex++;
-                nodePtr=NULL;
+                nodePtr=nullptr;
                 continue;
             }
         }
         else {
-            if ( patternMap->boot[bootIndex] != NULL ) {
+            if ( patternMap->boot[bootIndex] != nullptr ) {
                 nodePtr = patternMap->boot[bootIndex];
                 break;
             }
@@ -2329,7 +2439,7 @@
             }
         }
     }
-    if (nodePtr!=NULL) {
+    if (nodePtr!=nullptr) {
         matcher->copyFrom(*nodePtr->skeleton);
     }
     else {
@@ -2468,36 +2578,28 @@
 }
 
 PtnElem::PtnElem(const UnicodeString &basePat, const UnicodeString &pat) :
-basePattern(basePat),
-skeleton(NULL),
-pattern(pat),
-next(NULL)
+    basePattern(basePat), skeleton(nullptr), pattern(pat), next(nullptr)
 {
 }
 
 PtnElem::~PtnElem() {
-
-    if (next!=NULL) {
-        delete next;
-    }
-    delete skeleton;
 }
 
-DTSkeletonEnumeration::DTSkeletonEnumeration(PatternMap &patternMap, dtStrEnum type, UErrorCode& status) {
+DTSkeletonEnumeration::DTSkeletonEnumeration(PatternMap& patternMap, dtStrEnum type, UErrorCode& status) : fSkeletons(nullptr) {
     PtnElem  *curElem;
     PtnSkeleton *curSkeleton;
     UnicodeString s;
     int32_t bootIndex;
 
     pos=0;
-    fSkeletons = new UVector(status);
+    fSkeletons.adoptInsteadAndCheckErrorCode(new UVector(status), status);
     if (U_FAILURE(status)) {
-        delete fSkeletons;
         return;
     }
+
     for (bootIndex=0; bootIndex<MAX_PATTERN_ENTRIES; ++bootIndex ) {
         curElem = patternMap.boot[bootIndex];
-        while (curElem!=NULL) {
+        while (curElem!=nullptr) {
             switch(type) {
                 case DT_BASESKELETON:
                     s=curElem->basePattern;
@@ -2506,32 +2608,36 @@
                     s=curElem->pattern;
                     break;
                 case DT_SKELETON:
-                    curSkeleton=curElem->skeleton;
+                    curSkeleton=curElem->skeleton.getAlias();
                     s=curSkeleton->getSkeleton();
                     break;
             }
             if ( !isCanonicalItem(s) ) {
-                fSkeletons->addElement(new UnicodeString(s), status);
-                if (U_FAILURE(status)) {
-                    delete fSkeletons;
-                    fSkeletons = NULL;
+                LocalPointer<UnicodeString> newElem(new UnicodeString(s), status);
+                if (U_FAILURE(status)) { 
                     return;
                 }
+                fSkeletons->addElement(newElem.getAlias(), status);
+                if (U_FAILURE(status)) {
+                    fSkeletons.adoptInstead(nullptr);
+                    return;
+                }
+                newElem.orphan(); // fSkeletons vector now owns the UnicodeString.
             }
-            curElem = curElem->next;
+            curElem = curElem->next.getAlias();
         }
     }
-    if ((bootIndex==MAX_PATTERN_ENTRIES) && (curElem!=NULL) ) {
+    if ((bootIndex==MAX_PATTERN_ENTRIES) && (curElem!=nullptr) ) {
         status = U_BUFFER_OVERFLOW_ERROR;
     }
 }
 
 const UnicodeString*
 DTSkeletonEnumeration::snext(UErrorCode& status) {
-    if (U_SUCCESS(status) && pos < fSkeletons->size()) {
+    if (U_SUCCESS(status) && fSkeletons.isValid() && pos < fSkeletons->size()) {
         return (const UnicodeString*)fSkeletons->elementAt(pos++);
     }
-    return NULL;
+    return nullptr;
 }
 
 void
@@ -2541,7 +2647,7 @@
 
 int32_t
 DTSkeletonEnumeration::count(UErrorCode& /*status*/) const {
-   return (fSkeletons==NULL) ? 0 : fSkeletons->size();
+   return (fSkeletons.isNull()) ? 0 : fSkeletons->size();
 }
 
 UBool
@@ -2559,44 +2665,45 @@
 
 DTSkeletonEnumeration::~DTSkeletonEnumeration() {
     UnicodeString *s;
-    for (int32_t i=0; i<fSkeletons->size(); ++i) {
-        if ((s=(UnicodeString *)fSkeletons->elementAt(i))!=NULL) {
-            delete s;
+    if (fSkeletons.isValid()) {
+        for (int32_t i = 0; i < fSkeletons->size(); ++i) {
+            if ((s = (UnicodeString *)fSkeletons->elementAt(i)) != nullptr) {
+                delete s;
+            }
         }
     }
-    delete fSkeletons;
 }
 
-DTRedundantEnumeration::DTRedundantEnumeration() {
-    pos=0;
-    fPatterns = NULL;
+DTRedundantEnumeration::DTRedundantEnumeration() : pos(0), fPatterns(nullptr) {
 }
 
 void
 DTRedundantEnumeration::add(const UnicodeString& pattern, UErrorCode& status) {
-    if (U_FAILURE(status)) return;
-    if (fPatterns == NULL)  {
-        fPatterns = new UVector(status);
+    if (U_FAILURE(status)) { return; }
+    if (fPatterns.isNull())  {
+        fPatterns.adoptInsteadAndCheckErrorCode(new UVector(status), status);
         if (U_FAILURE(status)) {
-            delete fPatterns;
-            fPatterns = NULL;
             return;
        }
     }
-    fPatterns->addElement(new UnicodeString(pattern), status);
+    LocalPointer<UnicodeString> newElem(new UnicodeString(pattern), status);
     if (U_FAILURE(status)) {
-        delete fPatterns;
-        fPatterns = NULL;
         return;
     }
+    fPatterns->addElement(newElem.getAlias(), status);
+    if (U_FAILURE(status)) {
+        fPatterns.adoptInstead(nullptr);
+        return;
+    }
+    newElem.orphan(); // fPatterns now owns the string.
 }
 
 const UnicodeString*
 DTRedundantEnumeration::snext(UErrorCode& status) {
-    if (U_SUCCESS(status) && pos < fPatterns->size()) {
+    if (U_SUCCESS(status) && fPatterns.isValid() && pos < fPatterns->size()) {
         return (const UnicodeString*)fPatterns->elementAt(pos++);
     }
-    return NULL;
+    return nullptr;
 }
 
 void
@@ -2606,11 +2713,11 @@
 
 int32_t
 DTRedundantEnumeration::count(UErrorCode& /*status*/) const {
-       return (fPatterns==NULL) ? 0 : fPatterns->size();
+    return (fPatterns.isNull()) ? 0 : fPatterns->size();
 }
 
 UBool
-DTRedundantEnumeration::isCanonicalItem(const UnicodeString& item) {
+DTRedundantEnumeration::isCanonicalItem(const UnicodeString& item) const {
     if ( item.length() != 1 ) {
         return FALSE;
     }
@@ -2624,12 +2731,13 @@
 
 DTRedundantEnumeration::~DTRedundantEnumeration() {
     UnicodeString *s;
-    for (int32_t i=0; i<fPatterns->size(); ++i) {
-        if ((s=(UnicodeString *)fPatterns->elementAt(i))!=NULL) {
-            delete s;
+    if (fPatterns.isValid()) {
+        for (int32_t i = 0; i < fPatterns->size(); ++i) {
+            if ((s = (UnicodeString *)fPatterns->elementAt(i)) != nullptr) {
+                delete s;
+            }
         }
-    }
-    delete fPatterns;
+    }    
 }
 
 U_NAMESPACE_END
diff --git a/icu4c/source/i18n/dtptngen_impl.h b/icu4c/source/i18n/dtptngen_impl.h
index 2ea31a7..95219f0 100644
--- a/icu4c/source/i18n/dtptngen_impl.h
+++ b/icu4c/source/i18n/dtptngen_impl.h
@@ -116,7 +116,7 @@
     int16_t                type;
     int16_t                minLen;
     int16_t                weight;
-}dtTypeElem;
+} dtTypeElem;
 
 // A compact storage mechanism for skeleton field strings.  Several dozen of these will be created
 // for a typical DateTimePatternGenerator instance.
@@ -172,30 +172,28 @@
     virtual ~PtnSkeleton();
 };
 
-
 class PtnElem : public UMemory {
 public:
     UnicodeString basePattern;
-    PtnSkeleton   *skeleton;
+    LocalPointer<PtnSkeleton> skeleton;
     UnicodeString pattern;
     UBool         skeletonWasSpecified; // if specified in availableFormats, not derived
-    PtnElem       *next;
+    LocalPointer<PtnElem> next;
 
     PtnElem(const UnicodeString &basePattern, const UnicodeString &pattern);
     virtual ~PtnElem();
-
 };
 
 class FormatParser : public UMemory {
 public:
     UnicodeString items[MAX_DT_TOKEN];
-    int32_t  itemNumber;
+    int32_t itemNumber;
 
     FormatParser();
     virtual ~FormatParser();
     void set(const UnicodeString& patternString);
     void getQuoteLiteral(UnicodeString& quote, int32_t *itemIndex);
-    UBool isPatternSeparator(UnicodeString& field);
+    UBool isPatternSeparator(const UnicodeString& field) const;
     static UBool isQuoteLiteral(const UnicodeString& s);
     static int32_t getCanonicalIndex(const UnicodeString& s) { return getCanonicalIndex(s, TRUE); }
     static int32_t getCanonicalIndex(const UnicodeString& s, UBool strict);
@@ -206,7 +204,7 @@
        ADD_TOKEN,
        SYNTAX_ERROR,
        DONE
-   } ToeknStatus;
+   } TokenStatus;
 
    TokenStatus status;
    virtual TokenStatus setTokens(const UnicodeString& pattern, int32_t startPos, int32_t *len);
@@ -220,7 +218,7 @@
     DistanceInfo() {}
     virtual ~DistanceInfo();
     void clear() { missingFieldMask = extraFieldMask = 0; }
-    void setTo(DistanceInfo& other);
+    void setTo(const DistanceInfo& other);
     void addMissing(int32_t field) { missingFieldMask |= (1<<field); }
     void addExtra(int32_t field) { extraFieldMask |= (1<<field); }
 };
@@ -237,11 +235,11 @@
     void copyFrom();
     PtnSkeleton* getSkeletonPtr();
     UBool equals(const DateTimeMatcher* other) const;
-    int32_t getDistance(const DateTimeMatcher& other, int32_t includeMask, DistanceInfo& distanceInfo);
+    int32_t getDistance(const DateTimeMatcher& other, int32_t includeMask, DistanceInfo& distanceInfo) const;
     DateTimeMatcher();
     DateTimeMatcher(const DateTimeMatcher& other);
     virtual ~DateTimeMatcher();
-    int32_t getFieldMask();
+    int32_t getFieldMask() const;
 };
 
 class PatternMap : public UMemory {
@@ -250,34 +248,34 @@
     PatternMap();
     virtual  ~PatternMap();
     void  add(const UnicodeString& basePattern, const PtnSkeleton& skeleton, const UnicodeString& value, UBool skeletonWasSpecified, UErrorCode& status);
-    const UnicodeString* getPatternFromBasePattern(UnicodeString& basePattern, UBool& skeletonWasSpecified);
-    const UnicodeString* getPatternFromSkeleton(PtnSkeleton& skeleton, const PtnSkeleton** specifiedSkeletonPtr = 0);
+    const UnicodeString* getPatternFromBasePattern(const UnicodeString& basePattern, UBool& skeletonWasSpecified) const;
+    const UnicodeString* getPatternFromSkeleton(const PtnSkeleton& skeleton, const PtnSkeleton** specifiedSkeletonPtr = 0) const;
     void copyFrom(const PatternMap& other, UErrorCode& status);
-    PtnElem* getHeader(UChar baseChar);
-    UBool equals(const PatternMap& other);
+    PtnElem* getHeader(UChar baseChar) const;
+    UBool equals(const PatternMap& other) const;
 private:
     UBool isDupAllowed;
-    PtnElem*  getDuplicateElem(const UnicodeString &basePattern, const PtnSkeleton& skeleton, PtnElem *baseElem);
+    PtnElem*  getDuplicateElem(const UnicodeString& basePattern, const PtnSkeleton& skeleton, PtnElem *baseElem);
 }; // end  PatternMap
 
 class PatternMapIterator : public UMemory {
 public:
-    PatternMapIterator();
+    PatternMapIterator(UErrorCode &status);
     virtual ~PatternMapIterator();
     void set(PatternMap& patternMap);
-    PtnSkeleton* getSkeleton();
-    UBool hasNext();
+    PtnSkeleton* getSkeleton() const;
+    UBool hasNext() const;
     DateTimeMatcher& next();
 private:
     int32_t bootIndex;
     PtnElem *nodePtr;
-    DateTimeMatcher *matcher;
+    LocalPointer<DateTimeMatcher> matcher;
     PatternMap *patternMap;
 };
 
 class DTSkeletonEnumeration : public StringEnumeration {
 public:
-    DTSkeletonEnumeration(PatternMap &patternMap, dtStrEnum type, UErrorCode& status);
+    DTSkeletonEnumeration(PatternMap& patternMap, dtStrEnum type, UErrorCode& status);
     virtual ~DTSkeletonEnumeration();
     static UClassID U_EXPORT2 getStaticClassID(void);
     virtual UClassID getDynamicClassID(void) const;
@@ -287,7 +285,7 @@
 private:
     int32_t pos;
     UBool isCanonicalItem(const UnicodeString& item);
-    UVector *fSkeletons;
+    LocalPointer<UVector> fSkeletons;
 };
 
 class DTRedundantEnumeration : public StringEnumeration {
@@ -302,8 +300,8 @@
     void add(const UnicodeString &pattern, UErrorCode& status);
 private:
     int32_t pos;
-    UBool isCanonicalItem(const UnicodeString& item);
-    UVector *fPatterns;
+    UBool isCanonicalItem(const UnicodeString& item) const;
+    LocalPointer<UVector> fPatterns;
 };
 
 U_NAMESPACE_END
diff --git a/icu4c/source/i18n/unicode/dtptngen.h b/icu4c/source/i18n/unicode/dtptngen.h
index feb465e..21173fc 100644
--- a/icu4c/source/i18n/unicode/dtptngen.h
+++ b/icu4c/source/i18n/unicode/dtptngen.h
@@ -542,6 +542,11 @@
 
     int32_t fAllowedHourFormats[7];  // Actually an array of AllowedHourFormat enum type, ending with UNKNOWN.
 
+    // Internal error code used for recording/reporting errors that occur during methods that do not
+    // have a UErrorCode parameter. For example: the Copy Constructor, or the ::clone() method.
+    // When this is set to an error the object is in an invalid state.
+    UErrorCode internalErrorCode;
+
     /* internal flags masks for adjustFieldTypes etc. */
     enum {
         kDTPGNoFlags = 0,
@@ -569,11 +574,10 @@
 #endif  // U_HIDE_DRAFT_API
     void getAppendName(UDateTimePatternField field, UnicodeString& value);
     UnicodeString mapSkeletonMetacharacters(const UnicodeString& patternForm, int32_t* flags, UErrorCode& status);
-    int32_t getCanonicalIndex(const UnicodeString& field);
-    const UnicodeString* getBestRaw(DateTimeMatcher& source, int32_t includeMask, DistanceInfo* missingFields, const PtnSkeleton** specifiedSkeletonPtr = 0);
+    const UnicodeString* getBestRaw(DateTimeMatcher& source, int32_t includeMask, DistanceInfo* missingFields, UErrorCode& status, const PtnSkeleton** specifiedSkeletonPtr = 0);
     UnicodeString adjustFieldTypes(const UnicodeString& pattern, const PtnSkeleton* specifiedSkeleton, int32_t flags, UDateTimePatternMatchOptions options = UDATPG_MATCH_NO_OPTIONS);
-    UnicodeString getBestAppending(int32_t missingFields, int32_t flags, UDateTimePatternMatchOptions options = UDATPG_MATCH_NO_OPTIONS);
-    int32_t getTopBitNumber(int32_t foundMask);
+    UnicodeString getBestAppending(int32_t missingFields, int32_t flags, UErrorCode& status, UDateTimePatternMatchOptions options = UDATPG_MATCH_NO_OPTIONS);
+    int32_t getTopBitNumber(int32_t foundMask) const;
     void setAvailableFormat(const UnicodeString &key, UErrorCode& status);
     UBool isAvailableFormatSet(const UnicodeString &key) const;
     void copyHashtable(Hashtable *other, UErrorCode &status);