eis/inc/x2struct/go_writer.h

220 lines
6.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2019 YY Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __X_GO_WRITER_H
#define __X_GO_WRITER_H
#include "xstdint.h"
#include <string>
#include <map>
#include <vector>
#include <set>
#include <sstream>
#include <cxxabi.h>
#include "util.h"
namespace x2struct {
class GoCode {
public:
GoCode(std::set<std::string>& alls, bool json=true, bool bson=true, bool xml=true)
:_sub_struct_names(alls), _json(json),_bson(bson),_xml(xml) {
if (json) {
_types.push_back("json");
}
if (bson) {
_types.push_back("bson");
}
if (xml) {
_types.push_back("xml");
}
}
~GoCode() {}
public:
void set_type_id_name(const std::string& name) {
_name = raw_name(name);
}
std::string str() {
std::string code;
for (size_t i=0; i<_sub_structs.size(); ++i) {
code.append(_sub_structs[i]);
}
size_t max_var_len = 0;
size_t max_type_len = 0;
for (size_t i=0; i<_var_names.size(); ++i) {
if (_var_names[i].length() > max_var_len) {
max_var_len = _var_names[i].length();
}
}
for (size_t i=0; i<_var_types.size(); ++i) {
if (_var_types[i].length() > max_type_len) {
max_type_len = _var_types[i].length();
}
}
max_var_len = ((max_var_len+4)>>2)<<2;
max_type_len = ((max_type_len+4)>>2)<<2;
code.append("type ").append(_name).append(" struct {\n");
for (size_t i=0; i<_var_names.size(); ++i) {
code.append("\t").append(_var_names[i]).append(std::string(max_var_len-_var_names[i].length(), ' '));
code.append(_var_types[i]).append(std::string(max_type_len-_var_types[i].length(), ' '));
code.append(_marshal_string[i]).append("\n");
}
code.append("}\n\n");
return code;
}
public:
template<typename TYPE>
void convert(const TYPE&member, const char*member_name, const char*aliase_name=0) {
new_member(member_name, type_name(member), aliase_name);
}
private:
template <typename TYPE>
std::string type_name(const std::vector<TYPE>& v) {
TYPE t;
return std::string("[]").append(type_name(t));
}
template <typename TYPE>
std::string type_name(const std::set<TYPE>& v) {
TYPE t;
return std::string("[]").append(type_name(t));
}
template <typename TYPE>
std::string type_name(const TYPE& v) {
std::string tname = raw_name(typeid(v).name());
if (_sub_struct_names.find(tname) == _sub_struct_names.end()) {
_sub_struct_names.insert(tname);
GoCode obj(_sub_struct_names, _json, _bson, _xml);
_sub_structs.push_back(v.__struct_to_go(obj));
}
return tname;
}
template <typename KEY, typename VALUE>
std::string type_name(const std::map<KEY, VALUE>& m) {
KEY k;
VALUE v;
return std::string("map[").append(type_name(k)).append("]").append(type_name(v));
}
#define GOLANG_BASE_TYPE_NAME(type) \
std::string type_name(const type##_t & v) { \
return #type; \
}
GOLANG_BASE_TYPE_NAME(int16);
GOLANG_BASE_TYPE_NAME(int32);
GOLANG_BASE_TYPE_NAME(int64);
GOLANG_BASE_TYPE_NAME(uint16);
GOLANG_BASE_TYPE_NAME(uint32);
GOLANG_BASE_TYPE_NAME(uint64);
std::string type_name(const std::string& v) {
return std::string("string");
}
std::string type_name(bool v) {
return std::string("bool");
}
private:
std::string raw_name(const std::string& type_id_name) {
char* raw = abi::__cxa_demangle(type_id_name.c_str(), 0, 0, 0);
std::string str;
if (0 == raw) {
str = std::string(type_id_name);
} else {
str = std::string(raw);
free(raw);
}
std::vector<std::string> raw_types;
Util::split(raw_types, str, "::"); // remove name space
str = raw_types[raw_types.size()-1];
str[0] = std::toupper(str[0]);
return str;
}
// 变量原始名, go类型的名称已经处理了slice类型的 别名
void new_member(const char*var_name, const std::string&go_type_name, const char*aliase_name) {
std::string str(var_name);
str[0] = std::toupper(str[0]);
_var_names.push_back(str);
_var_types.push_back(go_type_name);
std::map<std::string, std::string> aliases;
if (0 != aliase_name) {
str = aliase_name;
std::vector<std::string> types;
Util::split(types, str, ' ');
for (size_t i=0; i<types.size(); ++i) {
std::vector<std::string> name_opts;
Util::split(name_opts, types[i], ':');
if (1 == name_opts.size()) {
aliases[""] = types[i];
} else {
std::vector<std::string> opts;
Util::split(opts, name_opts[1], ',');
aliases[name_opts[0]] = opts[0];
}
}
} else {
aliases[""] = var_name;
}
str = "`";
for (size_t i=0; i<_types.size(); ++i) {
std::map<std::string,std::string>::const_iterator iter = aliases.find(_types[i]);
std::string aname;
if (aliases.end() == iter) {
iter = aliases.find("");
}
if (iter == aliases.end()) {
aname = var_name;
} else {
aname = iter->second;
}
if (i != 0) {
str.append(" ");
}
str.append(_types[i]).append(":\"").append(aname).append("\"");
}
str.append("`");
_marshal_string.push_back(str);
}
private:
std::set<std::string>& _sub_struct_names; // 子结构体名称
std::string _name;
std::vector<std::string> _types; // marshal需要哪些类型, json/bson/xml
bool _json,_bson,_xml;
private:
std::vector<std::string> _var_names;
std::vector<std::string> _var_types;
std::vector<std::string> _marshal_string;
private:
std::vector<std::string> _sub_structs; // 子结构体的代码
};
}
#endif