<commit_before>
#include <string.h>
#include <stdio.h>
#include <assert.h>

#include "types_internal.h"
#include "mapper_internal.h"

const char* mapper_msg_param_strings[] =
{
    "@boundMax",        /* AT_BOUND_MAX */
    "@boundMin",        /* AT_BOUND_MIN */
    "@destLength",      /* AT_DEST_LENGTH */
    "@destPort",        /* AT_DEST_PORT */
    "@destType",        /* AT_DEST_TYPE */
    "@direction",       /* AT_DIRECTION */
    "@expression",      /* AT_EXPRESSION */
    "@ID",              /* AT_ID */
    "@instances",       /* AT_INSTANCES */
    "@IP",              /* AT_IP */
    "@length",          /* AT_LENGTH */
    "@libVersion",      /* AT_LIB_VERSION */
    "@max",             /* AT_MAX */
    "@min",             /* AT_MIN */
    "@mode",            /* AT_MODE */
    "@mute",            /* AT_MUTE */
    "@numConnectsIn",   /* AT_NUM_CONNECTIONS_IN */
    "@numConnectsOut",  /* AT_NUM_CONNECTIONS_OUT */
    "@numInputs",       /* AT_NUM_INPUTS */
    "@numLinksIn",      /* AT_NUM_LINKS_IN */
    "@numLinksOut",     /* AT_NUM_LINKS_OUT */
    "@numOutputs",      /* AT_NUM_OUTPUTS */
    "@port",            /* AT_PORT */
    "@range",           /* AT_RANGE */
    "@rate",            /* AT_RATE */
    "@rev",             /* AT_REV */
    "@scope",           /* AT_SCOPE */
    "@sendAsInstance",  /* AT_SEND_AS_INSTANCE */
    "@srcLength",       /* AT_SRC_LENGTH */
    "@srcPort",         /* AT_SRC_PORT */
    "@srcType",         /* AT_SRC_TYPE */
    "@type",            /* AT_TYPE */
    "@units",           /* AT_UNITS */
    "",                 /* AT_EXTRA (special case, does not represent a
                         * specific property name) */
};

