diff options
Diffstat (limited to 'src/afb-token.c')
-rw-r--r-- | src/afb-token.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/afb-token.c b/src/afb-token.c new file mode 100644 index 00000000..b81a87df --- /dev/null +++ b/src/afb-token.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2015-2019 "IoT.bzh" + * Author "Fulup Ar Foll" + * Author: José Bollo <jose.bollo@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include <errno.h> + +#include "afb-token.h" + +/** + * structure for recording a token + */ +struct afb_token +{ + /** link to the next token of the list */ + struct afb_token *next; + + /** reference of the token */ + uint16_t refcount; + + /** local numeric id of the token */ + uint16_t id; + + /** string value of the token */ + char text[]; +}; + +struct tokenset +{ + struct afb_token *first; + pthread_mutex_t mutex; + uint16_t idgen; +}; + +static struct tokenset tokenset = { + .first = 0, + .mutex = PTHREAD_MUTEX_INITIALIZER, + .idgen = 0 +}; + +static struct afb_token *searchid(uint16_t id) +{ + struct afb_token *r = tokenset.first; + while (r && r->id != id) + r = r->next; + return r; +} + +/** + * Get a token for the given value + * + * @param token address to return the pointer to the gotten token + * @param tokenstring string value of the token to get + * @return 0 in case of success or a -errno like negative code + */ +int afb_token_get(struct afb_token **token, const char *tokenstring) +{ + int rc; + struct afb_token *tok; + size_t length; + + /* get length of the token string */ + length = + strlen(tokenstring); + + /* concurrency */ + pthread_mutex_lock(&tokenset.mutex); + + /* search the token */ + tok = tokenset.first; + while (tok && memcmp(tokenstring, tok->text, length)) + tok = tok->next; + + /* search done */ + if (tok) { + /* found */ + tok = afb_token_addref(tok); + rc = 0; + } else { + /* not found, create */ + tok = malloc(length + sizeof *tok); + if (!tok) + /* creation failed */ + rc = -ENOMEM; + else { + while(!++tokenset.idgen || searchid(tokenset.idgen)); + tok->next = tokenset.first; + tokenset.first = tok; + tok->id = tokenset.idgen; + tok->refcount = 1; + memcpy(tok->text, tokenstring, length); + rc = 0; + } + } + pthread_mutex_unlock(&tokenset.mutex); + *token = tok; + return rc; +} + +/** + * Add a reference count to the given token + * + * @param token the token to reference + * @return the token with the reference added + */ +struct afb_token *afb_token_addref(struct afb_token *token) +{ + if (token) + __atomic_add_fetch(&token->refcount, 1, __ATOMIC_RELAXED); + return token; +} + +/** + * Remove a reference to the given token and clean the memory if needed + * + * @param token the token that is unreferenced + */ +void afb_token_unref(struct afb_token *token) +{ + struct afb_token **pt; + if (token && !__atomic_sub_fetch(&token->refcount, 1, __ATOMIC_RELAXED)) { + pthread_mutex_lock(&tokenset.mutex); + pt = &tokenset.first; + while (*pt && *pt != token) + if (*pt) + *pt = token->next; + pthread_mutex_unlock(&tokenset.mutex); + free(token); + } +} + +/** + * Check whether the token is valid or not + * + * @param token the token to check + * @return a boolean value: 0 if not valid, 1 if valid + */ +int afb_token_check(struct afb_token *token) +{ + /* TODO */ + return 1; +} + +/** + * Get the string value of the token + * + * @param token the token whose string value is queried + * @return the string value of the token + */ +const char *afb_token_string(const struct afb_token *token) +{ + return token->text; +} + +/** + * Get the "local" numeric id of the token + * + * @param token the token whose id is queried + * @return the numeric id of the token + */ +uint16_t afb_token_id(const struct afb_token *token) +{ + return token->id; +} |