C La fonction chaîne de la langue

C Langues string Fonctions,In C Disponible dans la langue char* Chaîne d'implémentation du tableau de caractères,C Bibliothèque de normes linguistiques string.h Plusieurs fonctions de manipulation de chaînes sont également définies dans.

Les chaînes sont largement utilisées,Besoins à satisfaire:

  • Fonctionnement efficace des chaînes,Comme ajouter、Copie、Comparaison、Obtenir la longueur
  • Capable de stocker des données binaires arbitraires,Comme des photos.
  • Économisez autant de mémoire que possible

Pourquoi Redis Ne pas utiliser directement C La chaîne de la langue?

  • C Langues char* Par '\0'Fin de la chaîne d'identification,Il y a'\0'La chaîne pour ne pas être correctement représentée;C'est pour ça.,Il n'y a aucun moyen de sauvegarder des données binaires comme des images.
  • C Langues char* La complexité temporelle pour obtenir la longueur de la chaîne est O(N);La complexité temporelle des chaînes supplémentaires est également O(N),Et peut - être parce qu'il n'y a pas assez d'espace disponible,Impossible d'ajouter.

Le code suivant montre C Dans la langue '\0' Effet du caractère de fin sur la chaîne.La figure ci - dessous montre une valeur de "Redis" De C String:

#include "stdio.h"
#include "string.h" int main(void) {
char *a = "red\0is";
char *b = "redis\0";
printf("%lu\n", strlen(a));
printf("%lu\n", strlen(b));
}

Le résultat est 3 Et 5.

SDS Définition

SDS(Simple chaîne dynamique) - Oui. simple dynamic string Abréviations,Redis Utiliser SDS Structure des données en tant que chaîne .Redis Toutes les clés(key)Le rez - de - chaussée est SDS Réalisé.

Par exemple,:

redis> SET msg "hello world"
OK
redis> RPUSH fruits "apple" "banana" "cherry"
(integer) 3

Redis sds Le code source se trouve principalement dans sds.h Et sds.c Moyenne. On y trouve Redis Voilà. char* Alias.:

typedef char *sds;

SDS Structure interne

SDS Il y a une Métadonnée dans la structure flags,Ça veut dire SDS Type(Minimum 3 Bits).En fait,SDS C'est fait. 5 Type d'espèce,Respectivement. sdshdr5、sdshdr8、sdshdr16、sdshdr32 Et sdshdr64.Voilà. 5 La principale différence entre les types est que , La longueur actuelle du tableau de caractères dans leur structure de données len Et la longueur de l'espace alloué alloc, Les deux métadonnées ont des types de données différents .

/* Note: sdshdr5 is never used, we just access the flags byte directly.
* However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len; /* used */
uint8_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
uint16_t len; /* used */
uint16_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
uint32_t len; /* used */
uint32_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
uint64_t len; /* used */
uint64_t alloc; /* excluding the header and null terminator */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};

static inline size_t sdslen(const sds s) {
unsigned char flags = s[-1];
switch(flags&SDS_TYPE_MASK) {
case SDS_TYPE_5:
return SDS_TYPE_5_LEN(flags);
case SDS_TYPE_8:
return SDS_HDR(8,s)->len;
case SDS_TYPE_16:
return SDS_HDR(16,s)->len;
case SDS_TYPE_32:
return SDS_HDR(32,s)->len;
case SDS_TYPE_64:
return SDS_HDR(64,s)->len;
}
return 0;
}

Obtenir la capacité restante :sdsavail Fonctions,Capacité totale alloc - Longueur utilisée len,La complexité temporelle est O(1).

static inline size_t sdsavail(const sds s) {
unsigned char flags = s[-1];
switch(flags&SDS_TYPE_MASK) {
case SDS_TYPE_5: {
return 0;
}
case SDS_TYPE_8: {
SDS_HDR_VAR(8,s);
return sh->alloc - sh->len;
}
case SDS_TYPE_16: {
SDS_HDR_VAR(16,s);
return sh->alloc - sh->len;
}
case SDS_TYPE_32: {
SDS_HDR_VAR(32,s);
return sh->alloc - sh->len;
}
case SDS_TYPE_64: {
SDS_HDR_VAR(64,s);
return sh->alloc - sh->len;
}
}
return 0;
}

