【オープンソース共有】すぐ使えるC言語文字列関数ライブラリ


作者:埋め込みハッカー
一、文字列関数ライブラリ:Simple Dynamic Strings 1.概要Simple Dynamic Strings(略称SDS)はC言語文字列ライブラリであり、C言語文字列処理の能力を強化しています.設計SDSは,もともと設計者自身の日常的なCプログラミングを満たすために設計されていたが,その後Redisに移行し,Redisで広く用いられ,高性能な操作に適した修正がなされた.現在、Redisから抽出され、forkは独立したプロジェクトです.1500行未満のコードだけで3.2 Kのstar、牛牛牛~~~何かメリットがありますか?より簡単に使用できます.•バイナリ・セキュリティ効率性の向上C文字列関数と互換性があります.
ソースリンク:
https://github.com/antirez/sds

ソースファイル:
sds.c
sdsalloc.h
sds.h
testhelp.h

関連API:
sds sdsnewlen(const void *init, size_t initlen) 
sds sdsempty(void) 
sds sdsnew(const char *init) 
sds sdsdup(const sds s) 
void sdsfree(sds s) 
void sdsupdatelen(sds s) 
void sdsclear(sds s) 
sds sdsMakeRoomFor(sds s, size_t addlen) 
sds sdsRemoveFreeSpace(sds s) 
size_t sdsAllocSize(sds s) 
void *sdsAllocPtr(sds s) 
void sdsIncrLen(sds s, ssize_t incr) 
sds sdsgrowzero(sds s, size_t len) 
sds sdscatlen(sds s, const void *t, size_t len) 
sds sdscat(sds s, const char *t) 
sds sdscatsds(sds s, const sds t) 
sds sdscpylen(sds s, const char *t, size_t len) 
sds sdscpy(sds s, const char *t) 
int sdsll2str(char *s, long long value) 
int sdsull2str(char *s, unsigned long long v) 
sds sdsfromlonglong(long long value) 
sds sdscatvprintf(sds s, const char *fmt, va_list ap) 
sds sdscatprintf(sds s, const char *fmt, ...) 
sds sdscatfmt(sds s, char const *fmt, ...) 
sds sdstrim(sds s, const char *cset) 
void sdsrange(sds s, ssize_t start, ssize_t end) 
void sdstolower(sds s) 
void sdstoupper(sds s) 
int sdscmp(const sds s1, const sds s2) 
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count) 
void sdsfreesplitres(sds *tokens, int count) 
sds sdscatrepr(sds s, const char *p, size_t len) 
int is_hex_digit(char c) 
int hex_digit_to_int(char c) 
sds *sdssplitargs(const char *line, int *argc) 
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) 
sds sdsjoin(char **argv, int argc, char *sep) 
sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen)

1.一般的な機能1.1文字列sdsnew()とsdsfree()の比較:
#include 
#include "sds.h"
#include "sdsalloc.h"

int main(void)
{
     
    sds mystr = sdsnew("Hello World!");
    printf("%s
"
, mystr); sdsfree(mystr); }

実行効果:
$ gcc -o sdsdemo sds.c sdsdemo.c
$ ./sdsdemo
Hello World!

見えますか?printfは直接sdsを印刷することができ、つまりsds自体がC言語の文字列タイプである.sdsの定義は以下の通りです.
typedef char *sds;

すなわち,sdsはlibcにおける文字列処理関数(例えばstrcpy,strcat...)と互換性がある.sds文字列を使用しない場合は、空白列であってもsdsfreeで文字列を破棄します.
1.2文字列長sdsnewlen()の取得:
int main(void)
{
     
    char buf[3];
    sds mystring;

    buf[0] = 'A';
    buf[1] = 'B';
    buf[2] = 'C';
    mystring = sdsnewlen(buf,3);
    printf("%s of len %d
"
, mystring, (int) sdslen(mystring)); }

実行効果:
$ ./sdsdemo
ABC of len 3

strlen()とは2つの違いがあります.•実行時間が固定され、sds内部にデータ構造が文字列の長さを保存しています.•長さは文字列内にNULLがあるかどうかとは関係ありません.
1.3結合文字列sdscat():
int main(void)
{
     
    sds s = sdsempty();
    s = sdscat(s, "Hello ");
    s = sdscat(s, "World!");
    printf("%s
"
, s); }

実行効果:
$ ./sdsdemo
Hello World!

sdscatが受け入れるパラメータはNULLで終わる文字列であり,この制限から抜け出すにはsdscatsds()を用いることができる.sdscatsds():
int main(void)
{
     
    sds s1 = sdsnew("aaa");
    sds s2 = sdsnew("bbb");
    s1 = sdscatsds(s1,s2);
    sdsfree(s2);
    printf("%s
"
, s1); }

