網頁

2017年9月1日 星期五

[C++] constant of pointer

身為一個專業的C/C++工程師如果不懂 constant of pointer 真的就太鳥了。

各位大神肯定了解,就容小弟整理出來。

If I write,

char     *const *const *const test1 = ppstr;

only ***test1 can be modified.

so,

char           *const *const *const test1 = ppstr;
char  const *         *const *const test2 = ppstr;
char  const *const *         *const test3 = ppstr;
char  const *const *const *         test4 = ppstr;

***test1 = NULL; //OK
**test2 = NULL; //OK
*test3 = NULL; //OK
test4 = NULL; //OK

//**test1 = NULL; //compile error
...

The method is viewing from right to left, and see if any const in the lefthand of to modified obj, if there is, this obj can not be modified or compile error.

e.g.
char  const *const *const *         test4 = ppstr;
                 ^4       ^3      ^2       ^1
// test4 can be modified, due to there is no 'const' in the lefthand of ^1.
// This also means test4 is pointer of pointer of pointer of char which can be modified


2017年7月21日 星期五

[AWS] run dynamodb example locally on macOS

目標:

run dynamodb example locally on macOS

環境:

macOS Sierra 10.12.5
node js

步驟:

1. install aws-sdk for node
npm install aws-sdk

2. install java (do not use oracle website to install or fail)
brew update;brew cask install java;

3. download dynamodb jar file
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html

4. run dynamodb locally
java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb

5. edit js file named MoviesCreateTable.js
http://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/GettingStarted.NodeJs.01.html

6. run js
node MoviesCreateTable.js

來源:

http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html

遇到的問題:
some api will not work

2017年6月2日 星期五

how to use synology docker gitlab and use xcode to commit and push code ?

step1. on Synology DSM, install "docker gitlab"
step2. login "docker gitlab"
step3. create project in "docker gitlab" (e.g. xxxx)
step4. open xcode and "source control > xxxx - master > configure xxxx > Remote (+)":
         [your DSM IP]:3000/root/xxxx.git

step5. commit code in xcode: "source control > commit..."
step6. push code in xcode: "source control > push..."

2017年4月17日 星期一

git grep for a pattern

假如想要找某一行 code 這樣的 pattern 在某個 commit 的 log
可以這樣下:

git grep '[pattern]' [sha]

如果想要找全 history 可以這樣下:

git grep '[pattern]' [sha] $(git rev-list --all)


如果還想要檢查前面 20 行 可以這樣下:

git grep -B20 '[pattern]' [sha] $(git rev-list --all)

2017年4月15日 星期六

[C++] Any input type template function

主題 : Any input type template function

引言 : C++ 11 引入了此功能,讓 function 可以吃同類型任何型態的參數進來,並且還保持原來 type 的樣子。

描述 :
這名字我亂取的,我只是想要說明這樣的 pattern 的寫法可以讓你寫出一個 template function 可以吃所有同類型的 TYPE, TYPE&, TYPE&& ...

這真的很強大,不必再 for reference input 寫一個 function,for right value input 再寫一個 function。

已經有文章寫得很好了,請參照
http://thbecker.net/articles/rvalue_references/section_01.html
~
http://thbecker.net/articles/rvalue_references/section_08.html

一句話解釋,"當你想把 type 忠實的傳入到 func 內使用請使用以下的 pattern"
細節請讀 section_01~section_08

以下是 section_01~section_08 給的 factory design pattern 的範例,
這個 factory template function 的 arg 可能吃 1. value 2. reference 3. right value ...
因為 C++ 很在意 type,type 不對就 compile error
那我們要怎麼寫一個任何 type 都能傳入的 function 呢 ? 如下 function,


template<typename T, typename Arg> 
shared_ptr<T> factory(Arg&& arg)
{ 
  return shared_ptr<T>(new T(std::forward<Arg>(arg)));
} 

當 Arg 是 X 則 new T(X)
當 Arg 是 X& 則 new T(X&)
當 Arg 是 X&& 則 new T(X&&)

