Permalink
Browse files

Add ICU DateTimePatternGenerator API to HPHP

Summary: Added a PHP API for the C++ icu::DateTimePatternGenerator. I tried to follow the conventions of the other ICU PHP classes. When there is an error, we throw an exception. The error message/code can be accessed through getErrorMessage/getErrorCode. Like many other Intl classes, the way to create a DatePatternGenerator is through a static method, createInstance or createEmptyInstance.

Reviewed By: @bgertzfield

Differential Revision: D1691412
  • Loading branch information...
Russell Porter authored and hhvm-bot committed Dec 5, 2014
1 parent a2aaaf8 commit bc84daf7816e4cd268da59d535dcadfc6cf01085
@@ -0,0 +1,388 @@
#include "hphp/runtime/ext/icu/ext_icu_date_pattern_gen.h"
#include "hphp/runtime/ext/icu/ext_icu_iterator.h"

namespace HPHP { namespace Intl {
//////////////////////////////////////////////////////////////////////////////
// Internal Resource Data

const StaticString s_IntlDatePatternGenerator("IntlDatePatternGenerator");

Class* IntlDatePatternGenerator::c_IntlDatePatternGenerator = nullptr;

#define GENERATOR_GET(dest, src) \
auto dest = IntlDatePatternGenerator::Get(src); \
if (!dest) { \
throw data->getException("Invalid date pattern generator"); \
}

#define ICU_ERR_CHECK(data, ec) \
if (U_FAILURE(ec)) { \
data->setError(ec); \
throw data->getException("Date pattern generator error: %d (%s)", \
error, u_errorName(error)); \
}

#define ICU_ERR_CHECK_MSG(data, ec, msg) \
if (U_FAILURE(ec)) { \
data->setError(ec, msg); \
throw data->getException(#msg ": %d (%s)", ec, u_errorName(ec)); \
}

static UDateTimePatternField cast_ptn_field(IntlError *errorHandler,
int64_t fieldInt) {
// The pattern fields are in an enum and should be less than the field count
if ((fieldInt < 0) || (fieldInt >= UDATPG_FIELD_COUNT)) {
const char *msg = "Invalid value: %ld for pattern field";
errorHandler->setError(U_ILLEGAL_ARGUMENT_ERROR, msg, fieldInt);
throw errorHandler->getException(msg, fieldInt);
}

return static_cast<UDateTimePatternField>(fieldInt);
}

//////////////////////////////////////////////////////////////////////////////
// class IntlDatePatternGenerator

static Object HHVM_STATIC_METHOD(IntlDatePatternGenerator, createInstance,
const String& locale) {
if (locale.empty()) {
throw s_intl_error->getException("No locale provided");
}

auto loc = icu::Locale::createFromName(locale.c_str());
UErrorCode error = U_ZERO_ERROR;
auto generator = std::unique_ptr<icu::DateTimePatternGenerator>(
icu::DateTimePatternGenerator::createInstance(loc, error));
ICU_ERR_CHECK_MSG(s_intl_error, error,
"Error creating ICU DateTimePatternGenerator object");

return IntlDatePatternGenerator::newInstance(std::move(generator));
}

static Object HHVM_STATIC_METHOD(IntlDatePatternGenerator,
createEmptyInstance) {
UErrorCode error = U_ZERO_ERROR;
auto generator = std::unique_ptr<icu::DateTimePatternGenerator>(
icu::DateTimePatternGenerator::createEmptyInstance(error));
ICU_ERR_CHECK_MSG(s_intl_error, error,
"Error creating ICU DateTimePatternGenerator object");

return IntlDatePatternGenerator::newInstance(std::move(generator));
}

static String HHVM_METHOD(IntlDatePatternGenerator,
getSkeleton,
const String& pattern) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString ptn(u16(pattern, error));
ICU_ERR_CHECK(data, error);

icu::UnicodeString ret = data->generator().getSkeleton(ptn, error);
ICU_ERR_CHECK_MSG(data, error, "Error getting skeleton");

String out(u8(ret, error));
ICU_ERR_CHECK(data, error);

return out;
}

static String HHVM_METHOD(IntlDatePatternGenerator,
getBaseSkeleton,
const String& pattern) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString ptn(u16(pattern, error));
ICU_ERR_CHECK(data, error);

icu::UnicodeString ret = data->generator().getBaseSkeleton(ptn, error);
ICU_ERR_CHECK_MSG(data, error, "Error getting base skeleton");

String out(u8(ret, error));
ICU_ERR_CHECK(data, error);

return out;
}

static int64_t HHVM_METHOD(IntlDatePatternGenerator,
addPattern,
const String& pattern,
bool override) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString ptn(u16(pattern, error));
icu::UnicodeString conflictingPtn;
ICU_ERR_CHECK(data, error);

int64_t ret;
ret = data->generator().addPattern(ptn, override, conflictingPtn, error);
ICU_ERR_CHECK_MSG(data, error, "Error adding pattern");

return ret;
}

