C - inet ntoa aton (網路轉換相關)




宣告及定義


#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int inet_aton(const char *cp, struct in_addr *inp); // 網路字串(char *cp)轉網路數值. 成功回傳1, 失敗回傳0
in_addr_t inet_addr(const char *cp); // 功能與 inet_aton 相同,但是失敗回傳的-1255.255.255.255衝突。所以改用 inet_aton
in_addr_t inet_network(const char *cp); // 功能與 inet_addr 相同,測試起來會數值會反轉

char *inet_ntoa(struct in_addr in); // 網路數值轉網路字串
struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host); // net host 合併
in_addr_t inet_lnaof(struct in_addr in); // 回傳網路數值的低位元部份 (依網路位元組序)
in_addr_t inet_netof(struct in_addr in); // 回傳網路數值的高位元部份 (依網路位元組序)

// 數值定義
typedef uint32_t in_addr_t;
// 結構定義
struct in_addr {
in_addr_t s_addr;
};



範例


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char **argv) {
struct in_addr inp;
int ret;
ret = inet_aton("192.168.111.222", & inp);
printf("inet_aton => %x, %d\n", inp.s_addr, ret);
printf("inet_addr => %x\n", inet_addr("192.168.111.222"));
printf("inet_network => %x\n", inet_network("192.168.111.222"));
printf("\n");
printf("inet_ntoa => %s\n", inet_ntoa(inp));
printf("inet_lnaof => %x\n", inet_lnaof(inp));
printf("inet_netof => %x\n", inet_netof(inp));
printf("\n");
ret = inet_aton("172.16.111.222", & inp);
printf("inet_aton => %x, %d\n", inp.s_addr, ret);
printf("inet_lnaof => %x\n", inet_lnaof(inp));
printf("inet_netof => %x\n", inet_netof(inp));
printf("inet_makeaddr => %x\n", inet_makeaddr(0x1122, 0x3344).s_addr);
return 0;
}

===== 執行結果 ======================
inet_aton => de6fa8c0, 1
inet_addr => de6fa8c0
inet_network => c0a86fde

inet_ntoa => 192.168.111.222
inet_lnaof => de
inet_netof => c0a86f

inet_aton => de6f10ac, 1
inet_lnaof => 6fde
inet_netof => ac10
inet_makeaddr => 44332211



其他常用


#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong); // 用於本機序轉換到網路序
uint16_t htons(uint16_t hostshort); // 用於本機序轉換到網路序
uint32_t ntohl(uint32_t netlong); // 用於網路序轉換到本機序
uint16_t ntohs(uint16_t netshort); // 用於網路序轉換到本機序

在x86用起來就是反轉順序,如:htonl(0xaa11bb22) 執行結果為 0x22bb11aa

註:在 little-endian 上呼叫,結果會跟輸入值相同


其他範例


char *my_ipv4_broadcast(char *ip, char *netmask)
{
static char buffer[32];
in_addr_t _ip = inet_addr(ip);
in_addr_t _netmask = inet_addr(netmask);
struct in_addr _broadcast;

_broadcast.s_addr = _ip | ~_netmask;
sprintf(buffer, "%s", inet_ntoa(_broadcast));

return buffer;
}
char *my_ipv4_netid(char *ip, char *netmask)
{
static char buffer[32];
in_addr_t _ip = inet_addr(ip);
in_addr_t _netmask = inet_addr(netmask);
struct in_addr _netid;

_netid.s_addr = _ip & _netmask;
sprintf(buffer, "%s", inet_ntoa(_netid));

return buffer;
}




C - open & flock & lseek

 

open 宣告及用法


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

flags 可代入的常用參數:
    O_RDWR (可讀可寫)
    O_WRONLY (只寫)
    O_RDONLY (唯讀)
    O_CREAT (不存在就建立)
        mode 可代入的參數:
                S_IRWXU 00700 user (file owner) has read, write, and execute permission
                S_IRUSR 00400 user has read permission
                S_IWUSR 00200 user has write permission
                S_IXUSR 00100 user has execute permission
                S_IRWXG 00070 group has read, write, and execute permission
                S_IRGRP 00040 group has read permission
                S_IWGRP 00020 group has write permission
                S_IXGRP 00010 group has execute permission
                S_IRWXO 00007 others have read, write, and execute permission
                S_IROTH 00004 others have read permission
                S_IWOTH 00002 others have write permission
                S_IXOTH 00001 others have execute permission
                According to POSIX, the effect when other bits are set in mode is unspecified. On Linux, the following bits are also honored in mode:
                S_ISUID 0004000 set-user-ID bit
                S_ISGID 0002000 set-group-ID bit (see inode(7)).
                S_ISVTX 0001000 sticky bit (see inode(7)).
    O_APPEND (以附加方式開啟)
    O_NOCTTY (這個程式不控制TTY介面)
    O_NONBLOCK (非阻塞式, 讀到檔尾回傳0, 讀失敗回傳-1並設定errnoEAGAIN)
    O_SYNC (同步相關,每次寫入都等待物理 IO 結束)

