コード例 #1
0
ファイル: ext_datetime.cpp プロジェクト: Yermo/hhvm
namespace HPHP {
static class DateExtension : public Extension {
 public:
  DateExtension() : Extension("date") { }
  void moduleInit() {
    IniSetting::Bind(
      "date.timezone",
      g_context->getDefaultTimeZone().c_str(),
      dateTimezoneIniCallback,
      nullptr
    );
  }

 private:
  static bool dateTimezoneIniCallback(const HPHP::String& value, void *p) {
    assert(p == nullptr);
    if (value.empty()) {
      return false;
    }
    return f_date_default_timezone_set(value);
  }
} s_date_extension;

///////////////////////////////////////////////////////////////////////////////
// constants

const StaticString q_DateTime$$ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_DateTime$$COOKIE(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_DateTime$$ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO"));
const StaticString q_DateTime$$RFC822(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_DateTime$$RFC850(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_DateTime$$RFC1036(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_DateTime$$RFC1123(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime$$RFC2822(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime$$RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_DateTime$$RSS(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime$$W3C(LITSTR_INIT("Y-m-d\\TH:i:sP"));

const int64_t q_DateTimeZone$$AFRICA = 1;
const int64_t q_DateTimeZone$$AMERICA = 2;
const int64_t q_DateTimeZone$$ANTARCTICA = 4;
const int64_t q_DateTimeZone$$ARCTIC = 8;
const int64_t q_DateTimeZone$$ASIA = 16;
const int64_t q_DateTimeZone$$ATLANTIC = 32;
const int64_t q_DateTimeZone$$AUSTRALIA = 64;
const int64_t q_DateTimeZone$$EUROPE = 128;
const int64_t q_DateTimeZone$$INDIAN = 256;
const int64_t q_DateTimeZone$$PACIFIC = 512;
const int64_t q_DateTimeZone$$UTC = 1024;
const int64_t q_DateTimeZone$$ALL = 2047;
const int64_t q_DateTimeZone$$ALL_WITH_BC = 4095;
const int64_t q_DateTimeZone$$PER_COUNTRY = 4096;

///////////////////////////////////////////////////////////////////////////////
// methods

Object c_DateTime::t_add(CObjRef interval) {
  m_dt->add(c_DateInterval::unwrap(interval));
  return this;
}

void c_DateTime::t___construct(const String& time /*= "now"*/,
                               CObjRef timezone /*= null_object*/) {
  m_dt = NEWOBJ(DateTime)(TimeStamp::Current());
  if (!time.empty()) {
    m_dt->fromString(time, c_DateTimeZone::unwrap(timezone));
  }
}

Object c_DateTime::ti_createfromformat(const String& format, const String& time,
                                       CObjRef timezone /*= null_object */) {
  c_DateTime *datetime = NEWOBJ(c_DateTime);
  datetime->m_dt = NEWOBJ(DateTime);
  datetime->m_dt->fromString(time, c_DateTimeZone::unwrap(timezone),
                             format.data());
  return datetime;
}

Object c_DateTime::t_diff(CObjRef datetime2, bool absolute) {
  return c_DateInterval::wrap(m_dt->diff(c_DateTime::unwrap(datetime2),
                                         absolute));
}

String c_DateTime::t_format(const String& format) {
  return m_dt->toString(format, false);
}

const StaticString
  s_warning_count("warning_count"),
  s_warnings("warnings"),
  s_error_count("error_count"),
  s_errors("errors");

Array c_DateTime::ti_getlasterrors() {
  Array errors = DateTime::getLastErrors();
  Array warnings = DateTime::getLastWarnings();
  Array ret = Array::Create();

  ret.add(s_warning_count, warnings.size());
  ret.add(s_warnings, warnings);
  ret.add(s_error_count, errors.size());
  ret.add(s_errors, errors);

  return ret;
}

int64_t c_DateTime::t_getoffset() {
  return m_dt->offset();
}

int64_t c_DateTime::t_gettimestamp() {
  return gettimestamp();
}

int64_t c_DateTime::gettimestamp() const {
  bool err = false;
  return m_dt->toTimeStamp(err);
}

Variant c_DateTime::t_gettimezone() {
  SmartResource<TimeZone> tz = m_dt->timezone();
  if (tz->isValid()) {
    return c_DateTimeZone::wrap(tz);
  }
  return false;
}

Object c_DateTime::t_modify(const String& modify) {
  m_dt->modify(modify);
  return this;
}

Object c_DateTime::t_setdate(int64_t year, int64_t month, int64_t day) {
  m_dt->setDate(year, month, day);
  return this;
}

Object c_DateTime::t_setisodate(int64_t year, int64_t week,
                                int64_t day /*= 1*/) {
  m_dt->setISODate(year, week, day);
  return this;
}

Object c_DateTime::t_settime(int64_t hour, int64_t minute,
                             int64_t second /*= 0*/) {
  m_dt->setTime(hour, minute, second);
  return this;
}

Object c_DateTime::t_settimestamp(int64_t unixtimestamp) {
  m_dt->fromTimeStamp(unixtimestamp, false);
  return this;
}

Object c_DateTime::t_settimezone(CObjRef timezone) {
  m_dt->setTimezone(c_DateTimeZone::unwrap(timezone));
  return this;
}

Object c_DateTime::t_sub(CObjRef interval) {
  m_dt->sub(c_DateInterval::unwrap(interval));
  return this;
}

c_DateTime* c_DateTime::Clone(ObjectData* obj) {
  c_DateTime* dt = static_cast<c_DateTime*>(obj->cloneImpl());
  dt->m_dt = static_cast<c_DateTime*>(obj)->m_dt->cloneDateTime();
  return dt;
}

void c_DateTimeZone::t___construct(const String& timezone) {
  m_tz = NEWOBJ(TimeZone)(timezone);
  if (!m_tz->isValid()) {
    std::string msg = "DateTimeZone::__construct(): Unknown or bad timezone (";
    msg += timezone.data();
    msg += ")";
    throw Object(SystemLib::AllocExceptionObject(msg));
  }
}

Array c_DateTimeZone::t_getlocation() {
  return m_tz->getLocation();
}

String c_DateTimeZone::t_getname() {
  return m_tz->name();
}

int64_t c_DateTimeZone::t_getoffset(CObjRef datetime) {
  bool error;
  int64_t ts = c_DateTime::unwrap(datetime)->toTimeStamp(error);
  return m_tz->offset(ts);
}

Array c_DateTimeZone::t_gettransitions() {
  return m_tz->transitions();
}

Array c_DateTimeZone::ti_listabbreviations() {
  return TimeZone::GetAbbreviations();
}

Array c_DateTimeZone::ti_listidentifiers() {
  return TimeZone::GetNames();
}

c_DateTimeZone* c_DateTimeZone::Clone(ObjectData* obj) {
  c_DateTimeZone* dtz = static_cast<c_DateTimeZone*>(obj->cloneImpl());
  dtz->m_tz = static_cast<c_DateTimeZone*>(obj)->m_tz->cloneTimeZone();
  return dtz;
}

void c_DateInterval::t___construct(const String& interval_spec) {
  m_di = NEWOBJ(DateInterval)(interval_spec);
  if (!m_di->isValid()) {
    std::string msg = "DateInterval::__construct: Invalid interval (";
    msg += interval_spec.data();
    msg += ")";
    throw Object(SystemLib::AllocExceptionObject(msg));
  }
}

const StaticString
  s_y("y"),
  s_m("m"),
  s_d("d"),
  s_h("h"),
  s_i("i"),
  s_s("s"),
  s_invert("invert"),
  s_days("days");

Variant c_DateInterval::t___get(Variant member) {
  if (member.isString()) {
    if (same(member, s_y))      return m_di->getYears();
    if (same(member, s_m))      return m_di->getMonths();
    if (same(member, s_d))      return m_di->getDays();
    if (same(member, s_h))      return m_di->getHours();
    if (same(member, s_i))      return m_di->getMinutes();
    if (same(member, s_s))      return m_di->getSeconds();
    if (same(member, s_invert)) return m_di->isInverted();
    if (same(member, s_days)) {
      if (m_di->haveTotalDays()) {
        return m_di->getTotalDays();
      } else {
        return false;
      }
    }
  }
  std::string msg = "Undefined property '";
  msg += member.toString().data();
  msg += ") on DateInterval object";
  throw Object(SystemLib::AllocExceptionObject(msg));
}

Variant c_DateInterval::t___set(Variant member, Variant value) {
  if (member.isString()) {
    if (same(member, s_y)) {
      m_di->setYears(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_m)) {
      m_di->setMonths(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_d)) {
      m_di->setDays(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_h)) {
      m_di->setHours(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_i)) {
      m_di->setMinutes(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_s)) {
      m_di->setSeconds(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_invert)) {
      m_di->setInverted(value.toBoolean());
      return uninit_null();
    }
    if (same(member, s_days)) {
      m_di->setTotalDays(value.toInt64());
      return uninit_null();
    }
  }

  std::string msg = "Undefined property '";
  msg += member.toString().data();
  msg += ") on DateInterval object";
  throw Object(SystemLib::AllocExceptionObject(msg));
}

Object c_DateInterval::ti_createfromdatestring(const String& time) {
  SmartResource<DateInterval> di(NEWOBJ(DateInterval)(time, true));
  return c_DateInterval::wrap(di);
}

String c_DateInterval::t_format(const String& format) {
  return m_di->format(format);
}

c_DateInterval* c_DateInterval::Clone(ObjectData* obj) {
  c_DateInterval *di = static_cast<c_DateInterval*>(obj->cloneImpl());
  di->m_di = static_cast<c_DateInterval*>(obj)->m_di->cloneDateInterval();
  return di;
}

///////////////////////////////////////////////////////////////////////////////
// timestamp

Variant f_gettimeofday(bool return_float /* = false */) {
  if (return_float) {
    return TimeStamp::CurrentSecond();
  }
  return TimeStamp::CurrentTime();
}

Variant f_microtime(bool get_as_float /* = false */) {
  if (get_as_float) {
    return TimeStamp::CurrentSecond();
  }
  return TimeStamp::CurrentMicroTime();
}

int64_t f_time() {
  return time(0);
}

Variant f_mktime(int hour /* = INT_MAX */, int minute /* = INT_MAX */,
                 int second /* = INT_MAX */, int month /* = INT_MAX */,
                 int day /* = INT_MAX */, int year /* = INT_MAX */) {
  bool error;
  int64_t ts = TimeStamp::Get(error, hour, minute, second, month, day, year,
                              false);
  if (error) return false;
  return ts;
}

Variant f_gmmktime(int hour /* = INT_MAX */, int minute /* = INT_MAX */,
                   int second /* = INT_MAX */,
                   int month /* = INT_MAX */, int day /* = INT_MAX */,
                   int year /* = INT_MAX */) {
  bool error;
  int64_t ts = TimeStamp::Get(error, hour, minute, second, month, day, year,
                              true);
  if (error) return false;
  return ts;
}

Variant f_idate(const String& format,
                int64_t timestamp /* = TimeStamp::Current() */) {
  if (format.size() != 1) {
    throw_invalid_argument("format: %s", format.data());
    return false;
  }
  int64_t ret = DateTime(timestamp, false).toInteger(*format.data());
  if (ret == -1) return false;
  return ret;
}

Variant f_date(const String& format,
               int64_t timestamp /* = TimeStamp::Current() */) {
  if (format.empty()) return "";
  String ret = DateTime(timestamp, false).toString(format, false);
  if (ret.isNull()) return false;
  return ret;
}

Variant f_gmdate(const String& format,
                 int64_t timestamp /* = TimeStamp::Current() */) {
  String ret = DateTime(timestamp, true).toString(format, false);
  if (ret.isNull()) return false;
  return ret;
}

Variant f_strftime(const String& format,
                   int64_t timestamp /* = TimeStamp::Current() */) {
  String ret = DateTime(timestamp, false).toString(format, true);
  if (ret.isNull()) return false;
  return ret;
}

String f_gmstrftime(const String& format,
                    int64_t timestamp /* = TimeStamp::Current() */) {
  String ret = DateTime(timestamp, true).toString(format, true);
  if (ret.isNull()) return false;
  return ret;
}

Array f_getdate(int64_t timestamp /* = TimeStamp::Current() */) {
  return DateTime(timestamp, false).toArray(DateTime::ArrayFormat::TimeMap);
}

Array f_localtime(int64_t timestamp /* = TimeStamp::Current() */,
                  bool is_associative /* = false */) {
  DateTime::ArrayFormat format =
    is_associative ? DateTime::ArrayFormat::TmMap :
                     DateTime::ArrayFormat::TmVector;
  return DateTime(timestamp, false).toArray(format);
}

Variant f_strptime(const String& date, const String& format) {
  Array ret = DateTime::ParseAsStrptime(format, date);
  if (ret.empty()) {
    return false;
  }
  return ret;
}

Variant f_strtotime(const String& input,
                    int64_t timestamp /* = TimeStamp::Current() */) {
  if (input.empty()) {
    return false;
  }

  DateTime dt(timestamp);
  if (!dt.fromString(input, SmartResource<TimeZone>())) {
    return false;
  }
  bool error;
  return dt.toTimeStamp(error);
}

///////////////////////////////////////////////////////////////////////////////
// timezone

String f_date_default_timezone_get() {
  return TimeZone::Current()->name();
}

bool f_date_default_timezone_set(const String& name) {
  return TimeZone::SetCurrent(name);
}

Array f_timezone_identifiers_list() {
  return c_DateTimeZone::ti_listidentifiers();
}

Array f_timezone_abbreviations_list() {
  return c_DateTimeZone::ti_listabbreviations();
}

Variant f_timezone_name_from_abbr(const String& abbr, int gmtoffset /* = -1 */,
                                  bool isdst /* = true */) {
  String ret = TimeZone::AbbreviationToName(abbr, gmtoffset, isdst);
  if (ret.isNull()) {
    return false;
  }
  return ret;
}

Object f_timezone_open(const String& timezone) {
  c_DateTimeZone *ctz = NEWOBJ(c_DateTimeZone)();
  Object ret(ctz);
  ctz->t___construct(timezone);
  return ret;
}

Array f_timezone_location_get(CObjRef timezone) {
  return timezone.getTyped<c_DateTimeZone>()->t_getlocation();
}

String f_timezone_name_get(CObjRef object) {
  return object.getTyped<c_DateTimeZone>()->t_getname();
}

int64_t f_timezone_offset_get(CObjRef object, CObjRef dt) {
  return object.getTyped<c_DateTimeZone>()->t_getoffset(dt);
}

Array f_timezone_transitions_get(CObjRef object) {
  return object.getTyped<c_DateTimeZone>()->t_gettransitions();
}

String f_timezone_version_get() {
  return TimeZone::getVersion();
}

///////////////////////////////////////////////////////////////////////////////
// datetime

bool f_checkdate(int month, int day, int year) {
  return DateTime::IsValid(year, month, day);
}

Object f_date_add(CObjRef datetime, CObjRef interval) {
  return datetime.getTyped<c_DateTime>()->
    t_add(interval.getTyped<c_DateInterval>());
}

Object f_date_create_from_format(const String& format,
                                 const String& time,
                                 CObjRef timezone /* = null_object */) {
  return c_DateTime::ti_createfromformat(format, time, timezone);
}

Variant f_date_parse_from_format(const String& format, const String& date) {
  Array ret = DateTime::Parse(format, date);
  if (ret.empty()) {
    return false;
  }
  return ret;
}

Object f_date_create(const String& time /* = null_string */,
                     CObjRef timezone /* = null_object */) {
  c_DateTime *cdt = NEWOBJ(c_DateTime)();
  Object ret(cdt);
  cdt->t___construct(time, timezone);
  return ret;
}

void f_date_date_set(CObjRef object, int year, int month, int day) {
  object.getTyped<c_DateTime>()->t_setdate(year, month, day);
}

Object f_date_diff(CObjRef datetime,
                   CObjRef datetime2,
                   bool absolute /* = false */) {
  return datetime.getTyped<c_DateTime>()->
    t_diff(datetime2.getTyped<c_DateTime>(), absolute);
}

void f_date_isodate_set(CObjRef object, int year, int week,
                        int day /* = 1 */) {
  object.getTyped<c_DateTime>()->t_setisodate(year, week, day);
}

String f_date_format(CObjRef object, const String& format) {
  return object.getTyped<c_DateTime>()->t_format(format);
}

Array f_date_get_last_errors() {
  return c_DateTime::ti_getlasterrors();
}

Object f_date_interval_create_from_date_string(const String& time) {
  return c_DateInterval::ti_createfromdatestring(time);
}

String f_date_interval_format(CObjRef interval, const String& format_spec) {
  return interval.getTyped<c_DateInterval>()->t_format(format_spec);
}

void f_date_modify(CObjRef object, const String& modify) {
  object.getTyped<c_DateTime>()->t_modify(modify);
}

int64_t f_date_offset_get(CObjRef object) {
  return object.getTyped<c_DateTime>()->t_getoffset();
}

Variant f_date_parse(const String& date) {
  Array ret = DateTime::Parse(date);
  if (ret.empty()) {
    return false;
  }
  return ret;
}

void f_date_time_set(CObjRef object, int hour, int minute,
                     int second /* = 0 */) {
  object.getTyped<c_DateTime>()->t_settime(hour, minute, second);
}

int64_t f_date_timestamp_get(CObjRef datetime) {
  return datetime.getTyped<c_DateTime>()->t_gettimestamp();
}

Object f_date_timestamp_set(CObjRef datetime, int64_t timestamp) {
  return datetime.getTyped<c_DateTime>()->
    t_settimestamp(timestamp);
}

Variant f_date_timezone_get(CObjRef object) {
  return object.getTyped<c_DateTime>()->t_gettimezone();
}

void f_date_timezone_set(CObjRef object, CObjRef timezone) {
  object.getTyped<c_DateTime>()->t_settimezone(timezone);
}

Object f_date_sub(CObjRef datetime, CObjRef interval) {
  return datetime.getTyped<c_DateTime>()->
    t_sub(interval.getTyped<c_DateInterval>());
}

///////////////////////////////////////////////////////////////////////////////
// sun

Array f_date_sun_info(int64_t ts, double latitude, double longitude) {
  return DateTime(ts, false).getSunInfo(latitude, longitude);
}

Variant f_date_sunrise(int64_t timestamp, int format /* = 0 */,
                       double latitude /* = 0.0 */, double longitude /* = 0.0 */,
                       double zenith /* = 0.0 */,
                       double gmt_offset /* = 99999.0 */) {
  return DateTime(timestamp, false).getSunInfo
    (static_cast<DateTime::SunInfoFormat>(format), latitude, longitude,
     zenith, gmt_offset, false);
}

Variant f_date_sunset(int64_t timestamp, int format /* = 0 */,
                      double latitude /* = 0.0 */, double longitude /* = 0.0 */,
                      double zenith /* = 0.0 */,
                      double gmt_offset /* = 99999.0 */) {
  return DateTime(timestamp, false).getSunInfo
    (static_cast<DateTime::SunInfoFormat>(format), latitude, longitude,
     zenith, gmt_offset, true);
}

///////////////////////////////////////////////////////////////////////////////
}
コード例 #2
0
ファイル: ext_datetime.cpp プロジェクト: yigithub/hiphop-php
namespace HPHP {
IMPLEMENT_DEFAULT_EXTENSION(date);
///////////////////////////////////////////////////////////////////////////////
// constants

const StaticString q_datetime_ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_datetime_COOKIE(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_datetime_ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO"));
const StaticString q_datetime_RFC822(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_datetime_RFC850(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_datetime_RFC1036(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_datetime_RFC1123(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_datetime_RFC2822(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_datetime_RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_datetime_RSS(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_datetime_W3C(LITSTR_INIT("Y-m-d\\TH:i:sP"));

const int64 q_datetimezone_AFRICA = 1;
const int64 q_datetimezone_AMERICA = 2;
const int64 q_datetimezone_ANTARCTICA = 4;
const int64 q_datetimezone_ARCTIC = 8;
const int64 q_datetimezone_ASIA = 16;
const int64 q_datetimezone_ATLANTIC = 32;
const int64 q_datetimezone_AUSTRALIA = 64;
const int64 q_datetimezone_EUROPE = 128;
const int64 q_datetimezone_INDIAN = 256;
const int64 q_datetimezone_PACIFIC = 512;
const int64 q_datetimezone_UTC = 1024;
const int64 q_datetimezone_ALL = 2047;
const int64 q_datetimezone_ALL_WITH_BC = 4095;
const int64 q_datetimezone_PER_COUNTRY = 4096;

///////////////////////////////////////////////////////////////////////////////
// methods

c_datetime::c_datetime() {
}

c_datetime::~c_datetime() {
}

void c_datetime::t___construct(CStrRef time /*= "now"*/,
                               CObjRef timezone /*= null_object*/) {
  m_dt = NEW(DateTime)(TimeStamp::Current());
  if (!time.empty()) {
    m_dt->fromString(time, c_datetimezone::unwrap(timezone));
  }
}

String c_datetime::t_format(CStrRef format) {
  return m_dt->toString(format, false);
}

int64 c_datetime::t_getoffset() {
  return m_dt->offset();
}

Variant c_datetime::t_gettimezone() {
  SmartObject<TimeZone> tz = m_dt->timezone();
  if (tz->isValid()) {
    return c_datetimezone::wrap(tz);
  }
  return false;
}

Object c_datetime::t_modify(CStrRef modify) {
  m_dt->modify(modify);
  return this;
}

Object c_datetime::t_setdate(int64 year, int64 month, int64 day) {
  m_dt->setDate(year, month, day);
  return this;
}

Object c_datetime::t_setisodate(int64 year, int64 week, int64 day /*= 1*/) {
  m_dt->setISODate(year, week, day);
  return this;
}

Object c_datetime::t_settime(int64 hour, int64 minute, int64 second /*= 0*/) {
  m_dt->setTime(hour, minute, second);
  return this;
}

Object c_datetime::t_settimezone(CObjRef timezone) {
  m_dt->setTimezone(c_datetimezone::unwrap(timezone));
  return this;
}

Variant c_datetime::t___destruct() {
  return null;
}

c_datetimezone::c_datetimezone() {
}

c_datetimezone::~c_datetimezone() {
}

void c_datetimezone::t___construct(CStrRef timezone) {
  m_tz = NEW(TimeZone)(timezone);
}

String c_datetimezone::t_getname() {
  return m_tz->name();
}

int64 c_datetimezone::t_getoffset(CObjRef datetime) {
  bool error;
  int64 ts = c_datetime::unwrap(datetime)->toTimeStamp(error);
  return m_tz->offset(ts);
}

Array c_datetimezone::t_gettransitions() {
  return m_tz->transitions();
}

Array c_datetimezone::ti_listabbreviations(const char* cls) {
  return TimeZone::GetAbbreviations();
}

Array c_datetimezone::ti_listidentifiers(const char* cls) {
  return TimeZone::GetNames();
}

Variant c_datetimezone::t___destruct() {
  return null;
}

///////////////////////////////////////////////////////////////////////////////
}
コード例 #3
0
ファイル: vm.cpp プロジェクト: KWMalik/hiphop-php
namespace VM {
///////////////////////////////////////////////////////////////////////////////

static StaticString s_stdclass(LITSTR_INIT("stdclass"));
static StaticString s_Exception(LITSTR_INIT("Exception"));
static StaticString s_BadMethodCallException(
  LITSTR_INIT("BadMethodCallException"));
static StaticString s_Directory(LITSTR_INIT("Directory"));
static StaticString s_RecursiveDirectoryIterator(
  LITSTR_INIT("RecursiveDirectoryIterator"));
static StaticString s_SplFileInfo(LITSTR_INIT("SplFileInfo"));
static StaticString s_SplFileObject(LITSTR_INIT("SplFileObject"));
static StaticString s_pinitSentinel(LITSTR_INIT("__pinitSentinel"));
static StaticString s_resource(LITSTR_INIT("__resource"));
static StaticString s_DOMException(LITSTR_INIT("DOMException"));
static StaticString s_PDOException(LITSTR_INIT("PDOException"));
static StaticString s_SoapFault(LITSTR_INIT("SoapFault"));

class VMClassInfoHook : public ClassInfoHook {
public:
  virtual Array getUserFunctions() const {
    return g_vmContext->getUserFunctionsInfo();
  }
  virtual Array getClasses() const {
    return Unit::getClassesInfo();
  }
  virtual Array getInterfaces() const {
    return Unit::getInterfacesInfo();
  }
  virtual Array getTraits() const {
    return Unit::getTraitsInfo();
  }
  virtual Array getConstants() const {
    return g_vmContext->getConstantsInfo();
  }
  virtual const ClassInfo::MethodInfo *findFunction(CStrRef name) const {
    return g_vmContext->findFunctionInfo(name);
  }
  virtual const ClassInfo *findClassLike(CStrRef name) const {
    const ClassInfo* ci;
    if ((ci = g_vmContext->findClassInfo(name)) != NULL
        || (ci = g_vmContext->findInterfaceInfo(name)) != NULL
        || (ci = g_vmContext->findTraitInfo(name)) != NULL) {
      return ci;
    }
    return NULL;
  }
  virtual const ClassInfo *findInterface(CStrRef name) const {
    return g_vmContext->findInterfaceInfo(name);
  }
  virtual const ClassInfo* findTrait(CStrRef name) const {
    return g_vmContext->findTraitInfo(name);
  }
  virtual const ClassInfo::ConstantInfo *findConstant(CStrRef name) const {
    return g_vmContext->findConstantInfo(name);
  }
};

static VMClassInfoHook vm_class_info_hook;

void ProcessInit() {
  // Initialize compiler state
  VM::compile_file(0, 0, MD5(), 0);
  // Install VM's ClassInfoHook
  ClassInfo::SetHook(&vm_class_info_hook);
  VM::Transl::Translator::Get()->processInit();

  Transl::TargetCache::requestInit();

  Unit* nativeFuncUnit = build_native_func_unit(hhbc_ext_funcs,
                                                hhbc_ext_funcs_count);
  SystemLib::s_nativeFuncUnit = nativeFuncUnit;

  // Search for systemlib.php in the following places:
  // 1) ${HHVM_LIB_PATH}/systemlib.php
  // 2) <dirname(realpath(hhvm))>/systemlib.php (requires proc filesystem)
  // 3) ${HPHP_LIB}/systemlib.php
  // 4) <HHVM_LIB_PATH_DEFAULT>/systemlib.php
  //
  // HHVM_LIB_PATH allows a manual override at runtime. If systemlib.php
  // exists next to the hhvm binary, that is likely to be the next best
  // version to use. The realpath()-based lookup will succeed as long as the
  // proc filesystem exists (e.g. on Linux and some FreeBSD configurations)
  // and no hard links are in use for the executable. Under certain build
  // situations, systemlib.php will not be generated next to hhvm binary, so
  // ${HPHP_LIB} is checked next. Failing all of those options, the
  // HHVM_LIB_PATH_DEFAULT-based lookup will always succeed, assuming that the
  // application was built and installed correctly.
  String currentDir = g_vmContext->getCwd();
  HPHP::Eval::PhpFile* file = NULL;

#define SYSTEMLIB_PHP "/systemlib.php"
#define LOOKUP_STR(s) do {                                                    \
  String systemlibPath = String(s) + SYSTEMLIB_PHP;                           \
  file = g_vmContext->lookupPhpFile(systemlibPath.get(), currentDir.data(),   \
                                    NULL);                                    \
} while (0)
#define LOOKUP_ENV(v) do {                                                    \
  if (!file) {                                                                \
    const char* s = getenv(#v);                                               \
    if (s && *s) {                                                            \
      LOOKUP_STR(s);                                                          \
    }                                                                         \
  }                                                                           \
} while (0)
#define LOOKUP_CPP(v) do {                                                    \
  if (!file) {                                                                \
    LOOKUP_STR(v);                                                            \
  }                                                                           \
} while (0)

  LOOKUP_ENV(HHVM_LIB_PATH);
  if (!file) {
    char hhvm_exe[PATH_MAX+1];
    char hhvm_path[PATH_MAX+1];
    ssize_t len = readlink("/proc/self/exe", hhvm_exe, sizeof(hhvm_exe));
    if (len >= 0) {
      hhvm_exe[len] = '\0';
      if (realpath(hhvm_exe, hhvm_path) != NULL) {
        char *hphp_lib = dirname(hhvm_path);
        LOOKUP_STR(hphp_lib);
      }
    }
  }
  LOOKUP_ENV(HPHP_LIB);
#ifdef HHVM_LIB_PATH_DEFAULT
  LOOKUP_CPP(HHVM_LIB_PATH_DEFAULT);
#endif
  if (!file) {
    // Die a horrible death.
    Logger::Error("Unable to find/load systemlib.php");
    _exit(1);
  }
#undef SYSTEMLIB_PHP
#undef LOOKUP_STR
#undef LOOKUP_ENV
#undef LOOKUP_CPP
  SystemLib::s_phpFile = file;
  file->incRef();
  SystemLib::s_unit = file->unit();

  // Load the systemlib unit to build the Class objects
  SystemLib::s_unit->merge();

  // load builtins
  SystemLib::s_nativeFuncUnit->merge();

#define INIT_SYSTEMLIB_CLASS_FIELD(cls)                                 \
  {                                                                     \
    Class *cls = *Unit::GetNamedEntity(s_##cls.get())->clsList();       \
    ASSERT(cls);                                                        \
    SystemLib::s_##cls##Class = cls;                                    \
  }

  // Stash a pointer to the VM Classes for stdclass, Exception,
  // pinitSentinel and resource
  INIT_SYSTEMLIB_CLASS_FIELD(stdclass);
  INIT_SYSTEMLIB_CLASS_FIELD(Exception);
  INIT_SYSTEMLIB_CLASS_FIELD(BadMethodCallException);
  INIT_SYSTEMLIB_CLASS_FIELD(Directory);
  INIT_SYSTEMLIB_CLASS_FIELD(RecursiveDirectoryIterator);
  INIT_SYSTEMLIB_CLASS_FIELD(SplFileInfo);
  INIT_SYSTEMLIB_CLASS_FIELD(SplFileObject);
  INIT_SYSTEMLIB_CLASS_FIELD(pinitSentinel);
  INIT_SYSTEMLIB_CLASS_FIELD(resource);
  INIT_SYSTEMLIB_CLASS_FIELD(DOMException);
  INIT_SYSTEMLIB_CLASS_FIELD(PDOException);
  INIT_SYSTEMLIB_CLASS_FIELD(SoapFault);

#undef INIT_SYSTEMLIB_CLASS_FIELD

  // We call a special bytecode emitter function to build the native
  // unit which will contain all of our cppext functions and classes.
  // Each function and method will have a bytecode body that will thunk
  // to the native implementation.
  Unit* nativeClassUnit = build_native_class_unit(hhbc_ext_classes,
                                                  hhbc_ext_class_count);
  SystemLib::s_nativeClassUnit = nativeClassUnit;

  // Load the nativelib unit to build the Class objects
  SystemLib::s_nativeClassUnit->merge();

  // Retrieve all of the class pointers
  for (long long i = 0LL; i < hhbc_ext_class_count; ++i) {
    const HhbcExtClassInfo* info = hhbc_ext_classes + i;
    const StringData* name = StringData::GetStaticString(info->m_name);
    const NamedEntity* ne = Unit::GetNamedEntity(name);
    Class* cls = Unit::lookupClass(ne);
    ASSERT(cls);
    const ObjectStaticCallbacks* osc =
      get_object_static_callbacks(info->m_name);
    ASSERT(osc != NULL);
    *(osc->os_cls_ptr) = cls;
  }

  Stack::ValidateStackSize();
  SystemLib::s_inited = true;

  // For debug build, run some quick unit tests at process start time
  if (debug) {
    VM::Transl::FixupMapUnitTest _;
  }
}

///////////////////////////////////////////////////////////////////////////////
}
コード例 #4
0
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////

String DebuggerThriftBuffer::readImpl() {
  assert(m_size <= BUFFER_SIZE);
  int nread = m_socket->readImpl(m_buffer, m_size);
  m_buffer[nread] = '\0';
  return String(m_buffer, nread, AttachLiteral);
}

void DebuggerThriftBuffer::flushImpl(CStrRef data) {
  m_socket->write(data);
}

void DebuggerThriftBuffer::throwError(const char *msg, int code) {
  throw Exception("Protocol Error (%d): %s", code, msg);
}

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

static StaticString s_hit_limit(LITSTR_INIT("Hit serialization limit"));
static StaticString s_unknown_exp(LITSTR_INIT("Hit unknown exception"));
static StaticString s_type_mismatch(LITSTR_INIT("Type mismatch"));

template<typename T>
static inline int serializeImpl(T data, String& sdata) {
  VariableSerializer vs(VariableSerializer::DebuggerSerialize);
  try {
    sdata = vs.serialize(data, true);
  } catch (StringBufferLimitException &e) {
    sdata = s_hit_limit;
    return DebuggerWireHelpers::HitLimit;
  } catch (...) {
    sdata = s_unknown_exp;
    return DebuggerWireHelpers::UnknownError;
  }
  return DebuggerWireHelpers::NoError;
}

static inline int unserializeImpl(CStrRef sdata, Variant& data) {
  if (sdata.same(s_hit_limit)) {
    return DebuggerWireHelpers::HitLimit;
  }
  if (sdata.same(s_unknown_exp)) {
    return DebuggerWireHelpers::UnknownError;
  }
  VariableUnserializer vu(sdata.data(), sdata.size(),
                          VariableUnserializer::Serialize, true);
  try {
    data = vu.unserialize();
  } catch (Exception &e) {
    data = null_variant;
    return DebuggerWireHelpers::UnknownError;
  }
  return DebuggerWireHelpers::NoError;
}

int DebuggerWireHelpers::WireSerialize(CArrRef data, String& sdata) {
  return serializeImpl(data, sdata);
}

int DebuggerWireHelpers::WireSerialize(CObjRef data, String& sdata) {
  return serializeImpl(data, sdata);
}

int DebuggerWireHelpers::WireSerialize(CVarRef data, String& sdata) {
  return serializeImpl(data, sdata);
}

int DebuggerWireHelpers::WireUnserialize(String& sdata, Array& data) {
  Variant v;
  int ret = unserializeImpl(sdata, v);
  if (ret != NoError) {
    return ret;
  }
  if (!v.isArray() && !v.isNull()) {
    sdata = s_type_mismatch;
    return TypeMismatch;
  }
  data = v;
  return NoError;
}

int DebuggerWireHelpers::WireUnserialize(String& sdata, Object& data) {
  Variant v;
  int ret = unserializeImpl(sdata, v);
  if (ret != NoError) {
    return ret;
  }
  if (!v.isObject() && !v.isNull()) {
    sdata = s_type_mismatch;
    return TypeMismatch;
  }
  data = v;
  return NoError;
}

int DebuggerWireHelpers::WireUnserialize(String& sdata, Variant& data) {
  return unserializeImpl(sdata, data);
}

///////////////////////////////////////////////////////////////////////////////
}
コード例 #5
0
ファイル: ext_datetime.cpp プロジェクト: hashaash/hiphop-php
namespace HPHP {
IMPLEMENT_DEFAULT_EXTENSION(date);
///////////////////////////////////////////////////////////////////////////////
// constants

const StaticString q_DateTime$$ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_DateTime$$COOKIE(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_DateTime$$ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO"));
const StaticString q_DateTime$$RFC822(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_DateTime$$RFC850(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_DateTime$$RFC1036(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_DateTime$$RFC1123(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime$$RFC2822(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime$$RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_DateTime$$RSS(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime$$W3C(LITSTR_INIT("Y-m-d\\TH:i:sP"));

const int64 q_DateTimeZone$$AFRICA = 1;
const int64 q_DateTimeZone$$AMERICA = 2;
const int64 q_DateTimeZone$$ANTARCTICA = 4;
const int64 q_DateTimeZone$$ARCTIC = 8;
const int64 q_DateTimeZone$$ASIA = 16;
const int64 q_DateTimeZone$$ATLANTIC = 32;
const int64 q_DateTimeZone$$AUSTRALIA = 64;
const int64 q_DateTimeZone$$EUROPE = 128;
const int64 q_DateTimeZone$$INDIAN = 256;
const int64 q_DateTimeZone$$PACIFIC = 512;
const int64 q_DateTimeZone$$UTC = 1024;
const int64 q_DateTimeZone$$ALL = 2047;
const int64 q_DateTimeZone$$ALL_WITH_BC = 4095;
const int64 q_DateTimeZone$$PER_COUNTRY = 4096;

///////////////////////////////////////////////////////////////////////////////
// methods

c_DateTime::c_DateTime(const ObjectStaticCallbacks *cb) : ExtObjectData(cb) {
  CPP_BUILTIN_CLASS_INIT(DateTime);
}

c_DateTime::~c_DateTime() {
}

void c_DateTime::t___construct(CStrRef time /*= "now"*/,
                               CObjRef timezone /*= null_object*/) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::__construct);
  m_dt = NEWOBJ(DateTime)(TimeStamp::Current());
  if (!time.empty()) {
    m_dt->fromString(time, c_DateTimeZone::unwrap(timezone));
  }
}

String c_DateTime::t_format(CStrRef format) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::format);
  return m_dt->toString(format, false);
}

int64 c_DateTime::t_getoffset() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::getoffset);
  return m_dt->offset();
}

Variant c_DateTime::t_gettimezone() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::gettimezone);
  SmartObject<TimeZone> tz = m_dt->timezone();
  if (tz->isValid()) {
    return c_DateTimeZone::wrap(tz);
  }
  return false;
}

Object c_DateTime::t_modify(CStrRef modify) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::modify);
  m_dt->modify(modify);
  return this;
}

Object c_DateTime::t_setdate(int64 year, int64 month, int64 day) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::setdate);
  m_dt->setDate(year, month, day);
  return this;
}

Object c_DateTime::t_setisodate(int64 year, int64 week, int64 day /*= 1*/) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::setisodate);
  m_dt->setISODate(year, week, day);
  return this;
}

Object c_DateTime::t_settime(int64 hour, int64 minute, int64 second /*= 0*/) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settime);
  m_dt->setTime(hour, minute, second);
  return this;
}

Object c_DateTime::t_settimezone(CObjRef timezone) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settimezone);
  m_dt->setTimezone(c_DateTimeZone::unwrap(timezone));
  return this;
}

Variant c_DateTime::t___destruct() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::__destruct);
  return null;
}