実行効果:
$ ./sdsdemo
aaabbb

1.4拡張文字列長sdsgrowzero():
int main(void)
{
     
    sds s = sdsnew("Hello");
    s = sdsgrowzero(s,6);
    s[5] = '!'; /* We are sure this is safe*/
    printf("%s
"
, s); }

実行効果:
$ ./sdsdemo
Hello!

1.5フォーマット文字列sdscatprintf():
int main(void)
{
     
    sds s;
    int a = 10, b = 20;
    s = sdsnew("The sum is: ");
    s = sdscatprintf(s,"%d+%d = %d",a,b,a+b);
    printf("%s
"
, s); }

実行効果:
$ ./sdsdemo
The sum is: 10+20 = 30

1.6文字列の切り取りsdstrim():指定した文字を削除する
int main(void)
{
     
    sds s = sdsnew("         my string

"
); sdstrim(s,"
"
); printf("-%s-
"
,s); }

実行効果:
$ ./sdsdemo
-my string-

スペースと改行を削除しました.sdsrange():指定範囲内の文字列を切り取る
int main(void)
{
     
    sds s = sdsnew("Hello World!");
    sdsrange(s,1,4);
    printf("-%s-
"
, s); }

実行効果:
$ ./sdsdemo
-ello-

1.7文字列分割(Tokenization)sdssplitlen()およびsdsfreesplitres()
int main(void)
{
     
    sds *tokens;
    int count, j;

    sds line = sdsnew("Hello World!");
    tokens = sdssplitlen(line, sdslen(line)," ",1,&count);

    for (j = 0; j < count; j++)
        printf("%s
"
, tokens[j]); sdsfreesplitres(tokens,count); }

sdssplitlen()の3番目と4番目のパラメータは、分割子をスペースとして指定します.
実行効果:
$ ./sdsdemo
Hello
World!

1.8文字列連結(String joining)sdssplitlen()およびsdsfreesplitres()
int main(void)
{
     
    char *tokens[3] = {
     "foo","bar","zap"};
    sds s = sdsjoin(tokens, 3, "|");
    printf("%s
"
, s); }

実行効果:
$ ./sdsdemo
foo|bar|zap

他にもいくつかの機能がありますから、使ってから検討しましょう.
2.SDSDにおいて、SDSがユーザに返す文字列の実際のポインタの前に、バイナリプレフィックス(ヘッダ)を使用して文字列に関する情報を保存する内部実装を簡単に理解する.
+--------+-------------------------------+-----------+
| Header | Binary safe C alike string... | Null term |
+--------+-------------------------------+-----------+
         |
         `-> Pointer returned to the user.

このヘッダはコードで構造体で記述されており、この構造体の定義は概ね以下の通りである.
struct sdshdr {
     
    [...]
    int len;
    char buf[];
};

•lenは文字列の長さを格納します.•bufは、後続の文字列ヘッダアドレスを指す.あなたが使用する文字列が「HELLOWORLD」であると仮定すると、効率を向上させるために、SDSは事前に多くのスペースを割り当てる可能性があるため、実際のメモリレイアウトは以下の通りです.
+------------+------------------------+-----------+---------------\
| len | buf | H E L L O W O R L D 
| Null term | Free space \ +------------+------------------------+-----------+---------------\ | `-> Pointer returned to the user.

ここで、SDSが文字列を割り当てるための大まかな手順を見てみましょう.
sds sdsnew(const char *init)
    initlen = (init == NULL) ? 0 : strlen(init);
    sdsnewlen(init, initlen);
        int hdrlen = sdsHdrSize(type);      //    Header    
        sh = s_malloc(hdrlen+initlen+1);    //    Header + String + 1       

        s = (char*)sh+hdrlen;       //    C string    
        SDS_HDR_VAR(8,s);           //    struct sdshdr sh
        sh->len = initlen;          //     struct sdshdr sh

        if (initlen && init)        //     C string 
            memcpy(s, init, initlen);
        
        s[initlen] = '\0';          //        NULL
        return s;                   //    C string
        

他のSDS APIがどのように実現されているのかは、自分で分析することになります.
3.関連参考-『Linuxプログラム設計』、6,7.1章-『C primer plus』、11,12章-『Cとポインタ』、9章-『Linuxシステムプログラミング』、9章-『C専門家プログラミング』、7.5章-『CとC++プログラマー面接の秘訣』、4章
**V baiwenwang 1を追加し、技術交流qunに招待