lags 可代入的其他參數:
    O_NDELAY (非阻塞式, 讀到檔尾回傳0, 讀失敗回傳0)
    O_ASYNC (同步相關, 使用信號驅動的IO)
    O_DSYNC (同步相關, 每次寫入都等待物理 IO 結束。但不含元信息, 僅保證文件內容寫入完畢)
    O_DIRECT (Direct IO 方式開啟)
    O_EXCL (檔案已存在就回傳失敗。需包含 O_CREATE 一併使用)
    O_DIRECTORY (開啟目錄,如果不是目錄會回傳失敗)
    O_NOFOLLOW (如果開啟的是 link 就回傳失敗)
    O_NOATIME(進行讀取操作時,不更新 access time)
    O_LARGEFILE (可開啟 2G 以上大檔,在 64bit 平台已是預設)
    O_CLOEXEC (執行 exec 函數族後,自動關閉此 fd)
    O_TRUNC (檔案開啟後,清空檔案內容)
    O_TMPFILE (建立臨時檔案,close後自動刪除,此時 pathname 要代入的是目錄路徑。可使用 linkat 建立檔名,造成保留效果)
        如:linkat(fd, "", AT_FDCWD, "Name", AT_EMPTY_PATH) or linkat(fd, path, AT_FDCWD, "Name", AT_SYMLINK_FOLLOW)
    O_PATH (只回傳文件描述符。回傳的fd可給close、fchdir、fstat...等使用,不可給read、write使用)

O_RDWR、O_WRONLY、O_RDONLY 這三個一定要選擇一項


flock 宣告及用法


#include <sys/file.h>

int flock(int fd, int operation);

operation 可代入參數:
    LOCK_SH (共用鎖。不需等待呼叫 LOCK_UN 也可在不同地方同時執行多次 LOCK_SH)
    LOCK_EX (獨佔鎖。先前已呼叫過 LOCK_SH or LOCK_EX 會在此等待呼叫 LOCK_UN 後,才繼續執行)
    LOCK_UN (解鎖)



lseek 宣告及用法


#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

whence 可代入參數:
    SEEK_SET (從頭開始加減 offset)
    SEEK_CUR (從目前位置開始加減 offset)
    SEEK_END (從尾開始加減 offset)
    SEEK_DATA (移動到 offset 的下一個 data 的位置, 版本 3.1 後才支援)
    SEEK_HOLE (移動到 offset 的下一個 hold 的位置, 版本 3.1 後才支援)

The SEEK_HOLE and SEEK_DATA operations are supported for the following filesystems:
    * Btrfs (since Linux 3.1)
    * OCFS (since Linux 3.2)
    * XFS (since Linux 3.5)
    * ext4 (since Linux 3.8)
    * tmpfs(5) (since Linux 3.8)
    * NFS (since Linux 3.18)
    * FUSE (since Linux 4.5)



範例


#include <sys/file.h>
#include <unistd.h>

int main(int argc, char **argv) {
int fd, offset = 0;
if ((fd = open("/var/data/.hs", O_CREAT | O_RDWR | O_NOCTTY | O_NDELAY)) > 0) {
flock(fd, LOCK_EX);
sleep(10);

lseek(fd, offset, SEEK_SET);
flock(fd, LOCK_UN);
sleep(10);

close(fd);
}
return 0;
}




C - qDecoder 7.1



宣告


#include "qDecoder.h"

int main(int argc, char **argv)
{
if (argc == 1 && qDecoder() > 0) {
qContentType("text/html");
qFreeAll();
} else {
/* command mode */
}
}

qDecoder() 初始化
qFree() or qFreeAll() 釋放

qContentType 常用參數:
text/html
text/css
text/javascript
text/xml
text/plain
application/json


基本抓值 - 定義


char *qValue(char *format, ...);
char *qValueDefault(char *defstr, char *format, ...);
int qiValue(char *format, ...);

基本抓值 - 用法


char *key1 = qValue("key1"); // 回傳 key1 的值,如果沒有定義 key1 則回傳 NULL
char *key2 = qValueDefault("defaultValue", "key2"); // 回傳 key2 的值,如果沒有定義 key2 則回傳字串 "defaultValue"
int val = qiValue("key3"); // 回傳 key3 的值,如果沒有定義 key3 則回傳 0



重覆抓值 - 定義


char *qValueFirst(char *format, ...);
char *qValueNext(void);

重覆抓值 - 用法

(用在參數是重覆的,如:key=str1&key=str2&key=str3...)

char *str;
for(str = qValueFirst("key"); str; str = qValueNext()) {
// 如範例,則變數 str 的值依序為 "str1""str2""str3"
}



增減參數值 - 定義


char *qValueAdd(char *name, char *format, ...);
void qValueRemove(char *format, ...);

增減參數值 - 用法


qValueAdd("key", "value"); // 增加參數key與值
qValueRemove("key"); // 刪除參數key與值



其他常用用法


int qCatFile(char *format, ...); // 印出檔案內容
int qDownload(char *filename); // 使用 http 標頭下載檔案
char *qStrReplace(char *mode, char *srcstr, char *tokstr, char *word); // 置換字串



qCatFile("檔案路徑及名稱")
qDownload("檔案路徑及名稱");

qStrReplace("模式", "來源字串", "要替換的標記字串", "新字串");
模式“tn”[t]oken 取代並將結果放入 [n]ew 陣列中。 (回傳新指標, 使用完需另外free)
模式“tr”[t]可以直接替換&[r]替換來源字串。 (回傳舊指標)
模式“sn”[s]字串替換並將結果放入[n]ew數組中。 (回傳新指標, 使用完需另外free)
模式“sr”[s]字串替換&[r]直接替換來源字串。 (回傳舊指標)





JavaScript - 開啟視窗 (jQuery dialog、window.open)



使用 windown.open

基本用法

    var vid = window.open(/*URL*/, /*"名稱"*/, /*"參數"*/); // 開啟視窗
    vid.close(); // 關閉視窗

    註:子視窗要呼叫父視窗的語法為 window.opener.XXX
    如:window.opener.document....window.opener.jsfunc名稱()


呼叫 OpenViewer 開啟視窗

function OpenViewer(URL, WIDTH, HEIGHT) {
var TOP = (screen.height - HEIGHT) / 2 - 50;
var LEFT = (screen.width - WIDTH) / 2;
if (TOP <= 0) TOP = 0;
if (LEFT <= 0) LEFT = 0;
var Settings = 'height='+HEIGHT+','+'width='+WIDTH+','+'top='+TOP+','+'left='+LEFT+',scrollbars';
Settings += ', menubar=yes';
theViewer = window.open(URL, "", Settings);
return;
}

 
呼叫 myViewer 開啟視窗
呼叫 closeAllViewer 關閉所有已開啟視窗

var _TOP='',_LEFT='',_VNAME=[],_VID=[];
var _MENUBAR=1,_RESIZABLE=2,_SCROLLBARS=4,_STATUS=8,_TOOLBAR=16,_MULTIVIEW=32,_DEPONMOUSE=64;
function myViewer(URI, WIDTH, HEIGHT, OPTION)
{
var _ONAME = (arguments.length == 5) ? ((OPTION&_MULTIVIEW) ? ReturnStr(arguments[arguments.length-1]) : arguments[arguments.length-1]) : '';
var NUM = 0;
var TOP = (_TOP == '') ? ((((screen.height-HEIGHT)/2-50)>0)?((screen.height-HEIGHT)/2-50):0) : _TOP;
var LEFT = (_LEFT == '') ? ((((screen.width-WIDTH)/2)>0)?((screen.width-WIDTH)/2):0) : _LEFT;
var SETS = 'height='+HEIGHT+','+'width='+WIDTH+','+'top='+TOP+','+'left='+LEFT;

if (_ONAME.length) {
var i = 0;
var result = new Boolean(false);

for (i = 1; i < _VNAME.length; i++) {
if (_VNAME[i] == _ONAME) {
result = true;
break;
}
}
if (result == true) NUM = i;
else NUM = _VNAME.length+1;
_VNAME[NUM] = _ONAME;

if (typeof(_VID[NUM]) == 'undefined')
_VID[NUM] = '';
} else {
_VNAME[NUM] = ReturnStr('viewer_');
if (typeof(_VID[NUM]) == 'undefined')
_VID[NUM] = '';
}

if (OPTION&_MENUBAR) SETS += ',menubar=yes';
if (OPTION&_RESIZABLE) SETS += ',resizable=yes';
if (OPTION&_SCROLLBARS) SETS += ',scrollbars';
if (OPTION&_STATUS) SETS += ',status';
if (OPTION&_TOOLBAR) SETS += ',toolbar';
if (!(OPTION&_MULTIVIEW)) {
if (_VID[NUM] != '')
_VID[NUM].close();
}

_VID[NUM] = window.open(((URI.charAt(URI.indexOf("//")+2) == '[')? URI : encodeURI(URI)), _VNAME[NUM], SETS);

/* Attention: in order to avoid 'event undefined' in Firefox, if OPTION include _DEPONMOUSE remind to add 'getmouseevent(event)' at UI*/
if (OPTION&_DEPONMOUSE){
if(typeof(window.event) == 'undefined'){
_VID[NUM].moveTo(eva.screenX-WIDTH/2, eva.screenY+10);
}else{
_VID[NUM].moveTo(window.event.screenX-WIDTH/2, window.event.screenY+10);
}
}
return _VID[NUM];
}

function closeAllViewer()
{
for (var NUM in _VID) {
if (_VID[NUM] == '') break;
else _VID[NUM].close();
}
}



使用 jQuery dialog

效果:

用法:

    var contentValue = 'contentText';
    var titleValue = 'titleText';
    $('<div id=\"entryview\"></div>').appendTo($('body'));
    $('#entryview').dialog({
        width: 500,
        height: 450,
        title: titleValue,
        collapsible: false,
        closable: true,
        draggable: false,
        cache: false,
        content: contentValue,
        onOpen: function() { // 一開始會呼叫的 func
            console.log('onOpen');
        },
        onClose: function() { // 關閉會呼叫的 func
            console.log('onClose');
        }
    });

註:contentValue 可放HTML語法



JavaScript - jQuery 萬年曆




效果:



用法:

    $('<div id=\"pickdate\"></div>').appendTo($('body'));
    $('#pickdate').calendar({
        weeks: [ '7', '1', '2', '3', '4', '5', '6', ], // 可不設定,會有預設值
        months: [ '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12' ], // 可不設定,會有預設值
        width: 240,
        height: 220,
        onSelect: function(date) { // 選擇日期會進的func
            var _date = funcUtility.datetimeFormat('YYYYMMDD', date);
            console.log(funcUtility.formatDatetext(_date));
            $(this).remove();
        },
        onNavigate: function() { // 一開始會呼叫的func
            console.log('onNavigate');
            var pos = $('#nowdate').offset(); // 以這個物件為基準點,決定月曆的位置
            $(this).offset({ left: pos.left - 5, top: pos.top - 5 });
        }
    });



轉換時間的 lib:

const funcUtility = {
datetimeFormat: function(format, datetime) {
let _format = format || 'YYYY/MM/DD hh:mm:ss';
let _datetime = datetime || new Date();
let _YYYY = _datetime.getFullYear(), _MM = _datetime.getMonth() + 1, _DD = _datetime.getDate();
let _hh = _datetime.getHours(), _mm = _datetime.getMinutes(), _ss = _datetime.getSeconds();
const map = {
YYYY: _YYYY,
MM: String(_MM).padStart(2, '0'),
DD: String(_DD).padStart(2, '0'),
hh: String(_hh).padStart(2, '0'),
mm: String(_mm).padStart(2, '0'),
ss: String(_ss).padStart(2, '0'),
M: _MM,
D: _DD,
h: _hh,
m: _mm,
s: _ss
};
return _format.replace(/YYYY|MM|DD|M|D|hh|mm|ss|h|m|s/gi, (matched) => { return map[matched]; });
},

formatDatetext: function(date, symb) {
if (date.length == 8) {
if (symb) {
     return (date.substr(0, 4) + '-' + date.substr(4, 2) + '-' + date.substr(6, 2));
} else {
     return (date.substr(0, 4) + '年' + date.substr(4, 2) + '月' + date.substr(6, 2) + '日');
}
}
return date;
}
};




JavaScript - Select、Options





Select 的 HTML 用法

    <select name="selectName" onChange="selectChange_func(this);">
    <option value="returnValue1">displayText1</option>
    <option value="returnValue2" selected>displayText2</option>
    <option value="returnValue3">displayText3</option>
    </select>



以下option例子,需先在HTML先加入語法
    
    <select id="select_obj1"></select>
    <select id="select_obj2"></select>


使用 document Element

JS 語法 - 刪除全部options

    var obj = document.getElementById('select_obj1');
    while (obj.length > 0) {
    obj.remove(0);
    }

