root/regress/lib/libsndio/tools.c
/*      $OpenBSD: tools.c,v 1.1 2010/11/06 20:25:42 ratchov Exp $       */
/*
 * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <sndio.h>
#include "tools.h"

/*
 * Generate a string corresponding to the encoding in par,
 * return the length of the resulting string
 */
int
sio_enctostr(struct sio_par *par, char *ostr)
{
        char *p = ostr;

        *p++ = par->sig ? 's' : 'u';
        if (par->bits > 9)
                *p++ = '0' + par->bits / 10;
        *p++ = '0' + par->bits % 10;
        if (par->bps > 1) {
                *p++ = par->le ? 'l' : 'b';
                *p++ = 'e';
                if (par->bps != SIO_BPS(par->bits) ||
                    par->bits < par->bps * 8) {
                        *p++ = par->bps + '0';
                        if (par->bits < par->bps * 8) {
                                *p++ = par->msb ? 'm' : 'l';
                                *p++ = 's';
                                *p++ = 'b';
                        }
                }
        }
        *p++ = '\0';
        return p - ostr - 1;
}

/*
 * Parse an encoding string, examples: s8, u8, s16, s16le, s24be ...
 * Return the number of bytes consumed
 */
int
sio_strtoenc(struct sio_par *par, char *istr)
{
        char *p = istr;
        int i, sig, bits, le, bps, msb;

#define IS_SEP(c)                       \
        (((c) < 'a' || (c) > 'z') &&    \
         ((c) < 'A' || (c) > 'Z') &&    \
         ((c) < '0' || (c) > '9'))

        /*
         * get signedness
         */
        if (*p == 's') {
                sig = 1;
        } else if (*p == 'u') {
                sig = 0;
        } else
                return 0;
        p++;

        /*
         * get number of bits per sample
         */
        bits = 0;
        for (i = 0; i < 2; i++) {
                if (*p < '0' || *p > '9')
                        break;
                bits = (bits * 10) + *p - '0';
                p++;
        }
        if (bits < 1 || bits > 32)
                return 0;
        bps = SIO_BPS(bits);
        le = SIO_LE_NATIVE;
        msb = 1;

        /*
         * get (optional) endianness
         */
        if (p[0] == 'l' && p[1] == 'e') {
                le = 1;
                p += 2;
        } else if (p[0] == 'b' && p[1] == 'e') {
                le = 0;
                p += 2;
        } else if (IS_SEP(*p)) {
                goto done;
        } else
                return 0;

        /*
         * get (optional) number of bytes
         */
        if (*p >= '1' && *p <= '4') {
                bps = *p - '0';
                if (bps * 8  < bits)
                        return 0;
                p++;

                /*
                 * get (optional) alignment
                 */
                if (p[0] == 'm' && p[1] == 's' && p[2] == 'b') {
                        msb = 1;
                        p += 3;
                } else if (p[0] == 'l' && p[1] == 's' && p[2] == 'b') {
                        msb = 0;
                        p += 3;
                } else if (IS_SEP(*p)) {
                        goto done;
                } else
                        return 0;
        } else if (!IS_SEP(*p))
                return 0;

done:
        par->msb = msb;
        par->sig = sig;
        par->bits = bits;
        par->bps = bps;
        par->le = le;
        return p - istr;
}