ObjectData *c_DateTime::clone() {
  ObjectData *obj = ObjectData::clone();
  c_DateTime *dt = static_cast<c_DateTime*>(obj);
  dt->m_dt = m_dt->cloneDateTime();
  return obj;
}

c_DateTimeZone::c_DateTimeZone(const ObjectStaticCallbacks *cb) :
    ExtObjectData(cb) {
  CPP_BUILTIN_CLASS_INIT(DateTimeZone);
}

c_DateTimeZone::~c_DateTimeZone() {
}

void c_DateTimeZone::t___construct(CStrRef timezone) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::__construct);
  m_tz = NEWOBJ(TimeZone)(timezone);
  if (!m_tz->isValid()) {
    std::string msg = "DateTimeZone::__construct(): Unknown or bad timezone (";
    msg += timezone.data();
    msg += ")";
    throw Object(SystemLib::AllocExceptionObject(msg));
  }
}

String c_DateTimeZone::t_getname() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getname);
  return m_tz->name();
}

int64 c_DateTimeZone::t_getoffset(CObjRef datetime) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getoffset);
  bool error;
  int64 ts = c_DateTime::unwrap(datetime)->toTimeStamp(error);
  return m_tz->offset(ts);
}

Array c_DateTimeZone::t_gettransitions() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::gettransitions);
  return m_tz->transitions();
}

