现在的位置: 首页 > 综合 > 正文

将C++代码全部写到头文件:)python脚本帮助自动生成相应的实现文件初始框架

2011年03月13日 ⁄ 综合 ⁄ 共 11226字 ⁄ 字号 评论关闭

嗯,现在基本没问题了,个人觉得类似python,java那样把类的实现完全写到类里面写起来更方便更快,(当然VC有写类函数的时候利用对话框自动生成实现函数的框架),我把程序放到了google code上:

http://code.google.com/p/h2cc/

利用Python脚本可以自动生成相应实现文件。

使用方法如下: h2cc.py -a a.h

//a.h 

int abc();           //函数声明会转换到实现文件中

int nba() {         //这种函数实现写法默认为在头文件中不变化

  int x = 3; 

int def()           //这种函数实现写法{在单独一行,会自动转化到实现文件中

{

  int x = 3; 

 转换之后

//a.h

 int abc();    

int nba() {         

  int x = 3; 

int def() ;         

//a.cc

#include "a.h" 

 int abc()

{

int def() 

{

  int x = 3; 

 

上面是最简单的示例,对于类和模版类也适用。

-a 表示会自动将上面的def这样的函数转换,而python3.1 a.h 没有-a选项的话,需要用户标明哪些函数要转到实现文件中,方法是如下的写法加一个多余的;在()后面

 int def() ;

{

  int x = 3; 

}

因为.h文件会变化,所以会备份执行操作前的a.h到a.h.bak.

另外有一个-t选项,开启-t的话表示处理模版类的情况即如下会加入些别的信息

在a.h 的namesapce 结束后

#ifndef A_CC_

#include "a.cc"

#endif

在a.cc文件的开头

#define A_CC_

#include "a.h"

 

这么做是为了避免循环引用是借鉴Openmesh的做法,对于模版函数的实现用户可以直接实现在.h文件中,现在我只支持分离的写法,这样更清晰些。

嗯看下实例,我原来将所有的模版类的函数都实现在.h类的定义内部,这样写起来很方便,但是看起来不舒服,希望把实现的部分,分离到.cc中。

于是调用python3.1 h2cc.py -a -t huff_tree.h  生成合适的huff_tree.cc并适当修改huff_tree.h,所以工作都由h2cc.py自动完成。已验证转换后通过编译链接。

当然目前不保证有些情况可能会出现未知的bug,那样用户可以参考头文件的拷贝文件.h.bak修正。

//原来写好的头文件

   1 /* 

  2  * Here use one class for both internal node and leaf.
  3  * This is easier to implement but will cost more space.
  4  *
  5  * For the implementation of differnting internal and leaf
  6  * refering to "A practical introduction to data structure
  7  * and algorithm analisis p 115"
  8  * */
  9 #ifndef _HUFF_TREE_H_
 10 #define _HUFF_TREE_H_  //TODO  automate this for .h file
 11 
 12 #include "type_traits.h"
 13 #include "buffer.h"
 14 #include "assert.h"
 15 #include <queue>
 16 #include <deque>
 17 #include <vector>
 18 #include <functional>
 19 #include <iostream>
 20 namespace glzip{
 21 //----------------------------------------------------------------------------HuffNode------
 22 template <typename _KeyType>
 23 struct HuffNode {
 24   typedef HuffNode<_KeyType>      Node;
 25   ///allow default construct
 26   HuffNode() {}
 27   ///construct a new leaf for character key or string key
 28   HuffNode(_KeyType key, size_t weight = 0
 29       : key_(key), weight_(weight),
 30         left_(NULL), right_(NULL){}
 31   
 32   ///construct a internal leaf from two child
 33   //TODO from const to non const fail
 34   HuffNode(HuffNode* lchild, HuffNode* rchild) 
 35       : left_(lchild), right_(rchild) {
 36     weight_ = lchild->weight() + rchild->weight();
 37   }
 38 
 39   _KeyType key() const{
 40     return key_;
 41   }
 42 
 43   size_t weight() const {
 44     return weight_;
 45   }
 46 
 47   Node* left() const {
 48     return left_;
 49   }
 50 
 51   Node* right() const {
 52     return right_;
 53   }
 54 
 55   bool is_leaf() {
 56     return !left_;  //left_ is NULL means right_ is also,for huf tree it is a full binary tree,every internal node is of degree 2
 57   }
 58   
 59   /////The comparison operator used to order the priority queue.
 60   ////-----But I choose to use the func object for storing pointer in the queuq
 61   ////-----not the Node it's self, TODO see the performance differnce 
 62   //bool operator > (const HuffNode& other) const {
 63   //  return weight > other.weight;
 64   //}
 65   
 66   //-------------------------------------------------------------------
 67   _KeyType  key_;
 68   size_t    weight_;   //here weight is frequency of char or string 
 69   Node*     left_;
 70   Node*     right_;
 71 };
 72 
 73 //-----------------------------------------------HuffTree-------------------HuffTreeBase----
 74 /**
 75  * For HuffTree
 76  * It take the frequency_map_ and encode_map_ as input.
 77  * Those two are not owned by HuffTree but HuffEncoder.
 78  * HuffTree will use frequence_map_ info to make encode_map_ ok.
 79  * 1. Wait until frequency_map_ is ready (which is handled by HuffEncoder)
 80  * 2. build_tree()  
 81  * 3. gen_encode()
 82  * 4. serialize_tree()
 83  * The sequence is important can not break!
 84  *
 85  * TODO(Array based HuffTree) actually the hufftree can be implemented using simple array do
 86  * not need building the tree.
 87  *
 88  * TODO For string type the tree might be so big, the rec is OK?
 89  * */
 90 template <typename _KeyType>
 91 class HuffTreeBase {
 92 public:
 93   typedef HuffNode<_KeyType>       Node;
 94 public:
 95   void set_root(Node* other) {
 96     root_ = other;
 97   }
 98 
 99   void delete_tree(Node* root) { //TODO rec what if the tree is so big?
100     if (root) {
101       delete_tree(root->left());
102       delete_tree(root->right());
103       delete root;
104     }
105   }
106  
107   //for test
108   void travel(Node* root) {
109     if (root) {
110       travel(root->left());
111       travel(root->right());
112     }
113   }
114 
115   Node* root() const {
116     return root_;
117   }
118 protected:
119   Node*   root_;
120 };
121 
122 //---------------------------------------------------------------------------HuffTree for encode---
123 template <typename _KeyType, typename _TreeType = encode_hufftree>
124 class HuffTree: public HuffTreeBase<_KeyType> {
125 public:
126   using HuffTreeBase<_KeyType>::root;
127   using HuffTreeBase<_KeyType>::set_root;
128   using HuffTreeBase<_KeyType>::delete_tree;
129 
130   typedef typename TypeTraits<_KeyType>::type_catergory             type_catergory;
131   typedef typename TypeTraits<_KeyType>::FrequencyHashMap           FrequencyHashMap;
132   typedef typename TypeTraits<_KeyType>::EncodeHashMap              EncodeHashMap;
133   typedef HuffNode<_KeyType>                                        Node;
134   
135   struct HuffNodePtrGreater:
136       public std::binary_function<const Node *const Node *bool> {
137     
138     bool operator() (const Node *p1, const Node *p2) {
139       return p1->weight() > p2->weight();
140     }
141   };
142   //typedef std::deque<Node> HuffDQU;   //TODO use vector to see which is better and why
143   //typedef std::priority_queue<Node,HuffDQU, greater<Node> >         HuffPRQUE; //desending order use less<HuffNode> if asending
144   typedef std::deque<Node*> HuffDQU;   //TODO use vector to see which is better and why
145   typedef std::priority_queue<Node*, HuffDQU, HuffNodePtrGreater>     HuffPRQUE; //desending order use less<HuffNode> if asending
146 
147 public:
148   HuffTree(EncodeHashMap& encode_map, FrequencyHashMap& frequency_map)  //long long int (&)[256] can not be inited by const long 
149         : encode_map_(encode_map), frequency_map_(frequency_map) 
150   {  
151     build_tree();        //assmue frequency_map is ready when creating the tree        
152   }  
153   ~HuffTree() {
154     //std::cout << "dstruct hufftree\n";
155     delete_tree(root());
156   }
157   void gen_encode() {
158     std::string encode;
159     do_gen_encode(root(), encode);   
160     //std::cout << "Finished encoding\n";
161   }
162   void build_tree() 
163   {
164     init_queue(type_catergory());
165     int times = pqueue_.size() - 1;
166     for (int i = 0; i < times; i++) {
167       Node* lchild = pqueue_.top();
168       pqueue_.pop();
169       Node* rchild = pqueue_.top();
170       pqueue_.pop();
171       Node* p_internal = new Node(lchild, rchild);
172       pqueue_.push(p_internal);
173     }
174     set_root(pqueue_.top());  
175     //std::cout << "Finished building tree\n"; 
176   }
177 
178   ///write the header info to the outfile, for decompressor to rebuild the tree
179   //----write in pre order travelling
180   void serialize_tree(FILE* outfile) {
181     Buffer writer(outfile);  //the input outfile cur should be at 0
182     do_serialize_tree(root(), writer);
183     writer.flush_buf();   //make sure writting to the file
184   }
185 private:
186   void init_queue(char_tag) {
187     for(int i = 0; i < 256; i++) {
188       if (frequency_map_[i]) {
189         Node* p_leaf = new Node(i, frequency_map_[i]); //key is i and weight is frequency_map_[i]
190         pqueue_.push(p_leaf);        //push leaf
191       }
192     }
193   }
194 
195   //TODO try to use char[256] to speed up!
196    void do_gen_encode(Node* root, std::string& encode) 
197    {
198     if (root->is_leaf()) {
199       encode_map_[root->key()] = encode;
200       return;
201     }
202     encode.append("0");              //TODO how string operation is implemented what is the effecience??
203     do_gen_encode(root->left(), encode);
204     encode[encode.size() - 1= '1';
205     do_gen_encode(root->right(), encode);
206     encode.erase(encode.size() - 11);
207   }
208 
209   //void do_gen_encode(Node* root, std::string encode) {
210   //  //if (root->is_leaf()) {
211   //  //if (root->left() == NULL || root->right() == NULL) {
212   //  //  //encode_map_[root->key()] = encode;
213   //  //  return;
214   //  //}
215   //  if (!root->right() && !root->left())
216   //    return;
217   //  do_gen_encode(root->left(), encode + "0");
218   //  do_gen_encode(root->right(), encode + "1");
219   //}
220 
221 
222   //serialize like (1, 1), (1, 1), (0, 'a').
223   void do_serialize_tree(Node* root, Buffer& writer) 
224   {
225     if (root->is_leaf()) {
226       writer.write_byte(0);  //0 means the leaf
227       writer.write_byte(root->key());  //write the key
228       return;
229     }
230     writer.write_byte(255);  //255 means the internal node
231     writer.write_byte(255);  //any num is ok
232     do_serialize_tree(root->left(), writer);
233     do_serialize_tree(root->right(), writer);
234   }
235 
236   //----------------------------------------------------for string_tag--------
237   void init_queue(string_tag) {
238     
239   }
240 private:
241   HuffPRQUE              pqueue_;
242   EncodeHashMap&         encode_map_;
243   FrequencyHashMap&      frequency_map_;
244 };
245 
246 //---------------------------------------------------------------------------HuffTree for decode---
247 /** Specitialized HuffTree for decoding*/
248 template <typename _KeyType>
249 class HuffTree<_KeyType, decode_hufftree>
250     : public HuffTreeBase<_KeyType>{
251 public:
252   using HuffTreeBase<_KeyType>::root;
253   using HuffTreeBase<_KeyType>::root_;
254   using HuffTreeBase<_KeyType>::set_root;
255   using HuffTreeBase<_KeyType>::delete_tree;
256   typedef HuffNode<_KeyType>  Node;
257 
258 public:
259   HuffTree(FILE* infile, FILE* outfile)
260       :infile_(infile), outfile_(outfile),
261        reader_(infile) {} 
262 
263   ~HuffTree() {
264     delete_tree(root());
265   }
266 
267   ///build_tree() is actually get_encode_info()
268   void build_tree() {  //From the infile header info we can build the tree
269     do_build_tree(root_);
270   }
271  
272   //help debug to see if the tree rebuild from file is the same as the intial one
273   void do_gen_encode(Node* root, std::string& encode) 
274   {
275     if (root->is_leaf()) {
276       std::cout << root->key() << " " << encode << "\n";
277       return;
278     }
279     encode.append("0");              //TODO how string operation is implemented what is the effecience??
280     do_gen_encode(root->left(), encode);
281     encode[encode.size() - 1= '1';
282     do_gen_encode(root->right(), encode);
283     encode.erase(encode.size() - 11);
284   }
285 
286   void decode_file();
287 private:
288   void do_build_tree(Node*& root) 
289   {
290     unsigned char first, second;
291     reader_.read_byte(first);
292     reader_.read_byte(second);
293     if (first == 0) {  //is leaf  TODO actually we do not need weight this time so HuffNode can be smaller
294       root = new Node(second);
295       return;
296     }
297     root = new Node();
298     do_build_tree(root

抱歉!评论已关闭.