您的位置:首页 > 编程语言 > Go语言

google probuf源码分析之descriptor

2013-11-30 23:10 288 查看
要把这个文件里所有变量和函数都看懂

1.讲字符串转为驼峰命名法:

string ToCamelCase(const string& input) {
bool capitalize_next = false;
string result;
result.reserve(input.size());

for (int i = 0; i < input.size(); i++) {
if (input[i] == '_') {
capitalize_next = true;
} else if (capitalize_next) {
// Note: I distrust ctype.h due to locales.
if ('a' <= input[i] && input[i] <= 'z') {
result.push_back(input[i] - 'a' + 'A');
} else {
result.push_back(input[i]);
}
capitalize_next = false;
} else {
result.push_back(input[i]);
}
}

// Lower-case the first letter.
if (!result.empty() && 'A' <= result[0] && result[0] <= 'Z') {
result[0] = result[0] - 'A' + 'a';
}

return result;
}

算法很简单:搞了一个vec来存档结果,遇到_就停下,把后面一个字符转为大写,最后检查第一个字符并转为小写。
比如we_aer_eyye_eee转为weAerEyyeEee;

2.hashmap的key扩展,关于原因,注释里写的很清楚

// A DescriptorPool contains a bunch of hash_maps to implement the

// various Find*By*() methods.  Since hashtable lookups are O(1), it's

// most efficient to construct a fixed set of large hash_maps used by

// all objects in the pool rather than construct one or more small

// hash_maps for each object.

//

// The keys to these hash_maps are (parent, name) or (parent, number)

// pairs.  Unfortunately STL doesn't provide hash functions for pair<>,

// so we must invent our own.

主要是有key可以是是一个pair,查询的时候可以这个pair,下面看看如何实现的嘛。

看了半天,貌似不怎么清晰,还是自己搞了个std::hash_map的key为pair的东东。

#include "stdio.h"
#include "Product.h"
#include "ProductConcurrentQueue.h"
#include "ProductQueue.h"
#include <windows.h>

#include <string>
#include <iostream>
#include <hash_map>

using namespace std;

typedef pair<const char*, const char*> PointerStringPair;

size_t SDBMHash(const char *str)
{
size_t hash = 0;

char* tst = (char*)(str);
while (*tst)
{
// equivalent to: hash = 65599*hash + (*str++);
hash = (*tst++) + (hash << 6) + (hash << 16) - hash;
}

return (hash & 0x7FFFFFFF);
}
inline size_t PointerStringPair_hash_value(const PointerStringPair& aPair)
{
return SDBMHash(aPair.first) + SDBMHash(aPair.second);
}

class PointerStringPair_hash_compare : public hash_compare<PointerStringPair>
{
public:
size_t operator()(const PointerStringPair& _Key) const
{
return((size_t)PointerStringPair_hash_value(_Key));
}

bool operator()(const PointerStringPair& _Keyval1, const PointerStringPair& _Keyval2) const
{
return strcmp(_Keyval1.first, _Keyval2.first) != 0
&& strcmp(_Keyval1.second, _Keyval2.second) != 0 ;
}
};
typedef hash_map<PointerStringPair, int, PointerStringPair_hash_compare> FieldsByNameMap;

int main()
{
string str1("11");
string str2("12");
PointerStringPair lkey1(str1.c_str(), str2.c_str());
FieldsByNameMap lMap;

lMap.insert(std::make_pair(lkey1,1));

PointerStringPair lkey2("12", "13");
lMap.insert(std::make_pair(lkey2,2));

for (FieldsByNameMap::iterator iter = lMap.begin();
iter != lMap.end(); ++iter)
{
PointerStringPair pair = iter->first;
printf("first: %s %s %d\n", pair.first,pair.second, iter->second);
}

FieldsByNameMap::iterator iter = lMap.find(lkey1);
if (iter != lMap.end())
{
printf("res:%d\n", iter->second);
}

}

这个很完整,连测试代码都有啦,嘎嘎!
明白原理就整下一步。

我们看下DescriptorPool这个重要的类是怎么加载的:

看了半天找不到头绪,猛然看到一个注释:

void DescriptorPool::InternalAddGeneratedFile(

    const void* encoded_file_descriptor, int size) {

  InitGeneratedPoolOnce();

  GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size));

}

注释:

  这个函数是在已经产生的proto类初始化descriptors的过程中调用的。每个产生的.pb.cc文件都要一个内部模块AddDescriptors(),它会在过程启动的时候被调用。

 那个函数调用这个函数用来将本类所代表原始FileDescriptorProto进行注册。

 我们实际上不会立即构建descriptor对象。在它实际调用的时候才会构建。第一次被调用才会构建。

之后是各种descriptors的声明和定义。

暂时写到这里。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: