Annotation of embedaddon/strongswan/src/libcharon/plugins/vici/vici_message.c, revision 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>