Add API that gets the timestamp data from the sentence 84/89384/7 accepted/tizen/common/20160927.152811 accepted/tizen/ivi/20160928.050124 accepted/tizen/mobile/20160928.050032 accepted/tizen/tv/20160928.050046 accepted/tizen/wearable/20160928.050106 submit/tizen/20160927.074456
authorstom.hwang <stom.hwang@samsung.com>
Fri, 23 Sep 2016 08:43:47 +0000 (17:43 +0900)
committerstom.hwang <stom.hwang@samsung.com>
Tue, 27 Sep 2016 07:25:17 +0000 (16:25 +0900)
Change-Id: Ie89ca887c005df4295ef53a035e0f915f9fd98f6
Signed-off-by: stom.hwang <stom.hwang@samsung.com>
common/vc_command.c [changed mode: 0644->0755]
common/vc_regex_rule.h [new file with mode: 0755]
include/voice_control_command_expand.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index e728fb5..61053a9
@@ -14,6 +14,8 @@
 * limitations under the License.
 */
 
+#define _GNU_SOURCE
+
 #include <cynara-client.h>
 #include <cynara-error.h>
 #include <cynara-session.h>
@@ -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(&reg[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(&reg[0], TIME_ABS1_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[1], TIME_ABS2_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[2], TIME_ABS3_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[3], TIME_REL1_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[4], TIME_REL2_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[5], TIME_REL3_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[6], TIME_PHR_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[7], DATE_ABS1_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[8], DATE_ABS2_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[9], DATE_ABS3_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[10], DATE_PHR1_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[11], DATE_PHR2_REGEX[lang_type], cflags);
+       if (0 != ret) {
+               regerror(ret, &reg[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(&reg[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(&reg[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(&reg[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(&reg[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(&reg[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(&reg[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(&reg[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(&reg[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(&reg[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(&reg[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(&reg[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(&reg[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 (executable)
index 0000000..973cbe4
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __VC_REGEX_RULE_H
+#define __VC_REGEX_RULE_H
+
+#define MAX_NUM_REGEX 12
+
+#include <string.h>
+#include <time.h>
+#include <regex.h>
+
+#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
old mode 100644 (file)
new mode 100755 (executable)
index 8bd196c..695641f
@@ -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
 }