static void HHVM_METHOD(IntlDatePatternGenerator,
setAppendItemFormat,
int64_t fieldInt,
const String& format) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString fmt(u16(format, error));
ICU_ERR_CHECK(data, error);

data->generator().setAppendItemFormat(cast_ptn_field(data, fieldInt), fmt);
ICU_ERR_CHECK_MSG(data, error, "Error setting append item format");
}

static String HHVM_METHOD(IntlDatePatternGenerator,
getAppendItemFormat,
int64_t fieldInt) {
GENERATOR_GET(data, this_);

icu::UnicodeString ret;
ret = data->generator().getAppendItemFormat(cast_ptn_field(data, fieldInt));

UErrorCode error = U_ZERO_ERROR;
String out(u8(ret, error));
ICU_ERR_CHECK(data, error);

return out;
}

static void HHVM_METHOD(IntlDatePatternGenerator,
setAppendItemName,
int64_t fieldInt,
const String& name) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString value(u16(name, error));
ICU_ERR_CHECK(data, error);

data->generator().setAppendItemName(cast_ptn_field(data, fieldInt), value);
ICU_ERR_CHECK_MSG(data, error, "Error setting append item name");
}

static String HHVM_METHOD(IntlDatePatternGenerator,
getAppendItemName,
int64_t fieldInt) {
GENERATOR_GET(data, this_);

icu::UnicodeString ret;
ret = data->generator().getAppendItemName(cast_ptn_field(data, fieldInt));

UErrorCode error = U_ZERO_ERROR;
String out(u8(ret, error));
ICU_ERR_CHECK(data, error);

return out;
}

static void HHVM_METHOD(IntlDatePatternGenerator,
setDateTimeFormat,
const String& dateTimeFormat) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString fmt(u16(dateTimeFormat, error));
ICU_ERR_CHECK(data, error);

data->generator().setDateTimeFormat(fmt);
ICU_ERR_CHECK_MSG(data, error, "Error setting date time format");
}

static String HHVM_METHOD(IntlDatePatternGenerator, getDateTimeFormat) {
GENERATOR_GET(data, this_);

icu::UnicodeString ret = data->generator().getDateTimeFormat();

UErrorCode error = U_ZERO_ERROR;
String out(u8(ret, error));
ICU_ERR_CHECK(data, error);

return out;
}

static String HHVM_METHOD(IntlDatePatternGenerator,
getBestPattern,
const String& skeleton) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString skel(u16(skeleton, error));
ICU_ERR_CHECK(data, error);

icu::UnicodeString ret = data->generator().getBestPattern(skel, error);
ICU_ERR_CHECK_MSG(data, error, "Error getting best pattern");

String out(u8(ret, error));
ICU_ERR_CHECK(data, error);

return out;
}

static String HHVM_METHOD(IntlDatePatternGenerator,
replaceFieldTypes,
const String& pattern,
const String& skeleton) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString ptn(u16(pattern, error));
ICU_ERR_CHECK(data, error);

icu::UnicodeString skel(u16(skeleton, error));
ICU_ERR_CHECK(data, error);

icu::UnicodeString ret;
ret = data->generator().replaceFieldTypes(ptn, skel, error);
ICU_ERR_CHECK_MSG(data, error, "Error replacing field types");

String out(u8(ret, error));
ICU_ERR_CHECK(data, error);

return out;
}

static Object HHVM_METHOD(IntlDatePatternGenerator, getSkeletons) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::StringEnumeration *se = data->generator().getSkeletons(error);
ICU_ERR_CHECK_MSG(data, error, "Error getting skeletons");

return IntlIterator::newInstance(se);
}

static String HHVM_METHOD(IntlDatePatternGenerator,
getPatternForSkeleton,
const String& skeleton) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString skel(u16(skeleton, error));
ICU_ERR_CHECK(data, error);

icu::UnicodeString ret = data->generator().getPatternForSkeleton(skel);

String out(u8(ret, error));
ICU_ERR_CHECK(data, error);

return out;
}

static Object HHVM_METHOD(IntlDatePatternGenerator, getBaseSkeletons) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::StringEnumeration *se = data->generator().getBaseSkeletons(error);
ICU_ERR_CHECK_MSG(data, error, "Error getting base skeletons");

return IntlIterator::newInstance(se);
}

