* limitations under the License.
*/
+#define _GNU_SOURCE
+
#include <cynara-client.h>
#include <cynara-error.h>
#include <cynara-session.h>
#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"
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) {
}
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;
}
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