/* =========================================== date author amend 4/27/2010 bs create file 4/27/2010 bs create the six be_* class ============================================= */ #pragma once #include <cstdlib> #include <cstdio> #include <string> #include <vector> #include <map> namespace tinybt { typedef enum { BE_STR, BE_INT, BE_LIST, BE_DICT, } be_type; class be_object; class be_string; class be_integer; class be_list; class be_dict; class be_factory; class be_object { protected: be_type type_; public: virtual void dump(){} virtual bool be_decode(const char* s_in, char** s_next) = 0; virtual bool be_encode(char* s_out, int* len) = 0; }; class be_factory { public: static be_object* create_be_object(const char* s_in) { if (!s_in) return NULL; be_object* o = NULL; switch (*s_in) { case 'l': o = new be_list; break; case 'd': o = new be_dict; break; case 'i': o = new be_integer; break; case '0'...'9': o = new be_string; break; default: break; } return o; } }; class be_string : public be_object { public: std::string *elem_; public: virtual void dump() { printf("str = %s/n", elem_->c_str()); } be_string() : type_(BE_STR){} be_string(const char*s) : elem_(s) , type_(BE_STR){} bool be_decode(const char* s_in, char** s_next) { if(!s_in || !s_next) return false; be_integer i; i.be_decode(s_in, s_next); long long len = i.elem_; elem_ = new string(s_next, len); return true; } bool be_encode(char* s_out, int* len) { if(!s_out || !len) return false; *len = sprintf(s_out, "%lli%s", elem_->size(), elem_->c_str()); return true; } }; class be_integer : public be_object { public: long long elem_; public: be_integer() : type_(BE_INT){} be_integer(long long l) : elem_(l), type_(BE_INT){} bool be_decode(const char* s_in, char** s_next) { if(!s_in || !s_next) return false; elem_ = strtoll(s_in, s_next, 10); if (*s_next++ != 'e') return false; return true; } bool be_encode(char* s_out, int* len) { if(!s_out || len) return false; *len = sprintf(s_out, "l%lle", elem_); return true; } void dump() { printf("int = %lli/n", elem_); } }; class be_dict : public be_object { public: std::map<be_string*, be_object*> elem_; public: be_dict() : type_(BE_DICT){} bool be_decode(const char* s_in, char** s_next) { if (!s_in || !s_next) return false; char pstr = s_in;// char *next; while (*s_in != 'e') { be_string s = new be_string; if (!s->be_decode(pstr, s_next)) return false; pstr = *s_next; be_object *o = be_factory::create_be_object(pstr); if (!o || !o->be_decode(pstr, s_next)) return false; pstr = *s_next; elem_.insert(make_pair(s, o)); } return true; } bool be_encode(char* s_out, int* len) { if (!s_out || !len) return false; char pstart = s_out; *s_out++ = 'd'; std::map<std::string*, be_object*>::const_iterator iter; for (iter = elem_.begin(); iter != elem_.end(); iter++) { iter->first->be_encode(s_out, len); s_out += *len; iter->second->be_encode(s_out, len); s_out += *len; } *s_out++ = 'e'; *len = s_out - pstart; return true; } void dump() { puts("dict {"); std::map<std::string*, be_object*>::const_iterator iter; for (iter = elem_.begin(); iter != elem_.end(); iter++) { printf("%s => ", iter->first->c_str()); iter->second->dump(); } } }; class be_list : public be_object { public: std::vector<be_object*> elem_; public: be_list() : type_(BE_LIST) {} bool be_decode(const char* s_in, char** s_next) { if (!s_in || !s_next) return false; while (*s_in != 'e') { be_object *o = be_factory::create_be_object(s_in); if (!o || !o.be_decode(s_in, s_next)) return false; s_in = *s_next; elem_.push_back(o); } return true; } bool be_encode(char* s_out, int* len) { if (!s_out || !len) return false; char pstart = s_out; *s_out++ = 'l'; std::vector<be_object*>::const_iterator iter; for (iter = elem_.begin(); iter != elem_.end(); iter++) { iter->be_encode(s_out, len); s_out += *len; } *s_out++ = 'e'; *len = s_out - pstart; return true; } }; }