Array c_DateTimeZone::ti_listabbreviations(const char* cls) {
  STATIC_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::listabbreviations);
  return TimeZone::GetAbbreviations();
}

Array c_DateTimeZone::ti_listidentifiers(const char* cls) {
  STATIC_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::listidentifiers);
  return TimeZone::GetNames();
}

Variant c_DateTimeZone::t___destruct() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::__destruct);
  return null;
}

ObjectData *c_DateTimeZone::clone() {
  ObjectData *obj = ObjectData::clone();
  c_DateTimeZone *dtz = static_cast<c_DateTimeZone*>(obj);
  dtz->m_tz = m_tz->cloneTimeZone();
  return obj;
}

///////////////////////////////////////////////////////////////////////////////
}
コード例 #6
0
ファイル: ext_datetime.cpp プロジェクト: 2bj/hhvm
namespace HPHP {

struct DateGlobals {
  double default_latitude;
  double default_longitude;
  double sunset_zenith;
  double sunrise_zenith;
};
IMPLEMENT_THREAD_LOCAL(DateGlobals, s_date_globals);

static class DateExtension : public Extension {
 public:
  DateExtension() : Extension("date", k_PHP_VERSION.c_str()) { }
  void threadInit() {
    IniSetting::Bind(
      this, IniSetting::PHP_INI_ALL,
      "date.timezone",
      g_context->getDefaultTimeZone().c_str(),
      IniSetting::SetAndGet<std::string>(
        dateTimezoneIniUpdate, dateTimezoneIniGet
      )
    );
    IniSetting::Bind(
      this, IniSetting::PHP_INI_ALL,
      "date.default_latitude", "31.7667",
      &s_date_globals->default_latitude
    );
    IniSetting::Bind(
      this, IniSetting::PHP_INI_ALL,
      "date.default_longitude", "35.2333",
      &s_date_globals->default_longitude
    );
    IniSetting::Bind(
      this, IniSetting::PHP_INI_ALL,
      "date.sunset_zenith", "90.583333",
      &s_date_globals->sunset_zenith
    );
    IniSetting::Bind(
      this, IniSetting::PHP_INI_ALL,
      "date.sunrise_zenith", "90.583333",
      &s_date_globals->sunrise_zenith
    );
  }

