Annotation of embedaddon/strongswan/src/libcharon/plugins/vici/vici_message.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2015 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * Copyright (C) 2014 Martin Willi
                      6:  * Copyright (C) 2014 revosec AG
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include "vici_message.h"
                     20: #include "vici_builder.h"
                     21: 
                     22: #include <bio/bio_reader.h>
                     23: #include <bio/bio_writer.h>
                     24: 
                     25: #include <errno.h>
                     26: 
                     27: typedef struct private_vici_message_t private_vici_message_t;
                     28: 
                     29: /**
                     30:  * Private data of an vici_message_t object.
                     31:  */
                     32: struct private_vici_message_t {
                     33: 
                     34:        /**
                     35:         * Public vici_message_t interface.
                     36:         */
                     37:        vici_message_t public;
                     38: 
                     39:        /**
                     40:         * Message encoding
                     41:         */
                     42:        chunk_t encoding;
                     43: 
                     44:        /**
                     45:         * Free encoding during destruction?
                     46:         */
                     47:        bool cleanup;
                     48: 
                     49:        /**
                     50:         * Allocated strings we maintain for get_str()
                     51:         */
                     52:        linked_list_t *strings;
                     53: };
                     54: 
                     55: ENUM(vici_type_names, VICI_START, VICI_END,
                     56:        "start",
                     57:        "section-start",
                     58:        "section-end",
                     59:        "key-value",
                     60:        "list-start",
                     61:        "list-item",
                     62:        "list-end",
                     63:        "end"
                     64: );
                     65: 
                     66: /**
                     67:  * See header.
                     68:  */
                     69: bool vici_stringify(chunk_t chunk, char *buf, size_t size)
                     70: {
                     71:        if (!chunk_printable(chunk, NULL, 0))
                     72:        {
                     73:                return FALSE;
                     74:        }
                     75:        snprintf(buf, size, "%.*s", (int)chunk.len, chunk.ptr);
                     76:        return TRUE;
                     77: }
                     78: 
                     79: /**
                     80:  * See header.
                     81:  */
                     82: bool vici_verify_type(vici_type_t type, u_int section, bool list)
                     83: {
                     84:        if (list)
                     85:        {
                     86:                if (type != VICI_LIST_END && type != VICI_LIST_ITEM)
                     87:                {
                     88:                        DBG1(DBG_ENC, "'%N' within list", vici_type_names, type);
                     89:                        return FALSE;
                     90:                }
                     91:        }
                     92:        else
                     93:        {
                     94:                if (type == VICI_LIST_ITEM || type == VICI_LIST_END)
                     95:                {
                     96:                        DBG1(DBG_ENC, "'%N' outside list", vici_type_names, type);
                     97:                        return FALSE;
                     98:                }
                     99:        }
                    100:        if (type == VICI_SECTION_END && section == 0)
                    101:        {
                    102:                DBG1(DBG_ENC, "'%N' outside of section", vici_type_names, type);
                    103:                return FALSE;
                    104:        }
                    105:        if (type == VICI_END && section)
                    106:        {
                    107:                DBG1(DBG_ENC, "'%N' within section", vici_type_names, type);
                    108:                return FALSE;
                    109:        }
                    110:        return TRUE;
                    111: }
                    112: 
                    113: /**
                    114:  * Enumerator parsing message
                    115:  */
                    116: typedef struct {
                    117:        /* implements enumerator */
                    118:        enumerator_t public;
                    119:        /** reader to parse from */
                    120:        bio_reader_t *reader;
                    121:        /** section nesting level */
                    122:        int section;
                    123:        /** currently parsing list? */
                    124:        bool list;
                    125:        /** string currently enumerating */
                    126:        char name[257];
                    127: } parse_enumerator_t;
                    128: 
                    129: METHOD(enumerator_t, parse_enumerate, bool,
                    130:        parse_enumerator_t *this, va_list args)
                    131: {
                    132:        vici_type_t *out;
                    133:        chunk_t *value;
                    134:        char **name;
                    135:        uint8_t type;
                    136:        chunk_t data;
                    137: 
                    138:        VA_ARGS_VGET(args, out, name, value);
                    139: 
                    140:        if (!this->reader->remaining(this->reader) ||
                    141:                !this->reader->read_uint8(this->reader, &type))
                    142:        {
                    143:                *out = VICI_END;
                    144:                return TRUE;
                    145:        }
                    146:        if (!vici_verify_type(type, this->section, this->list))
                    147:        {
                    148:                return FALSE;
                    149:        }
                    150: 
                    151:        switch (type)
                    152:        {
                    153:                case VICI_SECTION_START:
                    154:                        if (!this->reader->read_data8(this->reader, &data) ||
                    155:                                !vici_stringify(data, this->name, sizeof(this->name)))
                    156:                        {
                    157:                                DBG1(DBG_ENC, "invalid '%N' encoding", vici_type_names, type);
                    158:                                return FALSE;
                    159:                        }
                    160:                        *name = this->name;
                    161:                        this->section++;
                    162:                        break;
                    163:                case VICI_SECTION_END:
                    164:                        this->section--;
                    165:                        break;
                    166:                case VICI_KEY_VALUE:
                    167:                        if (!this->reader->read_data8(this->reader, &data) ||
                    168:                                !vici_stringify(data, this->name, sizeof(this->name)) ||
                    169:                                !this->reader->read_data16(this->reader, value))
                    170:                        {
                    171:                                DBG1(DBG_ENC, "invalid '%N' encoding", vici_type_names, type);
                    172:                                return FALSE;
                    173:                        }
                    174:                        *name = this->name;
                    175:                        break;
                    176:                case VICI_LIST_START:
                    177:                        if (!this->reader->read_data8(this->reader, &data) ||
                    178:                                !vici_stringify(data, this->name, sizeof(this->name)))
                    179:                        {
                    180:                                DBG1(DBG_ENC, "invalid '%N' encoding", vici_type_names, type);
                    181:                                return FALSE;
                    182:                        }
                    183:                        *name = this->name;
                    184:                        this->list = TRUE;
                    185:                        break;
                    186:                case VICI_LIST_ITEM:
                    187:                        this->reader->read_data16(this->reader, value);
                    188:                        break;
                    189:                case VICI_LIST_END:
                    190:                        this->list = FALSE;
                    191:                        break;
                    192:                case VICI_END:
                    193:                        return TRUE;
                    194:                default:
                    195:                        DBG1(DBG_ENC, "unknown encoding type: %u", type);
                    196:                        return FALSE;
                    197:        }
                    198: 
                    199:        *out = type;
                    200: 
                    201:        return TRUE;
                    202: }
                    203: 
                    204: METHOD(enumerator_t, parse_destroy, void,
                    205:        parse_enumerator_t *this)
                    206: {
                    207:        this->reader->destroy(this->reader);
                    208:        free(this);
                    209: }
                    210: 
                    211: METHOD(vici_message_t, create_enumerator, enumerator_t*,
                    212:        private_vici_message_t *this)
                    213: {
                    214:        parse_enumerator_t *enumerator;
                    215: 
                    216:        INIT(enumerator,
                    217:                .public = {
                    218:                        .enumerate = enumerator_enumerate_default,
                    219:                        .venumerate = _parse_enumerate,
                    220:                        .destroy = _parse_destroy,
                    221:                },
                    222:                .reader = bio_reader_create(this->encoding),
                    223:        );
                    224: 
                    225:        return &enumerator->public;
                    226: }
                    227: 
                    228: /**
                    229:  * Find a value for given vararg key
                    230:  */
                    231: static bool find_value(private_vici_message_t *this, chunk_t *value,
                    232:                                           char *fmt, va_list args)
                    233: {
                    234:        enumerator_t *enumerator;
                    235:        char buf[128], *name, *key, *dot, *next;
                    236:        int section = 0, keysection = 0;
                    237:        bool found = FALSE;
                    238:        chunk_t current;
                    239:        vici_type_t type;
                    240: 
                    241:        vsnprintf(buf, sizeof(buf), fmt, args);
                    242:        next = buf;
                    243: 
                    244:        enumerator = create_enumerator(this);
                    245: 
                    246:        /* descent into section */
                    247:        while (TRUE)
                    248:        {
                    249:                dot = strchr(next, '.');
                    250:                if (!dot)
                    251:                {
                    252:                        key = next;
                    253:                        break;
                    254:                }
                    255:                *dot = '\0';
                    256:                key = next;
                    257:                next = dot + 1;
                    258:                keysection++;
                    259: 
                    260:                while (enumerator->enumerate(enumerator, &type, &name, &current))
                    261:                {
                    262:                        switch (type)
                    263:                        {
                    264:                                case VICI_SECTION_START:
                    265:                                        section++;
                    266:                                        if (section == keysection && streq(name, key))
                    267:                                        {
                    268:                                                break;
                    269:                                        }
                    270:                                        continue;
                    271:                                case VICI_SECTION_END:
                    272:                                        section--;
                    273:                                        continue;
                    274:                                case VICI_END:
                    275:                                        break;
                    276:                                default:
                    277:                                        continue;
                    278:                        }
                    279:                        break;
                    280:                }
                    281:        }
                    282: 
                    283:        /* find key/value in current section */
                    284:        while (enumerator->enumerate(enumerator, &type, &name, &current))
                    285:        {
                    286:                switch (type)
                    287:                {
                    288:                        case VICI_KEY_VALUE:
                    289:                                if (section == keysection && streq(key, name))
                    290:                                {
                    291:                                        *value = current;
                    292:                                        found = TRUE;
                    293:                                        break;
                    294:                                }
                    295:                                continue;
                    296:                        case VICI_SECTION_START:
                    297:                                section++;
                    298:                                continue;
                    299:                        case VICI_SECTION_END:
                    300:                                section--;
                    301:                                continue;
                    302:                        case VICI_END:
                    303:                                break;
                    304:                        default:
                    305:                                continue;
                    306:                }
                    307:                break;
                    308:        }
                    309: 
                    310:        enumerator->destroy(enumerator);
                    311: 
                    312:        return found;
                    313: }
                    314: 
                    315: METHOD(vici_message_t, vget_str, char*,
                    316:        private_vici_message_t *this, char *def, char *fmt, va_list args)
                    317: {
                    318:        chunk_t value;
                    319:        bool found;
                    320:        char *str;
                    321: 
                    322:        found = find_value(this, &value, fmt, args);
                    323:        if (found)
                    324:        {
                    325:                if (chunk_printable(value, NULL, 0))
                    326:                {
                    327:                        str = strndup(value.ptr, value.len);
                    328:                        /* keep a reference to string, so caller doesn't have to care */
                    329:                        this->strings->insert_last(this->strings, str);
                    330:                        return str;
                    331:                }
                    332:        }
                    333:        return def;
                    334: }
                    335: 
                    336: METHOD(vici_message_t, get_str, char*,
                    337:        private_vici_message_t *this, char *def, char *fmt, ...)
                    338: {
                    339:        va_list args;
                    340:        char *str;
                    341: 
                    342:        va_start(args, fmt);
                    343:        str = vget_str(this, def, fmt, args);
                    344:        va_end(args);
                    345:        return str;
                    346: }
                    347: 
                    348: METHOD(vici_message_t, vget_int, int,
                    349:        private_vici_message_t *this, int def, char *fmt, va_list args)
                    350: {
                    351:        chunk_t value;
                    352:        bool found;
                    353:        char buf[32], *pos;
                    354:        int ret;
                    355: 
                    356:        found = find_value(this, &value, fmt, args);
                    357:        if (found)
                    358:        {
                    359:                if (value.len == 0)
                    360:                {
                    361:                        return def;
                    362:                }
                    363:                if (chunk_printable(value, NULL, 0))
                    364:                {
                    365:                        snprintf(buf, sizeof(buf), "%.*s", (int)value.len, value.ptr);
                    366:                        errno = 0;
                    367:                        ret = strtol(buf, &pos, 0);
                    368:                        if (errno == 0 && pos == buf + strlen(buf))
                    369:                        {
                    370:                                return ret;
                    371:                        }
                    372:                }
                    373:        }
                    374:        return def;
                    375: }
                    376: 
                    377: METHOD(vici_message_t, get_int, int,
                    378:        private_vici_message_t *this, int def, char *fmt, ...)
                    379: {
                    380:        va_list args;
                    381:        int val;
                    382: 
                    383:        va_start(args, fmt);
                    384:        val = vget_int(this, def, fmt, args);
                    385:        va_end(args);
                    386:        return val;
                    387: }
                    388: 
                    389: METHOD(vici_message_t, vget_bool, bool,
                    390:        private_vici_message_t *this, bool def, char *fmt, va_list args)
                    391: {
                    392:        chunk_t value;
                    393:        bool found;
                    394:        char buf[16];
                    395: 
                    396:        found = find_value(this, &value, fmt, args);
                    397:        if (found)
                    398:        {
                    399:                if (value.len == 0)
                    400:                {
                    401:                        return def;
                    402:                }
                    403:                if (chunk_printable(value, NULL, 0))
                    404:                {
                    405:                        snprintf(buf, sizeof(buf), "%.*s", (int)value.len, value.ptr);
                    406:                        return settings_value_as_bool(buf, def);
                    407:                }
                    408:        }
                    409:        return def;
                    410: }
                    411: 
                    412: METHOD(vici_message_t, get_bool, bool,
                    413:        private_vici_message_t *this, bool def, char *fmt, ...)
                    414: {
                    415:        va_list args;
                    416:        bool val;
                    417: 
                    418:        va_start(args, fmt);
                    419:        val = vget_bool(this, def, fmt, args);
                    420:        va_end(args);
                    421:        return val;
                    422: }
                    423: 
                    424: METHOD(vici_message_t, vget_value, chunk_t,
                    425:        private_vici_message_t *this, chunk_t def, char *fmt, va_list args)
                    426: {
                    427:        chunk_t value;
                    428:        bool found;
                    429: 
                    430:        found = find_value(this, &value, fmt, args);
                    431:        if (found)
                    432:        {
                    433:                return value;
                    434:        }
                    435:        return def;
                    436: }
                    437: 
                    438: METHOD(vici_message_t, get_value, chunk_t,
                    439:        private_vici_message_t *this, chunk_t def, char *fmt, ...)
                    440: {
                    441:        va_list args;
                    442:        chunk_t value;
                    443: 
                    444:        va_start(args, fmt);
                    445:        value = vget_value(this, def, fmt, args);
                    446:        va_end(args);
                    447:        return value;
                    448: }
                    449: 
                    450: METHOD(vici_message_t, get_encoding, chunk_t,
                    451:        private_vici_message_t *this)
                    452: {
                    453:        return this->encoding;
                    454: }
                    455: 
                    456: /**
                    457:  * Private parse context data
                    458:  */
                    459: struct vici_parse_context_t {
                    460:        /** current section nesting level */
                    461:        int level;
                    462:        /** parse enumerator */
                    463:        enumerator_t *e;
                    464: };
                    465: 
                    466: METHOD(vici_message_t, parse, bool,
                    467:        private_vici_message_t *this, vici_parse_context_t *ctx,
                    468:        vici_section_cb_t section, vici_value_cb_t kv, vici_value_cb_t li,
                    469:        void *user)
                    470: {
                    471:        vici_parse_context_t root = {};
                    472:        char *name, *list = NULL;
                    473:        vici_type_t type;
                    474:        chunk_t value;
                    475:        int base;
                    476:        bool ok = TRUE;
                    477: 
                    478:        if (!ctx)
                    479:        {
                    480:                ctx = &root;
                    481:                root.e = create_enumerator(this);
                    482:        }
                    483: 
                    484:        base = ctx->level;
                    485: 
                    486:        while (ok)
                    487:        {
                    488:                ok = ctx->e->enumerate(ctx->e, &type, &name, &value);
                    489:                if (ok)
                    490:                {
                    491:                        switch (type)
                    492:                        {
                    493:                                case VICI_START:
                    494:                                        /* should never occur */
                    495:                                        continue;
                    496:                                case VICI_KEY_VALUE:
                    497:                                        if (ctx->level == base && kv)
                    498:                                        {
                    499:                                                name = strdup(name);
                    500:                                                this->strings->insert_last(this->strings, name);
                    501:                                                ok = kv(user, &this->public, name, value);
                    502:                                        }
                    503:                                        continue;
                    504:                                case VICI_LIST_START:
                    505:                                        if (ctx->level == base)
                    506:                                        {
                    507:                                                list = strdup(name);
                    508:                                                this->strings->insert_last(this->strings, list);
                    509:                                        }
                    510:                                        continue;
                    511:                                case VICI_LIST_ITEM:
                    512:                                        if (list && li)
                    513:                                        {
                    514:                                                name = strdup(name);
                    515:                                                this->strings->insert_last(this->strings, name);
                    516:                                                ok = li(user, &this->public, list, value);
                    517:                                        }
                    518:                                        continue;
                    519:                                case VICI_LIST_END:
                    520:                                        if (ctx->level == base)
                    521:                                        {
                    522:                                                list = NULL;
                    523:                                        }
                    524:                                        continue;
                    525:                                case VICI_SECTION_START:
                    526:                                        if (ctx->level++ == base && section)
                    527:                                        {
                    528:                                                name = strdup(name);
                    529:                                                this->strings->insert_last(this->strings, name);
                    530:                                                ok = section(user, &this->public, ctx, name);
                    531:                                        }
                    532:                                        continue;
                    533:                                case VICI_SECTION_END:
                    534:                                        if (ctx->level-- == base)
                    535:                                        {
                    536:                                                break;
                    537:                                        }
                    538:                                        continue;
                    539:                                case VICI_END:
                    540:                                        break;
                    541:                        }
                    542:                }
                    543:                break;
                    544:        }
                    545: 
                    546:        if (ctx == &root)
                    547:        {
                    548:                root.e->destroy(root.e);
                    549:        }
                    550:        return ok;
                    551: }
                    552: 
                    553: METHOD(vici_message_t, dump, bool,
                    554:        private_vici_message_t *this, char *label, bool pretty, FILE *out)
                    555: {
                    556:        enumerator_t *enumerator;
                    557:        int ident = 0, delta;
                    558:        vici_type_t type, last_type = VICI_START;
                    559:        char *name, *term, *sep, *separ, *assign;
                    560:        chunk_t value;
                    561: 
                    562:        /* pretty print uses indentation on multiple lines */
                    563:        if (pretty)
                    564:        {
                    565:                delta  = 2;
                    566:                term   = "\n";
                    567:                separ  = "";
                    568:                assign = " = ";
                    569:        }
                    570:        else
                    571:        {
                    572:                delta  = 0;
                    573:                term   = "";
                    574:                separ  = " ";
                    575:                assign = "=";
                    576:        }
                    577: 
                    578:        fprintf(out, "%s {%s", label, term);
                    579:        ident += delta;
                    580: 
                    581:        enumerator = create_enumerator(this);
                    582:        while (enumerator->enumerate(enumerator, &type, &name, &value))
                    583:        {
                    584:                switch (type)
                    585:                {
                    586:                        case VICI_START:
                    587:                                /* should never occur */
                    588:                                break;
                    589:                        case VICI_SECTION_START:
                    590:                                sep = (last_type != VICI_SECTION_START &&
                    591:                                           last_type != VICI_START) ? separ : "";
                    592:                                fprintf(out, "%*s%s%s {%s", ident, "", sep, name, term);
                    593:                                ident += delta;
                    594:                                break;
                    595:                        case VICI_SECTION_END:
                    596:                                ident -= delta;
                    597:                                fprintf(out, "%*s}%s", ident, "", term);
                    598:                                break;
                    599:                        case VICI_KEY_VALUE:
                    600:                                sep = (last_type != VICI_SECTION_START &&
                    601:                                           last_type != VICI_START) ? separ : "";
                    602:                                if (chunk_printable(value, NULL, ' '))
                    603:                                {
                    604:                                        fprintf(out, "%*s%s%s%s%.*s%s", ident, "", sep, name,
                    605:                                                        assign, (int)value.len, value.ptr, term);
                    606:                                }
                    607:                                else
                    608:                                {
                    609:                                        fprintf(out, "%*s%s%s%s0x%+#B%s", ident, "", sep, name,
                    610:                                                        assign, &value, term);
                    611:                                }
                    612:                                break;
                    613:                        case VICI_LIST_START:
                    614:                                sep = (last_type != VICI_SECTION_START &&
                    615:                                           last_type != VICI_START) ? separ : "";
                    616:                                fprintf(out, "%*s%s%s%s[%s", ident, "", sep, name, assign, term);
                    617:                                ident += delta;
                    618:                                break;
                    619:                        case VICI_LIST_END:
                    620:                                ident -= delta;
                    621:                                fprintf(out, "%*s]%s", ident, "", term);
                    622:                                break;
                    623:                        case VICI_LIST_ITEM:
                    624:                                sep = (last_type != VICI_LIST_START) ? separ : "";
                    625:                                if (chunk_printable(value, NULL, ' '))
                    626:                                {
                    627:                                        fprintf(out, "%*s%s%.*s%s", ident, "", sep,
                    628:                                                        (int)value.len, value.ptr, term);
                    629:                                }
                    630:                                else
                    631:                                {
                    632:                                        fprintf(out, "%*s%s0x%+#B%s", ident, "", sep,
                    633:                                                        &value, term);
                    634:                                }
                    635:                                break;
                    636:                        case VICI_END:
                    637:                                fprintf(out, "}\n");
                    638:                                enumerator->destroy(enumerator);
                    639:                                return TRUE;
                    640:                }
                    641:                last_type = type;
                    642:        }
                    643:        enumerator->destroy(enumerator);
                    644:        return FALSE;
                    645: }
                    646: 
                    647: METHOD(vici_message_t, destroy, void,
                    648:        private_vici_message_t *this)
                    649: {
                    650:        if (this->cleanup)
                    651:        {
                    652:                chunk_clear(&this->encoding);
                    653:        }
                    654:        this->strings->destroy_function(this->strings, free);
                    655:        free(this);
                    656: }
                    657: 
                    658: /**
                    659:  * See header
                    660:  */
                    661: vici_message_t *vici_message_create_from_data(chunk_t data, bool cleanup)
                    662: {
                    663:        private_vici_message_t *this;
                    664: 
                    665:        INIT(this,
                    666:                .public = {
                    667:                        .create_enumerator = _create_enumerator,
                    668:                        .get_str = _get_str,
                    669:                        .vget_str = _vget_str,
                    670:                        .get_int = _get_int,
                    671:                        .vget_int = _vget_int,
                    672:                        .get_bool = _get_bool,
                    673:                        .vget_bool = _vget_bool,
                    674:                        .get_value = _get_value,
                    675:                        .vget_value = _vget_value,
                    676:                        .get_encoding = _get_encoding,
                    677:                        .parse = _parse,
                    678:                        .dump = _dump,
                    679:                        .destroy = _destroy,
                    680:                },
                    681:                .strings = linked_list_create(),
                    682:                .encoding = data,
                    683:                .cleanup = cleanup,
                    684:        );
                    685: 
                    686:        return &this->public;
                    687: }
                    688: 
                    689: /**
                    690:  * See header
                    691:  */
                    692: vici_message_t *vici_message_create_from_enumerator(enumerator_t *enumerator)
                    693: {
                    694:        vici_builder_t *builder;
                    695:        vici_type_t type;
                    696:        char *name;
                    697:        chunk_t value;
                    698: 
                    699:        builder = vici_builder_create();
                    700:        while (enumerator->enumerate(enumerator, &type, &name, &value))
                    701:        {
                    702:                switch (type)
                    703:                {
                    704:                        case VICI_SECTION_START:
                    705:                        case VICI_LIST_START:
                    706:                                builder->add(builder, type, name);
                    707:                                continue;
                    708:                        case VICI_KEY_VALUE:
                    709:                                builder->add(builder, type, name, value);
                    710:                                continue;
                    711:                        case VICI_LIST_ITEM:
                    712:                                builder->add(builder, type, value);
                    713:                                continue;
                    714:                        case VICI_SECTION_END:
                    715:                        case VICI_LIST_END:
                    716:                        default:
                    717:                                builder->add(builder, type);
                    718:                                continue;
                    719:                        case VICI_END:
                    720:                                break;
                    721:                }
                    722:                break;
                    723:        }
                    724:        enumerator->destroy(enumerator);
                    725: 
                    726:        return builder->finalize(builder);
                    727: }
                    728: 
                    729: /**
                    730:  * See header
                    731:  */
                    732: vici_message_t *vici_message_create_from_args(vici_type_t type, ...)
                    733: {
                    734:        vici_builder_t *builder;
                    735:        va_list args;
                    736:        char *name;
                    737:        chunk_t value;
                    738: 
                    739:        builder = vici_builder_create();
                    740:        va_start(args, type);
                    741:        while (type != VICI_END)
                    742:        {
                    743:                switch (type)
                    744:                {
                    745:                        case VICI_LIST_START:
                    746:                        case VICI_SECTION_START:
                    747:                                name = va_arg(args, char*);
                    748:                                builder->add(builder, type, name);
                    749:                                break;
                    750:                        case VICI_KEY_VALUE:
                    751:                                name = va_arg(args, char*);
                    752:                                value = va_arg(args, chunk_t);
                    753:                                builder->add(builder, type, name, value);
                    754:                                break;
                    755:                        case VICI_LIST_ITEM:
                    756:                                value = va_arg(args, chunk_t);
                    757:                                builder->add(builder, type, value);
                    758:                                break;
                    759:                        case VICI_SECTION_END:
                    760:                        case VICI_LIST_END:
                    761:                        default:
                    762:                                builder->add(builder, type);
                    763:                                break;
                    764:                }
                    765:                type = va_arg(args, vici_type_t);
                    766:        }
                    767:        va_end(args);
                    768:        return builder->finalize(builder);
                    769: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>