• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* //device/libs/android_runtime/android_pim_EventRecurrence.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
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
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
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
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 
31 static jclass clazz;
32 static jfieldID freq_field;
33 static jfieldID until_field;
34 static jfieldID count_field;
35 static jfieldID interval_field;
36 static jfieldID wkst_field;
37 static cached_array_fields_t bysecond_fields;
38 static cached_array_fields_t byminute_fields;
39 static cached_array_fields_t byhour_fields;
40 static cached_array_fields_t byday_fields;
41 static cached_array_fields_t bydayNum_fields;
42 static cached_array_fields_t bymonthday_fields;
43 static cached_array_fields_t byyearday_fields;
44 static cached_array_fields_t byweekno_fields;
45 static cached_array_fields_t bymonth_fields;
46 static cached_array_fields_t bysetpos_fields;
47 
48 static status_t
set_array(JNIEnv * env,int inCount,int * inArray,jobject This,const cached_array_fields_t & fields)49 set_array(JNIEnv* env, int inCount, int* inArray,
50             jobject This, const cached_array_fields_t& fields)
51 {
52     if (inCount > 0) {
53         jintArray array = (jintArray) env->GetObjectField(This, fields.array);
54         if (array == NULL || env->GetArrayLength(array) < inCount) {
55             // +4 because it's cheap to allocate a little extra here, and
56             // that reduces the chance that we'll come back here again
57             array = env->NewIntArray(inCount+4);
58             env->SetObjectField(This, fields.array, array);
59         }
60         if (array == NULL) {
61             return NO_MEMORY;
62         }
63         env->SetIntArrayRegion(array, 0, inCount, inArray);
64 
65     }
66     env->SetIntField(This, fields.count, inCount);
67     return NO_ERROR;
68 }
69 
70 /*
71  * In class android.pim.EventRecurrence
72  *  public native int parse(String str);
73  */
74 #define SET_ARRAY_AND_CHECK(name) \
75     /*printf("setting " #name " to %d elements\n", er.name##Count);*/ \
76     if (set_array(env, er.name##Count, er.name, This, name##_fields) \
77             != NO_ERROR) { \
78         jniThrowException(env, "java/lang/RuntimeException", \
79                 "EventRecurrence.parse error setting field " #name " or " \
80                 #name "Count."); \
81         return ; \
82     }
83 static void
EventRecurrence_parse(JNIEnv * env,jobject This,jstring jstr)84 EventRecurrence_parse(JNIEnv* env, jobject This, jstring jstr)
85 {
86     if (jstr == NULL) {
87         jniThrowException(env, "java/lang/NullPointerException",
88                 "EventRecurrence.parse str parameter null");
89         return ;
90     }
91     jboolean isCopy;
92     const jchar* jchars = env->GetStringChars(jstr, &isCopy);
93     jsize len = env->GetStringLength(jstr);
94     String16 str(jchars, len);
95     env->ReleaseStringChars(jstr, jchars);
96 
97     //printf("the string was '%s'\n", String8(str).string());
98 
99     EventRecurrence er;
100     if (NO_ERROR != er.parse(str)) {
101         String8 msg("Error parsing recurrence: '");
102         msg.append(String8(str));
103         msg.append("'");
104 
105         jniThrowException(env,
106                 "android/pim/EventRecurrence$InvalidFormatException",
107                 msg.string());
108         return ;
109     }
110 
111     jstring untilStr;
112     if (er.until.size() > 0) {
113         untilStr = env->NewString(er.until.string(), er.until.size());
114         if (untilStr == NULL) {
115             jniThrowException(env, "java/lang/RuntimeException",
116                     "EventRecurrence.parse error setting field 'until'");
117             return ;
118         }
119     } else {
120         untilStr = NULL;
121     }
122     env->SetObjectField(This, until_field, untilStr);
123 
124     env->SetIntField(This, freq_field, er.freq);
125     env->SetIntField(This, count_field, er.count);
126     env->SetIntField(This, interval_field, er.interval);
127     env->SetIntField(This, wkst_field, er.wkst);
128 
129     SET_ARRAY_AND_CHECK(bysecond)
130     SET_ARRAY_AND_CHECK(byminute)
131     SET_ARRAY_AND_CHECK(byhour)
132     SET_ARRAY_AND_CHECK(byday)
133     // we'll just set the bydayCount field twice, it'll be less code total
134     if (set_array(env, er.bydayCount, er.bydayNum, This, bydayNum_fields)
135             != NO_ERROR) {
136         jniThrowException(env, "java/lang/RuntimeException",
137                 "EventRecurrence.parse error setting field bydayNum or "
138                 "bydayCount.");
139         return ;
140     }
141     SET_ARRAY_AND_CHECK(bymonthday)
142     SET_ARRAY_AND_CHECK(byyearday)
143     SET_ARRAY_AND_CHECK(byweekno)
144     SET_ARRAY_AND_CHECK(bymonth)
145     SET_ARRAY_AND_CHECK(bysetpos)
146 }
147 
148 /*
149  * JNI registration.
150  */
151 static JNINativeMethod METHODS[] = {
152     /* name, signature, funcPtr */
153     { "parse", "(Ljava/lang/String;)V", (void*)EventRecurrence_parse }
154 };
155 
156 static const char*const CLASS_NAME = "android/pim/EventRecurrence";
157 
register_android_pim_EventRecurrence(JNIEnv * env)158 int register_android_pim_EventRecurrence(JNIEnv* env)
159 {
160     clazz = env->FindClass(CLASS_NAME);
161     if (clazz == NULL) {
162         LOGE("Field lookup unable to find class '%s'\n", CLASS_NAME);
163         return -1;
164     }
165 
166     freq_field = env->GetFieldID(clazz, "freq", "I");
167     count_field = env->GetFieldID(clazz, "count", "I");
168     interval_field = env->GetFieldID(clazz, "interval", "I");
169     wkst_field = env->GetFieldID(clazz, "wkst", "I");
170 
171     until_field = env->GetFieldID(clazz, "until", "Ljava/lang/String;");
172 
173     bysecond_fields.array = env->GetFieldID(clazz, "bysecond", "[I");
174     bysecond_fields.count = env->GetFieldID(clazz, "bysecondCount", "I");
175     byminute_fields.array = env->GetFieldID(clazz, "byminute", "[I");
176     byminute_fields.count = env->GetFieldID(clazz, "byminuteCount", "I");
177     byhour_fields.array = env->GetFieldID(clazz, "byhour", "[I");
178     byhour_fields.count = env->GetFieldID(clazz, "byhourCount", "I");
179     byday_fields.array = env->GetFieldID(clazz, "byday", "[I");
180     byday_fields.count = env->GetFieldID(clazz, "bydayCount", "I");
181     bydayNum_fields.array = env->GetFieldID(clazz, "bydayNum", "[I");
182     bydayNum_fields.count = byday_fields.count;
183     bymonthday_fields.array = env->GetFieldID(clazz, "bymonthday", "[I");
184     bymonthday_fields.count = env->GetFieldID(clazz, "bymonthdayCount", "I");
185     byyearday_fields.array = env->GetFieldID(clazz, "byyearday", "[I");
186     byyearday_fields.count = env->GetFieldID(clazz, "byyeardayCount", "I");
187     byweekno_fields.array = env->GetFieldID(clazz, "byweekno", "[I");
188     byweekno_fields.count = env->GetFieldID(clazz, "byweeknoCount", "I");
189     bymonth_fields.array = env->GetFieldID(clazz, "bymonth", "[I");
190     bymonth_fields.count = env->GetFieldID(clazz, "bymonthCount", "I");
191     bysetpos_fields.array = env->GetFieldID(clazz, "bysetpos", "[I");
192     bysetpos_fields.count = env->GetFieldID(clazz, "bysetposCount", "I");
193 
194     return jniRegisterNativeMethods(env, CLASS_NAME,
195         METHODS, sizeof(METHODS)/sizeof(METHODS[0]));
196 }
197 
198 }; // namespace android
199 
200