  double get_date_default_gmt_offset() {
    SmartResource<TimeZone> tzi = TimeZone::Current();
    // just get the offset form utc time
    // set the timestamp 0 is ok
    return tzi->offset(0) / 3600;
  }

 private:
  static bool dateTimezoneIniUpdate(const std::string& value) {
    if (value.empty()) {
      return false;
    }
    return f_date_default_timezone_set(value);
  }

  static std::string dateTimezoneIniGet() {
    auto ret = g_context->getTimeZone();
    if (ret.isNull()) {
      return "";
    }
    return ret.toCppString();
  }
} s_date_extension;

///////////////////////////////////////////////////////////////////////////////
// constants

const StaticString q_DateTime$$ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_DateTime$$COOKIE(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_DateTime$$ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO"));
const StaticString q_DateTime$$RFC822(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_DateTime$$RFC850(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_DateTime$$RFC1036(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_DateTime$$RFC1123(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime$$RFC2822(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime$$RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_DateTime$$RSS(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime$$W3C(LITSTR_INIT("Y-m-d\\TH:i:sP"));

const int64_t q_DateTimeZone$$AFRICA = 1;
const int64_t q_DateTimeZone$$AMERICA = 2;
const int64_t q_DateTimeZone$$ANTARCTICA = 4;
const int64_t q_DateTimeZone$$ARCTIC = 8;
const int64_t q_DateTimeZone$$ASIA = 16;
const int64_t q_DateTimeZone$$ATLANTIC = 32;
const int64_t q_DateTimeZone$$AUSTRALIA = 64;
const int64_t q_DateTimeZone$$EUROPE = 128;
const int64_t q_DateTimeZone$$INDIAN = 256;
const int64_t q_DateTimeZone$$PACIFIC = 512;
const int64_t q_DateTimeZone$$UTC = 1024;
const int64_t q_DateTimeZone$$ALL = 2047;
const int64_t q_DateTimeZone$$ALL_WITH_BC = 4095;
const int64_t q_DateTimeZone$$PER_COUNTRY = 4096;

///////////////////////////////////////////////////////////////////////////////
// methods

Object c_DateTime::t_add(const Object& interval) {
  m_dt->add(c_DateInterval::unwrap(interval));
  return this;
}

void c_DateTime::t___construct(const String& time /*= "now"*/,
                               const Object& timezone /*= null_object*/) {
  m_dt = NEWOBJ(DateTime)(TimeStamp::Current());
  if (!time.empty()) {
    m_dt->fromString(time, c_DateTimeZone::unwrap(timezone));
  } else if (!timezone.isNull()) {
    // We still have to tell the underlying DateTime the timezone incase they
    // call setTimestamp or something else later
    m_dt->setTimezone(c_DateTimeZone::unwrap(timezone));
  }
}

Variant c_DateTime::ti_createfromformat(const String& format,
                                        const String& time,
                                        const Object& timezone /*= null_object */) {
  c_DateTime *datetime = NEWOBJ(c_DateTime);
  const auto curr = (format.find("!") != String::npos) ? 0 : f_time() ;
  datetime->m_dt = NEWOBJ(DateTime(curr, false));
  if (!datetime->m_dt->fromString(time, c_DateTimeZone::unwrap(timezone),
                                 format.data(), false)) {
    return false;
  }

  return datetime;
}

Object c_DateTime::t_diff(const Object& datetime2, bool absolute) {
  return c_DateInterval::wrap(m_dt->diff(c_DateTime::unwrap(datetime2),
                                         absolute));
}

String c_DateTime::t_format(const String& format) {
  return m_dt->toString(format, false);
}

const StaticString s_data("data");
const StaticString s_getTimestamp("getTimestamp");

int64_t c_DateTime::GetTimestamp(const Object& obj) {
  if (LIKELY(obj.is<c_DateTime>())) {
    return obj.getTyped<c_DateTime>(true)->t_gettimestamp();
  }
  assert(obj->instanceof(SystemLib::s_DateTimeInterfaceClass));
  Variant result = obj->o_invoke(s_getTimestamp, Array::Create());
  return result.toInt64();
}

int64_t c_DateTime::GetTimestamp(const ObjectData* od) {
  return GetTimestamp(Object(const_cast<ObjectData*>(od)));
}

SmartResource<DateTime> c_DateTime::unwrap(const Object& datetime) {
  if (LIKELY(datetime.is<c_DateTime>())) {
    SmartObject<c_DateTime> cdt = datetime.getTyped<c_DateTime>(true);
    if (cdt.get() == nullptr)
      return SmartResource<DateTime>();
    return cdt->m_dt;
  }
  if (datetime->instanceof(SystemLib::s_DateTimeImmutableClass)) {
    bool visible, accessible, unset;
    TypedValue* tv = datetime->getProp(SystemLib::s_DateTimeImmutableClass,
                                       s_data.get(),
                                       visible,
                                       accessible,
                                       unset);
    assert(tv->m_type == KindOfObject);
    Object impl(tv->m_data.pobj);
    return unwrap(impl);
  }
  return SmartResource<DateTime>();
}

const StaticString
  s_warning_count("warning_count"),
  s_warnings("warnings"),
  s_error_count("error_count"),
  s_errors("errors");

Array c_DateTime::ti_getlasterrors() {
  Array errors = DateTime::getLastErrors();
  Array warnings = DateTime::getLastWarnings();
  Array ret = Array::Create();

  ret.add(s_warning_count, warnings.size());
  ret.add(s_warnings, warnings);
  ret.add(s_error_count, errors.size());
  ret.add(s_errors, errors);

  return ret;
}

int64_t c_DateTime::t_getoffset() {
  return m_dt->offset();
}

int64_t c_DateTime::t_gettimestamp() {
  return gettimestamp();
}

int64_t c_DateTime::gettimestamp() const {
  bool err = false;
  return m_dt->toTimeStamp(err);
}

Variant c_DateTime::t_gettimezone() {
  SmartResource<TimeZone> tz = m_dt->timezone();
  if (tz->isValid()) {
    return c_DateTimeZone::wrap(tz);
  }
  return false;
}

Object c_DateTime::t_modify(const String& modify) {
  m_dt->modify(modify);
  return this;
}

Object c_DateTime::t_setdate(int64_t year, int64_t month, int64_t day) {
  m_dt->setDate(year, month, day);
  return this;
}

Object c_DateTime::t_setisodate(int64_t year, int64_t week,
                                int64_t day /*= 1*/) {
  m_dt->setISODate(year, week, day);
  return this;
}

Object c_DateTime::t_settime(int64_t hour, int64_t minute,
                             int64_t second /*= 0*/) {
  m_dt->setTime(hour, minute, second);
  return this;
}

Object c_DateTime::t_settimestamp(int64_t unixtimestamp) {
  m_dt->fromTimeStamp(unixtimestamp, false);
  return this;
}

Object c_DateTime::t_settimezone(const Object& timezone) {
  m_dt->setTimezone(c_DateTimeZone::unwrap(timezone));
  return this;
}

Object c_DateTime::t_sub(const Object& interval) {
  m_dt->sub(c_DateInterval::unwrap(interval));
  return this;
}

const StaticString
  s_c("c"),
  s__date_time("_date_time");

Array c_DateTime::t___sleep() {
  o_set(s__date_time, t_format(s_c));
  return make_packed_array(s__date_time);
}

void c_DateTime::t___wakeup() {
  t___construct(o_get(s__date_time));
  unsetProp(getVMClass(), s__date_time.get());
}

const StaticString
  s_date("date"),
  s_timezone_type("timezone_type"),
  s_timezone("timezone"),
  s_ISOformat("Y-m-d H:i:s");

Array c_DateTime::t___debuginfo() {
  ArrayInit ret(3);
  ret.set(s_date, t_format(s_ISOformat));
  ret.set(s_timezone_type, m_dt->zoneType());
  ret.set(s_timezone, m_dt->timezone()->name());
  return ret.create();
}

c_DateTime* c_DateTime::Clone(ObjectData* obj) {
  c_DateTime* dt = static_cast<c_DateTime*>(obj->cloneImpl());
  dt->m_dt = static_cast<c_DateTime*>(obj)->m_dt->cloneDateTime();
  return dt;
}

void c_DateTimeZone::t___construct(const String& timezone) {
  m_tz = NEWOBJ(TimeZone)(timezone);
  if (!m_tz->isValid()) {
    std::string msg = "DateTimeZone::__construct(): Unknown or bad timezone (";
    msg += timezone.data();
    msg += ")";
    throw Object(SystemLib::AllocExceptionObject(msg));
  }
}

Array c_DateTimeZone::t_getlocation() {
  return m_tz->getLocation();
}

String c_DateTimeZone::t_getname() {
  return m_tz->name();
}

int64_t c_DateTimeZone::t_getoffset(const Object& datetime) {
  bool error;
  int64_t ts = c_DateTime::unwrap(datetime)->toTimeStamp(error);
  return m_tz->offset(ts);
}

Array c_DateTimeZone::t_gettransitions() {
  return m_tz->transitions();
}

Array c_DateTimeZone::ti_listabbreviations() {
  return TimeZone::GetAbbreviations();
}

Array c_DateTimeZone::ti_listidentifiers() {
  return TimeZone::GetNames();
}

c_DateTimeZone* c_DateTimeZone::Clone(ObjectData* obj) {
  c_DateTimeZone* dtz = static_cast<c_DateTimeZone*>(obj->cloneImpl());
  dtz->m_tz = static_cast<c_DateTimeZone*>(obj)->m_tz->cloneTimeZone();
  return dtz;
}

void c_DateInterval::t___construct(const String& interval_spec) {
  m_di = NEWOBJ(DateInterval)(interval_spec);
  if (!m_di->isValid()) {
    std::string msg = "DateInterval::__construct: Invalid interval (";
    msg += interval_spec.data();
    msg += ")";
    throw Object(SystemLib::AllocExceptionObject(msg));
  }
}

const StaticString
  s_y("y"),
  s_m("m"),
  s_d("d"),
  s_h("h"),
  s_i("i"),
  s_s("s"),
  s_invert("invert"),
  s_days("days");

Variant c_DateInterval::t___get(Variant member) {
  if (member.isString()) {
    if (same(member, s_y))      return m_di->getYears();
    if (same(member, s_m))      return m_di->getMonths();
    if (same(member, s_d))      return m_di->getDays();
    if (same(member, s_h))      return m_di->getHours();
    if (same(member, s_i))      return m_di->getMinutes();
    if (same(member, s_s))      return m_di->getSeconds();
    if (same(member, s_invert)) return m_di->isInverted();
    if (same(member, s_days)) {
      if (m_di->haveTotalDays()) {
        return m_di->getTotalDays();
      } else {
        return false;
      }
    }
  }
  std::string msg = "Undefined property '";
  msg += member.toString().data();
  msg += ") on DateInterval object";
  throw Object(SystemLib::AllocExceptionObject(msg));
}

Variant c_DateInterval::t___set(Variant member, Variant value) {
  if (member.isString()) {
    if (same(member, s_y)) {
      m_di->setYears(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_m)) {
      m_di->setMonths(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_d)) {
      m_di->setDays(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_h)) {
      m_di->setHours(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_i)) {
      m_di->setMinutes(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_s)) {
      m_di->setSeconds(value.toInt64());
      return uninit_null();
    }
    if (same(member, s_invert)) {
      m_di->setInverted(value.toBoolean());
      return uninit_null();
    }
    if (same(member, s_days)) {
      m_di->setTotalDays(value.toInt64());
      return uninit_null();
    }
  }

  std::string msg = "Undefined property '";
  msg += member.toString().data();
  msg += ") on DateInterval object";
  throw Object(SystemLib::AllocExceptionObject(msg));
}

Object c_DateInterval::ti_createfromdatestring(const String& time) {
  SmartResource<DateInterval> di(NEWOBJ(DateInterval)(time, true));
  return c_DateInterval::wrap(di);
}

String c_DateInterval::t_format(const String& format) {
  return m_di->format(format);
}

c_DateInterval* c_DateInterval::Clone(ObjectData* obj) {
  c_DateInterval *di = static_cast<c_DateInterval*>(obj->cloneImpl());
  di->m_di = static_cast<c_DateInterval*>(obj)->m_di->cloneDateInterval();
  return di;
}

///////////////////////////////////////////////////////////////////////////////
// timestamp

Variant f_gettimeofday(bool return_float /* = false */) {
  if (return_float) {
    return TimeStamp::CurrentSecond();
  }
  return TimeStamp::CurrentTime();
}

Variant f_microtime(bool get_as_float /* = false */) {
  if (get_as_float) {
    return TimeStamp::CurrentSecond();
  }
  return TimeStamp::CurrentMicroTime();
}

int64_t f_time() {
  return time(0);
}

Variant f_mktime(int hour /* = INT_MAX */, int minute /* = INT_MAX */,
                 int second /* = INT_MAX */, int month /* = INT_MAX */,
                 int day /* = INT_MAX */, int year /* = INT_MAX */) {
  bool error;
  int64_t ts = TimeStamp::Get(error, hour, minute, second, month, day, year,
                              false);
  if (error) return false;
  return ts;
}

Variant f_gmmktime(int hour /* = INT_MAX */, int minute /* = INT_MAX */,
                   int second /* = INT_MAX */,
                   int month /* = INT_MAX */, int day /* = INT_MAX */,
                   int year /* = INT_MAX */) {
  bool error;
  int64_t ts = TimeStamp::Get(error, hour, minute, second, month, day, year,
                              true);
  if (error) return false;
  return ts;
}

Variant f_idate(const String& format,
                int64_t timestamp /* = TimeStamp::Current() */) {
  if (format.size() != 1) {
    throw_invalid_argument("format: %s", format.data());
    return false;
  }
  int64_t ret = DateTime(timestamp, false).toInteger(*format.data());
  if (ret == -1) return false;
  return ret;
}

Variant f_date(const String& format,
               int64_t timestamp /* = TimeStamp::Current() */) {
  if (format.empty()) return "";
  String ret = DateTime(timestamp, false).toString(format, false);
  if (ret.isNull()) return false;
  return ret;
}

Variant f_gmdate(const String& format,
                 int64_t timestamp /* = TimeStamp::Current() */) {
  String ret = DateTime(timestamp, true).toString(format, false);
  if (ret.isNull()) return false;
  return ret;
}

Variant f_strftime(const String& format,
                   int64_t timestamp /* = TimeStamp::Current() */) {
  String ret = DateTime(timestamp, false).toString(format, true);
  if (ret.isNull()) return false;
  return ret;
}

String f_gmstrftime(const String& format,
                    int64_t timestamp /* = TimeStamp::Current() */) {
  String ret = DateTime(timestamp, true).toString(format, true);
  if (ret.isNull()) return false;
  return ret;
}

Array f_getdate(int64_t timestamp /* = TimeStamp::Current() */) {
  return DateTime(timestamp, false).toArray(DateTime::ArrayFormat::TimeMap);
}

Array f_localtime(int64_t timestamp /* = TimeStamp::Current() */,
                  bool is_associative /* = false */) {
  DateTime::ArrayFormat format =
    is_associative ? DateTime::ArrayFormat::TmMap :
                     DateTime::ArrayFormat::TmVector;
  return DateTime(timestamp, false).toArray(format);
}

Variant f_strptime(const String& date, const String& format) {
  Array ret = DateTime::ParseAsStrptime(format, date);
  if (ret.empty()) {
    return false;
  }
  return ret;
}

Variant f_strtotime(const String& input,
                    int64_t timestamp /* = TimeStamp::Current() */) {
  if (input.empty()) {
    return false;
  }

  DateTime dt(timestamp);
  if (!dt.fromString(input, SmartResource<TimeZone>(), nullptr, false)) {
    return false;
  }
  bool error;
  return dt.toTimeStamp(error);
}

///////////////////////////////////////////////////////////////////////////////
// timezone

String f_date_default_timezone_get() {
  return TimeZone::Current()->name();
}

bool f_date_default_timezone_set(const String& name) {
  return TimeZone::SetCurrent(name);
}

Array f_timezone_identifiers_list() {
  return c_DateTimeZone::ti_listidentifiers();
}

Array f_timezone_abbreviations_list() {
  return c_DateTimeZone::ti_listabbreviations();
}

Variant f_timezone_name_from_abbr(const String& abbr, int gmtoffset /* = -1 */,
                                  bool isdst /* = true */) {
  String ret = TimeZone::AbbreviationToName(abbr, gmtoffset, isdst);
  if (ret.isNull()) {
    return false;
  }
  return ret;
}

Object f_timezone_open(const String& timezone) {
  c_DateTimeZone *ctz = NEWOBJ(c_DateTimeZone)();
  Object ret(ctz);
  ctz->t___construct(timezone);
  return ret;
}

Array f_timezone_location_get(const Object& timezone) {
  return timezone.getTyped<c_DateTimeZone>()->t_getlocation();
}

String f_timezone_name_get(const Object& object) {
  return object.getTyped<c_DateTimeZone>()->t_getname();
}

int64_t f_timezone_offset_get(const Object& object, const Object& dt) {
  return object.getTyped<c_DateTimeZone>()->t_getoffset(dt);
}

Array f_timezone_transitions_get(const Object& object) {
  return object.getTyped<c_DateTimeZone>()->t_gettransitions();
}

String f_timezone_version_get() {
  return TimeZone::getVersion();
}

///////////////////////////////////////////////////////////////////////////////
// datetime

bool f_checkdate(int month, int day, int year) {
  return DateTime::IsValid(year, month, day);
}

Object f_date_add(const Object& datetime, const Object& interval) {
  return datetime.getTyped<c_DateTime>()->
    t_add(interval.getTyped<c_DateInterval>());
}

Variant f_date_create_from_format(const String& format,
                                 const String& time,
                                 const Object& timezone /* = null_object */) {
  return c_DateTime::ti_createfromformat(format, time, timezone);
}

Variant f_date_parse_from_format(const String& format, const String& date) {
  Array ret = DateTime::Parse(format, date);
  if (ret.empty()) {
    return false;
  }
  return ret;
}

Variant f_date_create(const String& time /* = null_string */,
                      const Object& timezone /* = null_object */) {
  c_DateTime *cdt = NEWOBJ(c_DateTime)();
  Object ret(cdt);
  // Don't set the time here because it will throw if it is bad
  cdt->t___construct();
  if (time.empty()) {
    // zend does this, so so do we
    return ret;
  }
  auto dt = c_DateTime::unwrap(ret);
  if (!dt->fromString(time, c_DateTimeZone::unwrap(timezone), nullptr, false)) {
    return false;
  }
  return ret;
}

void f_date_date_set(const Object& object, int year, int month, int day) {
  object.getTyped<c_DateTime>()->t_setdate(year, month, day);
}

Object f_date_diff(const Object& datetime,
                   const Object& datetime2,
                   bool absolute /* = false */) {
  return datetime.getTyped<c_DateTime>()->
    t_diff(datetime2.getTyped<c_DateTime>(), absolute);
}

void f_date_isodate_set(const Object& object, int year, int week,
                        int day /* = 1 */) {
  object.getTyped<c_DateTime>()->t_setisodate(year, week, day);
}

String f_date_format(const Object& object, const String& format) {
  return object.getTyped<c_DateTime>()->t_format(format);
}

Array f_date_get_last_errors() {
  return c_DateTime::ti_getlasterrors();
}

Object f_date_interval_create_from_date_string(const String& time) {
  return c_DateInterval::ti_createfromdatestring(time);
}

String f_date_interval_format(const Object& interval, const String& format_spec) {
  return interval.getTyped<c_DateInterval>()->t_format(format_spec);
}

void f_date_modify(const Object& object, const String& modify) {
  object.getTyped<c_DateTime>()->t_modify(modify);
}

Variant f_date_parse(const String& date) {
  Array ret = DateTime::Parse(date);
  if (ret.empty()) {
    return false;
  }
  return ret;
}

void f_date_time_set(const Object& object, int hour, int minute,
                     int second /* = 0 */) {
  object.getTyped<c_DateTime>()->t_settime(hour, minute, second);
}

int64_t f_date_timestamp_get(const Object& datetime) {
  return datetime.getTyped<c_DateTime>()->t_gettimestamp();
}

Object f_date_timestamp_set(const Object& datetime, int64_t timestamp) {
  return datetime.getTyped<c_DateTime>()->
    t_settimestamp(timestamp);
}

Variant f_date_timezone_get(const Object& object) {
  return object.getTyped<c_DateTime>()->t_gettimezone();
}

void f_date_timezone_set(const Object& object, const Object& timezone) {
  object.getTyped<c_DateTime>()->t_settimezone(timezone);
}

Object f_date_sub(const Object& datetime, const Object& interval) {
  return datetime.getTyped<c_DateTime>()->
    t_sub(interval.getTyped<c_DateInterval>());
}

///////////////////////////////////////////////////////////////////////////////
// sun

double get_date_default_latitude() {
  return s_date_globals->default_latitude;
}

double get_date_default_longitude() {
  return s_date_globals->default_longitude;
}

double get_date_default_sunset_zenith() {
  return s_date_globals->sunset_zenith;
}

double get_date_default_sunrise_zenith() {
  return s_date_globals->sunrise_zenith;
}

double get_date_default_gmt_offset() {
  return s_date_extension.get_date_default_gmt_offset();
}

Array f_date_sun_info(int64_t ts, double latitude, double longitude) {
  return DateTime(ts, false).getSunInfo(latitude, longitude);
}

Variant f_date_sunrise(int64_t timestamp,
                       int format,
                       double latitude,
                       double longitude,
                       double zenith,
                       double gmt_offset) {
  return DateTime(timestamp, false).getSunInfo
    (static_cast<DateTime::SunInfoFormat>(format), latitude, longitude,
     zenith, gmt_offset, false);
}

Variant f_date_sunset(int64_t timestamp,
                      int format,
                      double latitude,
                      double longitude,
                      double zenith,
                      double gmt_offset) {
  return DateTime(timestamp, false).getSunInfo
    (static_cast<DateTime::SunInfoFormat>(format), latitude, longitude,
     zenith, gmt_offset, true);
}

///////////////////////////////////////////////////////////////////////////////
}
コード例 #7
0
ファイル: ext_mail.cpp プロジェクト: shixiao/hhvm
namespace HPHP {

///////////////////////////////////////////////////////////////////////////////
// utility functions

/**
 * Removes whitespaces from the end, and replaces control characters with ' '
 * from the beginning.
 */
static String php_trim(const String& str) {
  std::string s(str.c_str());
  unsigned int l = s.length();
  while (l > 0 && isspace((unsigned char)s[l - 1])) {
    l--;
  }
  for (unsigned int i = 0; i < l; i++) {
    if (iscntrl((unsigned char)s[i])) {
      if (i + 2 < l && s[i] == '\r' && s[i + 1] == '\n' &&
          (s[i + 2] == ' ' || s[i + 2] == '\t')) {
        i += 2;
        while (i + 1 < l && (s[i + 1] == ' ' || s[i + 1] == '\t')) {
          i++;
        }
        continue;
      }
      s[i] = ' ';
    }
  }
  return s.substr(0, l);
}

bool php_mail(const String& to, const String& subject, const String& message,
              const String& headers, const String& extra_cmd) {
  // assumes we always have sendmail installed
  always_assert(!RuntimeOption::SendmailPath.empty());

  std::ostringstream os;
  os << RuntimeOption::SendmailPath;
  if (!extra_cmd.empty()) {
    os << ' ' << extra_cmd.c_str();
  }

  errno = 0;
  FILE *sendmail = popen(os.str().c_str(), "w");
  if (sendmail == NULL || EACCES == errno) {
    raise_warning("Unable to execute %s",
                  RuntimeOption::SendmailPath.c_str());
    return false;
  }

  fprintf(sendmail, "To: %s\n", to.c_str());
  fprintf(sendmail, "Subject: %s\n", subject.c_str());
  if (!headers.empty()) {
    fprintf(sendmail, "%s\n", headers.c_str());
  }
  fprintf(sendmail, "\n%s\n", message.c_str());

  int ret = pclose(sendmail);
  return (!ret);
}

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

const StaticString
  s_zero(LITSTR_INIT("\0")),
  s_space(" ");

bool HHVM_FUNCTION(mail,
                   const String& to,
                   const String& subject,
                   const String& message,
                   const String& additional_headers /* = null_string */,
                   const String& additional_parameters /* = null_string */) {

  // replace \0 with spaces
  String to2 = string_replace(to, s_zero, s_space);
  String subject2 = string_replace(subject, s_zero, s_space);
  String message2 = string_replace(message, s_zero, s_space);
  String headers2;
  if (!additional_headers.empty()) {
    headers2 = string_replace(additional_headers, s_zero, s_space);
  }
  String params2;
  if (!additional_parameters.empty()) {
    params2 = string_replace(additional_parameters, s_zero, s_space);
  }

  to2 = php_trim(to2);
  subject2 = php_trim(subject2);

  if (!RuntimeOption::MailForceExtraParameters.empty()) {
    params2 = string_escape_shell_cmd(
      RuntimeOption::MailForceExtraParameters.c_str());
  } else {
    params2 = string_escape_shell_cmd(params2.c_str());
  }

  return php_mail(to2, subject2, message2, headers2, params2);
}

int64_t HHVM_FUNCTION(ezmlm_hash, const String& addr) {
  unsigned int h = 5381;
  int str_len = addr.length();
  for (int i = 0; i < str_len; i++) {
    h = (h + (h << 5)) ^
        ((unsigned long)tolower(addr.charAt(i)));
  }
  h = (h % 53);
  return (int64_t)h;
}

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

class MailExtension final : public Extension {
 public:
  MailExtension() : Extension("mail") { }
  void moduleInit() override {
    HHVM_FE(mail);
    HHVM_FE(ezmlm_hash);
    loadSystemlib();
  }
} s_mail_extension;

///////////////////////////////////////////////////////////////////////////////
}
コード例 #8
0
ファイル: ext_datetime.cpp プロジェクト: lcastelli/hiphop-php
namespace HPHP {
IMPLEMENT_DEFAULT_EXTENSION(date);
///////////////////////////////////////////////////////////////////////////////
// constants

const StaticString q_DateTime_ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_DateTime_COOKIE(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_DateTime_ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO"));
const StaticString q_DateTime_RFC822(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_DateTime_RFC850(LITSTR_INIT("l, d-M-y H:i:s T"));
const StaticString q_DateTime_RFC1036(LITSTR_INIT("D, d M y H:i:s O"));
const StaticString q_DateTime_RFC1123(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime_RFC2822(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime_RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP"));
const StaticString q_DateTime_RSS(LITSTR_INIT("D, d M Y H:i:s O"));
const StaticString q_DateTime_W3C(LITSTR_INIT("Y-m-d\\TH:i:sP"));

const int64 q_DateTimeZone_AFRICA      = TimeZone::AFRICA;
const int64 q_DateTimeZone_AMERICA     = TimeZone::AMERICA;
const int64 q_DateTimeZone_ANTARCTICA  = TimeZone::ANTARCTICA;
const int64 q_DateTimeZone_ARCTIC      = TimeZone::ARCTIC;
const int64 q_DateTimeZone_ASIA        = TimeZone::ASIA;
const int64 q_DateTimeZone_ATLANTIC    = TimeZone::ATLANTIC;
const int64 q_DateTimeZone_AUSTRALIA   = TimeZone::AUSTRALIA;
const int64 q_DateTimeZone_EUROPE      = TimeZone::EUROPE;
const int64 q_DateTimeZone_INDIAN      = TimeZone::INDIAN;
const int64 q_DateTimeZone_PACIFIC     = TimeZone::PACIFIC;
const int64 q_DateTimeZone_UTC         = TimeZone::UTC;
const int64 q_DateTimeZone_ALL         = TimeZone::ALL;
const int64 q_DateTimeZone_ALL_WITH_BC = TimeZone::ALL_WITH_BC;
const int64 q_DateTimeZone_PER_COUNTRY = TimeZone::PER_COUNTRY;

///////////////////////////////////////////////////////////////////////////////
// methods

#define REL_TIME_INVALID_DAYS -99999

static void rel_time_to_interval(timelib_rel_time *relTime,
                                 c_DateInterval *interval) {
  interval->m_y = relTime->y;
  interval->m_m = relTime->m;
  interval->m_d = relTime->d;
  interval->m_h = relTime->h;
  interval->m_i = relTime->i;
  interval->m_s = relTime->s;
  interval->m_invert = relTime->invert;
  if (relTime->days != REL_TIME_INVALID_DAYS) {
    interval->m_days = relTime->days;
  } else {
    interval->m_days = null;
  }
}

static void interval_to_rel_time(c_DateInterval *interval,
                                  timelib_rel_time *relTime) {
  relTime->y = interval->m_y;
  relTime->m = interval->m_m;
  relTime->d = interval->m_d;
  relTime->h = interval->m_h;
  relTime->i = interval->m_i;
  relTime->s = interval->m_s;
  relTime->invert = interval->m_invert;
  if (interval->m_days.isInteger()) {
    relTime->days = interval->m_days.toInt64();
  } else {
    relTime->days = REL_TIME_INVALID_DAYS;
  }
}

c_DateTime::c_DateTime() {
}

c_DateTime::~c_DateTime() {
}

void c_DateTime::t___construct(CStrRef time /*= "now"*/,
                               CObjRef timezone /*= null_object*/) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::__construct);
  m_dt = NEWOBJ(DateTime)(TimeStamp::Current());
  if (!time.empty()) {
    m_dt->fromString(time, c_DateTimeZone::unwrap(timezone));
  }
}

Object c_DateTime::ti_createfromformat(const char* cls , CStrRef format,
                                       CStrRef time,
                                       CObjRef timezone /*= null_object*/) {
  STATIC_METHOD_INJECTION_BUILTIN(DateTime, DateTime::createfromformat);
  c_DateTime *datetime = NEWOBJ(c_DateTime);
  datetime->m_dt = NEWOBJ(DateTime);
  datetime->m_dt->fromString(time, c_DateTimeZone::unwrap(timezone),
                             format.data());
  return datetime;
}

Object c_DateTime::t_diff(CObjRef datetime2, bool absolute /*= false*/) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::diff);
  timelib_rel_time *relTime = m_dt->diff(*c_DateTime::unwrap(datetime2).get());
  c_DateInterval *interval = NEWOBJ(c_DateInterval);
  rel_time_to_interval(relTime, interval);
  timelib_rel_time_dtor(relTime);
  return interval;
}

Object c_DateTime::t_add(CObjRef interval) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::add);
  c_DateInterval *tInterval = interval.getTyped<c_DateInterval>();
  timelib_rel_time *relTime = timelib_rel_time_ctor();
  interval_to_rel_time(tInterval, relTime);
  m_dt->add(*relTime);
  timelib_rel_time_dtor(relTime);
  return this;
}

Object c_DateTime::t_sub(CObjRef interval) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::sub);
  c_DateInterval *tInterval = interval.getTyped<c_DateInterval>();
  timelib_rel_time *relTime = timelib_rel_time_ctor();
  interval_to_rel_time(tInterval, relTime);
  m_dt->sub(*relTime);
  timelib_rel_time_dtor(relTime);
  return this;
}

String c_DateTime::t_format(CStrRef format) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::format);
  return m_dt->toString(format, false);
}

Variant c_DateTime::ti_getlasterrors(const char* cls) {
  STATIC_METHOD_INJECTION_BUILTIN(DateTime, DateTime::getlasterrors);
  return DateTime::s_last_errors->get();
}

int64 c_DateTime::t_getoffset() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::getoffset);
  return m_dt->offset();
}

