1/**
2 * \file
3 * \brief Parse function for format returned by get_names.
4 */
5
6/*
7 * Copyright (c) 2014, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14#include <stdlib.h>
15#include <stdio.h>
16
17#include <barrelfish/barrelfish.h>
18#include <octopus/getset.h>
19
20#include "strnatcmp.h"
21
22static char* mystrdup(char* data)
23{
24
25    char *p = malloc(strlen(data) + 1);
26    if (p == NULL) {
27        return NULL;
28    }
29
30    strcpy(p, data);
31    return p;
32}
33
34static int cmpstringp(const void *p1, const void *p2)
35{
36    return strnatcmp(*(char * const *) p1, *(char * const *) p2);
37}
38
39/**
40 * \brief Parses output from get_names call and stores it in an array.
41 *
42 * \note Use oct_free_names() to free names array.
43 *
44 * \param[in] input Comma separated string of names
45 * \param[out] names Array of strings containing all names
46 * \param[out] len Size of array.
47 *
48 * \retval LIB_ERR_MALLOC_FAIL
49 * \retval SYS_ERR_OK
50 */
51errval_t oct_parse_names(char* input, char*** names, size_t* len)
52{
53    errval_t err = SYS_ERR_OK;
54
55    char *p = mystrdup(input);
56    if (p == NULL) {
57        err = LIB_ERR_MALLOC_FAIL;
58        goto out;
59    }
60
61    // first get the number of elements
62    char* saveptr = NULL;
63    size_t i;
64    char* tok = p; // just make sure it's non-null
65    char* first = p;
66    for (i = 0; tok != NULL; i++, first = NULL) {
67        tok = strtok(first, ",");
68    }
69    assert(p != NULL);
70    free(p);
71    p = NULL;
72    *len = --i;
73
74    *names = malloc(sizeof(char*) * i);
75    if (*names == NULL) {
76        *len = 0;
77        err = LIB_ERR_MALLOC_FAIL;
78        goto out;
79    }
80    memset(*names, 0, sizeof(char*) * i);
81
82    // now get the actual elements
83    saveptr = NULL;
84    tok = input; // just make sure it's non-null
85    first = input;
86    for (i = 0; tok != NULL; i++, first = NULL) {
87        tok = strtok(first, ", ");
88        if (tok != NULL) {
89            (*names)[i] = mystrdup(tok);
90            if ((*names)[i] == NULL) {
91                oct_free_names(*names, i);
92                *names = NULL;
93                *len = 0;
94                err = LIB_ERR_MALLOC_FAIL;
95                goto out;
96            }
97        } else {
98            break;
99        }
100    }
101    qsort(*names, *len, sizeof(char*), cmpstringp);
102
103out:
104    return err;
105}
106
107/**
108 * \brief Helper function to free an array of strings.
109 *
110 * Frees all entries of the array and the array itself.
111 *
112 * \param names Non-null array of strings.
113 * \param len Size of the names array
114
115 * \see oct_get_names
116 */
117void oct_free_names(char** names, size_t len)
118{
119    //assert(names != NULL);
120    for (size_t i = 0; i < len; i++) {
121        free(names[i]);
122    }
123
124    free(names);
125}