summaryrefslogtreecommitdiffstats
path: root/core/jni
diff options
context:
space:
mode:
authorNeil Fuller <nfuller@google.com>2014-07-22 16:13:26 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2014-07-22 16:13:26 +0000
commit5a5f8ca870c1b28093be9e4a61399da56c27e7c2 (patch)
treea7ca9d3a79a6dfc09d2f9b4a30d4222537f1a8a4 /core/jni
parentc3e6b211f6893c9c930cfc8e41eb29fd9136c2ee (diff)
parentcc7c4f882435e6971450e0bdb6a335f312af704d (diff)
downloadframeworks_base-5a5f8ca870c1b28093be9e4a61399da56c27e7c2.zip
frameworks_base-5a5f8ca870c1b28093be9e4a61399da56c27e7c2.tar.gz
frameworks_base-5a5f8ca870c1b28093be9e4a61399da56c27e7c2.tar.bz2
am 2b49b6af: am 1a429047: am fc6346d4: Merge "Rewriting android.text.format.Time without the native _tz functions"
* commit '2b49b6afa60724c8ad0383e732b116fffa6b1758': Rewriting android.text.format.Time without the native _tz functions
Diffstat (limited to 'core/jni')
-rw-r--r--core/jni/Android.mk2
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/Time.cpp199
-rw-r--r--core/jni/TimeUtils.h89
-rw-r--r--core/jni/android_text_format_Time.cpp689
5 files changed, 0 insertions, 981 deletions
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f65aab5..f003680 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -23,7 +23,6 @@ LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_SRC_FILES:= \
AndroidRuntime.cpp \
- Time.cpp \
com_android_internal_content_NativeLibraryHelper.cpp \
com_google_android_gles_jni_EGLImpl.cpp \
com_google_android_gles_jni_GLImpl.cpp.arm \
@@ -81,7 +80,6 @@ LOCAL_SRC_FILES:= \
android_net_NetUtils.cpp \
android_net_TrafficStats.cpp \
android_nio_utils.cpp \
- android_text_format_Time.cpp \
android_util_AssetManager.cpp \
android_util_Binder.cpp \
android_util_EventLog.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 92a8fca..3a02ab9 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -144,7 +144,6 @@ extern int register_android_database_SQLiteConnection(JNIEnv* env);
extern int register_android_database_SQLiteGlobal(JNIEnv* env);
extern int register_android_database_SQLiteDebug(JNIEnv* env);
extern int register_android_nio_utils(JNIEnv* env);
-extern int register_android_text_format_Time(JNIEnv* env);
extern int register_android_os_Debug(JNIEnv* env);
extern int register_android_os_MessageQueue(JNIEnv* env);
extern int register_android_os_Parcel(JNIEnv* env);
@@ -1223,7 +1222,6 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
REG_JNI(register_android_util_FloatMath),
- REG_JNI(register_android_text_format_Time),
REG_JNI(register_android_content_AssetManager),
REG_JNI(register_android_content_StringBlock),
REG_JNI(register_android_content_XmlBlock),
diff --git a/core/jni/Time.cpp b/core/jni/Time.cpp
deleted file mode 100644
index f3037f3..0000000
--- a/core/jni/Time.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-#include "TimeUtils.h"
-#include <stdio.h>
-#include <cutils/tztime.h>
-
-namespace android {
-
-static void
-dump(const Time& t)
-{
- #ifdef HAVE_TM_GMTOFF
- long tm_gmtoff = t.t.tm_gmtoff;
- #else
- long tm_gmtoff = 0;
- #endif
- printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n",
- t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday,
- t.t.tm_hour, t.t.tm_min, t.t.tm_sec,
- t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday);
-}
-
-Time::Time()
-{
- t.tm_sec = 0;
- t.tm_min = 0;
- t.tm_hour = 0;
- t.tm_mday = 0;
- t.tm_mon = 0;
- t.tm_year = 0;
- t.tm_wday = 0;
- t.tm_yday = 0;
- t.tm_isdst = -1; // we don't know, so let the C library determine
- #ifdef HAVE_TM_GMTOFF
- t.tm_gmtoff = 0;
- #endif
-}
-
-
-#define COMPARE_FIELD(field) do { \
- int diff = a.t.field - b.t.field; \
- if (diff != 0) return diff; \
- } while(0)
-
-int
-Time::compare(Time& a, Time& b)
-{
- if (0 == strcmp(a.timezone, b.timezone)) {
- // if the timezones are the same, we can easily compare the two
- // times. Otherwise, convert to milliseconds and compare that.
- // This requires that object be normalized.
- COMPARE_FIELD(tm_year);
- COMPARE_FIELD(tm_mon);
- COMPARE_FIELD(tm_mday);
- COMPARE_FIELD(tm_hour);
- COMPARE_FIELD(tm_min);
- COMPARE_FIELD(tm_sec);
- return 0;
- } else {
- int64_t am = a.toMillis(false /* use isDst */);
- int64_t bm = b.toMillis(false /* use isDst */);
- int64_t diff = am-bm;
- return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
- }
-}
-
-static const int DAYS_PER_MONTH[] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
-
-static inline int days_this_month(int year, int month)
-{
- int n = DAYS_PER_MONTH[month];
- if (n != 28) {
- return n;
- } else {
- int y = year;
- return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28;
- }
-}
-
-void
-Time::switchTimezone(const char* timezone)
-{
- time_t seconds = mktime_tz(&(this->t), this->timezone);
- localtime_tz(&seconds, &(this->t), timezone);
-}
-
-String8
-Time::format(const char *format, const struct strftime_locale *locale) const
-{
- char buf[257];
- int n = strftime_tz(buf, 257, format, &(this->t), locale);
- if (n > 0) {
- return String8(buf);
- } else {
- return String8();
- }
-}
-
-static inline short
-tochar(int n)
-{
- return (n >= 0 && n <= 9) ? ('0'+n) : ' ';
-}
-
-static inline short
-next_char(int *m, int k)
-{
- int n = *m / k;
- *m = *m % k;
- return tochar(n);
-}
-
-void
-Time::format2445(short* buf, bool hasTime) const
-{
- int n;
-
- n = t.tm_year+1900;
- buf[0] = next_char(&n, 1000);
- buf[1] = next_char(&n, 100);
- buf[2] = next_char(&n, 10);
- buf[3] = tochar(n);
-
- n = t.tm_mon+1;
- buf[4] = next_char(&n, 10);
- buf[5] = tochar(n);
-
- n = t.tm_mday;
- buf[6] = next_char(&n, 10);
- buf[7] = tochar(n);
-
- if (hasTime) {
- buf[8] = 'T';
-
- n = t.tm_hour;
- buf[9] = next_char(&n, 10);
- buf[10] = tochar(n);
-
- n = t.tm_min;
- buf[11] = next_char(&n, 10);
- buf[12] = tochar(n);
-
- n = t.tm_sec;
- buf[13] = next_char(&n, 10);
- buf[14] = tochar(n);
- bool inUtc = strcmp("UTC", timezone) == 0;
- if (inUtc) {
- buf[15] = 'Z';
- }
- }
-}
-
-String8
-Time::toString() const
-{
- String8 str;
- char* s = str.lockBuffer(150);
- #ifdef HAVE_TM_GMTOFF
- long tm_gmtoff = t.tm_gmtoff;
- #else
- long tm_gmtoff = 0;
- #endif
- sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)",
- t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min,
- t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst,
- (int)(((Time*)this)->toMillis(false /* use isDst */)/1000));
- str.unlockBuffer();
- return str;
-}
-
-void
-Time::setToNow()
-{
- time_t seconds;
- time(&seconds);
- localtime_tz(&seconds, &(this->t), this->timezone);
-}
-
-int64_t
-Time::toMillis(bool ignoreDst)
-{
- if (ignoreDst) {
- this->t.tm_isdst = -1;
- }
- int64_t r = mktime_tz(&(this->t), this->timezone);
- if (r == -1)
- return -1;
- return r * 1000;
-}
-
-void
-Time::set(int64_t millis)
-{
- time_t seconds = millis / 1000;
- localtime_tz(&seconds, &(this->t), this->timezone);
-}
-
-}; // namespace android
-
diff --git a/core/jni/TimeUtils.h b/core/jni/TimeUtils.h
deleted file mode 100644
index b19e021..0000000
--- a/core/jni/TimeUtils.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2005 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_TIME_H
-#define ANDROID_TIME_H
-
-#include <time.h>
-#include <cutils/tztime.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
-
-namespace android {
-
-/*
- * This class is the core implementation of the android.util.Time java
- * class. It doesn't implement some of the methods that are implemented
- * in Java. They could be done here, but it's not expected that this class
- * will be used. If that assumption is incorrect, feel free to update this
- * file. The reason to do it here is to not mix the implementation of this
- * class and the jni glue code.
- */
-class Time
-{
-public:
- struct tm t;
-
- // this object doesn't own this string
- const char *timezone;
-
- enum {
- SEC = 1,
- MIN = 2,
- HOUR = 3,
- MDAY = 4,
- MON = 5,
- YEAR = 6,
- WDAY = 7,
- YDAY = 8
- };
-
- static int compare(Time& a, Time& b);
-
- Time();
-
- void switchTimezone(const char *timezone);
- String8 format(const char *format, const struct strftime_locale *locale) const;
- void format2445(short* buf, bool hasTime) const;
- String8 toString() const;
- void setToNow();
- int64_t toMillis(bool ignoreDst);
- void set(int64_t millis);
-
- inline void set(int sec, int min, int hour, int mday, int mon, int year,
- int isdst)
- {
- this->t.tm_sec = sec;
- this->t.tm_min = min;
- this->t.tm_hour = hour;
- this->t.tm_mday = mday;
- this->t.tm_mon = mon;
- this->t.tm_year = year;
- this->t.tm_isdst = isdst;
-#ifdef HAVE_TM_GMTOFF
- this->t.tm_gmtoff = 0;
-#endif
- this->t.tm_wday = 0;
- this->t.tm_yday = 0;
- }
-};
-
-}; // namespace android
-
-#endif // ANDROID_TIME_H
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
deleted file mode 100644
index 28a8a5d..0000000
--- a/core/jni/android_text_format_Time.cpp
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "Log_println"
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <assert.h>
-
-#include "jni.h"
-#include "utils/misc.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "ScopedStringChars.h"
-#include "TimeUtils.h"
-#include <nativehelper/JNIHelp.h>
-#include <cutils/tztime.h>
-
-namespace android {
-
-static jfieldID g_allDayField = 0;
-static jfieldID g_secField = 0;
-static jfieldID g_minField = 0;
-static jfieldID g_hourField = 0;
-static jfieldID g_mdayField = 0;
-static jfieldID g_monField = 0;
-static jfieldID g_yearField = 0;
-static jfieldID g_wdayField = 0;
-static jfieldID g_ydayField = 0;
-static jfieldID g_isdstField = 0;
-static jfieldID g_gmtoffField = 0;
-static jfieldID g_timezoneField = 0;
-
-static jfieldID g_shortMonthsField = 0;
-static jfieldID g_longMonthsField = 0;
-static jfieldID g_longStandaloneMonthsField = 0;
-static jfieldID g_shortWeekdaysField = 0;
-static jfieldID g_longWeekdaysField = 0;
-static jfieldID g_timeOnlyFormatField = 0;
-static jfieldID g_dateOnlyFormatField = 0;
-static jfieldID g_dateTimeFormatField = 0;
-static jfieldID g_amField = 0;
-static jfieldID g_pmField = 0;
-static jfieldID g_dateCommandField = 0;
-static jfieldID g_localeField = 0;
-
-static jclass g_timeClass = NULL;
-
-static inline bool java2time(JNIEnv* env, Time* t, jobject o)
-{
- t->t.tm_sec = env->GetIntField(o, g_secField);
- t->t.tm_min = env->GetIntField(o, g_minField);
- t->t.tm_hour = env->GetIntField(o, g_hourField);
- t->t.tm_mday = env->GetIntField(o, g_mdayField);
- t->t.tm_mon = env->GetIntField(o, g_monField);
- t->t.tm_year = (env->GetIntField(o, g_yearField))-1900;
- t->t.tm_wday = env->GetIntField(o, g_wdayField);
- t->t.tm_yday = env->GetIntField(o, g_ydayField);
- t->t.tm_isdst = env->GetIntField(o, g_isdstField);
- t->t.tm_gmtoff = env->GetLongField(o, g_gmtoffField);
- bool allDay = env->GetBooleanField(o, g_allDayField);
- if (allDay &&
- ((t->t.tm_sec !=0) || (t->t.tm_min != 0) || (t->t.tm_hour != 0))) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "allDay is true but sec, min, hour are not 0.");
- return false;
- }
- return true;
-}
-
-static inline void time2java(JNIEnv* env, jobject o, const Time &t)
-{
- env->SetIntField(o, g_secField, t.t.tm_sec);
- env->SetIntField(o, g_minField, t.t.tm_min);
- env->SetIntField(o, g_hourField, t.t.tm_hour);
- env->SetIntField(o, g_mdayField, t.t.tm_mday);
- env->SetIntField(o, g_monField, t.t.tm_mon);
- env->SetIntField(o, g_yearField, t.t.tm_year+1900);
- env->SetIntField(o, g_wdayField, t.t.tm_wday);
- env->SetIntField(o, g_ydayField, t.t.tm_yday);
- env->SetIntField(o, g_isdstField, t.t.tm_isdst);
- env->SetLongField(o, g_gmtoffField, t.t.tm_gmtoff);
-}
-
-#define ACQUIRE_TIMEZONE(This, t) \
- jstring timezoneString_##This \
- = (jstring) env->GetObjectField(This, g_timezoneField); \
- t.timezone = env->GetStringUTFChars(timezoneString_##This, NULL);
-
-#define RELEASE_TIMEZONE(This, t) \
- env->ReleaseStringUTFChars(timezoneString_##This, t.timezone);
-
-
-// ============================================================================
-
-static jlong android_text_format_Time_normalize(JNIEnv* env, jobject This,
- jboolean ignoreDst)
-{
- Time t;
- if (!java2time(env, &t, This)) return 0L;
- ACQUIRE_TIMEZONE(This, t)
-
- int64_t result = t.toMillis(ignoreDst != 0);
-
- time2java(env, This, t);
- RELEASE_TIMEZONE(This, t)
-
- return static_cast<jlong>(result);
-}
-
-static void android_text_format_Time_switchTimezone(JNIEnv* env, jobject This,
- jstring timezoneObject)
-{
- Time t;
- if (!java2time(env, &t, This)) return;
- ACQUIRE_TIMEZONE(This, t)
-
- const char* timezone = env->GetStringUTFChars(timezoneObject, NULL);
-
- t.switchTimezone(timezone);
-
- time2java(env, This, t);
- env->ReleaseStringUTFChars(timezoneObject, timezone);
- RELEASE_TIMEZONE(This, t)
-
- // we do this here because there's no point in reallocating the string
- env->SetObjectField(This, g_timezoneField, timezoneObject);
-}
-
-static jint android_text_format_Time_compare(JNIEnv* env, jobject clazz,
- jobject aObject, jobject bObject)
-{
- Time a, b;
-
- if (!java2time(env, &a, aObject)) return 0;
- ACQUIRE_TIMEZONE(aObject, a)
-
- if (!java2time(env, &b, bObject)) return 0;
- ACQUIRE_TIMEZONE(bObject, b)
-
- int result = Time::compare(a, b);
-
- RELEASE_TIMEZONE(aObject, a)
- RELEASE_TIMEZONE(bObject, b)
-
- return static_cast<jint>(result);
-}
-
-static jstring android_text_format_Time_format2445(JNIEnv* env, jobject This)
-{
- Time t;
- if (!java2time(env, &t, This)) return env->NewStringUTF("");
- bool allDay = env->GetBooleanField(This, g_allDayField);
-
- if (!allDay) {
- ACQUIRE_TIMEZONE(This, t)
- bool inUtc = strcmp("UTC", t.timezone) == 0;
- short buf[16];
- t.format2445(buf, true);
- RELEASE_TIMEZONE(This, t)
- if (inUtc) {
- // The letter 'Z' is appended to the end so allow for one
- // more character in the buffer.
- return env->NewString((jchar*)buf, 16);
- } else {
- return env->NewString((jchar*)buf, 15);
- }
- } else {
- short buf[8];
- t.format2445(buf, false);
- return env->NewString((jchar*)buf, 8);
- }
-}
-
-static jstring android_text_format_Time_format(JNIEnv* env, jobject This,
- jstring formatObject)
-{
- // We only teardown and setup our 'locale' struct and other state
- // when the Java-side locale changed. This is safe to do here
- // without locking because we're always called from Java code
- // synchronized on the class instance.
- static jobject js_locale_previous = NULL;
- static struct strftime_locale locale;
- static jstring js_mon[12], js_month[12], js_wday[7], js_weekday[7];
- static jstring js_standalone_month[12];
- static jstring js_X_fmt, js_x_fmt, js_c_fmt, js_am, js_pm, js_date_fmt;
-
- Time t;
- if (!java2time(env, &t, This)) return env->NewStringUTF("");
-
- jclass timeClass = g_timeClass;
- jobject js_locale = (jobject) env->GetStaticObjectField(timeClass, g_localeField);
- if (js_locale_previous != js_locale) {
- if (js_locale_previous != NULL) {
- // Free the old one.
- for (int i = 0; i < 12; i++) {
- env->ReleaseStringUTFChars(js_mon[i], locale.mon[i]);
- env->ReleaseStringUTFChars(js_month[i], locale.month[i]);
- env->ReleaseStringUTFChars(js_standalone_month[i], locale.standalone_month[i]);
- env->DeleteGlobalRef(js_mon[i]);
- env->DeleteGlobalRef(js_month[i]);
- env->DeleteGlobalRef(js_standalone_month[i]);
- }
-
- for (int i = 0; i < 7; i++) {
- env->ReleaseStringUTFChars(js_wday[i], locale.wday[i]);
- env->ReleaseStringUTFChars(js_weekday[i], locale.weekday[i]);
- env->DeleteGlobalRef(js_wday[i]);
- env->DeleteGlobalRef(js_weekday[i]);
- }
-
- env->ReleaseStringUTFChars(js_X_fmt, locale.X_fmt);
- env->ReleaseStringUTFChars(js_x_fmt, locale.x_fmt);
- env->ReleaseStringUTFChars(js_c_fmt, locale.c_fmt);
- env->ReleaseStringUTFChars(js_am, locale.am);
- env->ReleaseStringUTFChars(js_pm, locale.pm);
- env->ReleaseStringUTFChars(js_date_fmt, locale.date_fmt);
- env->DeleteGlobalRef(js_X_fmt);
- env->DeleteGlobalRef(js_x_fmt);
- env->DeleteGlobalRef(js_c_fmt);
- env->DeleteGlobalRef(js_am);
- env->DeleteGlobalRef(js_pm);
- env->DeleteGlobalRef(js_date_fmt);
- }
- js_locale_previous = js_locale;
-
- jobjectArray ja;
- ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_shortMonthsField);
- for (int i = 0; i < 12; i++) {
- // Calendar.JANUARY == 0.
- js_mon[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
- locale.mon[i] = env->GetStringUTFChars(js_mon[i], NULL);
- }
-
- ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longMonthsField);
- for (int i = 0; i < 12; i++) {
- // Calendar.JANUARY == 0.
- js_month[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
- locale.month[i] = env->GetStringUTFChars(js_month[i], NULL);
- }
-
- ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longStandaloneMonthsField);
- for (int i = 0; i < 12; i++) {
- // Calendar.JANUARY == 0.
- js_standalone_month[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
- locale.standalone_month[i] = env->GetStringUTFChars(js_standalone_month[i], NULL);
- }
-
- ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_shortWeekdaysField);
- for (int i = 0; i < 7; i++) {
- // Calendar.SUNDAY == 1, and there's an empty string in element 0.
- js_wday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i + 1));
- locale.wday[i] = env->GetStringUTFChars(js_wday[i], NULL);
- }
-
- ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longWeekdaysField);
- for (int i = 0; i < 7; i++) {
- // Calendar.SUNDAY == 1, and there's an empty string in element 0.
- js_weekday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i + 1));
- locale.weekday[i] = env->GetStringUTFChars(js_weekday[i], NULL);
- }
-
- js_X_fmt = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
- timeClass, g_timeOnlyFormatField));
- locale.X_fmt = env->GetStringUTFChars(js_X_fmt, NULL);
-
- js_x_fmt = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
- timeClass, g_dateOnlyFormatField));
- locale.x_fmt = env->GetStringUTFChars(js_x_fmt, NULL);
-
- js_c_fmt = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
- timeClass, g_dateTimeFormatField));
- locale.c_fmt = env->GetStringUTFChars(js_c_fmt, NULL);
-
- js_am = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
- timeClass, g_amField));
- locale.am = env->GetStringUTFChars(js_am, NULL);
-
- js_pm = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
- timeClass, g_pmField));
- locale.pm = env->GetStringUTFChars(js_pm, NULL);
-
- js_date_fmt = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
- timeClass, g_dateCommandField));
- locale.date_fmt = env->GetStringUTFChars(js_date_fmt, NULL);
- }
-
- ACQUIRE_TIMEZONE(This, t)
-
- const char* format = env->GetStringUTFChars(formatObject, NULL);
-
- String8 r = t.format(format, &locale);
-
- env->ReleaseStringUTFChars(formatObject, format);
- RELEASE_TIMEZONE(This, t)
-
- return env->NewStringUTF(r.string());
-}
-
-
-static jstring android_text_format_Time_toString(JNIEnv* env, jobject This)
-{
- Time t;
- if (!java2time(env, &t, This)) return env->NewStringUTF("");
- ACQUIRE_TIMEZONE(This, t)
-
- String8 r = t.toString();
-
- RELEASE_TIMEZONE(This, t)
-
- return env->NewStringUTF(r.string());
-}
-
-static void android_text_format_Time_setToNow(JNIEnv* env, jobject This)
-{
- env->SetBooleanField(This, g_allDayField, JNI_FALSE);
- Time t;
- ACQUIRE_TIMEZONE(This, t)
-
- t.setToNow();
-
- time2java(env, This, t);
- RELEASE_TIMEZONE(This, t)
-}
-
-static jlong android_text_format_Time_toMillis(JNIEnv* env, jobject This,
- jboolean ignoreDst)
-{
- Time t;
- if (!java2time(env, &t, This)) return 0L;
- ACQUIRE_TIMEZONE(This, t)
-
- int64_t result = t.toMillis(ignoreDst != 0);
-
- RELEASE_TIMEZONE(This, t)
-
- return static_cast<jlong>(result);
-}
-
-static void android_text_format_Time_set(JNIEnv* env, jobject This, jlong millis)
-{
- env->SetBooleanField(This, g_allDayField, JNI_FALSE);
- Time t;
- ACQUIRE_TIMEZONE(This, t)
-
- t.set(millis);
-
- time2java(env, This, t);
- RELEASE_TIMEZONE(This, t)
-}
-
-
-// ============================================================================
-// Just do this here because it's not worth recreating the strings
-
-static int get_char(JNIEnv* env, const ScopedStringChars& s, int spos, int mul,
- bool* thrown)
-{
- jchar c = s[spos];
- if (c >= '0' && c <= '9') {
- return (c - '0') * mul;
- } else {
- if (!*thrown) {
- jniThrowExceptionFmt(env, "android/util/TimeFormatException",
- "Parse error at pos=%d", spos);
- *thrown = true;
- }
- return 0;
- }
-}
-
-static bool check_char(JNIEnv* env, const ScopedStringChars& s, int spos, jchar expected)
-{
- jchar c = s[spos];
- if (c != expected) {
- jniThrowExceptionFmt(env, "android/util/TimeFormatException",
- "Unexpected character 0x%02x at pos=%d. Expected %c.",
- c, spos, expected);
- return false;
- }
- return true;
-}
-
-
-static jboolean android_text_format_Time_parse(JNIEnv* env, jobject This, jstring strObj)
-{
- jsize len = env->GetStringLength(strObj);
- if (len < 8) {
- jniThrowException(env, "android/util/TimeFormatException",
- "String too short -- expected at least 8 characters.");
- return JNI_FALSE;
- }
-
- jboolean inUtc = JNI_FALSE;
-
- ScopedStringChars s(env, strObj);
-
- // year
- int n;
- bool thrown = false;
- n = get_char(env, s, 0, 1000, &thrown);
- n += get_char(env, s, 1, 100, &thrown);
- n += get_char(env, s, 2, 10, &thrown);
- n += get_char(env, s, 3, 1, &thrown);
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_yearField, n);
-
- // month
- n = get_char(env, s, 4, 10, &thrown);
- n += get_char(env, s, 5, 1, &thrown);
- n--;
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_monField, n);
-
- // day of month
- n = get_char(env, s, 6, 10, &thrown);
- n += get_char(env, s, 7, 1, &thrown);
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_mdayField, n);
-
- if (len > 8) {
- // T
- if (!check_char(env, s, 8, 'T')) return JNI_FALSE;
- env->SetBooleanField(This, g_allDayField, JNI_FALSE);
-
- // hour
- n = get_char(env, s, 9, 10, &thrown);
- n += get_char(env, s, 10, 1, &thrown);
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_hourField, n);
-
- // min
- n = get_char(env, s, 11, 10, &thrown);
- n += get_char(env, s, 12, 1, &thrown);
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_minField, n);
-
- // sec
- n = get_char(env, s, 13, 10, &thrown);
- n += get_char(env, s, 14, 1, &thrown);
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_secField, n);
-
- if (len > 15) {
- // Z
- if (!check_char(env, s, 15, 'Z')) return JNI_FALSE;
- inUtc = JNI_TRUE;
- }
- } else {
- env->SetBooleanField(This, g_allDayField, JNI_TRUE);
- env->SetIntField(This, g_hourField, 0);
- env->SetIntField(This, g_minField, 0);
- env->SetIntField(This, g_secField, 0);
- }
-
- env->SetIntField(This, g_wdayField, 0);
- env->SetIntField(This, g_ydayField, 0);
- env->SetIntField(This, g_isdstField, -1);
- env->SetLongField(This, g_gmtoffField, 0);
-
- return inUtc;
-}
-
-static jboolean android_text_format_Time_parse3339(JNIEnv* env,
- jobject This,
- jstring strObj)
-{
- jsize len = env->GetStringLength(strObj);
- if (len < 10) {
- jniThrowException(env, "android/util/TimeFormatException",
- "String too short --- expected at least 10 characters.");
- return JNI_FALSE;
- }
-
- jboolean inUtc = JNI_FALSE;
-
- ScopedStringChars s(env, strObj);
-
- // year
- int n;
- bool thrown = false;
- n = get_char(env, s, 0, 1000, &thrown);
- n += get_char(env, s, 1, 100, &thrown);
- n += get_char(env, s, 2, 10, &thrown);
- n += get_char(env, s, 3, 1, &thrown);
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_yearField, n);
-
- // -
- if (!check_char(env, s, 4, '-')) return JNI_FALSE;
-
- // month
- n = get_char(env, s, 5, 10, &thrown);
- n += get_char(env, s, 6, 1, &thrown);
- --n;
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_monField, n);
-
- // -
- if (!check_char(env, s, 7, '-')) return JNI_FALSE;
-
- // day
- n = get_char(env, s, 8, 10, &thrown);
- n += get_char(env, s, 9, 1, &thrown);
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_mdayField, n);
-
- if (len >= 19) {
- // T
- if (!check_char(env, s, 10, 'T')) return JNI_FALSE;
-
- env->SetBooleanField(This, g_allDayField, JNI_FALSE);
- // hour
- n = get_char(env, s, 11, 10, &thrown);
- n += get_char(env, s, 12, 1, &thrown);
- if (thrown) return JNI_FALSE;
- int hour = n;
- // env->SetIntField(This, g_hourField, n);
-
- // :
- if (!check_char(env, s, 13, ':')) return JNI_FALSE;
-
- // minute
- n = get_char(env, s, 14, 10, &thrown);
- n += get_char(env, s, 15, 1, &thrown);
- if (thrown) return JNI_FALSE;
- int minute = n;
- // env->SetIntField(This, g_minField, n);
-
- // :
- if (!check_char(env, s, 16, ':')) return JNI_FALSE;
-
- // second
- n = get_char(env, s, 17, 10, &thrown);
- n += get_char(env, s, 18, 1, &thrown);
- if (thrown) return JNI_FALSE;
- env->SetIntField(This, g_secField, n);
-
- // skip the '.XYZ' -- we don't care about subsecond precision.
- int tz_index = 19;
- if (tz_index < len && s[tz_index] == '.') {
- do {
- tz_index++;
- } while (tz_index < len
- && s[tz_index] >= '0'
- && s[tz_index] <= '9');
- }
-
- int offset = 0;
- if (len > tz_index) {
- char c = s[tz_index];
-
- // NOTE: the offset is meant to be subtracted to get from local time
- // to UTC. we therefore use 1 for '-' and -1 for '+'.
- switch (c) {
- case 'Z':
- // Zulu time -- UTC
- offset = 0;
- break;
- case '-':
- offset = 1;
- break;
- case '+':
- offset = -1;
- break;
- default:
- jniThrowExceptionFmt(env, "android/util/TimeFormatException",
- "Unexpected character 0x%02x at position %d. Expected + or -",
- c, tz_index);
- return JNI_FALSE;
- }
- inUtc = JNI_TRUE;
-
- if (offset != 0) {
- if (len < tz_index + 6) {
- jniThrowExceptionFmt(env, "android/util/TimeFormatException",
- "Unexpected length; should be %d characters",
- tz_index + 6);
- return JNI_FALSE;
- }
-
- // hour
- n = get_char(env, s, tz_index + 1, 10, &thrown);
- n += get_char(env, s, tz_index + 2, 1, &thrown);
- if (thrown) return JNI_FALSE;
- n *= offset;
- hour += n;
-
- // :
- if (!check_char(env, s, tz_index + 3, ':')) return JNI_FALSE;
-
- // minute
- n = get_char(env, s, tz_index + 4, 10, &thrown);
- n += get_char(env, s, tz_index + 5, 1, &thrown);
- if (thrown) return JNI_FALSE;
- n *= offset;
- minute += n;
- }
- }
- env->SetIntField(This, g_hourField, hour);
- env->SetIntField(This, g_minField, minute);
-
- if (offset != 0) {
- // we need to normalize after applying the hour and minute offsets
- android_text_format_Time_normalize(env, This, false /* use isdst */);
- // The timezone is set to UTC in the calling Java code.
- }
- } else {
- env->SetBooleanField(This, g_allDayField, JNI_TRUE);
- env->SetIntField(This, g_hourField, 0);
- env->SetIntField(This, g_minField, 0);
- env->SetIntField(This, g_secField, 0);
- }
-
- env->SetIntField(This, g_wdayField, 0);
- env->SetIntField(This, g_ydayField, 0);
- env->SetIntField(This, g_isdstField, -1);
- env->SetLongField(This, g_gmtoffField, 0);
-
- return inUtc;
-}
-
-// ============================================================================
-/*
- * JNI registration.
- */
-static JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- { "normalize", "(Z)J", (void*)android_text_format_Time_normalize },
- { "switchTimezone", "(Ljava/lang/String;)V", (void*)android_text_format_Time_switchTimezone },
- { "nativeCompare", "(Landroid/text/format/Time;Landroid/text/format/Time;)I", (void*)android_text_format_Time_compare },
- { "format1", "(Ljava/lang/String;)Ljava/lang/String;", (void*)android_text_format_Time_format },
- { "format2445", "()Ljava/lang/String;", (void*)android_text_format_Time_format2445 },
- { "toString", "()Ljava/lang/String;", (void*)android_text_format_Time_toString },
- { "nativeParse", "(Ljava/lang/String;)Z", (void*)android_text_format_Time_parse },
- { "nativeParse3339", "(Ljava/lang/String;)Z", (void*)android_text_format_Time_parse3339 },
- { "setToNow", "()V", (void*)android_text_format_Time_setToNow },
- { "toMillis", "(Z)J", (void*)android_text_format_Time_toMillis },
- { "set", "(J)V", (void*)android_text_format_Time_set }
-};
-
-int register_android_text_format_Time(JNIEnv* env)
-{
- jclass timeClass = env->FindClass("android/text/format/Time");
-
- g_timeClass = (jclass) env->NewGlobalRef(timeClass);
-
- g_allDayField = env->GetFieldID(timeClass, "allDay", "Z");
- g_secField = env->GetFieldID(timeClass, "second", "I");
- g_minField = env->GetFieldID(timeClass, "minute", "I");
- g_hourField = env->GetFieldID(timeClass, "hour", "I");
- g_mdayField = env->GetFieldID(timeClass, "monthDay", "I");
- g_monField = env->GetFieldID(timeClass, "month", "I");
- g_yearField = env->GetFieldID(timeClass, "year", "I");
- g_wdayField = env->GetFieldID(timeClass, "weekDay", "I");
- g_ydayField = env->GetFieldID(timeClass, "yearDay", "I");
- g_isdstField = env->GetFieldID(timeClass, "isDst", "I");
- g_gmtoffField = env->GetFieldID(timeClass, "gmtoff", "J");
- g_timezoneField = env->GetFieldID(timeClass, "timezone", "Ljava/lang/String;");
-
- g_shortMonthsField = env->GetStaticFieldID(timeClass, "sShortMonths", "[Ljava/lang/String;");
- g_longMonthsField = env->GetStaticFieldID(timeClass, "sLongMonths", "[Ljava/lang/String;");
- g_longStandaloneMonthsField = env->GetStaticFieldID(timeClass, "sLongStandaloneMonths", "[Ljava/lang/String;");
- g_shortWeekdaysField = env->GetStaticFieldID(timeClass, "sShortWeekdays", "[Ljava/lang/String;");
- g_longWeekdaysField = env->GetStaticFieldID(timeClass, "sLongWeekdays", "[Ljava/lang/String;");
- g_timeOnlyFormatField = env->GetStaticFieldID(timeClass, "sTimeOnlyFormat", "Ljava/lang/String;");
- g_dateOnlyFormatField = env->GetStaticFieldID(timeClass, "sDateOnlyFormat", "Ljava/lang/String;");
- g_dateTimeFormatField = env->GetStaticFieldID(timeClass, "sDateTimeFormat", "Ljava/lang/String;");
- g_amField = env->GetStaticFieldID(timeClass, "sAm", "Ljava/lang/String;");
- g_pmField = env->GetStaticFieldID(timeClass, "sPm", "Ljava/lang/String;");
- g_dateCommandField = env->GetStaticFieldID(timeClass, "sDateCommand", "Ljava/lang/String;");
- g_localeField = env->GetStaticFieldID(timeClass, "sLocale", "Ljava/util/Locale;");
-
- return AndroidRuntime::registerNativeMethods(env, "android/text/format/Time", gMethods, NELEM(gMethods));
-}
-
-}; // namespace android