Variant c_DateTime::t_gettimezone() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::gettimezone);
  SmartObject<TimeZone> tz = m_dt->timezone();
  if (tz->isValid()) {
    return c_DateTimeZone::wrap(tz);
  }
  return false;
}

Object c_DateTime::t_modify(CStrRef modify) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::modify);
  m_dt->modify(modify);
  return this;
}

Object c_DateTime::t_setdate(int64 year, int64 month, int64 day) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::setdate);
  m_dt->setDate(year, month, day);
  return this;
}

Object c_DateTime::t_setisodate(int64 year, int64 week, int64 day /*= 1*/) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::setisodate);
  m_dt->setISODate(year, week, day);
  return this;
}

Object c_DateTime::t_settime(int64 hour, int64 minute, int64 second /*= 0*/) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settime);
  m_dt->setTime(hour, minute, second);
  return this;
}

Variant c_DateTime::t_gettimestamp() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::gettimestamp);
  bool err;
  int64 timestamp = m_dt->toTimeStamp(err);
  if (!err) {
    return timestamp;
  } else {
    return false;
  }
}

Object c_DateTime::t_settimestamp(int64 unixtimestamp) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settimestamp);
  m_dt->fromTimeStamp(unixtimestamp, false);
  return this;
}

Object c_DateTime::t_settimezone(CObjRef timezone) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settimezone);
  m_dt->setTimezone(c_DateTimeZone::unwrap(timezone));
  return this;
}

