檢視原始碼 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]

所有編碼函數都假設 bufindex 參數指向一個足夠大的緩衝區,足以容納資料。請注意,二進位格式使用可變長度編碼,因此不同的值可能需要不同的空間量。例如,較小的整數值可能比大的整數值更緊湊。若要取得編碼詞項的大小,而不實際編碼它,請傳遞 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 相同。

如果 ab 相等,則傳回 0。如果 ab 小,則傳回小於 0 的值。如果 ab 大,則傳回大於 0 的值。

自 OTP 23.0 起可用

ei_cmp_ports()

int ei_cmp_ports(erlang_port *a, erlang_port *b);

比較兩個 Port 識別碼。比較方式與 Erlang 相同。

如果 ab 相等,則傳回 0。如果 ab 小,則傳回小於 0 的值。如果 ab 大,則傳回大於 0 的值。

自 OTP 23.0 起可用

ei_cmp_refs()

int ei_cmp_refs(erlang_ref *a, erlang_ref *b);

比較兩個參考。比較方式與 Erlang 相同。

如果 ab 相等,則傳回 0。如果 ab 小,則傳回小於 0 的值。如果 ab 大,則傳回大於 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 取得。wasresult 都可以是 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 參數指向的整數變數。sizeoutbuf 都可以設為 NULL。無論 sizeoutbuf 參數的狀態如何,由 index 參數指向的整數都會更新為參考 iodata/0 term 之後的 term。

請注意,如果傳遞非 NULL 值作為 outbuf,則由 outbuf 參數指向的緩衝區必須夠大。您通常會想要呼叫 ei_decode_iodata() 兩次。第一次使用非 NULLsize 參數和 NULLoutbuf 參數,以確定所需的緩衝區大小,然後再次呼叫以進行實際解碼。請注意,由 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)。如果 arity0,則為空 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 是下列之一

如果您對資料不感興趣,也可以使用 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_bitstringei_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 的結果碼。