檢視原始碼 ei
處理 Erlang 二進位格式的常式。
描述
函式庫 ei
包含巨集和函數,用於編碼和解碼 Erlang 二進位格式。
ei
允許您將原子(atoms)、列表(lists)、數字(numbers)和二進位資料(binaries)轉換為二進位格式,反之亦然。這在編寫 Port 程式和驅動程式時非常有用。ei
使用給定的緩衝區,不使用動態記憶體(除了 ei_decode_fun()
),而且通常速度很快。
ei
也處理 C 節點(C-nodes),即使用 Erlang 分散式格式與 Erlang 節點(或其他 C 節點)通訊的 C 程式。ei
函式庫是執行緒安全的,並且使用執行緒,一個程序可以處理多個 C 節點。
解碼和編碼函數使用緩衝區和緩衝區中的索引,索引指向編碼和解碼的位置。索引會更新,指向已編碼/解碼的詞項之後。不會檢查詞項是否適合緩衝區。如果編碼超出緩衝區,程式可能會崩潰。
所有函數都接受兩個參數
buf
是指向二進位資料所在的緩衝區的指標。index
是指向緩衝區中索引的指標。此參數會遞增,增加已解碼/編碼的詞項的大小。
因此,當呼叫 ei
函數時,資料位於 buf[*index]
。
所有編碼函數都假設 buf
和 index
參數指向一個足夠大的緩衝區,足以容納資料。請注意,二進位格式使用可變長度編碼,因此不同的值可能需要不同的空間量。例如,較小的整數值可能比大的整數值更緊湊。若要取得編碼詞項的大小,而不實際編碼它,請傳遞 NULL
而不是緩衝區指標。參數 index
會遞增,但不會編碼任何內容。這是 ei
中「預先驗證」詞項編碼的方法。
還有一些編碼函數使用動態緩衝區。通常使用這些函數來編碼資料更方便。所有編碼函數都有兩個版本;以 ei_x_
開頭的函數使用 ei_x_buff
類型的動態緩衝區。
如果成功,所有函數都會傳回 0
,否則傳回 -1
(例如,如果詞項不是預期的類型,或者要解碼的資料是無效的 Erlang 詞項)。
某些解碼函數需要預先配置的緩衝區。此緩衝區必須配置得足夠大,並且對於非複合類型,ei_get_type()
函數會傳回所需的大小(請注意,對於字串,需要額外一個位元組來表示 NULL
終止符)。
資料類型
ei_term
typedef struct { char ei_type; int arity; int size; union { long i_val; double d_val; char atom_name[MAXATOMLEN_UTF8]; erlang_pid pid; erlang_port port; erlang_ref ref; } value; } ei_term;
ei_decode_ei_term()
寫入的結構。ei_type
欄位是詞項的類型,等於ei_get_type()
設定*type
的值。ei_x_buff
- 動態調整大小的緩衝區。它是一個struct
,其中有兩個使用者感興趣的欄位char *buff
- 指向動態配置緩衝區的指標。int index
- 下一個要寫入的位元組的位移量,也等於目前已寫入的位元組數。
ei_x_buff
會透過呼叫ei_x_new()
或ei_x_new_with_version()
來初始化。已初始化的ei_x_buff
所使用的記憶體會透過呼叫ei_x_free()
來釋放。erlang_char_encoding
typedef enum { ERLANG_ASCII = 1, ERLANG_LATIN1 = 2, ERLANG_UTF8 = 4 } erlang_char_encoding;
用於原子的字元編碼。
ERLANG_ASCII
代表 7 位元的 ASCII。Latin-1 和 UTF-8 是 7 位元 ASCII 的不同延伸。所有 7 位元 ASCII 字元都是有效的 Latin-1 和 UTF-8 字元。ASCII 和 Latin-1 都用一個位元組表示每個字元。UTF-8 字元可以由 1 到 4 個位元組組成。請注意,這些常數是位元旗標,可以使用位元 OR 來組合。erlang_fun
- 代表 Erlang 函式的 不透明資料類型。erlang_pid
- 代表 Erlang 程序識別碼的不透明資料類型。erlang_port
- 代表 Erlang Port 識別碼的不透明資料類型。erlang_ref
- 代表 Erlang 參考的不透明資料類型。erlang_trace
- 代表 Erlang 循序追蹤權杖的不透明資料類型。
ei_cmp_pids()
int ei_cmp_pids(erlang_pid *a, erlang_pid *b);
比較兩個程序識別碼。比較方式與 Erlang 相同。
如果 a
和 b
相等,則傳回 0
。如果 a
比 b
小,則傳回小於 0
的值。如果 a
比 b
大,則傳回大於 0
的值。
自 OTP 23.0 起可用
ei_cmp_ports()
int ei_cmp_ports(erlang_port *a, erlang_port *b);
比較兩個 Port 識別碼。比較方式與 Erlang 相同。
如果 a
和 b
相等,則傳回 0
。如果 a
比 b
小,則傳回小於 0
的值。如果 a
比 b
大,則傳回大於 0
的值。
自 OTP 23.0 起可用
ei_cmp_refs()
int ei_cmp_refs(erlang_ref *a, erlang_ref *b);
比較兩個參考。比較方式與 Erlang 相同。
如果 a
和 b
相等,則傳回 0
。如果 a
比 b
小,則傳回小於 0
的值。如果 a
比 b
大,則傳回大於 0
的值。
自 OTP 23.0 起可用
ei_decode_atom()
int ei_decode_atom(const char *buf, int *index, char *p);
從二進位格式解碼原子。原子的 NULL
終止名稱會放置在 p
。緩衝區中最多可以放置 MAXATOMLEN
個位元組。
ei_decode_atom_as()
int ei_decode_atom_as(const char *buf, int *index, char *p, int plen,
erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result);
從二進位格式解碼原子。原子的 NULL
終止名稱會放置在 p
位置的緩衝區中,長度為 plen
個位元組。
想要的字串編碼由 want
指定。二進位格式中使用的原始編碼(Latin-1 或 UTF-8)可以從 *was
取得。結果字串的編碼(7 位元 ASCII、Latin-1 或 UTF-8)可以從 *result
取得。was
和 result
都可以是 NULL
。如果 want
是一個位元 OR 組合(例如 ERLANG_LATIN1|ERLANG_UTF8
),或者如果 *result
變成純 7 位元 ASCII(與 Latin-1 和 UTF-8 相容),則 *result
可能與 want
不同。
如果原子對於緩衝區而言太長,或者無法用編碼 want
表示,此函數將會失敗。
此函數在 Erlang/OTP R16 中引入,作為支援 UTF-8 原子的第一步。
自 OTP R16B 起可用
ei_decode_bignum()
int ei_decode_bignum(const char *buf, int *index, mpz_t obj);
將二進位格式中的整數解碼為 GMP mpz_t
整數。若要使用此函數,ei
函式庫必須經過設定和編譯,才能使用 GMP 函式庫。
ei_decode_binary()
int ei_decode_binary(const char *buf, int *index, void *p, long *len);
從二進位格式解碼二進位資料。參數 len
會設定為二進位資料的實際大小。請注意,ei_decode_binary()
假設有足夠的空間來容納二進位資料。所需的大小可以透過 ei_get_type()
取得。
ei_decode_bitstring()
int ei_decode_bitstring(const char *buf, int *index, const char **pp,
unsigned int *bitoffsp, size_t *nbitsp);
從二進位格式解碼位元字串。
pp
- 要麼是NULL
,要麼是*pp
會傳回指向位元字串第一個位元組的指標。只要buf
指向的緩衝區是可讀取的,並且未被寫入,傳回的位元字串就是可讀取的。bitoffsp
- 要麼是NULL
,要麼是*bitoffsp
會傳回*pp
指向的第一個位元組中未使用的位元數。*bitoffsp
的值介於 0 到 7 之間。第一個位元組中未使用的位元是最高有效位元。nbitsp
- 要麼是NULL
,要麼是*nbitsp
會傳回位元字串的長度,以位元為單位。
如果它是位元字串詞項,則傳回 0
。
*pp
指向的位元組數(屬於位元字串的一部分)是 (*bitoffsp + *nbitsp + 7)/8
。如果 (*bitoffsp + *bitsp)%8 > 0
,則只使用最後一個位元組的 (*bitoffsp + *bitsp)%8
個位元。最後一個位元組中未使用的位元是最低有效位元。
第一個和最後一個位元組中未使用的位元的值是未定義的,無法依賴。
位元數可能可以被 8 整除,這表示可被 ei_decode_binary
解碼的二進位資料,也能被 ei_decode_bitstring
解碼。
自 OTP 22.0 開始提供
ei_decode_boolean()
int ei_decode_boolean(const char *buf, int *index, int *p);
從二進位格式解碼布林值。布林值實際上是一個原子,true
解碼為 1,false
解碼為 0。
ei_decode_char()
int ei_decode_char(const char *buf, int *index, char *p);
從二進位格式解碼一個介於 0-255 之間的字元 (8 位元) 整數。由於歷史因素,返回的整數類型為 char
。 即使 C 編譯器和系統可能將 char
定義為有號,您的 C 程式碼仍應將返回的值視為 unsigned char
類型。
ei_decode_double()
int ei_decode_double(const char *buf, int *index, double *p);
從二進位格式解碼一個雙精度 (64 位元) 浮點數。
ei_decode_ei_term()
int ei_decode_ei_term(const char* buf, int* index, ei_term* term);
解碼任何 term,或至少嘗試解碼。如果 buf
中由 *index
指向的 term 符合 term
聯合,則會進行解碼,並設定 term->value
中的相應欄位,並且 *index
會遞增 term 的大小。
如果成功解碼,此函數會返回 1
;如果發生錯誤,則返回 -1
;如果 term 看起來沒問題,但無法放入 term
結構,則返回 0
。如果返回 1
,則 index
會遞增,並且 term
會包含解碼後的 term。
term
結構包含 tuple 或 list 的 arity、binary、string 或 atom 的大小。如果 term 是以下任何一種,則它會包含 term:整數、浮點數、atom、pid、port 或 ref。
ei_decode_fun()
free_fun()
int ei_decode_fun(const char *buf, int *index, erlang_fun *p);
void free_fun(erlang_fun* f);
從二進位格式解碼一個 fun。參數 p
應該為 NULL
或指向 erlang_fun
結構。這是唯一會配置記憶體的解碼函數。當不再需要 erlang_fun
時,應該使用 free_fun
釋放它。(這與 fun 的環境的任意大小有關。)
ei_decode_iodata()
int ei_decode_iodata(const char *buf, int *index, int *size, char *outbuf);
解碼類型為 iodata()
的 term。iodata/0
term 會被扁平化並寫入由 outbuf
參數指向的緩衝區。 iodata
的位元組大小會寫入由 size
參數指向的整數變數。size
和 outbuf
都可以設為 NULL
。無論 size
和 outbuf
參數的狀態如何,由 index
參數指向的整數都會更新為參考 iodata/0
term 之後的 term。
請注意,如果傳遞非 NULL
值作為 outbuf
,則由 outbuf
參數指向的緩衝區必須夠大。您通常會想要呼叫 ei_decode_iodata()
兩次。第一次使用非 NULL
的 size
參數和 NULL
的 outbuf
參數,以確定所需的緩衝區大小,然後再次呼叫以進行實際解碼。請注意,由 index
指向的整數也會由確定大小的呼叫更新,因此您需要在第二次呼叫進行實際解碼之前重設它。
成功時返回 0
,失敗時返回 -1
。失敗的原因可能是由於 term 的編碼無效,或者由於 term 的類型不是 iodata/0
。失敗時,由 index
參數指向的整數會更新為參考偵測到失敗的子 term。
自 OTP 23.0 起可用
ei_decode_list_header()
int ei_decode_list_header(const char *buf, int *index, int *arity);
從二進位格式解碼一個 list header。元素數量會返回在 arity
中。 arity+1
個元素會接續在後 (最後一個是 list 的尾部,通常是一個空 list)。如果 arity
為 0
,則為空 list。
請注意,如果 list 完全由 0..255 範圍內的整數組成,則會將 list 編碼為 string。 此函數不會解碼此類 string,請改用 ei_decode_string()
。
ei_decode_long()
int ei_decode_long(const char *buf, int *index, long *p);
從二進位格式解碼一個長整數。如果程式碼是 64 位元,則函數 ei_decode_long()
與 ei_decode_longlong()
相同。
ei_decode_longlong()
int ei_decode_longlong(const char *buf, int *index, long long *p);
從二進位格式解碼一個 GCC long long
或 Visual C++ __int64
(64 位元) 整數。
ei_decode_map_header()
int ei_decode_map_header(const char *buf, int *index, int *arity);
從二進位格式解碼一個 map header。鍵值對的數量會返回在 *arity
中。鍵和值會按此順序接續在後:K1, V1, K2, V2, ..., Kn, Vn
。這總共是 arity*2
個 term。如果 arity
為零,則為空 map。正確編碼的 map 沒有重複的鍵。
自 OTP 17.0 開始提供
ei_decode_pid()
int ei_decode_pid(const char *buf, int *index, erlang_pid *p);
從二進位格式解碼一個程序識別碼 (pid)。
ei_decode_port()
int ei_decode_port(const char *buf, int *index, erlang_port *p);
從二進位格式解碼一個 port 識別碼。
ei_decode_ref()
int ei_decode_ref(const char *buf, int *index, erlang_ref *p);
從二進位格式解碼一個參考。
ei_decode_string()
int ei_decode_string(const char *buf, int *index, char *p);
從二進位格式解碼一個 string。Erlang 中的 string 是介於 0 和 255 之間的整數 list。請注意,由於 string 只是 list,有時 list 會被 term_to_binary/1
編碼為 string,即使它不是預期的結果。
此 string 會被複製到 p
,並且必須配置足夠的空間。返回的 string 會以 NULL
結尾,因此您必須在記憶體需求中加入一個額外的位元組。
ei_decode_trace()
int ei_decode_trace(const char *buf, int *index, erlang_trace *p);
從二進位格式解碼一個 Erlang 追蹤 token。
ei_decode_tuple_header()
int ei_decode_tuple_header(const char *buf, int *index, int *arity);
解碼一個 tuple header,元素數量會返回在 arity
中。tuple 元素會按順序接續在緩衝區中。
ei_decode_ulong()
int ei_decode_ulong(const char *buf, int *index, unsigned long *p);
從二進位格式解碼一個無號長整數。如果程式碼是 64 位元,則函數 ei_decode_ulong()
與 ei_decode_ulonglong()
相同。
ei_decode_ulonglong()
int ei_decode_ulonglong(const char *buf, int *index, unsigned long long *p);
從二進位格式解碼一個 GCC unsigned long long
或 Visual C++ unsigned __int64
(64 位元) 整數。
ei_decode_version()
int ei_decode_version(const char *buf, int *index, int *version);
解碼 Erlang 二進位 term 格式的版本魔術數字。它必須是二進位 term 中的第一個 token。
ei_encode_atom()
ei_encode_atom_len()
ei_x_encode_atom()
ei_x_encode_atom_len()
int ei_encode_atom(char *buf, int *index, const char *p);
int ei_encode_atom_len(char *buf, int *index, const char *p, int len);
int ei_x_encode_atom(ei_x_buff* x, const char *p);
int ei_x_encode_atom_len(ei_x_buff* x, const char *p, int len);
以二進位格式編碼一個 atom。參數 p
是以 Latin-1 編碼的 atom 名稱。最多只能編碼 MAXATOMLEN-1
個位元組。除了 ei_x_encode_atom_len()
函數之外,名稱應該以 NULL
結尾。
ei_encode_atom_as()
自 OTP R16B 起可用
ei_encode_atom_len_as()
自 OTP R16B 起可用
ei_x_encode_atom_as()
自 OTP R16B 起可用
ei_x_encode_atom_len_as()
int ei_encode_atom_as(char *buf, int *index, const char *p,
erlang_char_encoding from_enc, erlang_char_encoding to_enc);
int ei_encode_atom_len_as(char *buf, int *index, const char *p, int len,
erlang_char_encoding from_enc, erlang_char_encoding to_enc);
int ei_x_encode_atom_as(ei_x_buff* x, const char *p,
erlang_char_encoding from_enc, erlang_char_encoding to_enc);
int ei_x_encode_atom_len_as(ei_x_buff* x, const char *p, int len,
erlang_char_encoding from_enc, erlang_char_encoding to_enc);
以二進位格式編碼一個 atom。參數 p
是具有字元編碼 from_enc
(ASCII、Latin-1 或 UTF-8) 的 atom 名稱。名稱必須以 NULL
結尾,或者必須使用具有 len
參數的函數變體。
如果 p
不是編碼 from_enc
中的有效 string,則編碼會失敗。
引數 to_enc
會被忽略。從 Erlang/OTP 20 開始,編碼始終以 UTF-8 完成,Erlang/OTP R16 或更舊版本節點也可以讀取。
自 OTP R16B 起可用
ei_encode_bignum()
ei_x_encode_bignum()
int ei_encode_bignum(char *buf, int *index, mpz_t obj);
int ei_x_encode_bignum(ei_x_buff *x, mpz_t obj);
將 GMP mpz_t
整數編碼為二進位格式。若要使用此函數,必須設定並編譯 ei
函式庫以使用 GMP 函式庫。
ei_encode_binary()
ei_x_encode_binary()
int ei_encode_binary(char *buf, int *index, const void *p, long len);
int ei_x_encode_binary(ei_x_buff* x, const void *p, long len);
以二進制格式編碼二進制數據。資料位於 p
,長度為 len
個位元組。
ei_encode_bitstring()
自 OTP 22.0 開始提供
ei_x_encode_bitstring()
int ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t nbits);
int ei_x_encode_bitstring(ei_x_buff* x, const char *p, size_t bitoffs, size_t nbits);
以二進制格式編碼位元字串。
資料位於 p
。位元字串的長度為 nbits
位元。位於 p
的資料的前 bitoffs
位元未使用。屬於位元字串的第一個位元組為 p[bitoffs/8]
。第一個位元組 p[bitoffs/8]
中最重要的 bitoffs%8
位元未使用。
屬於位元字串的位元組數為 (bitoffs + nbits + 7)/8
。如果 (bitoffs + nbits)%8 > 0
,則只使用最後一個位元組的 (bitoffs + nbits)%8
位元。最後一個位元組中未使用的位元為最不重要的位元。
未使用的位元值將被忽略,不需要清除。
自 OTP 22.0 開始提供
ei_encode_boolean()
ei_x_encode_boolean()
int ei_encode_boolean(char *buf, int *index, int p);
int ei_x_encode_boolean(ei_x_buff* x, int p);
如果 p
不為零,則將布林值編碼為原子 true
,如果 p
為零,則編碼為 false
。
ei_encode_char()
ei_x_encode_char()
int ei_encode_char(char *buf, int *index, char p);
int ei_x_encode_char(ei_x_buff* x, char p);
將字元 (8 位元) 編碼為二進制格式中介於 0-255 之間的整數。由於歷史原因,整數參數的類型為 char
。您的 C 程式碼應將指定的參數視為 unsigned char
類型,即使 C 編譯器和系統可能將 char
定義為有號。
ei_encode_double()
ei_x_encode_double()
int ei_encode_double(char *buf, int *index, double p);
int ei_x_encode_double(ei_x_buff* x, double p);
以二進制格式編碼雙精度 (64 位元) 浮點數。
如果浮點數不是有限值,則傳回 -1
。
ei_encode_empty_list()
ei_x_encode_empty_list()
int ei_encode_empty_list(char* buf, int* index);
int ei_x_encode_empty_list(ei_x_buff* x);
編碼一個空列表。它通常用在列表的尾部。
ei_encode_fun()
ei_x_encode_fun()
int ei_encode_fun(char *buf, int *index, const erlang_fun *p);
int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun);
以二進制格式編碼一個 fun。參數 p
指向一個 erlang_fun
結構。erlang_fun
不會自動釋放,如果編碼後不需要該 fun,則應呼叫 free_fun
。
ei_encode_list_header()
ei_x_encode_list_header()
int ei_encode_list_header(char *buf, int *index, int arity);
int ei_x_encode_list_header(ei_x_buff* x, int arity);
編碼一個具有指定元數的列表標頭。下一個 arity+1
個項是元素(實際上是它的 arity
個 cons 儲存格)和列表的尾部。列表和元組是遞迴編碼的,因此列表可以包含另一個列表或元組。
例如,要編碼列表 [c, d, [e | f]]
ei_encode_list_header(buf, &i, 3);
ei_encode_atom(buf, &i, "c");
ei_encode_atom(buf, &i, "d");
ei_encode_list_header(buf, &i, 1);
ei_encode_atom(buf, &i, "e");
ei_encode_atom(buf, &i, "f");
ei_encode_empty_list(buf, &i);
注意
似乎沒有辦法在事先不知道元素數目的情況下建立列表。但實際上是有辦法的。請注意,列表
[a, b, c]
可以寫為[a | [b | [c]]]
。使用這種方式,列表可以寫為 cons。
要編碼一個列表,而事先不知道它的元數
while (something()) {
ei_x_encode_list_header(&x, 1);
ei_x_encode_ulong(&x, i); /* just an example */
}
ei_x_encode_empty_list(&x);
ei_encode_long()
ei_x_encode_long()
int ei_encode_long(char *buf, int *index, long p);
int ei_x_encode_long(ei_x_buff* x, long p);
以二進制格式編碼一個長整數。如果程式碼為 64 位元,則函式 ei_encode_long()
與 ei_encode_longlong()
相同。
ei_encode_longlong()
ei_x_encode_longlong()
int ei_encode_longlong(char *buf, int *index, long long p);
int ei_x_encode_longlong(ei_x_buff* x, long long p);
以二進制格式編碼一個 GCC long long
或 Visual C++ __int64
(64 位元) 整數。
ei_encode_map_header()
自 OTP 17.0 開始提供
ei_x_encode_map_header()
int ei_encode_map_header(char *buf, int *index, int arity);
int ei_x_encode_map_header(ei_x_buff* x, int arity);
編碼一個具有指定元數的映射標頭。接下來編碼的 arity*2
個項將是映射的鍵和值,順序如下:K1, V1, K2, V2, ..., Kn, Vn
。
例如,要編碼映射 #{a => "Apple", b => "Banana"}
ei_x_encode_map_header(&x, 2);
ei_x_encode_atom(&x, "a");
ei_x_encode_string(&x, "Apple");
ei_x_encode_atom(&x, "b");
ei_x_encode_string(&x, "Banana");
正確編碼的映射不能有重複的鍵。
自 OTP 17.0 開始提供
ei_encode_pid()
ei_x_encode_pid()
int ei_encode_pid(char *buf, int *index, const erlang_pid *p);
int ei_x_encode_pid(ei_x_buff* x, const erlang_pid *p);
以二進制格式編碼一個 Erlang 處理程序識別碼 (pid)。參數 p
指向一個 erlang_pid
結構,該結構應事先透過 ei_decode_pid()
、ei_self()
取得,或透過 ei_make_pid()
建立。
ei_encode_port()
ei_x_encode_port()
int ei_encode_port(char *buf, int *index, const erlang_port *p);
int ei_x_encode_port(ei_x_buff* x, const erlang_port *p);
以二進制格式編碼一個 Erlang 連接埠。參數 p
指向一個 erlang_port
結構,該結構應事先透過 ei_decode_port()
取得。
ei_encode_ref()
ei_x_encode_ref()
int ei_encode_ref(char *buf, int *index, const erlang_ref *p);
int ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p);
以二進制格式編碼一個 Erlang 參考。參數 p
指向一個 erlang_ref
結構,該結構應事先透過 ei_decode_ref()
取得,或透過 ei_make_ref()
建立。
ei_encode_string()
ei_encode_string_len()
ei_x_encode_string()
ei_x_encode_string_len()
int ei_encode_string(char *buf, int *index, const char *p);
int ei_encode_string_len(char *buf, int *index, const char *p, int len);
int ei_x_encode_string(ei_x_buff* x, const char *p);
int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len);
以二進制格式編碼一個字串。(Erlang 中的字串是一個列表,但在二進制格式中編碼為字元陣列。)除了 ei_x_encode_string_len()
函式之外,該字串應以 NULL
結尾。
ei_encode_trace()
ei_x_encode_trace()
int ei_encode_trace(char *buf, int *index, const erlang_trace *p);
int ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p);
以二進制格式編碼一個 Erlang 追蹤令牌。參數 p
指向一個 erlang_trace
結構,該結構應事先透過 ei_decode_trace()
取得。
ei_encode_tuple_header()
ei_x_encode_tuple_header()
int ei_encode_tuple_header(char *buf, int *index, int arity);
int ei_x_encode_tuple_header(ei_x_buff* x, int arity);
編碼一個具有指定元數的元組標頭。接下來編碼的 arity
個項將是元組的元素。元組和列表是遞迴編碼的,因此元組可以包含另一個元組或列表。
例如,要編碼元組 {a, {b, {}}}
ei_encode_tuple_header(buf, &i, 2);
ei_encode_atom(buf, &i, "a");
ei_encode_tuple_header(buf, &i, 2);
ei_encode_atom(buf, &i, "b");
ei_encode_tuple_header(buf, &i, 0);
ei_encode_ulong()
ei_x_encode_ulong()
int ei_encode_ulong(char *buf, int *index, unsigned long p);
int ei_x_encode_ulong(ei_x_buff* x, unsigned long p);
以二進制格式編碼一個無號長整數。如果程式碼為 64 位元,則函式 ei_encode_ulong()
與 ei_encode_ulonglong()
相同。
ei_encode_ulonglong()
ei_x_encode_ulonglong()
int ei_encode_ulonglong(char *buf, int *index, unsigned long long p);
int ei_x_encode_ulonglong(ei_x_buff* x, unsigned long long p);
以二進制格式編碼一個 GCC unsigned long long
或 Visual C++ unsigned __int64
(64 位元) 整數。
ei_encode_version()
ei_x_encode_version()
int ei_encode_version(char *buf, int *index);
int ei_x_encode_version(ei_x_buff* x);
為二進制格式編碼一個版本魔術數字。必須是二進制項中的第一個令牌。
ei_get_type()
int ei_get_type(const char *buf, const int *index, int *type, int *size);
傳回編碼項的 *type
中的類型和 *size
中的大小。對於字串和原子,大小是不包括終止符 NULL
的字元數。對於二進制和位元字串,*size
是位元組數。對於列表、元組和映射,*size
是物件的元數。對於大數整數,*size
是大數絕對值的位元組數。對於其他類型,*size
為 0。在所有情況下,index
都保持不變。
目前,*type
是下列之一
ERL_ATOM_EXT - 使用
ei_decode_atom()
、ei_decode_atom_as()
或ei_decode_boolean()
進行解碼。ERL_BINARY_EXT - 使用
ei_decode_binary()
、ei_decode_bitstring()
或ei_decode_iodata()
進行解碼。ERL_BIT_BINARY_EXT - 使用
ei_decode_bitstring()
進行解碼。ERL_FLOAT_EXT - 使用
ei_decode_double()
進行解碼。ERL_NEW_FUN_EXT, ERL_FUN_EXT, ERL_EXPORT_EXT - 使用
ei_decode_fun()
進行解碼。ERL_SMALL_INTEGER_EXT、ERL_INTEGER_EXT、ERL_SMALL_BIG_EXT、ERL_LARGE_BIG_EXT - 使用
ei_decode_char()
、ei_decode_long()
、ei_decode_longlong()
、ei_decode_ulong()
、ei_decode_ulonglong()
或ei_decode_bignum()
進行解碼。ERL_LIST_EXT、ERL_NIL_EXT - 使用
ei_decode_list_header()
或ei_decode_iodata()
進行解碼。ERL_STRING_EXT - 使用
ei_decode_string()
或ei_decode_iodata()
進行解碼。ERL_MAP_EXT - 使用
ei_decode_map_header()
進行解碼。ERL_PID_EXT - 使用
ei_decode_pid()
進行解碼。ERL_PORT_EXT - 使用
ei_decode_port()
進行解碼。ERL_NEW_REFERENCE_EXT - 使用
ei_decode_ref()
進行解碼。ERL_SMALL_TUPLE_EXT、ERL_LARGE_TUPLE_EXT
使用ei_decode_tuple_header()
進行解碼。
如果您對資料不感興趣,也可以使用 ei_skip_term()
跳過一個項。
ei_init()
int ei_init(void);
初始化 ei
函式庫。在呼叫 ei
函式庫中的任何其他功能之前,應呼叫此函式一次 (且僅限一次)。
成功時返回零。失敗時返回 posix 錯誤碼。
自 OTP 21.3 起可用
ei_print_term()
ei_s_print_term()
int ei_print_term(FILE* fp, const char* buf, int* index);
int ei_s_print_term(char** s, const char* buf, int* index);
以明文形式將項印到 fp
指定的檔案,或 s
指向的緩衝區。它試圖模仿 Erlang shell 中的項列印。
在 ei_s_print_term()
中,參數 s
指向動態 (malloc) 配置的 BUFSIZ
位元組字串,或 NULL
指標。如果結果超過 BUFSIZ
個字元,此函式可以重新配置字串 (並更新 *s
)。傳回的字串以 NULL
結尾。
傳回值是寫入檔案或字串的字元數,如果 buf[index]
不包含有效項,則傳回 -1
。遺憾的是,不會檢查 fp
上的 I/O 錯誤。
參數 index
會被更新,也就是說,此函式可以被視為一個解碼函式,將項解碼為人類可讀的格式。
ei_set_compat_rel()
void ei_set_compat_rel(unsigned release_number);
一般而言,ei
函式庫保證與比 ei
函式庫本身舊或新 2 個主要版本的其他 Erlang/OTP 元件相容。
有時必須例外上述規則,以使新功能 (甚至錯誤修復) 成為可能。呼叫 ei_set_compat_rel(release_number)
會將 ei
函式庫設定為 OTP 版本 release_number
的相容模式。
目前 release_number
的唯一有用值是 21
。如果從連線節點接收到位元字串或匯出函式,這將非常有用並產生影響。在 OTP 22 之前,ei
不支援位元字串和匯出函式。相反地,當從模擬器傳送到 ei
時,它們會使用未公開的後備元組格式進行編碼。
位元字串
- 項<<42, 1:1>>
編碼為{<<42, 128>>, 1}
。元組的第一個元素是二進位,第二個元素表示最後一個位元組的多少位是位元字串的一部分。在此範例中,只有最後一個位元組 (128) 的最高有效位是位元字串的一部分。匯出函式
- 項fun lists:map/2
編碼為{lists,map}
。一個包含模組、函式和缺少引數的元組。
如果未呼叫 ei_set_compat_rel(21)
,則連線的模擬器會正確編碼傳送位元字串和匯出函式。必須使用函式 ei_decode_bitstring
和 ei_decode_fun
來解碼這類項。呼叫 ei_set_compat_rel(21)
應僅作為一種變通方法,以保持舊有的實作方式繼續運作,這種實作方式預期接收位元字串和/或匯出函式的未公開元組格式。
注意
如果呼叫此函式,則只能呼叫一次,且必須在呼叫
ei
函式庫中的任何其他函式之前呼叫。
ei_skip_term()
int ei_skip_term(const char* buf, int* index);
跳過指定緩衝區中的一個項;遞迴地跳過清單和元組的元素,以便跳過完整的項。這是一種取得 Erlang 項大小的方法。
buf
是緩衝區。
index
會更新為指向緩衝區中該項的後面。
注意
當您想要保存任意項時,這很有用:跳過它們並將二進位項資料複製到某些緩衝區。
成功時返回 0
,否則返回 -1
。
ei_x_append()
ei_x_append_buf()
int ei_x_append(ei_x_buff* x, const ei_x_buff* x2);
int ei_x_append_buf(ei_x_buff* x, const char* buf, int len);
將資料附加到緩衝區 x
的末端。
ei_x_format()
ei_x_format_wo_ver()
int ei_x_format(ei_x_buff* x, const char* fmt, ...);
int ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ... );
將以字串形式提供的項格式化到緩衝區。作用類似於 Erlang 項的 sprintf。fmt
包含格式字串,其中包含 ~d
之類的參數,以插入來自變數的項。支援以下格式 (並提供 C 類型)
~a An atom, char*
~c A character, char
~s A string, char*
~i An integer, int
~l A long integer, long int
~u A unsigned long integer, unsigned long int
~f A float, float
~d A double float, double float
~p An Erlang pid, erlang_pid*
例如,若要編碼一個包含某些內容的元組
ei_x_format("{~a,~i,~d}", "numbers", 12, 3.14159)
encodes the tuple {numbers,12,3.14159}
ei_x_format_wo_ver()
格式化到緩衝區,而不包含初始版本位元組。
變更
自 OTP 26.2 起,可以使用類似
"#{k1 => v1, k2 => v2}"
的語法來編碼對應。
ei_x_free()
int ei_x_free(ei_x_buff* x);
釋放 x
所參照的緩衝區的動態配置內容。釋放後,buff
欄位會設定為 NULL
。
ei_x_new()
ei_x_new_with_version()
int ei_x_new(ei_x_buff* x);
int ei_x_new_with_version(ei_x_buff* x);
初始化 x
所參照的動態可實現緩衝區。填入參數 x
指向的結構的欄位,並配置預設緩衝區。ei_x_new_with_version()
還會放入初始版本位元組,該位元組在二進位格式中使用 (因此不需要 ei_x_encode_version()
)。
偵錯資訊
當模擬器似乎未接收到您傳送的項時,有關應檢查事項的一些提示
- 請小心版本標頭,在適當的時候使用
ei_x_new_with_version()
。 - 開啟 Erlang 節點上的分佈追蹤。
- 檢查
ei_decode_-calls
的結果碼。