/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set et sw=2 ts=2: */ /*************************************************************************** * msgparser.cc * * Fri Feb 24 14:59:34 CET 2012 * Copyright 2012 Jonas Suhr Christensen * jsc@umbraculum.org ****************************************************************************/ /* * This file is part of Munia. * * Munia is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Munia is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "messageparser.h" #include #include #include #include typedef std::vector TokenVector; typedef std::list MsgTokensList; inline static void parse_into_msg_tokens(std::string& data, MsgTokensList& msgTokensList) { TokenVector tokenVector; std::string token; bool inside_quote = false; char prev_ch = '0'; for(size_t i = 0; i < data.length(); i++) { char ch = data[i]; switch(ch) { case '\"': if(prev_ch != '\\') inside_quote = !inside_quote; else { // printf("Appending %c\n", ch); token += ch; } break; case ' ': if(inside_quote) { // printf("Appending %c\n", ch); token += ch; break; } if(token.empty()) continue; // skip multiple white spaces and pre white space // printf("Adding token %s\n", token.c_str()); tokenVector.push_back(token); token.clear(); break; case ';': if(inside_quote) { // printf("Appending %c\n", ch); token += ch; break; } // printf("Adding msg...\n"); if(!token.empty()) { tokenVector.push_back(token); } msgTokensList.push_back(tokenVector); tokenVector.clear(); token.clear(); break; default: // printf("Appending %c\n", ch); token += ch; break; } prev_ch = ch; } if(!token.empty()) { tokenVector.push_back(token); token.clear(); } if(!tokenVector.empty()) { msgTokensList.push_back(tokenVector); tokenVector.clear(); } } inline static void create_msg_list(MsgTokensList& msgTokensList, MessageList& msgList) { MsgTokensList::iterator it_msg; for(it_msg = msgTokensList.begin(); it_msg != msgTokensList.end(); it_msg++) { TokenVector t = *it_msg; //malformed msg if(t.size() < 1) continue; message_t m; if(t[0] == "observe") m.cmd = cmd::observe; else if(t[0] == "unobserve") m.cmd = cmd::unobserve; else if(t[0] == "add") m.cmd = cmd::add; // else if(t[0] == "del") m.cmd = cmd::del; else if(t[0] == "move") m.cmd = cmd::move; else if(t[0] == "update") m.cmd = cmd::update; else m.cmd = cmd::error; // printf("Number of tokens %d\n", t.size()); switch(m.cmd) { case cmd::observe: { if(t.size() != 1+1) { printf("Wrong number of parameters\n"); continue; } m.observe.id = atoi(t[1].c_str()); break; } case cmd::unobserve: { if(t.size() != 1+1) { printf("Wrong number of parameters\n"); continue; } m.unobserve.id = atoi(t[1].c_str()); break; } case cmd::add: { if(t.size() != 3+1) { printf("Wrong number of parameters\n"); continue; } sprintf(m.add.title, "%s", t[1].c_str()); sprintf(m.add.desc, "%s", t[2].c_str()); m.add.parentid = atoi(t[3].c_str()); printf("addcmd: %s %s %d\n", m.add.title, m.add.desc, m.add.parentid); break; } // case cmd::del: { // if(t.size() != 1+1) { // printf("Wrong number of parameters\n"); // continue; // } // m.del.id = atoi(t[1].c_str()); // break; // } case cmd::move: { if(t.size() != 2+1) { printf("Wrong number of parameters\n"); continue; } m.move.id = atoi(t[1].c_str()); m.move.parentid = atoi(t[2].c_str()); break; } case cmd::update: { if(t.size() != 3+1) { printf("Wrong number of parameters\n"); continue; } m.update.id = atoi(t[1].c_str()); sprintf(m.update.title, "%s", t[2].c_str()); sprintf(m.update.desc, "%s", t[3].c_str()); break; } default: break; }; msgList.push_back(m); } } MessageList parse_msg(std::string data) { printf("Parsing: %s\n", data.c_str()); MsgTokensList msgTokensList; parse_into_msg_tokens(data, msgTokensList); MessageList msgList; create_msg_list(msgTokensList, msgList); return msgList; } std::string msg_tostring(message_t m) { char* buf = NULL; switch(m.cmd) { case cmd::add: { asprintf(&buf, "add %d \"%s\" \"%s\" %d;", m.add.id, m.add.title, m.add.desc, m.add.parentid); break; } // case cmd::del: { // asprintf(&buf, "del %d;", m.del.id); // break; // } case cmd::move: { asprintf(&buf, "move %d %d;", m.move.id, m.move.parentid); break; } case cmd::update: { //todo asprintf(&buf, "update %d \"%s\" \"%s\";", m.update.id, m.update.title, m.update.desc); break; }; default: break; } std::string r; if(buf) { r = buf; free(buf); } return r; } message_t create_msg_create(task_t t) { message_t m; m.cmd = cmd::add; m.add.id = t.id; return m; } message_t create_msg_update(task_t t) { message_t m; m.cmd = cmd::update; m.update.id = t.id; sprintf(m.add.title, "%s", t.title.c_str()); return m; } #ifdef TEST_MSGPARSER //Additional dependency files //deps: //Required cflags (autoconf vars may be used) //cflags: //Required link options (autoconf vars may be used) //libs: #include "test.h" TEST_BEGIN; // TODO: Put some testcode here (see test.h for usable macros). TEST_TRUE(false, "No tests yet!"); TEST_END; #endif/*TEST_MSGPARSER*/