diff --git a/cid/Makefile b/cid/Makefile index bb4c1ee..638d6c9 100644 --- a/cid/Makefile +++ b/cid/Makefile @@ -7,7 +7,7 @@ endif LFLAGS = DEPS = -OBJS = cid.o +OBJS = cid.o set.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/cid/set.c b/cid/set.c new file mode 100644 index 0000000..837ce06 --- /dev/null +++ b/cid/set.c @@ -0,0 +1,181 @@ +#include +#include +#include "ipfs/cid/cid.h" +#include "ipfs/util/errs.h" + +struct CidSet *ipfs_cid_set_new () +{ + return calloc(1, sizeof(struct CidSet)); +} + +void ipfs_cid_set_destroy (struct CidSet **set) +{ + struct CidSet *prev; + + if (set) { + while (*set) { + prev = *set; + *set = *set->next; + if (prev->cid) { + free (prev->cid); + } + free (prev); + } + } +} + +int ipfs_cid_set_add (struct CidSet *set, struct Cid *cid, int visit) +{ + if (!set || !cid) { + return ErrInvalidParam; + } + if (!set->cid) { // First item. + set->cid = malloc(sizeof (struct Cid)); + if (!set->cid) { + return ErrAllocFailed; + } + memcpy(set->cid, cid, sizeof (struct Cid)); + set->cid->hash = calloc(1, cid->hash_length); + if (!set->cid->hash) { + free (set->cid); + return ErrAllocFailed; + } + memcpy(set->cid->hash, cid->hash, cid->hash_length); + return 0; + } + for (;;) { + if ((set->cid->hash_length == cid->hash_length) && + (memcmp(set->cid->hash, cid->hash, cid->hash_length)==0)) { + // Already added. + if (!visit) { + // update with new cid. + free(set->cid->hash); + memcpy(set->cid, cid, sizeof (struct Cid)); + set->cid->hash = calloc(1, cid->hash_length); + if (!set->cid->hash) { + return ErrAllocFailed; + } + memcpy(set->cid->hash, cid->hash, cid->hash_length); + } + return 0; + } + if (!set->next) { + set->next = ipfs_cid_set_new(); + if (!set->next) { + return ErrAllocFailed; + } + set = set->next; + set->cid = malloc(sizeof (struct Cid)); + if (!set->cid) { + return ErrAllocFailed; + } + memcpy(set->cid, cid, sizeof (struct Cid)); + set->cid->hash = calloc(1, cid->hash_length); + if (!set->cid->hash) { + return ErrAllocFailed; + } + memcpy(set->cid->hash, cid->hash, cid->hash_length); + return 0; + } + set = set->next; + } +} + +int ipfs_cid_set_has (struct CidSet *set, struct Cid *cid) +{ + if (!set || !cid || !set->cid) { + return 0; + } + for (;;) { + if ((set->cid->hash_length == cid->hash_length) && + (memcmp(set->cid->hash, cid->hash, cid->hash_length)==0)) { + return 1; // has + } + if (!set->next) { + return 0; // end without found. + } + set = set->next; + } +} + +int ipfs_cid_set_remove (struct CidSet *set, struct Cid *cid) +{ + struct CidSet *prev = set; + + if (!set || !cid || !set->cid) { + return 0; + } + for (;;) { + if ((set->cid->hash_length == cid->hash_length) && + (memcmp(set->cid->hash, cid->hash, cid->hash_length)==0)) { + free (set->cid); + if (prev == set) { // first item + set = set->next; + if (!set) { + prev->cid = NULL; + return 1; + } + prev->cid = set->cid; + } else { + prev->next = set->next; + } + free (set); + return 1; // removed + } + if (!set->next) { + return 0; // end without found. + } + prev = set; + set = set->next; + } +} + +int ipfs_cid_set_len (struct CidSet *set) +{ + int len; + + if (!set || !set->cid) { + return 0; + } + + for (len = 0 ; set ; len++, set = set->next); + + return len; +} + +unsigned char **ipfs_cid_set_keys (struct CidSet *set) +{ + int i, len=ipfs_cid_set_len(set); + unsigned char **ret; + + ret = calloc(len+1, sizeof(char*)); + if (ret) { + for (i = 0 ; icid && set->cid->hash) { + ret[i] = calloc(1, set->cid->hash_length + 1); + if (ret[i]) { + memcpy(ret[i], set->cid->hash, set->cid->hash_length); + } + } + set = set->next; + } + } + return ret; +} + +int ipfs_cid_set_foreach (struct CidSet *set, int (*func)(struct Cid *)) +{ + int err = 0; + + while (set) { + if (set->cid) { + err = func (set->cid); + if (err) { + return err; + } + } + set = set->next; + } + + return err; +} diff --git a/include/ipfs/cid/cid.h b/include/ipfs/cid/cid.h index a145d7e..dfff375 100644 --- a/include/ipfs/cid/cid.h +++ b/include/ipfs/cid/cid.h @@ -26,6 +26,11 @@ struct Cid { size_t hash_length; }; +struct CidSet { + struct Cid *cid; + struct CidSet *next; +}; + /*** * encode a Cid into a protobuf array of bytes * @param incoming the incoming Cid struct @@ -95,4 +100,13 @@ int ipfs_cid_hash_to_base58(const unsigned char* hash, size_t hash_length, unsig */ int ipfs_cid_cast(const unsigned char* incoming, size_t incoming_size, struct Cid* cid); +struct CidSet *ipfs_cid_set_new (); +void ipfs_cid_set_destroy (struct CidSet **set); +int ipfs_cid_set_add (struct CidSet *set, struct Cid *cid, int visit); +int ipfs_cid_set_has (struct CidSet *set, struct Cid *cid); +int ipfs_cid_set_remove (struct CidSet *set, struct Cid *cid); +int ipfs_cid_set_len (struct CidSet *set); +unsigned char **ipfs_cid_set_keys (struct CidSet *set); +int ipfs_cid_set_foreach (struct CidSet *set, int (*func)(struct Cid *)); + #endif