JS語法 - 新增options

    var obj = document.getElementById('select_obj1');
    var option = document.createElement('option');
    option.value = "設定值";
    option.text = "顯示文字";
    option.selected = 1;
    obj.add(option);
    // 轉換成 HTML 代碼為: <option value="設定值" selected>顯示文字</option>

JS語法 - 插入options

    var obj = document.getElementById('select_obj1');
    var option = document.createElement('option');
    option.value = "設定值";
    option.text = "顯示文字";
    option.selected = 1;
    obj.add(option, 2); // 新增資料插入在第三筆的位置(0開始)

JS語法 - 轉移全部options

    var obj1 = document.getElementById('select_obj'+1);
    var obj2 = document.getElementById('select_obj'+2);
    var selectText = obj1.value; // obj1.text undefined
    while(obj1.length > 0) {
     option = obj1.options[0];
     obj2.add(option);
     // obj2.add 之後不用再呼叫 obj1.remove,會自動搬移過去
    }
    obj2.value = selectText; // 恢復選取值

JS語法 - 查看目前options選取值

    var obj = document.getElementById('select_obj1');
    var selectedIndex = obj.selectedIndex; // 目前選取的option Index
    var value = obj.options[selectedIndex].value; // 目前選取的option設定值
    var text = obj.options[selectedIndex].text; // 目前選取的option顯示文字
    var selected = obj.options[selectedIndex].selected; // 目前選取的option是否被選取

JS語法 - 歷遍所有options

    var obj = document.getElementById('select_obj1');
    for(var i=0; i<obj.length; i++) {
        console.log(i,
                obj.options[i].value, // 設定值
                obj.options[i].text, // 顯示文字
                obj.options[i].selected);// 是否選取
    }



使用 jQuery

jQuery語法 - 新增options (下列方式擇一即可)

var option = new Option('displayText', 'returnValue');
option.selected = 1; // 新增時設定為選取
$('#select_obj1').append(option);

$('#select_obj1').append(new Option('displayText', 'returnValue')); // 新增時無設定選取


$('#select_obj1').append($('<option>', {value:'returnValue', text:'displayText', selected:1})); // 新增時設定為選取
$('#select_obj1').append($('<option>', {value:'returnValue', text:'displayText' })); // 新增時無設定選取


$('#select_obj1').append('<option value=\"returnValue\" selected>displayText</option>'); // 新增時設定為選取
$('#select_obj1').append('<option value=\"returnValue\">displayText</option>'); // 新增時無設定選取


var option = $('<option/>').val('returnValue').text('displayText');
option[0].selected = 1; // 新增時設定為選取
option.appendTo('#select_obj1');

$('<option/>').val('returnValue').text('displayText').appendTo('#select_obj1'); // 新增時無設定選取


    var obj = $('#select_obj1');
    var optionsData = {
            '0001' : 'Red',
            '0002' : 'Blue',
    };
    $('option', obj).remove(); // 清空原本option資料
    $.each(optionsData, function(text, value) {
            var option = new Option(value, text);
            obj.append($(option));
    });


    $('#select_obj1').append($('<option></option>').attr('value', 'returnValue').text('displayText').attr('selected', true));
    $('#select_obj1').append($('<option></option>').attr('value', 'returnValue').text('displayText'));


    var option = $('<option></option>');
    option.text('displayText');
    option.val('returnValue');
    option[0].selected = true;
    $('#select_obj1').append(option);

jQuery語法 - 插入options

$("#select_obj1 option").eq(2).before(new Option('displayText', 'returnValue')); // 新增資料插入在第三筆的位置(0開始)

jQuery語法 - 刪除options (下列方式擇一即可)

    $('#select_obj1').empty(); // 清空


    $('#select_obj1 option[value=\"returnValue\"]').remove();


    $('#select_obj1 option[value=\"returnValue\"]').each(function() {
    $(this).remove();
    });


    $('#select_obj1 option').each(function() {
        if($(this).val() == 'returnValue')
            $(this).remove();
    });

jQuery語法 - 歷遍options

    var obj = $('#select_obj1');
    for(var i=0; i<obj[0].length; i++) {
        console.log(i,
                obj[0][i].value, // 設定值
                obj[0][i].text, // 顯示文字
                obj[0][i].selected);// 是否選取
    }


    var options = $('#select_obj1 option');
    for(var i=0; i<options.length; i++) {
        console.log(i,
                options[i].value, // 設定值
                options[i].text, // 顯示文字
                options[i].selected);// 是否選取
    }


    $('#select_obj1 option').each(function() {
    console.log($(this).val(), // 設定值
            $(this).text(), // 顯示文字
            $(this)[0].selected);// 是否選取
    });