-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathatom.xml
964 lines (695 loc) · 63.3 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Patricklog]]></title>
<link href="http://blog.patrickz.net/atom.xml" rel="self"/>
<link href="http://blog.patrickz.net/"/>
<updated>2012-11-28T01:49:30+08:00</updated>
<id>http://blog.patrickz.net/</id>
<author>
<name><![CDATA[kk1fff]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[版本控制系統和協作模式]]></title>
<link href="http://blog.patrickz.net/blog/2012/11/25/ban-ben-kong-zhi-yu-xie-zuo/"/>
<updated>2012-11-25T13:21:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/11/25/ban-ben-kong-zhi-yu-xie-zuo</id>
<content type="html"><![CDATA[<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/87A25E555FEB71672012-11-254E0B5348103724.png" title="'gitk 是 git 的 GUI front-end'" ></p>
<p>參與了幾個計畫,看一些 mailing list 裡面的作法,覺得版本控制真是一個非常有趣的事情。據說有些公司,仍然在沒有版本控制的世界裡。我很幸運,經歷過的公司都有,讓我學到很多。</p>
<p>版本控制的目的當然就是讓大家可以一起分享一份 source code,可以讓大家同時改自己想改的部份,可以讓 release 和 develop 的人從某一個時間點開始分開不同的路徑,release 可以專心讓
release 版本變得穩定。也可以在 release 完成後把他們並回主幹。順道一題,媒體常常會在某
W 開頭的作業系統出了以後,就說下一版的已經在開發,我想大家都知道這根本就是廢話,main trunk
本來就是一直走下去的。</p>
<p>廢話不多說。我遇到的第一套工具(自己唸書時用的 SVN 不算),叫做 perforce。Perforce 是一套商業版的版本控制系統。他是所謂集中式的版本控制。而且公司內部的管理邏輯算是簡單。也就是說,你改了一下,就 check-in 了。我在第一次上 code 的時候就把 main trunk 弄 build fail(汗),主要是因為我犯了個明顯的錯誤,但因為缺法 review 的過程,所以沒有人發現。</p>
<p>此外,基於版本管理系統的運作都相當的複雜,通常,除了一個好的客戶端工具(包括 GUI 和指令介面),還需要一些好的 Guide。Open source 的版本控制系統在網路上已經有很多,而 perforce 不是。因此少了社群高手對 perforce 的講解和推廣,獲取資訊的來源少了很多。甚至有人只把 perforce
當成是 ftp 抓 code 來用,基於又慢又不熟悉的環境,我一點也不驚訝。</p>
<!-- more -->
<h2>Git</h2>
<p>過了一些時間,我參與了另一項計畫。這個計畫使用大家都愛的 git。git,著名的分散式版本控制系統,對於當時的我,我根本不知道「分散式版本控制系統」的意義在何處。當時我們只用到 git 的其中一個特性:local branch。git 是非常容易使用和刪除 local branch 的。</p>
<pre><code>git checkout -b new_branch_namw # 從現在所在的版本處,開一個 branch,並切到那個 branch
git branch -D some_branch # 把某個 branch 砍了
</code></pre>
<p>但基於 git 本身就需要在 local branch 運作。其實你在開發的那個版本,相對於遠端來源的
branch,早就算是 local branch:從你下 pull 的那一刻起,你機器上的版本和 remote 的版本就分開了。直到下次 pull 才會重新 merge。</p>
<p>當時我們沒有正確的使用 issue tracking system。因此,local branch 的功能大多數都沒有用到,我們只是不停 pull,寫,pull,merge,push。也就是 git 最基本的循環。</p>
<pre><code>git pull # 取得遠端程式碼
# 開工,寫一些東西
git commit # 在本地 commit,順便寫些 log
git pull # 把在你寫程式這段時間的遠端程式 merge 回來
git mergetool # 如果有任何 conflict,就要用這個指令去啟動 meld 手動合併
git push # 把你改完的東西送上去
</code></pre>
<p>其實,這就是一般 SVN 的循環。除了 git 這個名字聽起來大勝以外。其他沒什麼值得驕傲的。</p>
<h2>Review system</h2>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/87A25E555FEB71672012-11-254E0B534820819.png" title="'Android Open Source Project 的 Gerrit system'" ></p>
<p>過了幾個月,我們的 review system 上線了。是 git 的好朋友,也就是 gerrit。這套在 Android
中廣為使用的 review system 跟 git 可以說是完美的結合。透過 google 提供的 repo 指令,送上
review system 一氣呵成。</p>
<pre><code>git commit
repo upload
</code></pre>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/87A25E555FEB71672012-11-254E0B534821833.png" title="'正在 Review 的 Gerrit patch'" ></p>
<p>他就會出現在 gerrit 上面,然後 reviewer 會檢視你的 source code,給你意見,最後你可以修改,改完後</p>
<pre><code>git commit --amend
repo upload
</code></pre>
<p>去覆蓋上一個 commit。來回幾次,當 review process 完成後,程式就會被送上 main trunk。</p>
<h2>Patch</h2>
<p>忘了提,那個我們寫完以後送到 review system 上的檔案,稱為 patch。open source 常用的開發模型,大抵上是我們一般人把 patch 完成後,交給某些核心成員 review。這些核心成員對 source
code 架構很清楚,也清楚知道目前專案進行的方向,他們會針對每個 patch 給予意見,並且把 review
完成的 patch 送進版本控制系統中。我們一般人只有傳送 patch 的權限,而這些人則有 commit
patch 的權限。</p>
<p>也因此,Patch 的傳遞在 open source 專案中非常重要。有一些 Patch 使用 mailing list
來傳遞,把 patch 檔案夾帶在附件中發送到 mailing list,讓大家去 review 這個 patch。</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/87A25E555FEB71672012-11-254E0B534822435.png" title="'夾帶在 mail 中的 patch'" ></p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/87A25E555FEB71672012-11-254E0B534822535.png" title="'Patch 檔案內容'" ></p>
<p>有一些則使用 Issue tracking system,比方說 Mozilla。Mozilla 使用自行開發的
Bugzilla 當作 Issue tracking system。每個要上 Patch 的人都會先把 Patch 傳送到 Bugzilla
上面去給相關領域的人 review,也可以討論。一旦 Review 完成,每天會有固定的人去蒐集 review
完成但沒有放進主線的 patch,最後把這個 patch 合併到 Mozilla 中稱為 inbound 的 repository。
inbound 可以給人抓下來 build,有些人(像我)喜歡用 inbound 的 source。inbound 經過一天的自動測試和人工試用以後,如果沒有問題這些 Patch 就會進到 central,也就是 mozilla
source code 的主線。</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/87A25E555FEB71672012-11-254E0B534822720.png" title="'Bugzilla 就是 Mozilla 討論或 review patch 的主要環境'" ></p>
<p>換句話說,Patch 的世界裡面,只管你產生出的 Patch,不管你使用的工具。Mozilla 是使用一套和 git 類似的分散式版本控制工具–mercurial,並且使用 mercurial queue 來管理 local patch。但這不代表熟悉 git 的人一定要學習 mercurial。mozilla 有一個對應的 git mirror。只要用
git 能夠產生出合乎格式的 patch,一樣可以 review 並且上到 central。</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/87A25E555FEB71672012-11-254E0B534823324.png" title="'Patch 進入 inbound 之後'" ></p>
<p>如果用 patch 的角度來看,gerrit 其實也是送 patch,只是 patch 是由自動化工具產生,並且自動上傳到 gerrit 去 review。</p>
<h2>Pull request</h2>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/87A25E555FEB71672012-11-254E0B534824555.png" title="'Review 一個 pull request'" ></p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/87A25E555FEB71672012-11-254E0B534824537.png" title="'檢視 Pull request 的 diff'" ></p>
<p>若要說起分散式版本控制的最大突破,我想 pull request 大概當之無愧。這得先說一下 git 的特性。當 A 和 B 是兩個不同的 repositery,卻有共用的歷史。此時,把 A merge 到 B 和把 B merge
到 A 都是可行的。分散式的世界裡,所有的 repositery 都可以是 server 也都可以是 client。換句話說,如果你從某個 repositery 拿到了一份 code,改完了,你想 merge 回主線,你不一定要親自 commit,也可以要求對方來 pull 你的 change,這就是 pull request。</p>
<p>要用 pull request,首先要先在 github 下 fork 一個專案,也就是說,把你想要改的專案整個複製一份到你自己的 github 帳號底下。接下來,把你自己的 fork 的專案 clone 到硬碟裡面,修改你想修改的部份,然後 commit、push 送回到 github,接下來,到 github 內,選取想要 pull request
的 branch,然後按下上面的 pull request 按鈕,選擇要送給哪個專案的哪個 branch,寫下
comment,一切就完工了。</p>
<p>收到 pull request 的一方,則會被 email 通知。就可以對這個 patch(沒錯,又是 patch)進行
review。review 完成後如果要 merge,可以選擇直接在旁邊的按鈕按下 merge。或是,使用指令介面。使用指令介面的好處是:可以 rebase,如此可以保持版本樹的乾淨。</p>
<p>假設我收到一個來自帳號 kk1fff,Repo gaia 而 branch 叫做 work793111 的 pull request,而我要 merge 進入我的主幹,那我可以進入 repostory 的資料夾:</p>
<pre><code>git remote kk1fff git://github.com/kk1fff/gaia.git # 加入一個 repo
git fetch kk1fff # 取回 git 資料
git checkout kk1fff/work793111 # 把 branch 的資料 fetch 出來
git checkout -b merging_kk1fff # 建立新分支
git rebase b2g/gaia # 把這個新分支 rebase 到現在的 main trunk 上
git push b2g gaia # 推上去,大功告成
</code></pre>
<h2>小結</h2>
<p>每個專案都有不同的協同開發方式。Open source 專案幾乎都是 based on patch,就是由有心人去修正軟體,產生 patch,在由比較熟悉專案的人物去合併進入主幹。Patch 的好處是增加了 review
的流程,但相對的畫的時間也比較多一點。針對不同的情況也可以進行討論。但小型專案的話,這樣的程序就顯得過於複雜。讓大家都有 checkin 版本控制的權限就會顯得簡單多。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[紀錄一下 tmux]]></title>
<link href="http://blog.patrickz.net/blog/2012/10/14/ji-lu-yi-xia-tmux/"/>
<updated>2012-10-14T00:02:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/10/14/ji-lu-yi-xia-tmux</id>
<content type="html"><![CDATA[<p>最近真是用 Tmux 用上癮了,好棒的東西!以前很少用 screen,也不是說 screen 不好,但對於
screen 分割視窗的方法不是很熟悉。另外,screen 使用 ctrl+a 來下指令,和 emacs 的指令衝突,我不是很喜歡改預設設定,除非我真的無法習慣又非用不可。就因此,我選了 tmux。</p>
<p>在 Mac 上安裝 tmux 和 ubuntu 上面一樣簡單。</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>brew install tmux <span class="c"># Mac</span>
</span><span class='line'>sudo apt-get install tmux <span class="c"># Ubuntu</span>
</span></code></pre></td></tr></table></div></figure>
<!-- more -->
<h2>啟動 tmux:輸入 tmux</h2>
<p>在終端機中輸入 tmux,開啟 tmux</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14120925.png"></p>
<h2>分割視窗:水平 ctrl-b %,垂直 ctrl-b ”</h2>
<p>下面有顯示基本資訊和視窗列表的 status bar,有一點類似 byobu。tmux 的控制 prefix 是
ctrl+b,使用 ctrl+b % 用來把視窗分割成水平兩半。</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14121427.png"></p>
<p>也可以分割為垂直的,只要使用 ctrl-b ”</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14121924.png"></p>
<p>分割出來的每一個視窗,稱為 pane。每個 pane 都可以再被分成更小的 pane。好比說剛剛垂直分割的視窗,也可以再分割為兩個水平的,只要再輸入一次 ctrl-b %</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14122140.png"></p>
<p>如此一來,切割 pane 的工作就完成了,那如何在 panel 中切換呢?</p>
<h2>切換 panel:ctrl-b <方向鍵> 或 ctrl-b o</h2>
<p>切割完 pane,要在 pane 之間切換,只要用 ctrl-b 和方向鍵就可完成。當然,也可以用 ctrl-b o,有點類似 emacs 的「往下一個 buffer c-x o」,但是在 pane 多的時候,用方向鍵直覺很多。</p>
<h2>開新視窗:ctrl-b c</h2>
<p>類似 screen 的新視窗,用 c 當作指令。輸入這個指令以後,我們會得到一個全新的 window,下面
status bar 也會出現一個新的項目。</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14122933.png"></p>
<h2>切換視窗:ctrl-b <數字> 或 下一個:ctrl-b n、前一個:ctrl-b p</h2>
<p>其中 status bar 上面寫的視窗編號,我們可以用 ctrl-b 數字,快速切換。比方說,按下 ctrl-b
0,就會回到最剛開始開的視窗。</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14123225.png"></p>
<p>而 ctrl-b n 和 ctrl-b p 分別代表 next 和 pervious,類似 emacs 的表達法(這就是為什麼我那麼愛 tmux,一整個很 emacs style)</p>
<h2>輸入指令:ctrl-b :</h2>
<p>tmux 眾多的指令,有些要使用參數,可以使用 ctrl-b : 快速鍵來輸入,按下這個快速鍵,游標會移到 status bar,就可以輸入指令了。</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14123605.png"></p>
<h2>為視窗改名:renamew <新名稱></h2>
<p>有時候我習慣用一個 window 代表一個針對 bug 工作。但是只要 window 數量一多,很容易搞混。而修改視窗的名稱,則會顯示在 status bar,算是相當實用的功能。使用 ctrl-b : renamew <new name>
可以完成。</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14124139.png"></p>
<h2>顯示 pane 的編號:ctrl-b q</h2>
<p>視窗有編號,pane 也有編號。知道 pane 的編號可以讓我們更容易操作 pane。按下 ctrl-b q,則
tmux 會用 ASCII art 顯示 pane 的編號。</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14125035.png"></p>
<h2>交換 pane:swapp -s <pane1> -t <pane2></h2>
<p>知道編號以後,就可以用 swapp 指令交換 pane 的位置,比方說</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>swapp -s 0 -t 1
</span></code></pre></td></tr></table></div></figure>
<p>就可以使得 pane 0 和 pane 1 的位置互相調換</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14125035-1.png"></p>
<h2>回捲:ctrl-b [</h2>
<p>如果輸出資料太長,一般圖形終端機可以用捲軸往回卷。tmux 也可以。按下 ctrl-b [ 以後,上下左右鍵可以用來控制捲動方向。此時,使用 ctrl-shift-2 可以開始選取。按下上下左右按鍵可以修改選取範圍。選取完畢後,可以按下 alt-w 複製。複製的通時會回到一般模式。再按下
ctrl-] 就可以把剛剛複製的東西貼到終端機上面!</p>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14102929.png"></p>
<h2>兩個終端機共用一個 tmux session:attach</h2>
<p>介紹最後一個功能,是我愛 tmux 超過 Terminator 的主要原因:假如我下班了,透過 vpn
連回公司。我卻沒有辦法單單用 ssh 就開始使用我在 Terminator 的 session。而是要透過
vnc。個人不喜歡 vnc,尤其是透過 vnc 只為了簡單的指令介面。這時,tmux 可以被共用的功能,就可以派上用場。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'># SSH to your office pc...
</span><span class='line'>
</span><span class='line'>$ tmux attach</span></code></pre></td></tr></table></div></figure>
<p><img src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-10-14104138.png"></p>
<h2>Else</h2>
<p>Tmux 是非常強的東西,還有很多東西沒有機會介紹到。常用的在這邊也整理一下。</p>
<pre><code>ctrl-b ctrl-<方向鍵> -- 調整 pane 大小
:joinp -s <Window編號>.<Pane編號> -- 把別的 window 的 pane 拉過來
ctrl-b <空白鍵> -- 改變 pane 的 layout
ctrl-b d -- Deattch session,把 session 留在機器上,終端機模擬器就可以關閉了
</code></pre>
<p>還有什麼想到在補上。</p>
<p>當然,如果用不慣純文字模式,用 Terminator 來作分割終端機也是非常好用。只是沒有辦法用 SSH 連回去而已。而 tmux 可以降低對滑鼠的依賴(滑鼠基本上可以說是用不上),又可以遠端工作。還可以類似 screen 般的保持 session 存活。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[C++ Regular Expression]]></title>
<link href="http://blog.patrickz.net/blog/2012/07/12/c-plus-plus-regular-expression/"/>
<updated>2012-07-12T17:54:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/07/12/c-plus-plus-regular-expression</id>
<content type="html"><![CDATA[<p>用過 Python 以後,就會深深愛上 Python 那強大的 Regex parsing 能力。回過頭來,對於 C++ parsing 的功能,我還停留在 scanf 和 >> 這兩個基本到到不行的功能,聽說 C++11 有加入了 Regular Expression 的功能。就順便來研究一下,希望 C++ 能夠有足以和 Perl 或 Python 那個家族的 Parsing 能力。</p>
<p>原本希望用 clang 3.1 來編譯,但是遇到</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="cp">#include <regex></span>
</span></code></pre></td></tr></table></div></figure>
<p>就掛了,顯然 based library 還沒 Ready。改用 g++-4.7 就過了,可是,一切沒那麼容易,我不管建立任何 Regular expression 都會被丟出例外,連 wikipedia 上面的範例都噴射,最後只好放棄。考慮到 C++11 的 regex 是來自 boost,乾脆直接拿 boost 來用。</p>
<!-- more -->
<p>使用 clang 或是 g++ 要注意指定 -std=c++11,而使用 boost,因為只是第三方 library,不需要指名使用 C++11 的標準,但是要注意連結 boost library。以我的 Mac 來說,使用 brew 安裝 Boost</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>brew install boost
</span><span class='line'><span class="c"># 會被安裝在 /usr/local/Cellar/boost/1.49.0</span>
</span></code></pre></td></tr></table></div></figure>
<p>要注意使用 -lboost_regex-mt 參數來連結。</p>
<p>那就直接來看檔案吧</p>
<figure class='code'><figcaption><span>regex.cpp </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="cp">#ifdef USE_BOOST_REGEX</span>
</span><span class='line'><span class="cp">#include <boost/regex.hpp></span>
</span><span class='line'><span class="cp">#else</span>
</span><span class='line'><span class="cp">#include <regex></span>
</span><span class='line'><span class="cp">#endif</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#include <iostream></span>
</span><span class='line'><span class="cp">#include <string></span>
</span><span class='line'>
</span><span class='line'><span class="cp">#ifdef USE_BOOST_REGEX</span>
</span><span class='line'><span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="p">;</span>
</span><span class='line'><span class="cp">#endif</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="k">try</span> <span class="p">{</span>
</span><span class='line'> <span class="n">regex</span> <span class="n">reg</span><span class="p">(</span><span class="s">"[0-9]+"</span><span class="p">);</span>
</span><span class='line'> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">s</span> <span class="o">=</span> <span class="s">"<tag>1</tag>"</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="n">smatch</span> <span class="n">mat</span><span class="p">;</span>
</span><span class='line'> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Matched: "</span> <span class="o"><<</span> <span class="n">regex_search</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">mat</span><span class="p">,</span> <span class="n">reg</span><span class="p">)</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'> <span class="n">ssub_match</span> <span class="n">prefix</span> <span class="o">=</span> <span class="n">mat</span><span class="p">.</span><span class="n">prefix</span><span class="p">();</span>
</span><span class='line'> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">str_prefix</span><span class="p">(</span><span class="n">prefix</span><span class="p">.</span><span class="n">first</span><span class="p">,</span> <span class="n">prefix</span><span class="p">.</span><span class="n">second</span><span class="p">);</span>
</span><span class='line'> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Prefix: "</span> <span class="o"><<</span> <span class="n">str_prefix</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Length: "</span> <span class="o"><<</span> <span class="n">prefix</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'> <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="k">const</span> <span class="n">regex_error</span><span class="o">&</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Error: "</span> <span class="o"><<</span> <span class="n">e</span><span class="p">.</span><span class="n">what</span><span class="p">()</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span>Makefile </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='makefile'><span class='line'><span class="nf">regex</span><span class="o">:</span> <span class="m">regex.cpp</span>
</span><span class='line'> @echo <span class="s2">"Will now build"</span> <span class="nv">$^</span>
</span><span class='line'> <span class="k">$(</span>CXX<span class="k">)</span> <span class="nv">$^</span> -g3 -lboost_regex-mt -DUSE_BOOST_REGEX -o regex
</span><span class='line'>
</span><span class='line'><span class="nf">.PHONY</span><span class="o">:</span> <span class="m">regex</span>
</span></code></pre></td></tr></table></div></figure>
<p>Regex 在 C++11 和 boost 有些許差異:在 C++11 中,使用 <regex> 標頭,函數命名空間在 std;在 boost 中,使用 <boost/regex.hpp> 標頭檔,命名空間是
boost。其他部分幾乎是相同的。</p>
<p>regex 類別是用來放 regex pattern 的類別,使 basic_regex 樣板定義的類別,宣告是這樣</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="k">typedef</span> <span class="n">basic_regex</span><span class="o"><</span><span class="kt">char</span><span class="o">></span> <span class="n">regex</span><span class="p">;</span>
</span><span class='line'><span class="k">typedef</span> <span class="n">basic_regex</span><span class="o"><</span><span class="kt">wchar_t</span><span class="o">></span> <span class="n">wregex</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>
<p>所以寬字元使用 wregex。但我們一般使用 UTF-8 使用 regex 就可以。</p>
<p>regex matching 提供兩個 function:regex_match 和 regex_search。這兩個函數的功用分別是:regex_match 要 match 整個輸入字串,而 regex_search 只需要 match 部分字串。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[在 Mac 上面 Build GCC 4.7]]></title>
<link href="http://blog.patrickz.net/blog/2012/06/03/zai-mac-shang-mian-build-gcc-4-dot-7/"/>
<updated>2012-06-03T02:02:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/06/03/zai-mac-shang-mian-build-gcc-4-dot-7</id>
<content type="html"><![CDATA[<p>Homebrew 和 Macports 不相容,所以只能選一個。不過 Homebrew 追 gcc 的版本似乎是很慢。也因此,想要體驗 C++ 11 只有靠自己。還好,build GCC 的指令並不難,但是卻有一些小小的眉角。</p>
<h3>下載檔案</h3>
<p>依據 GCC 的網頁,安裝 GCC 除了需要下載 GCC Source Code 以外,還需要下載 GMP、MPFR
和 MPC 三個套件。這些東西除了 MPC 以外,其他都可以在高速電腦中心的 FTP 下載到。</p>
<p>下載 GCC 原始碼</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>wget ftp://ftp.twaren.net/Unix/GNU/gnu/gcc/gcc-4.7.0/gcc-4.7.0.tar.bz2
</span><span class='line'>tar jxf gcc-4.7.0.tar.bz2
</span><span class='line'>mv gcc-4.7.0 gcc
</span></code></pre></td></tr></table></div></figure>
<p>下載附加套件,然後把這些套件放進 GCC 原始碼資料夾下,並且把資料夾的版號去掉,這樣 GCC
就可以搜尋到這些套件,不需要在 configure 下面設定</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nb">cd </span>gcc
</span><span class='line'>wget ftp://ftp.twaren.net/Unix/GNU/gnu/gmp/gmp-5.0.5.tar.bz2
</span><span class='line'>tar jxf gmp-5.0.5.tar.bz2
</span><span class='line'>mv gmp-5.0.5 gmp
</span><span class='line'>wget ftp://ftp.twaren.net/Unix/GNU/gnu/mpfr/mpfr-3.1.0.tar.bz2
</span><span class='line'>tar mpfr-3.1.0.tar.bz2
</span><span class='line'>mv mpfr-3.1.0 mpfr
</span><span class='line'>wget http://www.multiprecision.org/mpc/download/mpc-0.9.tar.gz
</span><span class='line'>tar zxf mpc-0.9.tar.gz
</span><span class='line'>mv mpc-0.9 mpc
</span></code></pre></td></tr></table></div></figure>
<!-- more -->
<h3>Configure</h3>
<p>首先,建立一個和 gcc 目錄同級的 build 目錄,然後進入 build 目錄內進行編譯。這樣可以讓編譯的結果和 gcc 原始碼分開,確保編譯出來的東西可以很輕易的被 clean。</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>../gcc/configure <span class="se">\</span>
</span><span class='line'> --prefix<span class="o">=</span><span class="nv">$HOME</span>/local/ <span class="se">\</span>
</span><span class='line'> --program-suffix<span class="o">=</span>-4.7 <span class="se">\</span>
</span><span class='line'> --enable-language<span class="o">=</span>c,c++ <span class="se">\</span>
</span><span class='line'> --with-mpfr-lib<span class="o">=</span><span class="nv">$PWD</span>/mpfr/src/.libs <span class="se">\</span>
</span><span class='line'> --with-mpfr-include<span class="o">=</span><span class="nv">$PWD</span>/../gcc/mpfr/src
</span></code></pre></td></tr></table></div></figure>
<p>其中 –prefix 自然就是這個程式的目錄,而 –program-suffix 則是未來接在 gcc 工具後面的字串,在這裡加上 -4.7 也就是以後要使用 gcc-4.7 和 g++-4.7 以當作和 Mac 內建 tool 的區別。</p>
<p>後面的 MPFR 參數則是 configure 的重點,這些沒寫會 build 不過,因為 configure mpc 時會找不到 mpfr 的 include。如果組態順利,就可以 make 了</p>
<h3>Make</h3>
<p>Make 過程很簡單,就是那個老招</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>make -j4
</span><span class='line'>make install
</span></code></pre></td></tr></table></div></figure>
<p>如果安裝路徑的 bin 是在 path 以下,那就會有 gcc-4.7 和 g++-4.7 指令。</p>
<h3>Try it</h3>
<p>使用 GCC 4.7 當然就是要適用一下 C++11 的功能。這邊去網路上面找到了一個簡單的 lambda
function 程式碼,來嘗試一下。</p>
<figure class='code'><figcaption><span>lambda.cpp </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="cp">#include <iostream></span>
</span><span class='line'>
</span><span class='line'><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="k">auto</span> <span class="n">func</span> <span class="o">=</span> <span class="p">[]</span> <span class="p">()</span> <span class="p">{</span> <span class="n">cout</span> <span class="o"><<</span> <span class="s">"Hello world"</span><span class="p">;</span> <span class="p">};</span>
</span><span class='line'> <span class="n">func</span><span class="p">();</span> <span class="c1">// now call the function</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>編譯時記得使用 c++11 的標準</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>g++-4.7 lambda.cpp -std=c++11</span></code></pre></td></tr></table></div></figure>
<h3>Note</h3>
<p>本來想把他做成 Homebrew 套件的,可是看到 gcc45 的 rb 檔,就嚇到了!如果有人會製作
Homebrew 套件,也請指教一下!</p>
<p><a href="https://github.com/staticfloat/homebrew-versions/blob/master/gcc45.rb">gcc45.rb</a></p>
<h3>Reference</h3>
<ul>
<li><a href="http://gcc.gnu.org/install/download.html">Downloading GCC</a></li>
<li><a href="http://gcc.gnu.org/install/configure.html">Installing GCC: Configuration</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[簽發 TLS 憑證]]></title>
<link href="http://blog.patrickz.net/blog/2012/05/26/qian-fa-tls-ping-zheng/"/>
<updated>2012-05-26T04:39:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/05/26/qian-fa-tls-ping-zheng</id>
<content type="html"><![CDATA[<p>使用 SSL 真的是個痛苦的過程,最麻煩的部份莫過於憑證。SSL 除了保障資料不被竊聽以外,還會保障
Server 沒有被調包。為了作這件事情,瀏覽器透過一系列的方法去確定這個 Server 真的就是字面上打的那個 Server。</p>
<p>瀏覽器如何檢查呢?首先,瀏覽器內建有許多根憑證,這些根憑證憑證商自己簽發給自己的憑證,他的保證來自於使用者對於瀏覽器廠商的信任,所以我們假設這些憑證都是可被相信的,會一直強調信任是因為這些根憑證是之後驗證其他憑證的基礎,所以我們如果不相信他,那其他的驗證也別說了。當我們嘗試連線到一個網站時,瀏覽器會對這個網站作 SSL Handshake,建立 session layer
的連線。這個連線位於 TCP 和 HTTP 之間,可以把他當作是一個安全的可信賴連線。在 SSL
Handshark 的時候,瀏覽器會從 Server 下載 Server 憑證和 Server 的 CA 憑證。這兩個憑證用來建立所謂的 trust chain。</p>
<!-- more -->
<p>什麼是 trust chain 呢?trust chain 就是一種類似老鼠會的組織。剛剛不是說過,我們的瀏覽器裡面有內建一些根憑證嗎?因為我們已經相信了這些根憑證,所以我們也就相信了他們認證的憑證,而他們認證的憑證又認證了新的憑證,我們也相信,如此一來,只要我們從 server 下載到的憑證的認證單位的認證單位的認證單位….最後是我們瀏覽器的根憑證,那我們就可以相信這個憑證是有效的。</p>
<p>問題是,你要怎麼取得這種憑證?基本上,沒辦法,除非付錢。你可以付錢,請某個單位幫你認證你的憑證,這樣的話,因為幫你認證的單位的憑證有被內建在瀏覽器,所以瀏覽器就會認為你的憑證有效。或者,你也可以自己造一張自簽的憑證,然後用這張憑證去認證你的 server 憑證,再請使用者把這張自簽憑證手動加入瀏覽器根憑證,當然這狀況就是你的使用者肯、而且他要知道怎麼弄。</p>
<p>測試 SSL 連線當然用後者就可以了。這些步驟都可以使用 OpenSSL 來完成。</p>
<p>簽發 Self-signed 憑證的過程</p>
<h3>建立 CA 憑證</h3>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>openssl genrsa -des3 -out ca.key 4096 <span class="c"># 建立 CA 私鑰</span>
</span><span class='line'>openssl req -new -x509 -days 365 -key ca.key -out ca.crt <span class="c"># 簽發 CA 憑證</span>
</span><span class='line'>
</span><span class='line'><span class="c"># 驗證一下,是不是正確</span>
</span><span class='line'>openssl x509 -in ca.crt -text -noout
</span></code></pre></td></tr></table></div></figure>
<h3>建立 Server 憑證</h3>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>openssl genrsa -des3 -out server.key 4096 <span class="c"># 建立 Server 私鑰</span>
</span><span class='line'>openssl req -new -key server.key -out server.csr <span class="c"># 建立 CSR,這個步驟會要求輸入基本資料,記得,CN 一定要符合 Domain(可以是 localhost 囉)</span>
</span><span class='line'>openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt <span class="c"># 使用 CA Key 簽發憑證</span>
</span></code></pre></td></tr></table></div></figure>
<h3>匯入瀏覽器</h3>
<p>匯入瀏覽器的流程很容易,以 Firefox 來說,在 [設定] -> [Advanced] -> [Encryption]
可以找到 [View Certificates] 按鈕。</p>
<p><img class="center" src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-05-2642500.png"></p>
<p>按下這個按鈕後,出現憑證列表,選擇 [Authorities],就會出現所有認證機構的憑證。</p>
<p><img class="center" src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-05-2642358.png"></p>
<p>最後選擇 [Import] 選取剛剛建立好的 ca.crt,出現一個選項,至少要在相信他簽發的 Website</p>
<p><img class="center" src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-05-2643502.png"></p>
<p>最後憑證就會出現在列表之中了</p>
<p><img class="center" src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-05-2642500.png"></p>
<p>匯入 Server 的方式因各種不同 Server 而異,主要會使用到 ca.crt、server.crt 和 server.key
因為使用者已經相信簽發機構簽發的憑證,所以我們匯入 Server 之後,建立的 ssl 就可以被 user
信任。</p>
<h3>Reference</h3>
<ul>
<li><a href="http://www.tc.umn.edu/~brams006/selfsign.html">Creating Certificate Authorities and self-signed SSL certificates</a></li>
<li><a href="http://www.akadia.com/services/ssh_test_certificate.html">How to create a self-signed SSL Certificate</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[C 和 C++ 的 Callback]]></title>
<link href="http://blog.patrickz.net/blog/2012/05/21/c-he-c-plus-plus-de-callback/"/>
<updated>2012-05-21T11:58:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/05/21/c-he-c-plus-plus-de-callback</id>
<content type="html"><![CDATA[<h3>C 的 Callback</h3>
<p>Callback 把函數當成指標,在 C 裡面是這樣用</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="cp">#include <stdio.h></span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="nf">compute</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">,</span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">op</span><span class="p">)(</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="n">op</span><span class="p">)(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="nf">add</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">a</span><span class="o">+</span><span class="n">b</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="nf">sub</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">a</span><span class="o">-</span><span class="n">b</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="n">fprintf</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="s">"add: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">compute</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="o">&</span><span class="n">add</span><span class="p">));</span>
</span><span class='line'> <span class="n">fprintf</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="s">"sub: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">compute</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="o">&</span><span class="n">sub</span><span class="p">));</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>宣告時包含函數雛型,用 * 來宣告</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">op</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<!-- more -->
<p>傳入時使用取址運算子去取得函數指標</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="o">&</span><span class="n">add</span>
</span></code></pre></td></tr></table></div></figure>
<p>呼叫時 dereference 然後當函數使用</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">op</span><span class="p">)(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>這樣的方法也可以用在 C++ 的靜態函數中(類別函數),但是不能用在物件函數。</p>
<h3>C++ 的 Callback</h3>
<p>C++ 有 this 指標,物件函數是需要有物件資料的。所以不能用傳統 C 的方式傳遞函數指標。C++
物件函數的指標使用是這樣。</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="cp">#include <iostream></span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Ops</span> <span class="p">{</span>
</span><span class='line'> <span class="k">public</span><span class="o">:</span>
</span><span class='line'> <span class="kt">int</span> <span class="n">add</span><span class="p">(</span><span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">a</span><span class="o">+</span><span class="n">b</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="kt">int</span> <span class="n">sub</span><span class="p">(</span><span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">a</span><span class="o">-</span><span class="n">b</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="kt">int</span> <span class="n">a</span><span class="p">;</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">compute</span><span class="p">(</span><span class="n">Ops</span><span class="o">*</span> <span class="n">obj</span><span class="p">,</span> <span class="kt">int</span> <span class="p">(</span><span class="n">Ops</span><span class="o">::*</span><span class="n">op</span><span class="p">)(</span><span class="kt">int</span><span class="p">),</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">(</span><span class="n">obj</span><span class="o">->*</span><span class="n">op</span><span class="p">)(</span><span class="n">b</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="n">Ops</span> <span class="n">obj</span><span class="p">;</span>
</span><span class='line'> <span class="n">obj</span><span class="p">.</span><span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
</span><span class='line'> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Add: "</span> <span class="o"><<</span> <span class="n">compute</span><span class="p">(</span><span class="o">&</span><span class="n">obj</span><span class="p">,</span> <span class="o">&</span><span class="n">Ops</span><span class="o">::</span><span class="n">add</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Sub: "</span> <span class="o"><<</span> <span class="n">compute</span><span class="p">(</span><span class="o">&</span><span class="n">obj</span><span class="p">,</span> <span class="o">&</span><span class="n">Ops</span><span class="o">::</span><span class="n">sub</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>宣告的時候需要帶類別和雛型</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="kt">int</span> <span class="p">(</span><span class="n">Ops</span><span class="o">::*</span><span class="n">op</span><span class="p">)(</span><span class="kt">int</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>傳送時用 & 運算子取址</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="o">&</span><span class="n">Ops</span><span class="o">::</span><span class="n">add</span>
</span></code></pre></td></tr></table></div></figure>
<p>呼叫時,需要使用實體來呼叫,實體可以是指標也可以是物件參考</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">obj</span><span class="o">->*</span><span class="n">op</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="c1">// 物件是指標形式時</span>
</span><span class='line'><span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">obj</span><span class="p">.</span><span class="o">*</span><span class="n">op</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="c1">// 物件是參考形式時</span>
</span></code></pre></td></tr></table></div></figure>
<h3>Reference</h3>
<ul>
<li><a href="http://www.newty.de/fpt/fpt.html#chapter2">The Syntax of C and C++ Function Pointers</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Hello World to B2G]]></title>
<link href="http://blog.patrickz.net/blog/2012/05/20/hello-world-to-b2g/"/>
<updated>2012-05-20T00:25:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/05/20/hello-world-to-b2g</id>
<content type="html"><![CDATA[<p><img class="center" src="http://i1162.photobucket.com/albums/q535/kk1fff/b2g_lock.png"></p>
<p>今天趁 JSDC 一股熱忱,決定來練習一個 B2G App。</p>
<h3>Hello Gaia</h3>
<p>建立 B2G App 首先要當然是要替檔案建立資料夾,我直接建立在 Gaia/apps 底下,開一個 hello 資料夾,再來建立的是 mainfest.json,依據 <a href="https://developer.mozilla.org/en/Apps/Manifest">App manifest</a>
網頁上的描述,這個檔案至少有 name 和 description 要寫,類似這樣</p>
<figure class='code'><figcaption><span>manifest.json </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="s2">"name"</span> <span class="o">:</span> <span class="s2">"hello world"</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"version"</span> <span class="o">:</span> <span class="s2">"0.0.1"</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"description"</span> <span class="o">:</span> <span class="s2">"this is hello"</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<!-- more -->
<p>其中要注意就是 XULRunner 對於 json 的處理似乎比 node 還要更嚴謹,JSON 的 key 值一定要用雙引號,而且結尾不可以有逗號。</p>
<p>再來就是一個簡單的 index.html</p>
<figure class='code'><figcaption><span>index.html </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt"><html></span>
</span><span class='line'><span class="nt"><head></head></span>
</span><span class='line'><span class="nt"><body></span>
</span><span class='line'>hello gaia.
</span><span class='line'><span class="nt"></body></span>
</span><span class='line'><span class="nt"></html></span>
</span></code></pre></td></tr></table></div></figure>
<p>之後到 gaia 的 root,先砍掉已經 build 好的 profile (如果先前有 build 過),再重新
make</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>rm -r profile
</span><span class='line'><span class="nv">$ </span>make
</span></code></pre></td></tr></table></div></figure>
<p>Build 完以後,重新執行 Gaia 的模擬器,就可以看到:app 出現了!!</p>
<p><img class="center" src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-05-2015813.png"></p>
<p>點一下我們剛剛弄好的 hello,就會跑出剛剛網頁的內容</p>
<p><img class="center" src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-05-2020205.png"></p>
<h3>Map</h3>
<p>從 Openstreet Map 上面可以取得我們所想要的地圖資料,在透過 iframe 就可以把他嵌進網頁裡面只要把剛剛的 hello gaia 稍微小改一下</p>
<figure class='code'><figcaption><span>index.html </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt"><html></span>
</span><span class='line'><span class="nt"><head></head></span>
</span><span class='line'><span class="nt"><body></span>
</span><span class='line'><span class="nt"><iframe</span> <span class="na">width=</span><span class="s">"425"</span> <span class="na">height=</span><span class="s">"350"</span> <span class="na">frameborder=</span><span class="s">"0"</span> <span class="na">scrolling=</span><span class="s">"no"</span> <span class="na">marginheight=</span><span class="s">"0"</span> <span class="na">marginwidth=</span><span class="s">"0"</span> <span class="na">src=</span><span class="s">"http://www.openstreetmap.org/export/embed.html?bbox=121.296,24.9586,121.3607,25.0079&amp;layer=mapnik"</span> <span class="na">style=</span><span class="s">"border: 1px solid black"</span><span class="nt">></iframe><br</span> <span class="nt">/><small><a</span> <span class="na">href=</span><span class="s">"http://www.openstreetmap.org/?lat=24.98325&amp;lon=121.32835&amp;zoom=14&amp;layers=M"</span><span class="nt">></span>View Larger Map<span class="nt"></a></small></span>
</span><span class='line'><span class="nt"></body></span>
</span><span class='line'><span class="nt"></html></span>
</span></code></pre></td></tr></table></div></figure>
<p>重新編譯後,馬上,地圖就出現了</p>
<p><img class="center" src="http://i1162.photobucket.com/albums/q535/kk1fff/2012-05-2020648.png"></p>
<h3>Reference</h3>
<ul>
<li><a href="https://wiki.mozilla.org/WebAPI">WebAPI</a></li>
<li><a href="https://developer.mozilla.org/en/Apps/Getting_Started">Getting started with making apps</a></li>
<li><a href="https://developer.mozilla.org/en/Apps/Manifest">App manifest</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[來紀錄一下怎麼用 Octopress 好了]]></title>
<link href="http://blog.patrickz.net/blog/2012/05/18/lai-ji-lu-%5B%3F%5D-xia-zen-mo-yong-octopress-hao-liao/"/>
<updated>2012-05-18T01:25:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/05/18/lai-ji-lu-[?]-xia-zen-mo-yong-octopress-hao-liao</id>
<content type="html"><![CDATA[<p>新增一篇文章</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>bundle <span class="nb">exec </span>rake new_post<span class="o">[</span><span class="s1">'文章的標題'</span><span class="o">]</span>
</span></code></pre></td></tr></table></div></figure>
<p>在本機預覽</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>bundle <span class="nb">exec </span>rake preview
</span></code></pre></td></tr></table></div></figure>
<p>發佈出去</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>bundle <span class="nb">exec </span>rake generate
</span><span class='line'><span class="nv">$ </span>bundle <span class="nb">exec </span>rake deploy
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Blog 架好以後]]></title>
<link href="http://blog.patrickz.net/blog/2012/05/18/blog-jia-hao-yi-hou/"/>
<updated>2012-05-18T01:15:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/05/18/blog-jia-hao-yi-hou</id>
<content type="html"><![CDATA[<p>也不知道要寫什麼 XD
架的這麼辛苦耶</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[新 Blog 開張]]></title>
<link href="http://blog.patrickz.net/blog/2012/05/13/xin-blog-kai-zhang/"/>
<updated>2012-05-13T00:48:00+08:00</updated>
<id>http://blog.patrickz.net/blog/2012/05/13/xin-blog-kai-zhang</id>
<content type="html"><![CDATA[<p>這次選用 Octopress 當作 Blog backend,真是經歷波折啊,全然不同的體驗。Octopress 不像以前用 blogspot,有漂亮的 UI 來設定網頁。他是用 markdown 撰寫,用 Ruby 去整理所有的樣板,在產生出靜態網頁,發布到網站。網站可以用 github page 來 host,搭配私有域名,可以真的弄出一個「很有個人味道」的 blog。</p>
<p>只是為了要設定樣板,也真是折騰。尤其我不會 scss,幾乎沒辦法做事,上網去爬了一堆文,才找到方法在我的標題列上面放上背景。不過看到了精美的程式碼區塊,也覺得這應該還算是值得啦 XD。</p>
<p>接下來還要弄 Google adsense 和 Google Analytics,就慢慢來。希望這個 Blog 可以使用順利。</p>
]]></content>
</entry>
</feed>