The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* //device/libs/android_runtime/android_pim_EventRecurrence.cpp
|
| 2 | **
|
Elliott Hughes | 69a017b | 2011-04-08 14:10:28 -0700 | [diff] [blame] | 3 | ** Copyright 2006, The Android Open Source Project
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 4 | **
|
Elliott Hughes | 69a017b | 2011-04-08 14:10:28 -0700 | [diff] [blame] | 5 | ** Licensed under the Apache License, Version 2.0 (the "License");
|
| 6 | ** you may not use this file except in compliance with the License.
|
| 7 | ** You may obtain a copy of the License at
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 8 | **
|
Elliott Hughes | 69a017b | 2011-04-08 14:10:28 -0700 | [diff] [blame] | 9 | ** http://www.apache.org/licenses/LICENSE-2.0
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 10 | **
|
Elliott Hughes | 69a017b | 2011-04-08 14:10:28 -0700 | [diff] [blame] | 11 | ** Unless required by applicable law or agreed to in writing, software
|
| 12 | ** distributed under the License is distributed on an "AS IS" BASIS,
|
| 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 14 | ** See the License for the specific language governing permissions and
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 15 | ** limitations under the License.
|
| 16 | */
|
| 17 |
|
| 18 | #include <pim/EventRecurrence.h>
|
| 19 | #include "jni.h"
|
| 20 | #include "nativehelper/JNIHelp.h"
|
| 21 | #include <utils/String8.h>
|
| 22 |
|
| 23 | namespace android {
|
| 24 |
|
| 25 | struct cached_array_fields_t
|
| 26 | {
|
| 27 | jfieldID array;
|
| 28 | jfieldID count;
|
| 29 | };
|
| 30 |
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 31 | static jfieldID freq_field;
|
| 32 | static jfieldID until_field;
|
| 33 | static jfieldID count_field;
|
| 34 | static jfieldID interval_field;
|
| 35 | static jfieldID wkst_field;
|
| 36 | static cached_array_fields_t bysecond_fields;
|
| 37 | static cached_array_fields_t byminute_fields;
|
| 38 | static cached_array_fields_t byhour_fields;
|
| 39 | static cached_array_fields_t byday_fields;
|
| 40 | static cached_array_fields_t bydayNum_fields;
|
| 41 | static cached_array_fields_t bymonthday_fields;
|
| 42 | static cached_array_fields_t byyearday_fields;
|
| 43 | static cached_array_fields_t byweekno_fields;
|
| 44 | static cached_array_fields_t bymonth_fields;
|
| 45 | static cached_array_fields_t bysetpos_fields;
|
| 46 |
|
| 47 | static status_t
|
| 48 | set_array(JNIEnv* env, int inCount, int* inArray,
|
| 49 | jobject This, const cached_array_fields_t& fields)
|
| 50 | {
|
| 51 | if (inCount > 0) {
|
| 52 | jintArray array = (jintArray) env->GetObjectField(This, fields.array);
|
| 53 | if (array == NULL || env->GetArrayLength(array) < inCount) {
|
| 54 | // +4 because it's cheap to allocate a little extra here, and
|
| 55 | // that reduces the chance that we'll come back here again
|
| 56 | array = env->NewIntArray(inCount+4);
|
| 57 | env->SetObjectField(This, fields.array, array);
|
| 58 | }
|
| 59 | if (array == NULL) {
|
| 60 | return NO_MEMORY;
|
| 61 | }
|
| 62 | env->SetIntArrayRegion(array, 0, inCount, inArray);
|
| 63 |
|
| 64 | }
|
| 65 | env->SetIntField(This, fields.count, inCount);
|
| 66 | return NO_ERROR;
|
| 67 | }
|
| 68 |
|
| 69 | /*
|
| 70 | * In class android.pim.EventRecurrence
|
| 71 | * public native int parse(String str);
|
| 72 | */
|
| 73 | #define SET_ARRAY_AND_CHECK(name) \
|
| 74 | /*printf("setting " #name " to %d elements\n", er.name##Count);*/ \
|
| 75 | if (set_array(env, er.name##Count, er.name, This, name##_fields) \
|
| 76 | != NO_ERROR) { \
|
| 77 | jniThrowException(env, "java/lang/RuntimeException", \
|
| 78 | "EventRecurrence.parse error setting field " #name " or " \
|
| 79 | #name "Count."); \
|
| 80 | return ; \
|
| 81 | }
|
| 82 | static void
|
| 83 | EventRecurrence_parse(JNIEnv* env, jobject This, jstring jstr)
|
| 84 | {
|
| 85 | if (jstr == NULL) {
|
Elliott Hughes | 69a017b | 2011-04-08 14:10:28 -0700 | [diff] [blame] | 86 | jniThrowNullPointerException(env, "EventRecurrence.parse str parameter null");
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 87 | return ;
|
| 88 | }
|
Elliott Hughes | dd66bcb | 2011-04-12 11:28:59 -0700 | [diff] [blame] | 89 | const jchar* jchars = env->GetStringChars(jstr, NULL);
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 90 | jsize len = env->GetStringLength(jstr);
|
| 91 | String16 str(jchars, len);
|
| 92 | env->ReleaseStringChars(jstr, jchars);
|
| 93 |
|
| 94 | //printf("the string was '%s'\n", String8(str).string());
|
| 95 |
|
| 96 | EventRecurrence er;
|
| 97 | if (NO_ERROR != er.parse(str)) {
|
| 98 | String8 msg("Error parsing recurrence: '");
|
| 99 | msg.append(String8(str));
|
| 100 | msg.append("'");
|
| 101 |
|
| 102 | jniThrowException(env,
|
| 103 | "android/pim/EventRecurrence$InvalidFormatException",
|
| 104 | msg.string());
|
| 105 | return ;
|
| 106 | }
|
| 107 |
|
| 108 | jstring untilStr;
|
| 109 | if (er.until.size() > 0) {
|
| 110 | untilStr = env->NewString(er.until.string(), er.until.size());
|
| 111 | if (untilStr == NULL) {
|
Elliott Hughes | 69a017b | 2011-04-08 14:10:28 -0700 | [diff] [blame] | 112 | jniThrowException(env, "java/lang/RuntimeException",
|
| 113 | "EventRecurrence.parse error setting field 'until'");
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 114 | return ;
|
| 115 | }
|
| 116 | } else {
|
| 117 | untilStr = NULL;
|
| 118 | }
|
| 119 | env->SetObjectField(This, until_field, untilStr);
|
| 120 |
|
| 121 | env->SetIntField(This, freq_field, er.freq);
|
| 122 | env->SetIntField(This, count_field, er.count);
|
| 123 | env->SetIntField(This, interval_field, er.interval);
|
| 124 | env->SetIntField(This, wkst_field, er.wkst);
|
| 125 |
|
| 126 | SET_ARRAY_AND_CHECK(bysecond)
|
| 127 | SET_ARRAY_AND_CHECK(byminute)
|
| 128 | SET_ARRAY_AND_CHECK(byhour)
|
| 129 | SET_ARRAY_AND_CHECK(byday)
|
| 130 | // we'll just set the bydayCount field twice, it'll be less code total
|
| 131 | if (set_array(env, er.bydayCount, er.bydayNum, This, bydayNum_fields)
|
Elliott Hughes | 69a017b | 2011-04-08 14:10:28 -0700 | [diff] [blame] | 132 | != NO_ERROR) {
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 133 | jniThrowException(env, "java/lang/RuntimeException",
|
| 134 | "EventRecurrence.parse error setting field bydayNum or "
|
| 135 | "bydayCount.");
|
| 136 | return ;
|
| 137 | }
|
| 138 | SET_ARRAY_AND_CHECK(bymonthday)
|
| 139 | SET_ARRAY_AND_CHECK(byyearday)
|
| 140 | SET_ARRAY_AND_CHECK(byweekno)
|
| 141 | SET_ARRAY_AND_CHECK(bymonth)
|
| 142 | SET_ARRAY_AND_CHECK(bysetpos)
|
| 143 | }
|
| 144 |
|
| 145 | /*
|
| 146 | * JNI registration.
|
| 147 | */
|
| 148 | static JNINativeMethod METHODS[] = {
|
| 149 | /* name, signature, funcPtr */
|
| 150 | { "parse", "(Ljava/lang/String;)V", (void*)EventRecurrence_parse }
|
| 151 | };
|
| 152 |
|
| 153 | static const char*const CLASS_NAME = "android/pim/EventRecurrence";
|
| 154 |
|
| 155 | int register_android_pim_EventRecurrence(JNIEnv* env)
|
| 156 | {
|
Elliott Hughes | dd66bcb | 2011-04-12 11:28:59 -0700 | [diff] [blame] | 157 | jclass clazz = env->FindClass(CLASS_NAME);
|
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 158 | if (clazz == NULL) {
|
| 159 | LOGE("Field lookup unable to find class '%s'\n", CLASS_NAME);
|
| 160 | return -1;
|
| 161 | }
|
| 162 |
|
| 163 | freq_field = env->GetFieldID(clazz, "freq", "I");
|
| 164 | count_field = env->GetFieldID(clazz, "count", "I");
|
| 165 | interval_field = env->GetFieldID(clazz, "interval", "I");
|
| 166 | wkst_field = env->GetFieldID(clazz, "wkst", "I");
|
| 167 |
|
| 168 | until_field = env->GetFieldID(clazz, "until", "Ljava/lang/String;");
|
| 169 |
|
| 170 | bysecond_fields.array = env->GetFieldID(clazz, "bysecond", "[I");
|
| 171 | bysecond_fields.count = env->GetFieldID(clazz, "bysecondCount", "I");
|
| 172 | byminute_fields.array = env->GetFieldID(clazz, "byminute", "[I");
|
| 173 | byminute_fields.count = env->GetFieldID(clazz, "byminuteCount", "I");
|
| 174 | byhour_fields.array = env->GetFieldID(clazz, "byhour", "[I");
|
| 175 | byhour_fields.count = env->GetFieldID(clazz, "byhourCount", "I");
|
| 176 | byday_fields.array = env->GetFieldID(clazz, "byday", "[I");
|
| 177 | byday_fields.count = env->GetFieldID(clazz, "bydayCount", "I");
|
| 178 | bydayNum_fields.array = env->GetFieldID(clazz, "bydayNum", "[I");
|
| 179 | bydayNum_fields.count = byday_fields.count;
|
| 180 | bymonthday_fields.array = env->GetFieldID(clazz, "bymonthday", "[I");
|
| 181 | bymonthday_fields.count = env->GetFieldID(clazz, "bymonthdayCount", "I");
|
| 182 | byyearday_fields.array = env->GetFieldID(clazz, "byyearday", "[I");
|
| 183 | byyearday_fields.count = env->GetFieldID(clazz, "byyeardayCount", "I");
|
| 184 | byweekno_fields.array = env->GetFieldID(clazz, "byweekno", "[I");
|
| 185 | byweekno_fields.count = env->GetFieldID(clazz, "byweeknoCount", "I");
|
| 186 | bymonth_fields.array = env->GetFieldID(clazz, "bymonth", "[I");
|
| 187 | bymonth_fields.count = env->GetFieldID(clazz, "bymonthCount", "I");
|
| 188 | bysetpos_fields.array = env->GetFieldID(clazz, "bysetpos", "[I");
|
| 189 | bysetpos_fields.count = env->GetFieldID(clazz, "bysetposCount", "I");
|
| 190 |
|
| 191 | return jniRegisterNativeMethods(env, CLASS_NAME,
|
| 192 | METHODS, sizeof(METHODS)/sizeof(METHODS[0]));
|
| 193 | }
|
| 194 |
|
| 195 | }; // namespace android
|