很神奇吧,我的說明肯定不會比 section_01~section_08 還好。
如果你想知道為什麼,耐著性子看完你就會知道為什麼了。

2017年4月14日 星期五

[App] iTunes Connect Screenshot Sizes for iPhone and iPad

image:
iPhone 6 Plus(5.5 Inch): 1242 x 2208 px

iPad Pro (12.9 Inch): 2732 x 2048 px

video: (in 15 or 30 seconds)
iPhone 6 Plus(5.5 Inch): 1080 x 1920 (Portrait)

https://developer.apple.com/support/app-previews/

2017年4月8日 星期六

[App] 如何一鍵刪除 iPhone/iPad 裡面所有的照片 ?

【軟體名稱】Photo Trash Can
【程式開發】Chun-Pai Yang
【軟體類別】工具
【軟體大小】13.5MB
【軟體售價】0.99 鎂
【下載連結】點我


【Photo Trash Can 介紹】如何一鍵刪除 iPhone/iPad 裡面所有的照片 ?

Photo Trash Can 是一款刪除所有照片/影像的 App。許多用戶在使用完一些備份軟體如: Synology DS Photo 或是 dropbox .. 將 iPhone/iPad 裡面的照片/影片全部備份完後,這些軟體並不會自動地將 iPhone/iPad 裡面的照片/影片刪除。此時就是使用此軟體的時機。

▼ 若沒有此軟體在相片備份完後必須使用 Mac Book 的 Photo App 匯入並且一次刪除所有照片。
相當的麻煩 ...
Inline image 7
Inline image 5

▼ Photo Trash Can 一開始的畫面,意思就是你真的要想清楚才按下此鍵:
Inline image 1▼ 當點下這個紅色的按鈕後,會要求你輸入你 iPhone/Ipad 裡的 相片:影片 數目,以避免誤操作:
Inline image 3

▼ 當做完一些最終的確認後,你所有的照片和影片就全數被刪除了:
Inline image 4

▼ 刪除後其實全部的照片都可以從 Apple 的內建 Photos App 的 "最近刪除" (Recently Deleted) 相簿中。
若想要回復可要一張張的救回來了。
所以在使用此軟體前可要先確保你所有的照片都已經備份了喲。

但對於像是作者平時很懶,會有幾千張照片才會用 Synology DS Photo 備份一次並在備份完想要刪除所有照片的人真的是相當的方便。


如果您喜歡 Photo Trash Can的話,還請您不吝於給予我們五顆星的評價 (馬上前往)
有任何疑問/功能建議,都歡迎聯絡我們喔!
Photo Trash Can Facebook粉絲團:https://www.facebook.com/Photo-Trash-Can-716543165173369
Photo Trash Can 聯絡Email:phototrashcan@gmail.com
Inline image 2

2017年1月18日 星期三

ssh tunnel

記錄一下。
之前都不知道怎麼建,應該說我知道這東西,但沒實際使用的經驗。

最近有一個 support 要我幫 user 看 router 上的設定,但即使開了 remote beckend,仍然是無法連到 router 網頁的阿。

這時候就是 ssh tunnel 使用的時機:

   ssh -L 11111:192.168.1.1:80 -p [port] admin@[public ip]

以上的前提是你有 ssh 的 admin 帳密以及 public ip 在加上你知道 ssh 的 port 是多少並且 ssh port 有被 portforward 出來。
那麼下了以上的指令,你就可以把 [public ip] 內網的 192.168.1.1:80 和 localhost:11111 連在一起了。

以下是示意圖:


   [localhost]:11111 <= ssh tunnel => [public ip]:[port] <= connect & redirect => 192.168.1.1:80


也就是下完以上 command,並用網頁瀏覽器開啟 localhost:11111 就可以進到 router 的網頁介面了。

話說開 ssh tunnel 真的很可怕,內網可以說整個全開了,顆顆。

