Remove native EventRecurrence parser
Switch over to the new parser. Bug 4575374 Change-Id: If78d8042fb266182900398f7fc464a048c779966
This commit is contained in:
parent
2b4b4f44e5
commit
bae6579eb2
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
//
|
||||
#ifndef _PIM_EVENT_RECURRENCE_H
|
||||
#define _PIM_EVENT_RECURRENCE_H
|
||||
|
||||
#include <utils/String16.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
struct EventRecurrence
|
||||
{
|
||||
public:
|
||||
EventRecurrence();
|
||||
~EventRecurrence();
|
||||
|
||||
status_t parse(const String16&);
|
||||
|
||||
|
||||
enum freq_t {
|
||||
SECONDLY = 1,
|
||||
MINUTELY = 2,
|
||||
HOURLY = 3,
|
||||
DAILY = 4,
|
||||
WEEKLY = 5,
|
||||
MONTHLY = 6,
|
||||
YEARLY = 7
|
||||
};
|
||||
|
||||
enum {
|
||||
SU = 0x00010000,
|
||||
MO = 0x00020000,
|
||||
TU = 0x00040000,
|
||||
WE = 0x00080000,
|
||||
TH = 0x00100000,
|
||||
FR = 0x00200000,
|
||||
SA = 0x00400000
|
||||
};
|
||||
|
||||
freq_t freq;
|
||||
String16 until;
|
||||
int count;
|
||||
int interval;
|
||||
int* bysecond;
|
||||
int bysecondCount;
|
||||
int* byminute;
|
||||
int byminuteCount;
|
||||
int* byhour;
|
||||
int byhourCount;
|
||||
int* byday;
|
||||
int* bydayNum;
|
||||
int bydayCount;
|
||||
int* bymonthday;
|
||||
int bymonthdayCount;
|
||||
int* byyearday;
|
||||
int byyeardayCount;
|
||||
int* byweekno;
|
||||
int byweeknoCount;
|
||||
int* bymonth;
|
||||
int bymonthCount;
|
||||
int* bysetpos;
|
||||
int bysetposCount;
|
||||
int wkst;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // _PIM_EVENT_RECURRENCE_H
|
@ -43,7 +43,6 @@ include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES:= \
|
||||
$(commonSources) \
|
||||
EGLUtils.cpp \
|
||||
EventRecurrence.cpp \
|
||||
FramebufferNativeWindow.cpp \
|
||||
GraphicBuffer.cpp \
|
||||
GraphicBufferAllocator.cpp \
|
||||
|
@ -1,484 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006 The Android Open Source Project
|
||||
*/
|
||||
|
||||
#include <pim/EventRecurrence.h>
|
||||
#include <utils/String8.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
#define FAIL_HERE() do { \
|
||||
printf("Parsing failed at line %d\n", __LINE__); \
|
||||
return UNKNOWN_ERROR; \
|
||||
} while(0)
|
||||
|
||||
EventRecurrence::EventRecurrence()
|
||||
:freq((freq_t)0),
|
||||
until(),
|
||||
count(0),
|
||||
interval(0),
|
||||
bysecond(0),
|
||||
bysecondCount(0),
|
||||
byminute(0),
|
||||
byminuteCount(0),
|
||||
byhour(0),
|
||||
byhourCount(0),
|
||||
byday(0),
|
||||
bydayNum(0),
|
||||
bydayCount(0),
|
||||
bymonthday(0),
|
||||
bymonthdayCount(0),
|
||||
byyearday(0),
|
||||
byyeardayCount(0),
|
||||
byweekno(0),
|
||||
byweeknoCount(0),
|
||||
bymonth(0),
|
||||
bymonthCount(0),
|
||||
bysetpos(0),
|
||||
bysetposCount(0),
|
||||
wkst(0)
|
||||
{
|
||||
}
|
||||
|
||||
EventRecurrence::~EventRecurrence()
|
||||
{
|
||||
delete[] bysecond;
|
||||
delete[] byminute;
|
||||
delete[] byhour;
|
||||
delete[] byday;
|
||||
delete[] bydayNum;
|
||||
delete[] byyearday;
|
||||
delete[] bymonthday;
|
||||
delete[] byweekno;
|
||||
delete[] bymonth;
|
||||
delete[] bysetpos;
|
||||
}
|
||||
|
||||
enum LHS {
|
||||
NONE_LHS = 0,
|
||||
FREQ,
|
||||
UNTIL,
|
||||
COUNT,
|
||||
INTERVAL,
|
||||
BYSECOND,
|
||||
BYMINUTE,
|
||||
BYHOUR,
|
||||
BYDAY,
|
||||
BYMONTHDAY,
|
||||
BYYEARDAY,
|
||||
BYWEEKNO,
|
||||
BYMONTH,
|
||||
BYSETPOS,
|
||||
WKST
|
||||
};
|
||||
|
||||
struct LHSProc
|
||||
{
|
||||
const char16_t* text;
|
||||
size_t textSize;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
const char16_t FREQ_text[] = { 'F', 'R', 'E', 'Q' };
|
||||
const char16_t UNTIL_text[] = { 'U', 'N', 'T', 'I', 'L' };
|
||||
const char16_t COUNT_text[] = { 'C', 'O', 'U', 'N', 'T' };
|
||||
const char16_t INTERVAL_text[] = { 'I', 'N', 'T', 'E', 'R', 'V', 'A', 'L'};
|
||||
const char16_t BYSECOND_text[] = { 'B', 'Y', 'S', 'E', 'C', 'O', 'N', 'D' };
|
||||
const char16_t BYMINUTE_text[] = { 'B', 'Y', 'M', 'I', 'N', 'U', 'T', 'E' };
|
||||
const char16_t BYHOUR_text[] = { 'B', 'Y', 'H', 'O', 'U', 'R' };
|
||||
const char16_t BYDAY_text[] = { 'B', 'Y', 'D', 'A', 'Y' };
|
||||
const char16_t BYMONTHDAY_text[] = { 'B','Y','M','O','N','T','H','D','A','Y' };
|
||||
const char16_t BYYEARDAY_text[] = { 'B','Y','Y','E','A','R','D','A','Y' };
|
||||
const char16_t BYWEEKNO_text[] = { 'B', 'Y', 'W', 'E', 'E', 'K', 'N', 'O' };
|
||||
const char16_t BYMONTH_text[] = { 'B', 'Y', 'M', 'O', 'N', 'T', 'H' };
|
||||
const char16_t BYSETPOS_text[] = { 'B', 'Y', 'S', 'E', 'T', 'P', 'O', 'S' };
|
||||
const char16_t WKST_text[] = { 'W', 'K', 'S', 'T' };
|
||||
|
||||
#define SIZ(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
const LHSProc LHSPROC[] = {
|
||||
{ FREQ_text, SIZ(FREQ_text), FREQ },
|
||||
{ UNTIL_text, SIZ(UNTIL_text), UNTIL },
|
||||
{ COUNT_text, SIZ(COUNT_text), COUNT },
|
||||
{ INTERVAL_text, SIZ(INTERVAL_text), INTERVAL },
|
||||
{ BYSECOND_text, SIZ(BYSECOND_text), BYSECOND },
|
||||
{ BYMINUTE_text, SIZ(BYMINUTE_text), BYMINUTE },
|
||||
{ BYHOUR_text, SIZ(BYHOUR_text), BYHOUR },
|
||||
{ BYDAY_text, SIZ(BYDAY_text), BYDAY },
|
||||
{ BYMONTHDAY_text, SIZ(BYMONTHDAY_text), BYMONTHDAY },
|
||||
{ BYYEARDAY_text, SIZ(BYYEARDAY_text), BYYEARDAY },
|
||||
{ BYWEEKNO_text, SIZ(BYWEEKNO_text), BYWEEKNO },
|
||||
{ BYMONTH_text, SIZ(BYMONTH_text), BYMONTH },
|
||||
{ BYSETPOS_text, SIZ(BYSETPOS_text), BYSETPOS },
|
||||
{ WKST_text, SIZ(WKST_text), WKST },
|
||||
{ NULL, 0, NONE_LHS },
|
||||
};
|
||||
|
||||
const char16_t SECONDLY_text[] = { 'S','E','C','O','N','D','L','Y' };
|
||||
const char16_t MINUTELY_text[] = { 'M','I','N','U','T','E','L','Y' };
|
||||
const char16_t HOURLY_text[] = { 'H','O','U','R','L','Y' };
|
||||
const char16_t DAILY_text[] = { 'D','A','I','L','Y' };
|
||||
const char16_t WEEKLY_text[] = { 'W','E','E','K','L','Y' };
|
||||
const char16_t MONTHLY_text[] = { 'M','O','N','T','H','L','Y' };
|
||||
const char16_t YEARLY_text[] = { 'Y','E','A','R','L','Y' };
|
||||
|
||||
typedef LHSProc FreqProc;
|
||||
|
||||
const FreqProc FREQPROC[] = {
|
||||
{ SECONDLY_text, SIZ(SECONDLY_text), EventRecurrence::SECONDLY },
|
||||
{ MINUTELY_text, SIZ(MINUTELY_text), EventRecurrence::MINUTELY },
|
||||
{ HOURLY_text, SIZ(HOURLY_text), EventRecurrence::HOURLY },
|
||||
{ DAILY_text, SIZ(DAILY_text), EventRecurrence::DAILY },
|
||||
{ WEEKLY_text, SIZ(WEEKLY_text), EventRecurrence::WEEKLY },
|
||||
{ MONTHLY_text, SIZ(MONTHLY_text), EventRecurrence::MONTHLY },
|
||||
{ YEARLY_text, SIZ(YEARLY_text), EventRecurrence::YEARLY },
|
||||
{ NULL, 0, NONE_LHS },
|
||||
};
|
||||
|
||||
const char16_t SU_text[] = { 'S','U' };
|
||||
const char16_t MO_text[] = { 'M','O' };
|
||||
const char16_t TU_text[] = { 'T','U' };
|
||||
const char16_t WE_text[] = { 'W','E' };
|
||||
const char16_t TH_text[] = { 'T','H' };
|
||||
const char16_t FR_text[] = { 'F','R' };
|
||||
const char16_t SA_text[] = { 'S','A' };
|
||||
|
||||
const FreqProc WEEKDAYPROC[] = {
|
||||
{ SU_text, SIZ(SU_text), EventRecurrence::SU },
|
||||
{ MO_text, SIZ(MO_text), EventRecurrence::MO },
|
||||
{ TU_text, SIZ(TU_text), EventRecurrence::TU },
|
||||
{ WE_text, SIZ(WE_text), EventRecurrence::WE },
|
||||
{ TH_text, SIZ(TH_text), EventRecurrence::TH },
|
||||
{ FR_text, SIZ(FR_text), EventRecurrence::FR },
|
||||
{ SA_text, SIZ(SA_text), EventRecurrence::SA },
|
||||
{ NULL, 0, NONE_LHS },
|
||||
};
|
||||
|
||||
// returns the index into LHSPROC for the match or -1 if not found
|
||||
inline static int
|
||||
match_proc(const LHSProc* p, const char16_t* str, size_t len)
|
||||
{
|
||||
int i = 0;
|
||||
while (p->text != NULL) {
|
||||
if (p->textSize == len) {
|
||||
if (0 == memcmp(p->text, str, len*sizeof(char16_t))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// rangeMin and rangeMax are inclusive
|
||||
static status_t
|
||||
parse_int(const char16_t* str, size_t len, int* out,
|
||||
int rangeMin, int rangeMax, bool zeroOK)
|
||||
{
|
||||
char16_t c;
|
||||
size_t i=0;
|
||||
|
||||
if (len == 0) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
bool negative = false;
|
||||
c = str[0];
|
||||
if (c == '-' ) {
|
||||
negative = true;
|
||||
i++;
|
||||
}
|
||||
else if (c == '+') {
|
||||
i++;
|
||||
}
|
||||
int n = 0;
|
||||
for (; i<len; i++) {
|
||||
c = str[i];
|
||||
if (c < '0' || c > '9') {
|
||||
FAIL_HERE();
|
||||
}
|
||||
int prev = n;
|
||||
n *= 10;
|
||||
// the spec doesn't address how big these numbers can be,
|
||||
// so we're not going to worry about not being able to represent
|
||||
// INT_MIN, and if we're going to wrap, we'll just clamp to
|
||||
// INT_MAX instead
|
||||
if (n < prev) {
|
||||
n = INT_MAX;
|
||||
} else {
|
||||
n += c - '0';
|
||||
}
|
||||
}
|
||||
if (negative) {
|
||||
n = -n;
|
||||
}
|
||||
if (n < rangeMin || n > rangeMax) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
if (!zeroOK && n == 0) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
*out = n;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
static status_t
|
||||
parse_int_list(const char16_t* str, size_t len, int* countOut, int** listOut,
|
||||
int rangeMin, int rangeMax, bool zeroOK,
|
||||
status_t (*func)(const char16_t*,size_t,int*,int,int,bool)=parse_int)
|
||||
{
|
||||
status_t err;
|
||||
|
||||
if (len == 0) {
|
||||
*countOut = 0;
|
||||
*listOut = NULL;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// make one pass through looking for commas so we know how big to make our
|
||||
// out array.
|
||||
int count = 1;
|
||||
for (size_t i=0; i<len; i++) {
|
||||
if (str[i] == ',') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
int* list = new int[count];
|
||||
const char16_t* p = str;
|
||||
int commaIndex = 0;
|
||||
size_t i;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
if (str[i] == ',') {
|
||||
err = func(p, (str+i-p), list+commaIndex, rangeMin,
|
||||
rangeMax, zeroOK);
|
||||
if (err != NO_ERROR) {
|
||||
goto bail;
|
||||
}
|
||||
commaIndex++;
|
||||
p = str+i+1;
|
||||
}
|
||||
}
|
||||
|
||||
err = func(p, (str+i-p), list+commaIndex, rangeMin, rangeMax, zeroOK);
|
||||
if (err != NO_ERROR) {
|
||||
goto bail;
|
||||
}
|
||||
commaIndex++;
|
||||
|
||||
*countOut = count;
|
||||
*listOut = list;
|
||||
|
||||
return NO_ERROR;
|
||||
|
||||
bail:
|
||||
delete[] list;
|
||||
FAIL_HERE();
|
||||
}
|
||||
|
||||
// the numbers here are small, so we pack them both into one value, and then
|
||||
// split it out later. it lets us reuse all the comma separated list code.
|
||||
static status_t
|
||||
parse_byday(const char16_t* s, size_t len, int* out,
|
||||
int rangeMin, int rangeMax, bool zeroOK)
|
||||
{
|
||||
status_t err;
|
||||
int n = 0;
|
||||
const char16_t* p = s;
|
||||
size_t plen = len;
|
||||
|
||||
if (len > 0) {
|
||||
char16_t c = s[0];
|
||||
if (c == '-' || c == '+' || (c >= '0' && c <= '9')) {
|
||||
if (len > 1) {
|
||||
size_t nlen = 0;
|
||||
c = s[nlen];
|
||||
while (nlen < len
|
||||
&& (c == '-' || c == '+' || (c >= '0' && c <= '9'))) {
|
||||
c = s[nlen];
|
||||
nlen++;
|
||||
}
|
||||
if (nlen > 0) {
|
||||
nlen--;
|
||||
err = parse_int(s, nlen, &n, rangeMin, rangeMax, zeroOK);
|
||||
if (err != NO_ERROR) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
p += nlen;
|
||||
plen -= nlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int index = match_proc(WEEKDAYPROC, p, plen);
|
||||
if (index >= 0) {
|
||||
*out = (0xffff0000 & WEEKDAYPROC[index].value)
|
||||
| (0x0000ffff & n);
|
||||
return NO_ERROR;
|
||||
}
|
||||
}
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
static void
|
||||
postprocess_byday(int count, int* byday, int** bydayNum)
|
||||
{
|
||||
int* bdn = new int[count];
|
||||
*bydayNum = bdn;
|
||||
for (int i=0; i<count; i++) {
|
||||
uint32_t v = byday[i];
|
||||
int16_t num = v & 0x0000ffff;
|
||||
byday[i] = v & 0xffff0000;
|
||||
// will sign extend:
|
||||
bdn[i] = num;
|
||||
}
|
||||
}
|
||||
|
||||
#define PARSE_INT_LIST_CHECKED(name, rangeMin, rangeMax, zeroOK) \
|
||||
if (name##Count != 0 || NO_ERROR != parse_int_list(s, slen, \
|
||||
&name##Count, &name, rangeMin, rangeMax, zeroOK)) { \
|
||||
FAIL_HERE(); \
|
||||
}
|
||||
status_t
|
||||
EventRecurrence::parse(const String16& str)
|
||||
{
|
||||
char16_t const* work = str.string();
|
||||
size_t len = str.size();
|
||||
|
||||
int lhsIndex = NONE_LHS;
|
||||
int index;
|
||||
|
||||
size_t start = 0;
|
||||
for (size_t i=0; i<len; i++) {
|
||||
char16_t c = work[i];
|
||||
if (c != ';' && i == len-1) {
|
||||
c = ';';
|
||||
i++;
|
||||
}
|
||||
if (c == ';' || c == '=') {
|
||||
if (i != start) {
|
||||
const char16_t* s = work+start;
|
||||
const size_t slen = i-start;
|
||||
|
||||
String8 thestring(String16(s, slen));
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '=':
|
||||
if (lhsIndex == NONE_LHS) {
|
||||
lhsIndex = match_proc(LHSPROC, s, slen);
|
||||
if (lhsIndex >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
FAIL_HERE();
|
||||
case ';':
|
||||
{
|
||||
switch (LHSPROC[lhsIndex].value)
|
||||
{
|
||||
case FREQ:
|
||||
if (this->freq != 0) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
index = match_proc(FREQPROC, s, slen);
|
||||
if (index >= 0) {
|
||||
this->freq = (freq_t)FREQPROC[index].value;
|
||||
}
|
||||
break;
|
||||
case UNTIL:
|
||||
// XXX should check that this is a valid time
|
||||
until.setTo(String16(s, slen));
|
||||
break;
|
||||
case COUNT:
|
||||
if (count != 0
|
||||
|| NO_ERROR != parse_int(s, slen,
|
||||
&count, INT_MIN, INT_MAX, true)) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
break;
|
||||
case INTERVAL:
|
||||
if (interval != 0
|
||||
|| NO_ERROR != parse_int(s, slen,
|
||||
&interval, INT_MIN, INT_MAX, false)) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
break;
|
||||
case BYSECOND:
|
||||
PARSE_INT_LIST_CHECKED(bysecond, 0, 59, true)
|
||||
break;
|
||||
case BYMINUTE:
|
||||
PARSE_INT_LIST_CHECKED(byminute, 0, 59, true)
|
||||
break;
|
||||
case BYHOUR:
|
||||
PARSE_INT_LIST_CHECKED(byhour, 0, 23, true)
|
||||
break;
|
||||
case BYDAY:
|
||||
if (bydayCount != 0 || NO_ERROR !=
|
||||
parse_int_list(s, slen, &bydayCount,
|
||||
&byday, -53, 53, false,
|
||||
parse_byday)) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
postprocess_byday(bydayCount, byday, &bydayNum);
|
||||
break;
|
||||
case BYMONTHDAY:
|
||||
PARSE_INT_LIST_CHECKED(bymonthday, -31, 31,
|
||||
false)
|
||||
break;
|
||||
case BYYEARDAY:
|
||||
PARSE_INT_LIST_CHECKED(byyearday, -366, 366,
|
||||
false)
|
||||
break;
|
||||
case BYWEEKNO:
|
||||
PARSE_INT_LIST_CHECKED(byweekno, -53, 53,
|
||||
false)
|
||||
break;
|
||||
case BYMONTH:
|
||||
PARSE_INT_LIST_CHECKED(bymonth, 1, 12, false)
|
||||
break;
|
||||
case BYSETPOS:
|
||||
PARSE_INT_LIST_CHECKED(bysetpos,
|
||||
INT_MIN, INT_MAX, true)
|
||||
break;
|
||||
case WKST:
|
||||
if (this->wkst != 0) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
index = match_proc(WEEKDAYPROC, s, slen);
|
||||
if (index >= 0) {
|
||||
this->wkst = (int)WEEKDAYPROC[index].value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FAIL_HERE();
|
||||
}
|
||||
lhsIndex = NONE_LHS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
start = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// enforce that there was a FREQ
|
||||
if (freq == 0) {
|
||||
FAIL_HERE();
|
||||
}
|
||||
|
||||
// default wkst to MO if it wasn't specified
|
||||
if (wkst == 0) {
|
||||
wkst = MO;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user