SDS Fonctionnement principal de API

L'approche de base est :

sds sdsnewlen(const void *init, size_t initlen);
sds sdstrynewlen(const void *init, size_t initlen);
sds sdsnew(const char *init);
sds sdsempty(void);
sds sdsdup(const sds s);
void sdsfree(sds s);
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); sds sdscatvprintf(sds s, const char *fmt, va_list ap);
#ifdef __GNUC__
sds sdscatprintf(sds s, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
#else
sds sdscatprintf(sds s, const char *fmt, ...);
#endif sds sdscatfmt(sds s, char const *fmt, ...);
sds sdstrim(sds s, const char *cset);
void sdssubstr(sds s, size_t start, size_t len);
void sdsrange(sds s, ssize_t start, ssize_t end);
void sdsupdatelen(sds s);
void sdsclear(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);
void sdstolower(sds s);
void sdstoupper(sds s);
sds sdsfromlonglong(long long value);
sds sdscatrepr(sds s, const char *p, size_t len);
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); /* Callback for sdstemplate. The function gets called by sdstemplate
* every time a variable needs to be expanded. The variable name is
* provided as variable, and the callback is expected to return a
* substitution value. Returning a NULL indicates an error.
*/
typedef sds (*sdstemplate_callback_t)(const sds variable, void *arg);
sds sdstemplate(const char *template, sdstemplate_callback_t cb_func, void *cb_arg); /* Low level functions exposed to the user API */
sds sdsMakeRoomFor(sds s, size_t addlen);
void sdsIncrLen(sds s, ssize_t incr);
sds sdsRemoveFreeSpace(sds s);
size_t sdsAllocSize(sds s);
void *sdsAllocPtr(sds s); /* Export the allocator used by SDS to the program using SDS.
* Sometimes the program SDS is linked to, may use a different set of
* allocators, but may want to allocate or free things that SDS will
* respectively free or allocate. */
void *sds_malloc(size_t size);
void *sds_realloc(void *ptr, size_t size);
void sds_free(void *ptr);

Initialisation des chaînes

Total et Java De StringBuilder C'est très similaire. O_o

/* Create a new sds string starting from a null terminated C string. */
sds sdsnew(const char *init) {
size_t initlen = (init == NULL) ? 0 : strlen(init);
return sdsnewlen(init, initlen);
}

Le premier est de juger l'entrée init Longueur de la chaîne,Puis appelez sdsnewlen Allouer de l'espace mémoire et assigner des valeurs .

sds sdsnewlen(const void *init, size_t initlen) {
return _sdsnewlen(init, initlen, 0);
}

Fonctions de base_sdsnewlen Comme suit, Il s'agit avant tout de s'assurer que l'espace est suffisant 、Espace alloué,Puis appelez memcpy Oui. *init Copier dans l'espace mémoire correspondant .