Variant c_DateTime::t___destruct() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::__destruct);
  return null;
}

ObjectData *c_DateTime::clone() {
  ObjectData *obj = cloneImpl();
  c_DateTime *dt = static_cast<c_DateTime*>(obj);
  dt->m_dt = m_dt->cloneDateTime();
  return obj;
}

c_DateTimeZone::c_DateTimeZone() {
}

c_DateTimeZone::~c_DateTimeZone() {
}

void c_DateTimeZone::t___construct(CStrRef timezone) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::__construct);
  m_tz = NEWOBJ(TimeZone)(timezone);
  if (!m_tz->isValid()) {
    raise_error("DateTimeZone::__construct(): Unknown or bad timezone (%s)",
                timezone.data());
  }
}

String c_DateTimeZone::t_getname() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getname);
  return m_tz->name();
}

int64 c_DateTimeZone::t_getoffset(CObjRef datetime) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getoffset);
  bool error;
  int64 ts = c_DateTime::unwrap(datetime)->toTimeStamp(error);
  return m_tz->offset(ts);
}

Array c_DateTimeZone::t_getlocation() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getlocation);
  return m_tz->getLocation();
}

Array c_DateTimeZone::t_gettransitions(int64 timestamp_begin /*= LLONG_MIN*/,
                                       int64 timestamp_end /*= LLONG_MAX*/) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::gettransitions);
  return m_tz->transitions(timestamp_begin, timestamp_end);
}

