blob: 44e898d4f2324c8b1151ce8046b701c5700c867a [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/android_pim_EventRecurrence.cpp
2**
Elliott Hughes69a017b2011-04-08 14:10:28 -07003** Copyright 2006, The Android Open Source Project
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004**
Elliott Hughes69a017b2011-04-08 14:10:28 -07005** 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 Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes69a017b2011-04-08 14:10:28 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes69a017b2011-04-08 14:10:28 -070011** 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 Project9066cfe2009-03-03 19:31:44 -080015** 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
23namespace android {
24
25struct cached_array_fields_t
26{
27 jfieldID array;
28 jfieldID count;
29};
30
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031static jfieldID freq_field;
32static jfieldID until_field;
33static jfieldID count_field;
34static jfieldID interval_field;
35static jfieldID wkst_field;
36static cached_array_fields_t bysecond_fields;
37static cached_array_fields_t byminute_fields;
38static cached_array_fields_t byhour_fields;
39static cached_array_fields_t byday_fields;
40static cached_array_fields_t bydayNum_fields;
41static cached_array_fields_t bymonthday_fields;
42static cached_array_fields_t byyearday_fields;
43static cached_array_fields_t byweekno_fields;
44static cached_array_fields_t bymonth_fields;
45static cached_array_fields_t bysetpos_fields;
46
47static status_t
48set_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 }
82static void
83EventRecurrence_parse(JNIEnv* env, jobject This, jstring jstr)
84{
85 if (jstr == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -070086 jniThrowNullPointerException(env, "EventRecurrence.parse str parameter null");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 return ;
88 }
Elliott Hughesdd66bcb2011-04-12 11:28:59 -070089 const jchar* jchars = env->GetStringChars(jstr, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 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 Hughes69a017b2011-04-08 14:10:28 -0700112 jniThrowException(env, "java/lang/RuntimeException",
113 "EventRecurrence.parse error setting field 'until'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 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 Hughes69a017b2011-04-08 14:10:28 -0700132 != NO_ERROR) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 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 */
148static JNINativeMethod METHODS[] = {
149 /* name, signature, funcPtr */
150 { "parse", "(Ljava/lang/String;)V", (void*)EventRecurrence_parse }
151};
152
153static const char*const CLASS_NAME = "android/pim/EventRecurrence";
154
155int register_android_pim_EventRecurrence(JNIEnv* env)
156{
Elliott Hughesdd66bcb2011-04-12 11:28:59 -0700157 jclass clazz = env->FindClass(CLASS_NAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 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