--- /dev/null
+// © 2018 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#ifndef __CAPI_HELPER_H__
+#define __CAPI_HELPER_H__
+
+#include "unicode/utypes.h"
+
+U_NAMESPACE_BEGIN
+
+/**
+ * An internal helper class to help convert between C and C++ APIs.
+ */
+template<typename CType, typename CPPType, int32_t kMagic>
+class IcuCApiHelper {
+ public:
+ /**
+ * Convert from the C type to the C++ type (const version).
+ */
+ static const CPPType* validate(const CType* input, UErrorCode& status);
+
+ /**
+ * Convert from the C type to the C++ type (non-const version).
+ */
+ static CPPType* validate(CType* input, UErrorCode& status);
+
+ /**
+ * Convert from the C++ type to the C type.
+ */
+ CType* exportForC();
+
+ /**
+ * Invalidates the object.
+ */
+ ~IcuCApiHelper();
+
+ private:
+ /**
+ * While the object is valid, fMagic equals kMagic.
+ */
+ int32_t fMagic = kMagic;
+};
+
+
+template<typename CType, typename CPPType, int32_t kMagic>
+const CPPType*
+IcuCApiHelper<CType, CPPType, kMagic>::validate(const CType* input, UErrorCode& status) {
+ if (U_FAILURE(status)) {
+ return nullptr;
+ }
+ if (input == nullptr) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return nullptr;
+ }
+ auto* impl = reinterpret_cast<const CPPType*>(input);
+ if (impl->fMagic != kMagic) {
+ status = U_INVALID_FORMAT_ERROR;
+ return nullptr;
+ }
+ return impl;
+}
+
+template<typename CType, typename CPPType, int32_t kMagic>
+CPPType*
+IcuCApiHelper<CType, CPPType, kMagic>::validate(CType* input, UErrorCode& status) {
+ auto* constInput = static_cast<const CType*>(input);
+ auto* validated = validate(constInput, status);
+ return const_cast<CPPType*>(validated);
+}
+
+template<typename CType, typename CPPType, int32_t kMagic>
+CType*
+IcuCApiHelper<CType, CPPType, kMagic>::exportForC() {
+ return reinterpret_cast<CType*>(static_cast<CPPType*>(this));
+}
+
+template<typename CType, typename CPPType, int32_t kMagic>
+IcuCApiHelper<CType, CPPType, kMagic>::~IcuCApiHelper() {
+ // head off application errors by preventing use of of deleted objects.
+ fMagic = 0;
+}
+
+
+U_NAMESPACE_END
+
+#endif // __CAPI_HELPER_H__
<ClInclude Include="ustr_cnv.h" />
<ClInclude Include="ustr_imp.h" />
<ClInclude Include="static_unicode_sets.h" />
+ <ClInclude Include="capi_helper.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="common.rc" />
<ClInclude Include="static_unicode_sets.h">
<Filter>formatting</Filter>
</ClInclude>
+ <CustomBuild Include="capi_helper.h">
+ <Filter>data & memory</Filter>
+ </CustomBuild>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="common.rc">
<ClInclude Include="ustr_cnv.h" />
<ClInclude Include="ustr_imp.h" />
<ClInclude Include="static_unicode_sets.h" />
+ <ClInclude Include="capi_helper.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="common.rc" />
using namespace icu::number::impl;
-//////////////////////////////////
-/// C API CONVERSION FUNCTIONS ///
-//////////////////////////////////
-
-UNumberFormatterData* UNumberFormatterData::validate(UNumberFormatter* input, UErrorCode& status) {
- auto* constInput = static_cast<const UNumberFormatter*>(input);
- auto* validated = validate(constInput, status);
- return const_cast<UNumberFormatterData*>(validated);
-}
-
-const UNumberFormatterData*
-UNumberFormatterData::validate(const UNumberFormatter* input, UErrorCode& status) {
- if (U_FAILURE(status)) {
- return nullptr;
- }
- if (input == nullptr) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return nullptr;
- }
- auto* impl = reinterpret_cast<const UNumberFormatterData*>(input);
- if (impl->fMagic != UNumberFormatterData::kMagic) {
- status = U_INVALID_FORMAT_ERROR;
- return nullptr;
- }
- return impl;
-}
-
-UNumberFormatter* UNumberFormatterData::exportForC() {
- return reinterpret_cast<UNumberFormatter*>(this);
-}
-
-UFormattedNumberData* UFormattedNumberData::validate(UFormattedNumber* input, UErrorCode& status) {
- auto* constInput = static_cast<const UFormattedNumber*>(input);
- auto* validated = validate(constInput, status);
- return const_cast<UFormattedNumberData*>(validated);
-}
-
-const UFormattedNumberData*
-UFormattedNumberData::validate(const UFormattedNumber* input, UErrorCode& status) {
- if (U_FAILURE(status)) {
- return nullptr;
- }
- if (input == nullptr) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return nullptr;
- }
- auto* impl = reinterpret_cast<const UFormattedNumberData*>(input);
- if (impl->fMagic != UFormattedNumberData::kMagic) {
- status = U_INVALID_FORMAT_ERROR;
- return nullptr;
- }
- return impl;
-}
-
-UFormattedNumber* UFormattedNumberData::exportForC() {
- return reinterpret_cast<UFormattedNumber*>(this);
-}
-
-/////////////////////////////////////
-/// END CAPI CONVERSION FUNCTIONS ///
-/////////////////////////////////////
-
-
U_CAPI UNumberFormatter* U_EXPORT2
unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const char* locale,
UErrorCode* ec) {
#include "number_types.h"
#include "number_decimalquantity.h"
#include "number_stringbuilder.h"
+#include "capi_helper.h"
U_NAMESPACE_BEGIN namespace number {
namespace impl {
/**
- * Implementation class for UNumberFormatter with a magic number for safety.
- *
- * Wraps a LocalizedNumberFormatter by value.
+ * Implementation class for UNumberFormatter. Wraps a LocalizedNumberFormatter.
*/
-struct UNumberFormatterData : public UMemory {
- // The magic number to identify incoming objects.
- // Reads in ASCII as "NFR" (NumberFormatteR with room at the end)
- static constexpr int32_t kMagic = 0x4E465200;
-
- // Data members:
- int32_t fMagic = kMagic;
+struct UNumberFormatterData : public UMemory,
+ // Magic number as ASCII == "NFR" (NumberFormatteR)
+ public IcuCApiHelper<UNumberFormatter, UNumberFormatterData, 0x4E465200> {
LocalizedNumberFormatter fFormatter;
-
- /** Convert from UNumberFormatter -> UNumberFormatterData. */
- static UNumberFormatterData* validate(UNumberFormatter* input, UErrorCode& status);
-
- /** Convert from UNumberFormatter -> UNumberFormatterData (const version). */
- static const UNumberFormatterData* validate(const UNumberFormatter* input, UErrorCode& status);
-
- /** Convert from UNumberFormatterData -> UNumberFormatter. */
- UNumberFormatter* exportForC();
};
/**
- * Implementation class for UFormattedNumber with magic number for safety.
+ * Implementation class for UFormattedNumber.
*
* This struct is also held internally by the C++ version FormattedNumber since the member types are not
* declared in the public header file.
* The DecimalQuantity is not currently being used by FormattedNumber, but at some point it could be used
* to add a toDecNumber() or similar method.
*/
-struct UFormattedNumberData : public UMemory {
- // The magic number to identify incoming objects.
- // Reads in ASCII as "FDN" (FormatteDNumber with room at the end)
- static constexpr int32_t kMagic = 0x46444E00;
-
- // Data members:
- int32_t fMagic = kMagic;
+struct UFormattedNumberData : public UMemory,
+ // Magic number as ASCII == "FDN" (FormatteDNumber)
+ public IcuCApiHelper<UFormattedNumber, UFormattedNumberData, 0x46444E00> {
DecimalQuantity quantity;
NumberStringBuilder string;
-
- /** Convert from UFormattedNumber -> UFormattedNumberData. */
- static UFormattedNumberData* validate(UFormattedNumber* input, UErrorCode& status);
-
- /** Convert from UFormattedNumber -> UFormattedNumberData (const version). */
- static const UFormattedNumberData* validate(const UFormattedNumber* input, UErrorCode& status);
-
- /** Convert from UFormattedNumberData -> UFormattedNumber. */
- UFormattedNumber* exportForC();
};
}
void SpoofImpl::construct(UErrorCode& status) {
- fMagic = USPOOF_MAGIC;
fChecks = USPOOF_ALL_CHECKS;
fSpoofData = NULL;
fAllowedCharsSet = NULL;
// Copy Constructor, used by the user level clone() function.
SpoofImpl::SpoofImpl(const SpoofImpl &src, UErrorCode &status) :
- fMagic(0), fChecks(USPOOF_ALL_CHECKS), fSpoofData(NULL), fAllowedCharsSet(NULL) ,
+ fChecks(USPOOF_ALL_CHECKS), fSpoofData(NULL), fAllowedCharsSet(NULL) ,
fAllowedLocales(NULL) {
if (U_FAILURE(status)) {
return;
}
- fMagic = src.fMagic;
fChecks = src.fChecks;
if (src.fSpoofData != NULL) {
fSpoofData = src.fSpoofData->addReference();
}
SpoofImpl::~SpoofImpl() {
- fMagic = 0; // head off application errors by preventing use of
- // of deleted objects.
if (fSpoofData != NULL) {
fSpoofData->removeReference(); // Will delete if refCount goes to zero.
}
// Cast this instance as a USpoofChecker for the C API.
USpoofChecker *SpoofImpl::asUSpoofChecker() {
- return reinterpret_cast<USpoofChecker*>(this);
+ return exportForC();
}
//
// received from the C API.
//
const SpoofImpl *SpoofImpl::validateThis(const USpoofChecker *sc, UErrorCode &status) {
+ auto* This = validate(sc, status);
if (U_FAILURE(status)) {
return NULL;
}
- if (sc == NULL) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return NULL;
- }
- SpoofImpl *This = (SpoofImpl *)sc;
- if (This->fMagic != USPOOF_MAGIC) {
- status = U_INVALID_FORMAT_ERROR;
- return NULL;
- }
if (This->fSpoofData != NULL && !This->fSpoofData->validateDataVersion(status)) {
return NULL;
}
//
//-----------------------------------------
-CheckResult::CheckResult() : fMagic(USPOOF_CHECK_MAGIC) {
+CheckResult::CheckResult() {
clear();
}
USpoofCheckResult* CheckResult::asUSpoofCheckResult() {
- return reinterpret_cast<USpoofCheckResult*>(this);
+ return exportForC();
}
//
// received from the C API.
//
const CheckResult* CheckResult::validateThis(const USpoofCheckResult *ptr, UErrorCode &status) {
- if (U_FAILURE(status)) { return NULL; }
- if (ptr == NULL) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return NULL;
- }
- CheckResult *This = (CheckResult*) ptr;
- if (This->fMagic != USPOOF_CHECK_MAGIC) {
- status = U_INVALID_FORMAT_ERROR;
- return NULL;
- }
- return This;
+ return validate(ptr, status);
}
CheckResult* CheckResult::validateThis(USpoofCheckResult *ptr, UErrorCode &status) {
- return const_cast<CheckResult *>
- (CheckResult::validateThis(const_cast<const USpoofCheckResult*>(ptr), status));
+ return validate(ptr, status);
}
void CheckResult::clear() {
#ifdef __cplusplus
+#include "capi_helper.h"
+
U_NAMESPACE_BEGIN
// The maximium length (in UTF-16 UChars) of the skeleton replacement string resulting from
* Class SpoofImpl corresponds directly to the plain C API opaque type
* USpoofChecker. One can be cast to the other.
*/
-class SpoofImpl : public UObject {
+class SpoofImpl : public UObject,
+ public IcuCApiHelper<USpoofChecker, SpoofImpl, USPOOF_MAGIC> {
public:
SpoofImpl(SpoofData *data, UErrorCode& status);
SpoofImpl(UErrorCode& status);
// Data Members
//
- int32_t fMagic; // Internal sanity check.
int32_t fChecks; // Bit vector of checks to perform.
SpoofData *fSpoofData;
* Class CheckResult corresponds directly to the plain C API opaque type
* USpoofCheckResult. One can be cast to the other.
*/
-class CheckResult : public UObject {
+class CheckResult : public UObject,
+ public IcuCApiHelper<USpoofCheckResult, CheckResult, USPOOF_CHECK_MAGIC> {
public:
CheckResult();
virtual ~CheckResult();
int32_t toCombinedBitmask(int32_t expectedChecks);
// Data Members
- int32_t fMagic; // Internal sanity check.
int32_t fChecks; // Bit vector of checks that were failed.
UnicodeSet fNumerics; // Set of numerics found in the string.
URestrictionLevel fRestrictionLevel; // The restriction level of the string.