------------------------------- 2017.02.20 reverse tunnel ----------------------------------------
話說以上是 forward tunnel,
      建 forward tunnel 是想要 " local 這台 ssh client 機器額外開 port 導到 ssh server 端,然後在由 ssh server 再幫我們導向另外一台的某個 port"。
      ssh client (開 port) <================> ssh server =============> forward packet

以下是 reverse tunnel, reverse tunnel 就是幫 ssh server 開後門,
    建 reverse tunnel 是想要 "在 remote ssh server 那台機器上額外開 port,然後希望 remote ssh 的那個 port 收到的東西都幫我們導到 local 這台機器的的某個 port"
    ssh client  <================> ssh server (開 port) <============= receive packet

2016年8月5日 星期五

[gitlab] how to merge request by gitlab

主題:
How to merge request by gitlab

步驟:
1. fork project on gitlab UI, and you will get a git respository location like: git@git.xxxx:[yourname]/[projectname].git
    gitlab -> select project -> fork
    
2. add respository
      git remote add upstream git@git.xxxx:[yourname]/[projectname].git

3. check if the repository is added
      git remote -v

4. fetch the repository
     git fetch upstream

5. push your commit to the repository instead of 'origin' repository
    git push upstream master

6. create merge request on gitlab UI
    gitlab -> select [merge requests] -> click [New merge request] ....

7. wait project owner to merge the code

8. delete the repository on gitlab UI

2016年5月11日 星期三

use c++ regex parse string enclosed in double quote

主題:

use c++ regex parse string enclosed in double quote

難處:

考慮 escaped quote


範例:

如果是 std::string s = "\"\\\"aaa\"\"bbb\"";   要 parse 成  \"aaa & bbb
以下我直接貼 code, 後面註解是想要 parse 的結果

std::string s = "\"\\\\\"aaa\"\"bbb\"";       // \\"aaa & bbb
std::string s = "\"aa\\\"a\" \"bbb\"";        // aa\"a  & bbb
std::string s = "\"aa\\\\\"a\" \"bbb\"";      // aa\\"a & bbb
std::string s = "\"\"\"aaa\"\t \"bbb\"";     // empty & aaa & bbb



怎麼寫:

std::regex e ("\"((([^\\\\]*\\\\.)|([^\"]*))*)\"");
std::smatch sm;
std::string line = s;
while (std::regex_search (line, sm, e)) {
    std::cout << "range with " << sm.size() << " matches\n";
    std::cout << "the matches were: ";
    for (unsigned i=0; i<sm.size(); ++i) {
        std::cout << "[" << sm[i] << "] ";
    }
    line = sm.suffix().str();
    std::cout << std::endl << "line: " << line;
    std::cout << std::endl;
}

// 裡面印出的 sm[1] 就是我們想要的結果

參考: 

http://stackoverflow.com/questions/21658860/how-to-use-regex-c
http://www.cplusplus.com/reference/regex/match_results/suffix/
http://stackoverflow.com/questions/6863518/regex-match-one-of-two-words
http://stackoverflow.com/questions/249791/regex-for-quoted-string-with-escaping-quotes (Guy BedFord 的寫法再改良)


2015年7月23日 星期四

[vim] display trailing white space

in vim

:highlight ExtraWhitespace ctermbg=red guibg=red
:match ExtraWhitespace /\s\+$/                

2015年7月17日 星期五

[data base] mariadb install for python

Env:

Ubuntu 14.10
python 2.7


Commands:

import MySQLdb needs
apt-get install python2.7-mysqldb

import mysql.connector as mariadb needs
http://dev.mysql.com/downloads/connector/python/

2015年7月15日 星期三

[vimdiff] diffg

在vimdiff下我們可以用好用的diffg來同步

當我們用vimdiff時左右兩邊視窗不一致時,我們可以在左邊視窗用 "大寫V" 選擇要左右sync的區塊,然後再按下 :diffg ,就會把右邊視窗所選的同步到左邊。

如果是按下 :diffget,就會把左邊同步到右邊。