Array c_DateTimeZone::ti_listabbreviations(const char* cls) {
  STATIC_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::listabbreviations);
  return TimeZone::GetAbbreviations();
}

Array c_DateTimeZone::ti_listidentifiers(const char* cls, int64 what /*= 2047*/,
                                         CStrRef country /*= null_string*/) {
  STATIC_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::listidentifiers);
  return TimeZone::GetNames(what, country);
}

Variant c_DateTimeZone::t___destruct() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::__destruct);
  return null;
}

ObjectData *c_DateTimeZone::clone() {
  ObjectData *obj = cloneImpl();
  c_DateTimeZone *dtz = static_cast<c_DateTimeZone*>(obj);
  dtz->m_tz = m_tz->cloneTimeZone();
  return obj;
}

c_DateInterval::c_DateInterval() {
}

c_DateInterval::~c_DateInterval() {
}

void c_DateInterval::t___construct(CStrRef interval_spec) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateInterval, DateInterval::__construct);
  timelib_time     *b = NULL, *e = NULL;
  timelib_rel_time *relTime = NULL;
  int               r = 0;
  timelib_error_container *errors;

  timelib_strtointerval((char*)interval_spec.data(), interval_spec.size(),
                        &b, &e, &relTime, &r, &errors);

  int errors1 = errors->error_count;
  timelib_error_container_dtor(errors);
  if (errors1 > 0) {
    timelib_rel_time_dtor(relTime);
    raise_error("Unknown or bad format (%s)", interval_spec.c_str());
  } else {
    rel_time_to_interval(relTime, this);
    timelib_rel_time_dtor(relTime);
  }
}