/* Create a new sds string with the content specified by the 'init' pointer
* and 'initlen'.
* If NULL is used for 'init' the string is initialized with zero bytes.
* If SDS_NOINIT is used, the buffer is left uninitialized;
*
* The string is always null-termined (all the sds strings are, always) so
* even if you create an sds string with:
*
* mystring = sdsnewlen("abc",3);
*
* You can print the string with printf() as there is an implicit \0 at the
* end of the string. However the string is binary safe and can contain
* \0 characters in the middle, as the length is stored in the sds header. */
sds _sdsnewlen(const void *init, size_t initlen, int trymalloc) {
void *sh;
sds s;
char type = sdsReqType(initlen);
/* Empty strings are usually created in order to append. Use type 8
* since type 5 is not good at this. */
if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;
int hdrlen = sdsHdrSize(type);
unsigned char *fp; /* flags pointer. */
size_t usable; assert(initlen + hdrlen + 1 > initlen); /* Catch size_t overflow */
sh = trymalloc?
s_trymalloc_usable(hdrlen+initlen+1, &usable) :
s_malloc_usable(hdrlen+initlen+1, &usable);
if (sh == NULL) return NULL;
if (init==SDS_NOINIT)
init = NULL;
else if (!init)
memset(sh, 0, hdrlen+initlen+1);
s = (char*)sh+hdrlen;
fp = ((unsigned char*)s)-1;
usable = usable-hdrlen-1;
if (usable > sdsTypeMaxSize(type))
usable = sdsTypeMaxSize(type);
switch(type) {
case SDS_TYPE_5: {
*fp = type | (initlen << SDS_TYPE_BITS);
break;
}
case SDS_TYPE_8: {
SDS_HDR_VAR(8,s);
sh->len = initlen;
sh->alloc = usable;
*fp = type;
break;
}
case SDS_TYPE_16: {
SDS_HDR_VAR(16,s);
sh->len = initlen;
sh->alloc = usable;
*fp = type;
break;
}
case SDS_TYPE_32: {
SDS_HDR_VAR(32,s);
sh->len = initlen;
sh->alloc = usable;
*fp = type;
break;
}
case SDS_TYPE_64: {
SDS_HDR_VAR(64,s);
sh->len = initlen;
sh->alloc = usable;
*fp = type;
break;
}
}
if (initlen && init)
memcpy(s, init, initlen);
s[initlen] = '\0';
return s;
}

Redis Série d'analyse concise du code source

Le plus simple Redis Série d'articles sur l'analyse des sources

Java Idées de programmation-Carte mentale la plus complète-GitHub Télécharger le lien,Les petits partenaires qui en ont besoin peuvent s'en servir.~

L'originalité n'est pas facile,J'espère que vous me contacterez d'abord pour la réimpression.,Et annoter le lien original.

Redis Analyse concise du code source 02 - SDS Autres articles en relation avec string

  1. RedisSource read one:Simple chaîne dynamiqueSDS

    La lecture du code source est basée sur Redis4.0.9 SDSIntroduction redis 127.0.0.1:6379> SET dbname redis OK redis 127.0.0.1:6379> GET dbn ...

  2. RedisAnalyse du code source:02Liste des liens

    Les listes de liens offrent une capacité efficace de réarrangement des noeuds,Et l'accès séquentiel aux noeuds,Parce queRedisUtilisationCLa langue n'a pas cette structure de données intégrée,Alors...RedisJ'ai mis en place ma propre liste de liens. Liste des liensRedisTrès largement utilisé dans, Par exemple, une des implémentations sous - jacentes de la liste est la chaîne ...

  3. redisApprentissage des sources_Simple chaîne dynamique

    SDSPar rapport à la traditionC Les chaînes de la langue ont les avantages suivants : (1) Pré - allocation de l'espace et libération inerte , Cela réduit le nombre de réallocations de mémoire (2)O(1) Pour obtenir la longueur de la chaîne (3)Sécurité binaire En résumésds.cEtsds.hMoyenne ...

  4. [RedisLecture du code source]sdsImplémentation de chaînes

    Objectif initial Utiliser dès le début du travail Redis,Ça fait un moment, Mais tout reste dans la phase d'utilisation , Sans aller plus loin , Chaque fois que vous voulez lire le code source, arrêtez de lire des livres , Parce qu'après avoir lu le livre, j'ai vite oublié , Cette fois, force - toi à lire le Code . Parce que la personne pense que l'écriture a besoin de lire ...

  5. RedisNotes de lecture du code source(1)——Simple chaîne dynamiquesdsPrincipe de réalisation

    Tout d'abord,,sdsC'est - à - dire:simple dynamic string,redis Pour ce faire, on a utilisé une technique ,EtC99 Inclus comme standard , C'est - à - dire les membres flexibles du tableau (flexible array member), Les références se trouvent ici ...

  6. RedisAnalyse du code source-- Analyse de la structure du code source

    Restez à l'écoute de mon blog personnel :https://zcheng.ren À la recherche d'un emploi , J'ai vu le Professeur Huang Jianhong <RedisConception et mise en œuvre>,C'est exact.redis Une partie de la mise en oeuvre a une compréhension concise .Pendant l'entrevue,redisC'est vrai. ...

  7. redis Lecture du code source Structure interne des données--String

    redis La structure interne des données pour :String,Liste à double extrémité,Dictionnaire,Table de saut. Voici les principaux enregistrementsredise La conception de la chaîne . Les sources pertinentes se trouvent à :src/sds.h Et src/sds.c.   Un. String sdsStructure de s ...

  8. RedisApprentissage des sources:String

    RedisApprentissage des sources:String 1.Première connaissanceSDS 1.1 SDSDéfinition RedisQui définit un système appelésdshdr(SDS or simple dynamic string)Structure des données pour.SDSPas seulement pour Enregistrer la chaîne, ...

  9. Redis Analyse du code source et commentaires (Sept)--- Liste rapide(quicklist)

    Redis Liste rapide(quicklist)1. IntroductionquicklistLa structure estredis 3.2 Nouvelle structure de données dans la version , Mise en œuvre au bas de la liste . Regardez à travers les touches de liste :redis Détails de la commande de la clé de liste 127.0. ...

  10. RedisAnalyse du code source

    Redis Analyse du code source et commentaires (Un.)---Structure de la liste Redis Analyse du code source et commentaires (2.)--- Simple chaîne dynamique Redis Analyse du code source et commentaires (Trois)--- Redis Structure du Dictionnaire Redis Analyse du code source et commentaires (Quatre)--- Saute! ...