NOTE: 通常不額外設定 git difftool 使用的也是vimdiff。

2015年7月13日 星期一

[opencv] install

主題: opencv install


很難安裝, 筆記一下

Ubuntu 14.10

- pre install QT4

apt-get install qt4-default libqt4-dev qtchooser qt4-designer

- git clone opencv

git clone https://github.com/Itseez/opencv.git

cd opencv
mkdir release
cd release

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON -D WITH_QT=ON -D WITH_OPENGL=ON ..

sudo make
sudo make install

成功

MAC OS Yosemite 10.10.4

直接brew install opencv會有問題

- 一樣要先裝QT, 但要brew要多下"build-from-source"的option

brew install qt --build-from-source

- git clone opencv(這邊就和上面一樣)

失敗... 

2015年7月9日 星期四

[Python] hook function for self.x, self.x = 3, delete self.x

主題: hook function for self.x, self.x = 3, delete self.x


說明:

我們有一個class A,
假設我們想要在"讀取"self.x或在"設定"self.x時或在"刪除"self.x時可以多做一些"額外的事情(某個function)",那麼該怎麼把我們的function插入呢?

實作:

實作一個descriptor, 並安裝到A中成為class member data。

#!/usr/bin/python

class Integer(object):
        def __init__(self, name):
                self.name = name

        def __get__(self, instance, cls):
                if instance is None:
                        return self
                else:
                        return instance.__dict__[self.name]

        def __set__(self, instance, value):
                if not isinstance(value, int):
                        raise TypeError('Expected an int')
                instance.__dict__[self.name] = value

        def __delete__(self, instance):
                del instance.__dict__[self.name]

class A(object):
        x = Integer('x')
        def __init__(self, x, y):
                self.x = x
                self.y = y

a = A(1.0, 2)

結果:

Traceback (most recent call last):
  File "./descriptor.py", line 27, in 
    a = A(1.0, 2)
  File "./descriptor.py", line 24, in __init__
    self.x = x
  File "./descriptor.py", line 15, in __set__
    raise TypeError('Expected an int')
TypeError: Expected an int

無效: 

因為這件事情很重要,再重複一次,
"實作一個descriptor, 並安裝到A中成為class member data。"
如果你實作了一個descriptor,但安裝到class中不是成為class member data而是instance data, 這樣是不起作用的。

class A(object):
        def __init__(self, x, y):
                self.x = Integer('x')
                self.y = y

繼承還是有效: 

class B(A):
        def __init__(self, x, y):
                self.x = x
                self.y = y

b = B(1.0, 2)
繼承還是有效,因為child class繼承了class member data
Traceback (most recent call last):
  File "./descriptor.py", line 32, in 
    b = B(1.0, 2)
  File "./descriptor.py", line 29, in __init__
    self.x = x
  File "./descriptor.py", line 15, in __set__
    raise TypeError('Expected an int')
TypeError: Expected an int

順帶一題: 

property, classmethod, staticmethod, __slots__都是相同概念:
安裝一個descriptor到class上

2015年7月8日 星期三

[linux] add user

主題: 假設想要多個可信認的user共用一台機器,每個user有權限可以轉換身分到root


How to ?

1. 加入一般身分的user
2. 修改visudo

2015年7月6日 星期一

[Python] @staticmethod 和 @classmethod

主題: @staticmethod和@classmethod的差別

說明:

這兩個都是decorator,
一言以蔽之 classmethod的input function第一個參數必須是class,
而staticmethod則第一個參數就是真的參數。

可以參考這邊(staticmethod/classmethod)

另外一提,這兩個的實作方式和@property的做法很像。

[Python] __slots__ 記憶體優化工具

主題: __slots__

範例:



不使用__slots__優化記憶體(內部為一個hash table)
#!/usr/bin/python
from pympler import asizeof

class A(object):
        #__slots__ = ['year', 'month', 'day']
        def __init__(self, year, month, day):
                self.year = year
                self.month = month
                self.day = day

