个人笔记(3)

今天帮一个同事把CPP代码改成对应的python代码,cpp代码很简单,如下:

 1 static inline
 2 std::string calc_tid(uint32_t threshold, uint64_t filesize)
 3 {
 4     static const char trailing_bytes[] = {47, 13, 94, 118, 39, 71, 156, 59};
 5     char values[16], hashed_md5[33];
 6     
 7     const uint32_t vid = ~threshold;
 8     const uint32_t lower_filesize = static_cast<uint32_t>(filesize);
 9     
10     std::memcpy(values, &vid, sizeof(vid));
11     std::memcpy(values + sizeof(vid), &lower_filesize, sizeof(lower_filesize));
12     std::memcpy(values + sizeof(vid) + sizeof(lower_filesize), trailing_bytes, sizeof(trailing_bytes));
13 
14     //对values进行md5,并格式化成16进制字符串,得到tid_code。
15     md5_string(values, 16, hashed_md5);
16     return std::string(hashed_md5, 32);
17 }
18 
19 static inline
20 std::string calc_fid(const std::string &cid, uint64_t file_size, const std::string &gcid)
21 {
22     if(cid.empty() || gcid.empty())
23     {
24         return std::string();
25     }
26 
27     assert(cid.size() == 40);
28     assert(gcid.size() == 40);
29 
30     std::string cid_binary = xdrive::unhex_string(cid);
31     std::string gcid_binary = xdrive::unhex_string(gcid);
32 
33     char input[48];
34     std::memcpy( input , cid_binary.c_str() , cid_binary.size() );
35     std::memcpy( input + cid_binary.size() , &file_size , sizeof(file_size) );
36     std::memcpy( input + cid_binary.size() + sizeof(file_size) , gcid_binary.c_str() , gcid_binary.size() );
37 
38     return Base64::encode(std::string(input, 48));
39 }

本来以为挺简单,做的时候才发现好多细节要注意,总结了一下,大概有以下几点:

1、C++中的整数转Python中的数

总所周知,python中的整数只有int和long两种形式,而c++中有很多种,而且还包括有符号和无符号。怎么在python中区分这些类型呢?

例如:

①CPP中uint32_t转uint32_t

1 const uint32_t vid = ~threshold;

threshold是uint32_t类型,取反后赋值给vid,在python中改为:

1 vid = (~threshold) & 0xFFFFFFFF

算是强制转化为32位的。

②CPP中uint64_t转CPP中uint32_t:

1 const uint32_t lower_filesize = static_cast<uint32_t>(filesize);

file_size是uint64_t类型,截断为uint32_t,在python中改为:

1 lower_filesize = filesize & 0xFFFFFFFF

算是强制截断,取最后32位

 

2、对整数的memcpy

C++中可以直接操作内存,python中不需要直接操作内存(当然你也可以调用python的c接口来操作内存)

例如,CPP代码:

1 std::memcpy(values, &vid, sizeof(vid));
2 std::memcpy(values + sizeof(vid), &lower_filesize, sizeof(lower_filesize));
3 std::memcpy(values + sizeof(vid) + sizeof(lower_filesize), trailing_bytes, sizeof(trailing_bytes));

在python中需要把整形对应的内存数据转为字符串类拷贝,python代码如下:

1 vid_buff = struct.pack("I", vid)
2 file_size_buff = struct.pack("I", lower_filesize)
3 values = vid_buff + file_size_buff
4 n = len(trailing_bytes)
5 for i in range(0, n):
6     values = values + struct.pack("i", trailing_bytes[i])[0]

注意:

①这里用到了python的struct模块,先把整数转为str类型,然后直接追加就完成了memcpy的功能。转str类型时注意pack的格式,其中“I”表示的是unsigned int类型,字节数为4,“i”表示的是int类型,字节数为4,如果是无符号64位整数,可以用“Q”,其他情况可以自己查询。

②在整数(小于256)转为单字节字符时,这里先把对应的整数格式化为内存字符串,然后取第一个字节,具体取第一个字节还是最后一个字节,需要根据你自己的机器是大端还是小端来确定,切记!

 

3、字符对应的acsii码整数

使用python内置函数ord('A'), ord('0')即可

 

4、python的位操作与C语言是一样的

按位与(&),按位或(|),按位取反(~)

 

以上两个cpp函数改为python之后的代码如下:

 

 1 #!/bin/env python
 2 #coding=utf-8
 3 
 4 import md5
 5 import base64
 6 import struct
 7 
 8 def calc_tid(threshold, filesize):
 9     trailing_bytes = [47, 13, 94, 118, 39, 71, 156, 59]
10     vid = (~threshold) & 0xFFFFFFFF
11     lower_filesize = filesize & 0xFFFFFFFF
12     
13     vid_buff = struct.pack("I", vid)
14     file_size_buff = struct.pack("I", lower_filesize)
15     values = vid_buff + file_size_buff
16     n = len(trailing_bytes)
17     for i in range(0, n):
18         values = values + struct.pack("i", trailing_bytes[i])[0]
19         
20     return md5.new(str(values)).hexdigest().upper()
21 
22 
23 def calc_fid(cid, file_size, gcid):
24     # if not cid or not gcid:
25         # return ""
26         
27     # reg_p = r"[0-9a-fA-F]{40}$"
28     # pattern = re.compile(reg_p)
29     # if not pattern.match(cid) or not pattern.match(gcid):
30         # sys.exit(-1)
31         
32     cid_binary = unhex_string(cid)
33     gcid_binary = unhex_string(gcid)
34     
35     file_size_buff = struct.pack("Q", file_size)
36     
37     input = cid_binary + file_size_buff + gcid_binary
38     
39     return base64.encodestring(input)

 

 

 

参考资料:

1、http://www.cnblogs.com/gala/archive/2011/09/22/2184801.html

2、http://blog.csdn.net/JGood/article/details/4290158

3、http://www.cnblogs.com/tonychopper/archive/2010/07/23/1783501.html

4、http://blog.163.com/sukerl@126/blog/static/1120276492009111494052196/

5、http://bbs.chinaunix.net/thread-921983-1-1.html

 

 

 

 

 

posted @ 2013-02-25 18:54  么幺  阅读(451)  评论(0编辑  收藏  举报