int mapper_msg_parse_params(mapper_message_t *msg,
                            const char *path, const char *types,
                            int argc, lo_arg **argv)
{
    int i, j;

    /* Sanity check: complain loudly and quit string if number of
     * strings and params doesn't match up. */
    die_unless(sizeof(mapper_msg_param_strings)/sizeof(const char*)
               == N_AT_PARAMS,
               "libmapper ERROR: wrong number of known parameters\n");

    memset(msg, 0, sizeof(mapper_message_t));
    msg->path = path;
    msg->extra_args[0] = 0;
    int extra_count = 0;

    for (i=0; i<argc; i++) {
        if (types[i]!='s') {
            /* parameter ID not a string */
#ifdef DEBUG
            trace("message %s, parameter '", path);
            lo_arg_pp(types[i], argv[i]);
            trace("' not a string.\n");
#endif
            return 1;
        }

        for (j=0; j<N_AT_PARAMS; j++)
            if (strcmp(&argv[i]->s, mapper_msg_param_strings[j])==0)
                break;

        if (j==N_AT_PARAMS) {
            if (argv[i]->s == '@' && extra_count < N_EXTRA_PARAMS) {
                /* Unknown "extra" parameter, record the key index. */
                msg->extra_args[extra_count] = &argv[i];
                msg->extra_types[extra_count] = types[i+1];
                msg->extra_lengths[extra_count] = 0;
                while (++i < argc) {
                    if ((types[i] == 's' || types[i] == 'S')
                        && (&argv[i]->s)[0] == '@') {
                        /* arrived at next parameter index. */
                        i--;
                        break;
                    }
                    msg->extra_lengths[extra_count]++;
                }
                if (!msg->extra_lengths[extra_count]) {
                    trace("message %s, key %s has no values.\n",
                          path, &(*msg->extra_args[extra_count])->s);
                    return 1;
                }
                extra_count++;
                continue;
            }
            else
                /* Skip non-keyed parameters */
                continue;
        }

        /* special case: range has 4 float or int parameters */
        if (j==AT_RANGE) {
            int k;
            msg->types[j] = &types[i+1];
            msg->values[j] = &argv[i+1];
            for (k=0; k<4; k++) {
                i++;
                if (i >= argc) {
                    trace("message %s, not enough parameters "
                          "for @range.\n", path);
                    return 1;
                }
                if (((types[i] == 's' || types[i] == 'S')
                     && strcmp("-", &argv[i]->s)==0)
                    || (types[i] == 'c' && argv[i]->c == '-'))
                {
                    /* The '-' character means "don't change this
                     * value", and here we ignore it.  It will be
                     * considered "unknown" during get_range(), and
                     * therefore not modified if already known by some
                     * other means. */
                    // TODO: should use OSC "false" type instead?
                }
                else if (types[i] != 'i' && types[i] != 'f') {
                    /* range parameter bad type */
#ifdef DEBUG
                    trace("message %s, @range parameter ", path);
                    lo_arg_pp(types[i], argv[i]);
                    trace("not float or int\n");
#endif
                    return 1;
                }
            }
            msg->lengths[j] = 4;
        }
        else {
            msg->types[j] = &types[i+1];
            msg->values[j] = &argv[i+1];
            msg->lengths[j] = 0;<commit_msg>Allow double type for range data.<commit_after>
#include <string.h>
#include <stdio.h>
#include <assert.h>

#include "types_internal.h"
#include "mapper_internal.h"

const char* mapper_msg_param_strings[] =
{
    "@boundMax",        /* AT_BOUND_MAX */
    "@boundMin",        /* AT_BOUND_MIN */
    "@destLength",      /* AT_DEST_LENGTH */
    "@destPort",        /* AT_DEST_PORT */
    "@destType",        /* AT_DEST_TYPE */
    "@direction",       /* AT_DIRECTION */
    "@expression",      /* AT_EXPRESSION */
    "@ID",              /* AT_ID */
    "@instances",       /* AT_INSTANCES */
    "@IP",              /* AT_IP */
    "@length",          /* AT_LENGTH */
    "@libVersion",      /* AT_LIB_VERSION */
    "@max",             /* AT_MAX */
    "@min",             /* AT_MIN */
    "@mode",            /* AT_MODE */
    "@mute",            /* AT_MUTE */
    "@numConnectsIn",   /* AT_NUM_CONNECTIONS_IN */
    "@numConnectsOut",  /* AT_NUM_CONNECTIONS_OUT */
    "@numInputs",       /* AT_NUM_INPUTS */
    "@numLinksIn",      /* AT_NUM_LINKS_IN */
    "@numLinksOut",     /* AT_NUM_LINKS_OUT */
    "@numOutputs",      /* AT_NUM_OUTPUTS */
    "@port",            /* AT_PORT */
    "@range",           /* AT_RANGE */
    "@rate",            /* AT_RATE */
    "@rev",             /* AT_REV */
    "@scope",           /* AT_SCOPE */
    "@sendAsInstance",  /* AT_SEND_AS_INSTANCE */
    "@srcLength",       /* AT_SRC_LENGTH */
    "@srcPort",         /* AT_SRC_PORT */
    "@srcType",         /* AT_SRC_TYPE */
    "@type",            /* AT_TYPE */
    "@units",           /* AT_UNITS */
    "",                 /* AT_EXTRA (special case, does not represent a
                         * specific property name) */
};

int mapper_msg_parse_params(mapper_message_t *msg,
                            const char *path, const char *types,
                            int argc, lo_arg **argv)
{
    int i, j;

    /* Sanity check: complain loudly and quit string if number of
     * strings and params doesn't match up. */
    die_unless(sizeof(mapper_msg_param_strings)/sizeof(const char*)
               == N_AT_PARAMS,
               "libmapper ERROR: wrong number of known parameters\n");

    memset(msg, 0, sizeof(mapper_message_t));
    msg->path = path;
    msg->extra_args[0] = 0;
    int extra_count = 0;

    for (i=0; i<argc; i++) {
        if (types[i]!='s') {
            /* parameter ID not a string */
#ifdef DEBUG
            trace("message %s, parameter '", path);
            lo_arg_pp(types[i], argv[i]);
            trace("' not a string.\n");
#endif
            return 1;
        }

        for (j=0; j<N_AT_PARAMS; j++)
            if (strcmp(&argv[i]->s, mapper_msg_param_strings[j])==0)
                break;

        if (j==N_AT_PARAMS) {
            if (argv[i]->s == '@' && extra_count < N_EXTRA_PARAMS) {
                /* Unknown "extra" parameter, record the key index. */
                msg->extra_args[extra_count] = &argv[i];
                msg->extra_types[extra_count] = types[i+1];
                msg->extra_lengths[extra_count] = 0;
                while (++i < argc) {
                    if ((types[i] == 's' || types[i] == 'S')
                        && (&argv[i]->s)[0] == '@') {
                        /* arrived at next parameter index. */
                        i--;
                        break;
                    }
                    msg->extra_lengths[extra_count]++;
                }
                if (!msg->extra_lengths[extra_count]) {
                    trace("message %s, key %s has no values.\n",
                          path, &(*msg->extra_args[extra_count])->s);
                    return 1;
                }
                extra_count++;
                continue;
            }
            else
                /* Skip non-keyed parameters */
                continue;
        }

        /* special case: range has 4 float or int parameters */
        if (j==AT_RANGE) {
            int k;
            msg->types[j] = &types[i+1];
            msg->values[j] = &argv[i+1];
            for (k=0; k<4; k++) {
                i++;
                if (i >= argc) {
                    trace("message %s, not enough parameters "
                          "for @range.\n", path);
                    return 1;
                }
                if (((types[i] == 's' || types[i] == 'S')
                     && strcmp("-", &argv[i]->s)==0)
                    || (types[i] == 'c' && argv[i]->c == '-'))
                {
                    /* The '-' character means "don't change this
                     * value", and here we ignore it.  It will be
                     * considered "unknown" during get_range(), and
                     * therefore not modified if already known by some
                     * other means. */
                    // TODO: should use OSC "false" type instead?
                }
                else if (types[i] != 'i' && types[i] != 'f' && types[i] != 'd') {
                    /* range parameter bad type */
#ifdef DEBUG
                    trace("message %s, @range parameter ", path);
                    lo_arg_pp(types[i], argv[i]);
                    trace("not float or int\n");
#endif
                    return 1;
                }
            }
            msg->lengths[j] = 4;
        }
        else {
            msg->types[j] = &types[i+1];
            msg->values[j] = &argv[i+1];
            msg->lengths[j] = 0;
{'fraction_non_alphanumeric': 0.15268936248731432, 'fraction_numerical': 0.004428452809299751, 'mean_word_length': 1.2682569575224942, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5951973', 'n_tokens_mistral': 3301, 'n_tokens_neox': 3237, 'n_words': 704}