mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-20293 Adds common base class to implement C API validation methods.
This commit is contained in:
parent
e1e5f363a0
commit
cd4644c4a0
8 changed files with 113 additions and 133 deletions
86
icu4c/source/common/capi_helper.h
Normal file
86
icu4c/source/common/capi_helper.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
// © 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__
|
|
@ -444,6 +444,7 @@
|
|||
<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" />
|
||||
|
|
|
@ -948,6 +948,9 @@
|
|||
<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">
|
||||
|
|
|
@ -570,6 +570,7 @@
|
|||
<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" />
|
||||
|
|
|
@ -20,69 +20,6 @@ using namespace icu::number;
|
|||
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) {
|
||||
|
|
|
@ -11,38 +11,24 @@
|
|||
#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.
|
||||
|
@ -50,24 +36,11 @@ struct UNumberFormatterData : public UMemory {
|
|||
* 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();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@ SpoofImpl::SpoofImpl() {
|
|||
}
|
||||
|
||||
void SpoofImpl::construct(UErrorCode& status) {
|
||||
fMagic = USPOOF_MAGIC;
|
||||
fChecks = USPOOF_ALL_CHECKS;
|
||||
fSpoofData = NULL;
|
||||
fAllowedCharsSet = NULL;
|
||||
|
@ -74,12 +73,11 @@ void SpoofImpl::construct(UErrorCode& status) {
|
|||
|
||||
// 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();
|
||||
|
@ -93,8 +91,6 @@ SpoofImpl::SpoofImpl(const SpoofImpl &src, UErrorCode &status) :
|
|||
}
|
||||
|
||||
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.
|
||||
}
|
||||
|
@ -104,7 +100,7 @@ SpoofImpl::~SpoofImpl() {
|
|||
|
||||
// Cast this instance as a USpoofChecker for the C API.
|
||||
USpoofChecker *SpoofImpl::asUSpoofChecker() {
|
||||
return reinterpret_cast<USpoofChecker*>(this);
|
||||
return exportForC();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -112,18 +108,10 @@ USpoofChecker *SpoofImpl::asUSpoofChecker() {
|
|||
// 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;
|
||||
}
|
||||
|
@ -454,12 +442,12 @@ UChar32 SpoofImpl::ScanHex(const UChar *s, int32_t start, int32_t limit, UErrorC
|
|||
//
|
||||
//-----------------------------------------
|
||||
|
||||
CheckResult::CheckResult() : fMagic(USPOOF_CHECK_MAGIC) {
|
||||
CheckResult::CheckResult() {
|
||||
clear();
|
||||
}
|
||||
|
||||
USpoofCheckResult* CheckResult::asUSpoofCheckResult() {
|
||||
return reinterpret_cast<USpoofCheckResult*>(this);
|
||||
return exportForC();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -467,22 +455,11 @@ USpoofCheckResult* CheckResult::asUSpoofCheckResult() {
|
|||
// 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() {
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "capi_helper.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
// The maximium length (in UTF-16 UChars) of the skeleton replacement string resulting from
|
||||
|
@ -52,7 +54,8 @@ class ConfusableDataUtils;
|
|||
* 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);
|
||||
|
@ -96,7 +99,6 @@ public:
|
|||
// Data Members
|
||||
//
|
||||
|
||||
int32_t fMagic; // Internal sanity check.
|
||||
int32_t fChecks; // Bit vector of checks to perform.
|
||||
|
||||
SpoofData *fSpoofData;
|
||||
|
@ -112,7 +114,8 @@ public:
|
|||
* 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();
|
||||
|
@ -127,7 +130,6 @@ public:
|
|||
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.
|
||||
|
|
Loading…
Add table
Reference in a new issue