google probuf源码分析之descriptor

要把这个文件里所有变量和函数都看懂

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的声明和定义。

暂时写到这里。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值