From: stom.hwang Date: Fri, 23 Sep 2016 08:43:47 +0000 (+0900) Subject: Add API that gets the timestamp data from the sentence X-Git-Tag: accepted/tizen/common/20160927.152811^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b4a01fc7783a1f5f58c56508b3d315c5316bec92;p=platform%2Fcore%2Fuifw%2Fvoice-control.git Add API that gets the timestamp data from the sentence Change-Id: Ie89ca887c005df4295ef53a035e0f915f9fd98f6 Signed-off-by: stom.hwang --- diff --git a/common/vc_command.c b/common/vc_command.c old mode 100644 new mode 100755 index e728fb5..61053a9 --- a/common/vc_command.c +++ b/common/vc_command.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#define _GNU_SOURCE + #include #include #include @@ -24,6 +26,8 @@ #include "vc_command.h" #include "vc_info_parser.h" #include "vc_main.h" +#include "vc_regex_rule.h" +#include "vc_config_mgr.h" #include "voice_control_command.h" #include "voice_control_command_expand.h" #include "voice_control_common.h" @@ -34,6 +38,17 @@ static int g_feature_enabled = -1; static int g_privilege_allowed = 1; /* Always True */ static cynara *p_cynara = NULL; +// For getting timestamp using regular expression +static regex_t reg[MAX_NUM_REGEX]; +static time_t t_now; //time_t is based on UTC +static struct tm *td_now; //if use localtime function, the value follows the local time zone, otherwise it follows the UTC. + +static int g_time_flag; +static int g_date_flag; + +static int g_data_sidx; +static int g_data_eidx; + static int __vc_cmd_get_feature_enabled() { if (0 == g_feature_enabled) { @@ -1341,7 +1356,7 @@ int vc_cmd_get_nlu_json(vc_cmd_h vc_cmd, char** json) } if (NULL == vc_cmd || NULL == json) { - SLOG(LOG_ERROR, TAG_VCM, "[ERROR] NULL parameter"); + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] NULL parameter"); return VC_ERROR_INVALID_PARAMETER; } @@ -1349,14 +1364,909 @@ int vc_cmd_get_nlu_json(vc_cmd_h vc_cmd, char** json) cmd = (vc_cmd_s*)vc_cmd; if (VC_CMD_FORMAT_ACTION != cmd->format) { - SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Not Action format"); + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Not Action format"); return VC_ERROR_INVALID_PARAMETER; } if (0 != vc_info_parser_get_nlu_result(json)) { - SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get nlu result"); + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Fail to get nlu result"); return VC_ERROR_OPERATION_FAILED; } return 0; } + +static void __vc_cmd_regex_deinit(int num_regex) +{ + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Start Deinitialize regex ===="); + int i; + + for (i = 0; i < num_regex; i++) { + regfree(®[i]); + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "===="); + SLOG(LOG_DEBUG, TAG_VCCMD, ""); +} + +static int __vc_cmd_regex_init() +{ + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Initialize regular expression ===="); + + int cflags = REG_EXTENDED | REG_ICASE; + int ret; + char errStr[128]; + char *lang = NULL; + int lang_type = 1; + + vc_config_mgr_get_default_language(&lang); + if (NULL == lang) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Fail to get current language"); + return VC_ERROR_OPERATION_FAILED; + } + + if (!strcmp("en_US", lang)) { + lang_type = 1; + } else if (!strcmp("ko_KR", lang)) { + lang_type = 0; + } else { + free(lang); + lang = NULL; + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Not supported language type"); + return VC_ERROR_INVALID_LANGUAGE; + } + + free(lang); + lang = NULL; + + SLOG(LOG_DEBUG, TAG_VCCMD, "==== lang type > %d ====", lang_type); + + re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s" , TIME_ABS1_REGEX[lang_type]); + ret = regcomp(®[0], TIME_ABS1_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[0], errStr, sizeof(errStr)); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", TIME_ABS2_REGEX[lang_type]); + ret = regcomp(®[1], TIME_ABS2_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[1], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(1); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", TIME_ABS3_REGEX[lang_type]); + ret = regcomp(®[2], TIME_ABS3_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[2], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(2); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", TIME_REL1_REGEX[lang_type]); + ret = regcomp(®[3], TIME_REL1_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[3], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(3); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", TIME_REL2_REGEX[lang_type]); + ret = regcomp(®[4], TIME_REL2_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[4], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(4); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", TIME_REL3_REGEX[lang_type]); + ret = regcomp(®[5], TIME_REL3_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[5], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(5); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", TIME_PHR_REGEX[lang_type]); + ret = regcomp(®[6], TIME_PHR_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[6], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(6); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", DATE_ABS1_REGEX[lang_type]); + ret = regcomp(®[7], DATE_ABS1_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[7], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(7); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", DATE_ABS2_REGEX[lang_type]); + ret = regcomp(®[8], DATE_ABS2_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[8], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(8); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", DATE_ABS3_REGEX[lang_type]); + ret = regcomp(®[9], DATE_ABS3_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[9], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(9); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", DATE_PHR1_REGEX[lang_type]); + ret = regcomp(®[10], DATE_PHR1_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[10], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(10); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Regular expression > %s", DATE_PHR2_REGEX[lang_type]); + ret = regcomp(®[11], DATE_PHR2_REGEX[lang_type], cflags); + if (0 != ret) { + regerror(ret, ®[11], errStr, sizeof(errStr)); + __vc_cmd_regex_deinit(11); + + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] regcomp() error > %s", errStr); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "===="); + SLOG(LOG_DEBUG, TAG_VCCMD, ""); + + return VC_ERROR_NONE; +} + +static void __vc_cmd_add_year(struct tm *td, int year) +{ + td->tm_year += year; +} + +static void __vc_cmd_add_mon(struct tm *td, int mon) +{ + int year = 0; + + mon = td->tm_mon + mon; + year = mon / 12; + + if (0 < year) { + __vc_cmd_add_year(td, year); + } + + td->tm_mon = mon % 12; +} + +static void __vc_cmd_add_mday(struct tm *td, int mday) +{ + int max_day[12] = {31, 28, 31, 30, 31, 30, 31, 30, 30, 31, 30, 31}; + int year = td->tm_year + 1900; + + int mon = 0; + + if ((0 == year % 4 && 0 != year % 100) || 0 == year % 400) max_day[1] = 29; + + mday = td->tm_mday + mday; + + for (mon = td->tm_mon; mday >= max_day[mon % 12]; mon++) { + mday -= max_day[mon % 12]; + + if (mon % 12 == 11) { + year++; + + if ((0 == year % 4 && 0 != year % 100) || 0 == year % 400) { + max_day[1] = 29; + } else { + max_day[1] = 28; + } + } + } + + mon = mon - td->tm_mon; + + if (0 < mon) { + __vc_cmd_add_mon(td, mon); + } + + td->tm_mday = mday; +} + +static void __vc_cmd_add_hour(struct tm *td, int hour) +{ + int day = 0; + + hour = td->tm_hour + hour; + day = hour / 24; + + if (0 < day) { + __vc_cmd_add_mday(td, day); + } + + td->tm_hour = hour % 24; +} + +static void __vc_cmd_add_min(struct tm *td, int min) +{ + int hour = 0; + + min = td->tm_min + min; + hour = min / 60; + + if (0 < hour) { + __vc_cmd_add_hour(td, hour); + } + + td->tm_min = min % 60; +} + +static void __copy_struct_tm(struct tm *des, struct tm *src) +{ + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Start to copy struct tm ===="); + + des->tm_sec = src->tm_sec; + des->tm_min = src->tm_min; + des->tm_hour = src->tm_hour; + des->tm_mday = src->tm_mday; + des->tm_mon = src->tm_mon; + des->tm_year = src->tm_year; + des->tm_wday = src->tm_wday; + des->tm_yday = src->tm_yday; + des->tm_isdst = src->tm_isdst; + + des->tm_gmtoff = src->tm_gmtoff; + des->tm_zone = src->tm_zone; +} + +static void __update_data_sidx(int idx) +{ + if (g_data_sidx < 0 || g_data_sidx > idx) g_data_sidx = idx; +} + +static void __update_data_eidx(int idx) +{ + if (g_data_eidx < 0 || g_data_eidx < idx) g_data_eidx = idx; +} + +static int __vc_cmd_tphrase_check(const char *str, struct tm *td, int *exist) +{ + regmatch_t pmatch[3]; + int ret; + int len; + int idx; + + *exist = 0; + ret = regexec(®[6], str, 3, pmatch, 0); + if (0 == ret) { + idx = 1; + len = pmatch[idx].rm_eo - pmatch[idx].rm_so; + if (0 < len) { + if (12 < td->tm_hour) { + __vc_cmd_add_mday(td, 1); + } + + td->tm_hour = 12; + } else { + idx = 2; + len = pmatch[idx].rm_eo - pmatch[idx].rm_so; + + __vc_cmd_add_mday(td, 1); + } + + td->tm_min = 0; + td->tm_sec = 0; + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", len, str + pmatch[idx].rm_so); + + __update_data_sidx(pmatch[0].rm_so); + __update_data_eidx(pmatch[0].rm_eo); + + *exist = 1; + return VC_ERROR_NONE; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] There is no matched string"); + return VC_ERROR_NONE; +} + +static int __vc_cmd_trelative_check(const char *str, struct tm *td, int *exist) +{ + regmatch_t pmatch[2]; + int ret; + int len; + int sidx = -1; + int eidx = -1; + int hour = -1; + int min = -1; + + char *tempstr = NULL; + + *exist = 0; + ret = regexec(®[3], str, 1, pmatch, 0); + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", pmatch[0].rm_eo - pmatch[0].rm_so, str+pmatch[0].rm_so); + hour = min = -1; + + if (sidx < 0 || sidx > pmatch[0].rm_so) sidx = pmatch[0].rm_so; + if (eidx < 0 || eidx < pmatch[0].rm_eo) eidx = pmatch[0].rm_eo; + + ret = regexec(®[4], str, 2, pmatch, 0); + if (0 == ret) { + len = pmatch[1].rm_eo - pmatch[1].rm_so; + tempstr = strndup(str + pmatch[1].rm_so, len); + + if (NULL == tempstr) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); + return VC_ERROR_OUT_OF_MEMORY; + } + + hour = atoi(tempstr); + + free(tempstr); + tempstr = NULL; + + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", len, str + pmatch[1].rm_so); + + if (sidx < 0 || sidx > pmatch[0].rm_so) sidx = pmatch[0].rm_so; + if (eidx < 0 || eidx < pmatch[0].rm_eo) eidx = pmatch[0].rm_eo; + } + + ret = regexec(®[5], str, 2, pmatch, 0); + if (0 == ret) { + len = pmatch[1].rm_eo - pmatch[1].rm_so; + tempstr = strndup(str + pmatch[1].rm_so, len); + + if (NULL == tempstr) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); + return VC_ERROR_OUT_OF_MEMORY; + } + + min = atoi(tempstr); + + free(tempstr); + tempstr = NULL; + + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", len, str + pmatch[1].rm_so); + + if (sidx < 0 || sidx > pmatch[0].rm_so) sidx = pmatch[0].rm_so; + if (eidx < 0 || eidx < pmatch[0].rm_eo) eidx = pmatch[0].rm_eo; + } + + if (hour < 0 && min < 0) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] There is no matched string"); + return VC_ERROR_NONE; + } + + hour = hour < 0 ? 0 : hour; + min = min < 0 ? 0 : min; + + min = min + (hour * 60); + + __vc_cmd_add_min(td, min); + td->tm_sec = 0; + + __update_data_sidx(sidx); + __update_data_eidx(eidx); + + *exist = 1; + return VC_ERROR_NONE; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] There is no matched string"); + return VC_ERROR_NONE; +} + +static int __vc_cmd_tabsolute_check(const char *str, struct tm *td, int *exist) +{ + regmatch_t pmatch[5]; + int ret; + int len; + int idx; + int flag = -1; + int hour = -1; + int min = -1; + int sidx = -1; + int eidx = -1; + char *tempstr = NULL; + + *exist = 0; + ret = regexec(®[0], str, 5, pmatch, 0); + if (0 == ret) { + for (idx = 1; idx < 5 && 0 >= pmatch[idx].rm_eo - pmatch[idx].rm_so; idx++); + + flag = idx & 1; + + if (sidx < 0 || sidx > pmatch[0].rm_so) sidx = pmatch[0].rm_so; + if (eidx < 0 || eidx < pmatch[0].rm_eo) eidx = pmatch[0].rm_eo; + } + + ret = regexec(®[1], str, 2, pmatch, 0); + if (0 == ret) { + len = pmatch[1].rm_eo - pmatch[1].rm_so; + tempstr = strndup(str + pmatch[1].rm_so, len); + + if (NULL == tempstr) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); + return VC_ERROR_OUT_OF_MEMORY; + } + + hour = atoi(tempstr); + + if (0 <= flag) { + hour = hour + 12 * flag; + + if (12 == hour) hour = 0; + else if(24 == hour) hour = 12; + } + + if (0 > hour || 24 <= hour || (0 == flag && 12 < hour)) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] Incomming sentence is weird"); + return VC_ERROR_NONE; + } + + free(tempstr); + tempstr = NULL; + + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", len, str + pmatch[1].rm_so); + + if (sidx < 0 || sidx > pmatch[0].rm_so) sidx = pmatch[0].rm_so; + if (eidx < 0 || eidx < pmatch[0].rm_eo) eidx = pmatch[0].rm_eo; + } else if (0 < flag) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] Incomming sentence is weird"); + return VC_ERROR_NONE; + } + + ret = regexec(®[2], str, 2, pmatch, 0); + if (0 == ret) { + idx = 1; + len = pmatch[idx].rm_eo - pmatch[idx].rm_so; + if (0 < len) { + tempstr = strndup(str + pmatch[idx].rm_so, len); + + if (NULL == tempstr) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); + return VC_ERROR_OUT_OF_MEMORY; + } + + min = atoi(tempstr); + + if (0 > min || 60 <= min) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] Incomming sentence is weird"); + return VC_ERROR_NONE; + } + + td->tm_sec = 0; + + free(tempstr); + tempstr = NULL; + } else { + idx = 0; + min = 30; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", pmatch[idx].rm_eo - pmatch[idx].rm_so, str + pmatch[idx].rm_so); + if (sidx < 0 || sidx > pmatch[0].rm_so) sidx = pmatch[0].rm_so; + if (eidx < 0 || eidx < pmatch[0].rm_eo) eidx = pmatch[0].rm_eo; + } + + if (hour < 0 && min < 0) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] There is no matched string"); + return VC_ERROR_NONE; + } + + if (min >= 0 && hour >= 0) { + if (hour < td->tm_hour || (hour == td->tm_hour && min <= td->tm_min)) __vc_cmd_add_mday(td, 1); + + td->tm_hour = hour; + td->tm_min = min; + } else if (min >= 0) { + char *lang = NULL; + vc_config_mgr_get_default_language(&lang); + if (NULL == lang) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Fail to get current language"); + return VC_ERROR_OPERATION_FAILED; + } + + if (!strcmp("en_US", lang)) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] Incomming sentence is weird"); + free(lang); + lang = NULL; + return VC_ERROR_NONE; + } + if (min <= td->tm_min) __vc_cmd_add_hour(td, 1); + + td->tm_min = min; + + free(lang); + lang = NULL; + } else { + if (hour <= td->tm_hour) __vc_cmd_add_mday(td, 1); + + td->tm_hour = hour; + td->tm_min = 0; + } + + td->tm_sec = 0; + + __update_data_sidx(sidx); + __update_data_eidx(eidx); + + *exist = 1; + return VC_ERROR_NONE; +} + +static int __vc_cmd_dphrase_check(const char *str, struct tm *td, int *exist) +{ + regmatch_t pmatch[9]; + int ret; + int len; + int idx; + + *exist = 0; + ret = regexec(®[10], str, 5, pmatch, 0); + if (0 == ret) { + for (idx = 1; idx < 5 && 0 >= pmatch[idx].rm_eo - pmatch[idx].rm_so; idx++); + + len = pmatch[idx].rm_eo - pmatch[idx].rm_so; + + td->tm_year = td_now->tm_year; + td->tm_mon = td_now->tm_mon; + td->tm_mday = td_now->tm_mday; + + __vc_cmd_add_mday(td, idx - 1); + + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", len, str + pmatch[idx].rm_so); + + __update_data_sidx(pmatch[0].rm_so); + __update_data_eidx(pmatch[0].rm_eo); + + *exist = 1; + return VC_ERROR_NONE; + } + + ret = regexec(®[11], str, 9, pmatch, 0); + if (0 == ret) { + for (idx = 1; idx < 9; idx++) { + len = pmatch[idx].rm_eo - pmatch[idx].rm_so; + + if (0 < len) break; + } + + td->tm_year = td_now->tm_year; + td->tm_mon = td_now->tm_mon; + td->tm_mday = td_now->tm_mday; + + __vc_cmd_add_mday(td, idx + 1); + + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", len, str + pmatch[idx].rm_so); + + __update_data_sidx(pmatch[0].rm_so); + __update_data_eidx(pmatch[0].rm_eo); + + *exist = 1; + return VC_ERROR_NONE; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] There is no matched string"); + return VC_ERROR_NONE; +} + +static int __vc_cmd_dabsolute_check(const char *str, struct tm *td, int *exist) +{ + regmatch_t pmatch[13]; + int ret; + int len; + int idx; + int sidx = -1; + int eidx = -1; + int y_flag = 0; + int m_flag = 0; + int year = -1; + int mon = -1; + int day = -1; + char *tempstr = NULL; + + *exist = 0; + ret = regexec(®[9], str, 2, pmatch, 0); + if (0 == ret) { + len = pmatch[1].rm_eo - pmatch[1].rm_so; + tempstr = strndup(str + pmatch[1].rm_so, len); + + if (NULL == tempstr) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); + return VC_ERROR_OUT_OF_MEMORY; + } + + day = atoi(tempstr); + + free(tempstr); + tempstr = NULL; + + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", len, str + pmatch[1].rm_so); + + if (sidx < 0 || sidx > pmatch[0].rm_so) sidx = pmatch[0].rm_so; + if (eidx < 0 || eidx < pmatch[0].rm_eo) eidx = pmatch[0].rm_eo; + } else { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] Incomming sentence is weird"); + return VC_ERROR_NONE; + } + + ret = regexec(®[8], str, 13, pmatch, 0); + if (0 == ret) { + for (idx = 1; idx < 13; idx++) { + len = pmatch[idx].rm_eo - pmatch[idx].rm_so; + + if (0 < len) { + mon = idx - 1; + break; + } + } + + m_flag = 1; + + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", len, str + pmatch[idx].rm_so); + + if (sidx < 0 || sidx > pmatch[0].rm_so) sidx = pmatch[0].rm_so; + if (eidx < 0 || eidx < pmatch[0].rm_eo) eidx = pmatch[0].rm_eo; + } else { + char *lang = NULL; + vc_config_mgr_get_default_language(&lang); + if (NULL == lang) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Fail to get current language"); + return VC_ERROR_OPERATION_FAILED; + } + + if (!strcmp("en_US", lang)) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] Incomming sentence is weird"); + free(lang); + lang = NULL; + return VC_ERROR_NONE; + } + + free(lang); + lang = NULL; + + mon = td->tm_mon; + } + + ret = regexec(®[7], str, 3, pmatch, 0); + if (0 == ret) { + if (!m_flag) return -1; + + len = pmatch[2].rm_eo - pmatch[2].rm_so; + tempstr = strndup(str + pmatch[2].rm_so, len); + + if (NULL == tempstr) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Memory allocation is failed"); + return VC_ERROR_OUT_OF_MEMORY; + } + + year = atoi(tempstr); + year = year > 1900 ? year - 1900 : year + 100; + + free(tempstr); + tempstr = NULL; + + y_flag = 1; + SLOG(LOG_DEBUG, TAG_VCCMD, "Matched string > %.*s", len, str + pmatch[2].rm_so); + + if (sidx < 0 || sidx > pmatch[0].rm_so) sidx = pmatch[0].rm_so; + if (eidx < 0 || eidx < pmatch[0].rm_eo) eidx = pmatch[0].rm_eo; + } else { + year = td->tm_year; + } + + if (g_time_flag < 0) { + td->tm_hour = 0; + td->tm_min = 0; + td->tm_sec = 0; + } else if (g_time_flag == 2) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] Incomming sentence is weird"); + return VC_ERROR_NONE; + } + + int max_day[12] = {31, 28, 31, 30, 31, 30, 31, 30, 30, 31, 30, 31}; + if ((0 == (year + 1900) % 4 && 0 != (year + 1900) % 100) || 0 == (year + 1900) % 400) max_day[1] = 29; + + if (max_day[mon] < day || 1 > day) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] Incomming sentence is weird"); + return VC_ERROR_NONE; + } + + td->tm_year = year; + td->tm_mon = mon; + td->tm_mday = day; + + if (!y_flag) { + if (!m_flag) { + if (day < td_now->tm_mday) __vc_cmd_add_mon(td, 1); + } else { + if (mon < td_now->tm_mon) __vc_cmd_add_year(td, 1); + else if (mon == td_now->tm_mon && day < td_now->tm_mday) __vc_cmd_add_year(td, 1); + } + } + + __update_data_sidx(sidx); + __update_data_eidx(eidx); + + *exist = 1; + return VC_ERROR_NONE; +} + +static int __vc_cmd_time_check(const char *str, struct tm *td) +{ + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Check time value in string \"%s\"", str); + + vc_error_e ret; + int exist = 0; + + ret = __vc_cmd_tphrase_check(str, td, &exist); + if (1 == exist) { + g_time_flag = 1; + + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Time value is exist"); + return ret; + } else if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Error is occured > (%d)", ret); + return ret; + } + + ret = __vc_cmd_trelative_check(str, td, &exist); + if (1 == exist) { + g_time_flag = 2; + + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Time value is exist"); + return ret; + } else if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Error is occured > (%d)", ret); + return ret; + } + + ret = __vc_cmd_tabsolute_check(str, td, &exist); + if (1 == exist) { + g_time_flag = 3; + + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Time value is exist"); + return ret; + } else if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Error is occured > (%d)", ret); + return ret; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "==== There is no time value"); + return VC_ERROR_NONE; +} + +static int __vc_cmd_date_check(const char *str, struct tm *td) +{ + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Check date value in string \"%s\"", str); + + vc_error_e ret; + int exist = 0; + + ret = __vc_cmd_dphrase_check(str, td, &exist); + if (1 == exist) { + g_date_flag = 1; + + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Date value is exist"); + return ret; + } else if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Error is occured > (%d)", ret); + return ret; + } + + ret = __vc_cmd_dabsolute_check(str, td, &exist); + if (1 == exist) { + g_date_flag = 1; + + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Date value is exist"); + return ret; + } else if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Error is occured > (%d)", ret); + return ret; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "==== There is no date value"); + return VC_ERROR_NONE; +} + +int vc_cmd_get_datetime(const char *text, time_t *result, char **remain) +{ + SLOG(LOG_DEBUG, TAG_VCCMD, "==== Get timestamp data"); + + struct tm td; + const char *day_name[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + vc_error_e ret; + + *result = -1; + if (NULL == text || NULL == result || NULL == remain) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter"); + return VC_ERROR_INVALID_PARAMETER; + } + + ret = __vc_cmd_regex_init(); + if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] initialize regex failed"); + return ret; + } + + g_data_sidx = g_data_eidx = -1; + + t_now = time(NULL); + td_now = localtime(&t_now); + SLOG(LOG_DEBUG, TAG_VCCMD, "Current timestamp = %d", (int)t_now); + + __copy_struct_tm(&td, td_now); + SLOG(LOG_DEBUG, TAG_VCCMD, "%d-%d-%d (%s), %d:%d:%d", + td.tm_year + 1900, td.tm_mon + 1, td.tm_mday, day_name[td.tm_wday], td.tm_hour, td.tm_min, td.tm_sec); + + g_time_flag = g_date_flag = -1; + + ret = __vc_cmd_time_check(text, &td); + if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Error is occured in the check > (%d)", ret); + return ret; + } + + ret = __vc_cmd_date_check(text, &td); + if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Error is occured in the check > (%d)", ret); + return ret; + } + + __vc_cmd_regex_deinit(12); + + if (g_time_flag > 0 || g_date_flag > 0) { + *result = mktime(&td); + + SLOG(LOG_DEBUG, TAG_VCCMD, "Timestamp in the text = %d", *result); + SLOG(LOG_DEBUG, TAG_VCCMD, "%d-%d-%d (%s), %d:%d:%d", + td.tm_year + 1900, td.tm_mon + 1, td.tm_mday, day_name[td.tm_wday], td.tm_hour, td.tm_min, td.tm_sec, td.tm_yday); + + *remain = (char *)calloc(sizeof(char), (strlen(text) + 1 - g_data_eidx + g_data_sidx)); + + if (NULL == *remain) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Out of memory error"); + return VC_ERROR_OUT_OF_MEMORY; + } + + strncpy(*remain, text, g_data_sidx); + strncat(*remain, text + g_data_eidx, strlen(text) - g_data_eidx); + } else { + SLOG(LOG_DEBUG, TAG_VCCMD, "[REGEX] There is no data in the text"); + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "===="); + SLOG(LOG_DEBUG, TAG_VCCMD, ""); + + return VC_ERROR_NONE; +} \ No newline at end of file diff --git a/common/vc_regex_rule.h b/common/vc_regex_rule.h new file mode 100755 index 0000000..973cbe4 --- /dev/null +++ b/common/vc_regex_rule.h @@ -0,0 +1,57 @@ +#ifndef __VC_REGEX_RULE_H +#define __VC_REGEX_RULE_H + +#define MAX_NUM_REGEX 12 + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +//at noon / at midnight +const char *TIME_PHR_REGEX[2] = {"(정오)|(자정)", + "( at noon)|( at midnight)"}; +//morning / afternoon +const char *TIME_ABS1_REGEX[2] = {"(오후)|(오전)|(저녁)|(아침)", + "([0-9] p.?m.?)|([0-9] a.?m.?)|( afternoon)|( morning)"}; +//hh:mm / :mm / hh o'clock / pm / am +const char *TIME_ABS2_REGEX[2] = {"([1-9]|1[0-9]|2[0-4])시", + " at ([1-9]|1[0-9]|2[0-4])( o'clock|:| pm| p.m.| am| a.m.|$)"}; +const char *TIME_ABS3_REGEX[2] = {"([1-9]|[1-5][0-9])분|반", + ":([0-5][0-9])"}; +//hh hour(s) mm minute(s) (after / later) / hh hour(s) (after / later) / mm minute(s) (after / later) +const char *TIME_REL1_REGEX[2] = {"(시간|분).*[^오](뒤|후|있다가)", + " after([^a-zA-Z]|$)| later([^a-zA-Z]|$)| in [0-9]+ (minute|hour)"}; +const char *TIME_REL2_REGEX[2] = {"([1-9][0-9]*)시간", + "([1-9][0-9]*) hours?"}; +const char *TIME_REL3_REGEX[2] = {"([1-9][0-9]*)분", + "([1-9][0-9]*) minutes?"}; + +//day month, year / day month / day +const char *DATE_ABS1_REGEX[2] = {"(([1-2][0-9]{3})년)", + "(st|nd|rd|th),? ([1-2][0-9]{3})"}; +const char *DATE_ABS2_REGEX[2] = {"(1월)|(2월)|(3월)|(4월)|(5월)|(6월)|(7월)|(8월)|(9월)|(10월)|(11월)|(12월)", + "(January)|(February)|(March)|(April)|(May)|(June)|(July)|(August)|(September)|(October)|(November)|(December)"}; +const char *DATE_ABS3_REGEX[2] = {"([1-9]|[1-2][0-9]|3[0-1])일", + "([1-9]|[1-2][0-9]|3[0-1])(st|nd|rd|th)"}; +//today / tommorow / the day after tommorow +const char *DATE_PHR1_REGEX[2] = {"(오늘)|(내일)|(모레)|(글피)", + "(today)|(tommorow)|(the day after tommorow)"}; +const char *DATE_PHR2_REGEX[2] = {"(이틀)|(사흘)|(나흘)|(닷새)|(엿새)|(이레)|(여드레)|(아흐레)|(열흘)", + "(이틀)|(사흘)|(나흘)|(닷새)|(엿새)|(이레)|(여드레)|(아흐레)|(열흘)"}; + +//Monday / Tuesday / Wednesday / Thursday / Satruday / Sunday +const char *DATE_PHR3_REGEX[2] = {"(월|화|수|목|금|토|일)(요일)?", + "(Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)(day)?"}; + + +#ifdef __cplusplus +} +#endif + + +#endif \ No newline at end of file diff --git a/include/voice_control_command_expand.h b/include/voice_control_command_expand.h old mode 100644 new mode 100755 index 8bd196c..695641f --- a/include/voice_control_command_expand.h +++ b/include/voice_control_command_expand.h @@ -198,6 +198,27 @@ int vc_cmd_set_unfixed_command(vc_cmd_h vc_command, const char* command); */ int vc_cmd_get_nlu_json(vc_cmd_h vc_cmd, char** json); +/** +* @brief Gets the datetime value from the setence. +* @since_tizen 3.0 +* +* @param[in] text The sentence to analyze +* @param[out] result The datetime value in the sentence +* @param[out] remain Remained text except time +* +* @remark If the function succeeds, @a remain must be released with free() by you when you no longer need it. +* If there is no time value in @a text or the function does not work correctly, +* @a result is -1. Otherwise @a result has the time value in @a text. +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_CMD_ERROR_NONE Successful +* @retval #VC_ERROR_OPERATION_FAILED operation failure +* @retval #VC_ERROR_OUT_OF_MEMORY Not enough memory +* @retval #VC_CMD_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see vc_cmd_set_datetime_lang() +*/ +int vc_cmd_get_datetime(const char *text, time_t *result, char **remain); #ifdef __cplusplus }