a = A(1,2,3)
print asizeof.asized(a, detail=1).format()
<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x7f15e50e9cd0="" data-blogger-escaped-at="" data-blogger-escaped-object=""> size=552 flat=64
    __dict__ size=488 flat=280
    __class__ size=0 flat=0
使用__slots__優化記憶體(不存table, 分開以更節省記憶體的方式存)
#!/usr/bin/python
from pympler import asizeof

class A(object):
        __slots__ = ['year', 'month', 'day']
        def __init__(self, year, month, day):
                self.year = year
                self.month = month
                self.day = day

a = A(1,2,3)
print asizeof.asized(a, detail=1).format()
<__main__ data-blogger-escaped-.a="" data-blogger-escaped-0x191f6c8="" data-blogger-escaped-at="" data-blogger-escaped-object=""> size=224 flat=72
    __slots__ size=80 flat=80
    month size=24 flat=24
    day size=24 flat=24
    year size=24 flat=24
    __class__ size=0 flat=0

結論:

使用__slots__優化記憶體 552->224
缺點就是因為內部不存hash table, 所以你也只能使用__slots__指定的那些屬性名稱

2015年7月5日 星期日

[Python] property繼承的寫法

主題: property繼承的寫法


假設我們有一個擁有name property的class A:

class A(object):
        def __init__(self):
                print ("A init")
        @property
        def name(self):
                print ("A name getter")
        @name.setter
        def name(self, x):
                print ("A name setter")
我們想要對A的name property繼承,並且改寫。 改寫的方式想要繼承A原本的一些code再附加新的class的一些code,可以這樣寫:
class B(A):
        def __init__(self):
                print ("B init")

        @property
        def name(self):
                super(B, B).name.fget(self)
                print ("B name getter")

        @name.setter
        def name(self, x):
                super(B, B).name.fset(self, x)
                print ("B name setter")

或者把fget和fset換成__get__和__set__
class B(A):
        def __init__(self):
                print ("B init")

        @property
        def name(self):
                super(B, B).name.__get__(self)
                print ("B name getter")

        @name.setter
        def name(self, x):
                super(B, B).name.__set__(self, x)
                print ("B name setter")

為什麼可以這樣? 有興趣的人可以去研究一下 property這個class

還有一點要注意, 其實這樣的寫法是"定義B的自己版本name property", 換句話說,
B.name和A.name是兩個不同的版本。
也就是如果B只有定義getter或是setter,那麼這個property也只會剩下getter或是setter的能力:


#!/usr/bin/python

class A(object):
        def __init__(self):
                print ("A init")
        @property
        def name(self):
                print ("A name getter")
        @name.setter
        def name(self, x):
                print ("A name setter")


class B(A):
        def __init__(self):
                print ("B init")

        @property
        def name(self):
                super(B, B).name.__get__(self)
                print ("B name getter")

b = B()
b.name
b.name = 3

結果:
B init
A name getter
B name getter
Traceback (most recent call last):
  File "./property.py", line 25, in 
    b.name = 3
AttributeError: can't set attribute

Shell 已返回1

結論:

1. child class要改寫parent class的property最好全部都改寫,除非你知道你在做什麼,你真的想閹割parent class的setter or getter or deleter ?
2. child class若要呼叫parent class的class method(memer data), 那就要用 super(B, B).name的寫法
3. property class有實作"descriptor protocol"(__get__, __set__, __delete__這三個function),
property class的__get__會去呼叫 property class的instance method: fget
property class的__set__會去呼叫 property class的instance method: fset
property class的__delete__會去呼叫 property class的instance method: fdel

2015年7月4日 星期六

[Python] decorator的等價寫法

主題: decorator的等價寫法


class A(object):
    @property
    def func(self):
       ...

同

class A(object):
    def func(self):
       ...
    func = property(func)

換句話說這時候 func經過property之後
1. 從單純的func變成為property
2. func則變為 class variable (不是intance variable)