static void HHVM_METHOD(IntlDatePatternGenerator,
setDecimal,
const String& decimal) {
GENERATOR_GET(data, this_);

UErrorCode error = U_ZERO_ERROR;
icu::UnicodeString dec(u16(decimal, error));
ICU_ERR_CHECK(data, error);

data->generator().setDecimal(dec);
}

static String HHVM_METHOD(IntlDatePatternGenerator, getDecimal) {
GENERATOR_GET(data, this_);

icu::UnicodeString ret = data->generator().getDecimal();

UErrorCode error = U_ZERO_ERROR;
String out(u8(ret, error));
ICU_ERR_CHECK(data, error);

return out;
}

static int64_t HHVM_METHOD(IntlDatePatternGenerator, getErrorCode) {
GENERATOR_GET(data, this_);
return data->getErrorCode();
}

static String HHVM_METHOD(IntlDatePatternGenerator, getErrorMessage) {
GENERATOR_GET(data, this_);
return data->getErrorMessage();
}

//////////////////////////////////////////////////////////////////////////////

#define UDATPG_CONST_FIELD(nm)Native::registerClassConstant<KindOfInt64>( \
s_IntlDatePatternGenerator.get(), \
makeStaticString(#nm "_PATTERN_FIELD"), \
UDATPG_ ## nm ## _FIELD);

#define UDATPG_CONST(nm)Native::registerClassConstant<KindOfInt64>( \
s_IntlDatePatternGenerator.get(), \
makeStaticString("PATTERN_" #nm), \
UDATPG_ ## nm);

void IntlExtension::initDatePatternGenerator() {
// UDateTimePatternField
UDATPG_CONST_FIELD(ERA);
UDATPG_CONST_FIELD(YEAR);
UDATPG_CONST_FIELD(QUARTER);
UDATPG_CONST_FIELD(MONTH);
UDATPG_CONST_FIELD(WEEK_OF_YEAR);
UDATPG_CONST_FIELD(WEEK_OF_MONTH);
UDATPG_CONST_FIELD(WEEKDAY);
UDATPG_CONST_FIELD(DAY_OF_YEAR);
UDATPG_CONST_FIELD(DAY_OF_WEEK_IN_MONTH);
UDATPG_CONST_FIELD(DAY);
UDATPG_CONST_FIELD(DAYPERIOD);
UDATPG_CONST_FIELD(HOUR);
UDATPG_CONST_FIELD(MINUTE);
UDATPG_CONST_FIELD(SECOND);
UDATPG_CONST_FIELD(FRACTIONAL_SECOND);
UDATPG_CONST_FIELD(ZONE);
UDATPG_CONST(FIELD_COUNT);

// UDateTimePatternConflict
UDATPG_CONST(NO_CONFLICT);
UDATPG_CONST(BASE_CONFLICT);
UDATPG_CONST(CONFLICT);
UDATPG_CONST(CONFLICT_COUNT);

HHVM_STATIC_ME(IntlDatePatternGenerator, createInstance);
HHVM_STATIC_ME(IntlDatePatternGenerator, createEmptyInstance);
HHVM_ME(IntlDatePatternGenerator, getSkeleton);
HHVM_ME(IntlDatePatternGenerator, getBaseSkeleton);
HHVM_ME(IntlDatePatternGenerator, addPattern);
HHVM_ME(IntlDatePatternGenerator, setAppendItemFormat);
HHVM_ME(IntlDatePatternGenerator, getAppendItemFormat);
HHVM_ME(IntlDatePatternGenerator, setAppendItemName);
HHVM_ME(IntlDatePatternGenerator, getAppendItemName);
HHVM_ME(IntlDatePatternGenerator, setDateTimeFormat);
HHVM_ME(IntlDatePatternGenerator, getDateTimeFormat);
HHVM_ME(IntlDatePatternGenerator, getBestPattern);
HHVM_ME(IntlDatePatternGenerator, replaceFieldTypes);
HHVM_ME(IntlDatePatternGenerator, getSkeletons);
HHVM_ME(IntlDatePatternGenerator, getPatternForSkeleton);
HHVM_ME(IntlDatePatternGenerator, getBaseSkeletons);
HHVM_ME(IntlDatePatternGenerator, setDecimal);
HHVM_ME(IntlDatePatternGenerator, getDecimal);
HHVM_ME(IntlDatePatternGenerator, getErrorCode);
HHVM_ME(IntlDatePatternGenerator, getErrorMessage);

auto gen = s_IntlDatePatternGenerator.get();
Native::registerNativeDataInfo<IntlDatePatternGenerator>(gen);

loadSystemlib("icu_date_pattern_gen");
}

//////////////////////////////////////////////////////////////////////////////
}} // namespace HPHP::Intl
Oops, something went wrong.

0 comments on commit bc84daf

Please sign in to comment.