Recommandation aléatoire

  1. iOS Barre de progression personnalisée

    Barre de progression personnalisée (iOS) ViewController.mDocumentation #import "ViewController.h" @interface ViewController () @ ...

  2. ocp 1Z0-047 1-60Analyse des problèmes

    1. You need to load information about new customers from the NEW_CUST table into the tables CUST and ...

  3. KindEditor Aucune valeur trouvée Et ne peut pas vider la valeur

    var editor; KindEditor.ready(function(K) { editor = K.create('textarea[name="content"]', { ...

  4. springNotes-“@Scope”

    @Scope Peut être utilisé pour spécifier SpringCréationbeanDe la façon dont Par défaut à une seule instance ,C'est - à - dire:@Scope("singleton").IOC Lorsque le conteneur démarre, la méthode est appelée pour créer l'objet et le placer dans IOCDans le récipient, Chaque fois que vous obtenez ...

  5. C# Problèmes d'accessibilité incohérents ( Modifier le modificateur d'accès du membre ).

    Exemple d'erreur I : La classe mère est moins accessible que la classe Enfant class Person { } public class Students:Person { } Exemple d'erreur II : Le modificateur d'accès de la méthode doit être compatible avec le modificateur d'accès du type de paramètre cl ...

  6. egretMoniteur d'événements clavier

    document.addEventListener("keydown", function (event: any) { //alert(event.key); //console ...

  7. Découvrir les secretsuc Navigateur II

    Cette section, Quatre sujets : ① Une page Web est affichée à webviewDans le contrôle ② Comment masquer correctement la barre de titre d'affichage . ③Comment utiliserrunnable Pour cacher la barre de titre , De cette façon, il devient plus professionnel . ④ On a dit la dernière fois QuickActionGrid, Regarde - le grandir. ...

  8. 【Oracle】OracleRésumé des types de données de base

    ORACLEType de données de base(Aussi appelé type de données intégré built-in datatypes)Peut être classé par type:Type de chaîne.Type numérique.Type de date.LOBType.LONG RAW& RAWType.ROWID &am ...

  9. 【MYSQLSauvegarde】Utilisationmysqldump Copier une base de données dans une autre

    Supposons que le serveur ABase de données surtest Sauvegarde vers le serveur B 1.Sur le serveurB Nouvelle base de données sur cp_test mysql> create database cp_test; Query OK, row affec ...

  10. Codeforces Round #265 (Div. 2) B. Inbox (100500)

    Over time, Alexey's mail box got littered with too many letters. Some of them are read, while others ...