Variant c_DateInterval::t___destruct() {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateInterval, DateInterval::__destruct);
  return null;
}

Object c_DateInterval::ti_createfromdatestring(const char* cls , CStrRef time) {
  STATIC_METHOD_INJECTION_BUILTIN(DateInterval, DateInterval::createfromdatestring);
  DateTime datetime;
  datetime.fromString(time, SmartObject<TimeZone>());
  c_DateInterval *interval = NEWOBJ(c_DateInterval);
  rel_time_to_interval(datetime.getRelTime(), interval);
  return interval;
}

String c_DateInterval::t_format(CStrRef format) {
  INSTANCE_METHOD_INJECTION_BUILTIN(DateInterval, DateInterval::format);
  StringBuffer s;
  const int LENGTH = 33;
  char buf[LENGTH];
  int l;
  bool hasFormatSpec = false;
  for (int i = 0; i < format.length(); ++i) {
    char c = format.charAt(i);
    if (!hasFormatSpec) {
      if (c == '%') {
        hasFormatSpec = true;
      } else {
        s.append(c);
      }
    } else {
      switch (c) {
      case 'Y': l = snprintf(buf, LENGTH, "%02lld", m_y); break;
      case 'y': l = snprintf(buf, LENGTH, "%lld", m_y); break;

      case 'M': l = snprintf(buf, LENGTH, "%02lld", m_m); break;
      case 'm': l = snprintf(buf, LENGTH, "%lld", m_m); break;

      case 'D': l = snprintf(buf, LENGTH, "%02lld", m_d); break;
      case 'd': l = snprintf(buf, LENGTH, "%lld", m_d); break;

      case 'H': l = snprintf(buf, LENGTH, "%02lld", m_h); break;
      case 'h': l = snprintf(buf, LENGTH, "%lld", m_h); break;

      case 'I': l = snprintf(buf, LENGTH, "%02lld", m_i); break;
      case 'i': l = snprintf(buf, LENGTH, "%lld", m_i); break;

      case 'S': l = snprintf(buf, LENGTH, "%02lld", m_s); break;
      case 's': l = snprintf(buf, LENGTH, "%lld", m_s); break;

      case 'a': {
        if (m_days.isInteger()) {
          l = snprintf(buf, LENGTH, "%lld", m_days.toInt64());
        } else {
          l = snprintf(buf, LENGTH, "(unknown)");
        }
        break;
      }

      case 'r': l = snprintf(buf, LENGTH, "%s", m_invert ? "-" : ""); break;
      case 'R': l = snprintf(buf, LENGTH, "%c", m_invert ? '-' : '+'); break;

      case '%': l = snprintf(buf, 32, "%%"); break;
      default: buf[0] = '%'; buf[1] = c; buf[2] = '\0'; l = 2; break;
      }

      s.append(buf, std::min(l, LENGTH - 1));
      hasFormatSpec = false;
    }
  }
  return s.detach();
}

///////////////////////////////////////////////////////////////////////////////
}