[PD-cvs] externals/mrpeach/str str-help.pd, NONE, 1.1 str-to-comport.pd, NONE, 1.1 str.c, NONE, 1.1

Martin Peach mrpeach at users.sourceforge.net
Sun Jan 28 22:22:01 CET 2007


Update of /cvsroot/pure-data/externals/mrpeach/str
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29476

Added Files:
	str-help.pd str-to-comport.pd str.c 
Log Message:
An external that uses the string type. PD needs to be patched for this...


--- NEW FILE: str-help.pd ---
#N canvas 93 115 450 300 10;
#N canvas 32 72 706 515 string 0;
#X obj 88 454 print;
#X obj 143 328 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
#X floatatom 37 53 5 0 0 0 - - -;
#X obj 88 387 str hello 32 there 10 no more;
#X obj 16 7 str nono 32 pitek;
#X obj 16 -15 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X obj 88 429 str to_list;
#X obj 67 123 symbol tikka;
#X obj 67 100 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X msg 117 218 str 2;
#X text 174 430 str to_list outputs the string as a list of floats.
;
#X text 299 378 str string (the default) converts nearly anything to
a string.;
#X msg 100 190 set one 2;
#X msg 82 155 list 1 2 3 alpha;
#X text 80 51 Whole numbers from -127 through 255 are converted to
single bytes. All others are formatted as floats using ASCII characters.
;
#X text 173 190 Set the string quietly;
#X floatatom 130 29 5 0 0 0 - - -;
#X text 165 0 The basic [str] or [str string] outputs a string on its
left outlet and the length of the string at the reight outlet.;
#X floatatom 286 410 5 0 0 0 - - -;
#X msg 127 260 file_read test.txt;
#X text 159 124 Symbols are interpreted as text strings.;
#X text 210 156 List elements are converted to numbers or strings.
;
#X text 167 215 Messages other than [list ...( or [set ...( are transcribed
directly.;
#X msg 136 282 file_write test.txt;
#X text 265 261 String data can be stored in and retrieved from files.
;
#X text 163 327 [Bang] generates output.;
#X connect 1 0 3 0;
#X connect 2 0 3 0;
#X connect 3 0 6 0;
#X connect 3 1 18 0;
#X connect 4 0 3 0;
#X connect 4 1 16 0;
#X connect 5 0 4 0;
#X connect 6 0 0 0;
#X connect 7 0 3 0;
#X connect 8 0 7 0;
#X connect 9 0 3 0;
#X connect 12 0 3 0;
#X connect 13 0 3 0;
#X connect 19 0 3 0;
#X connect 23 0 3 0;
#X restore 3 31 pd string;
#N canvas 259 148 678 300 split 0;
#X obj 67 101 str to_list;
#X obj 174 100 str to_list;
#X obj 67 126 print left;
#X obj 174 125 print right;
#X obj 95 55 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X obj 95 79 str nsplit 6;
#X floatatom 174 55 5 0 0 0 - - -;
#X text 192 79 [str nsplit] splits a string in two at the nth character.
;
#X msg 42 31 set microscope;
#X obj 75 244 str to_list;
#X obj 156 244 str to_list;
#X obj 75 269 print left;
#X obj 156 269 print right;
#X obj 142 193 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
#X obj 142 218 str csplit 32;
#X msg 65 170 what 32 are 32 you 10 13;
#X msg 176 193 set t 32;
#X text 251 193 Set the target character(s);
#X text 244 217 [str csplit] splits incoming strings in two at the
first occurrence of any of the characters in its string. The second
string begins with the first remaining non-target character.;
#X text 153 31 Quietly set the string to be split;
#X text 219 54 Split position: positive from start \, negative from
end;
#X text 252 11 Split this string;
#X msg 6 10 10 11 12 13 14 15 16 17 18 19 20;
#X connect 0 0 2 0;
#X connect 1 0 3 0;
#X connect 4 0 5 0;
#X connect 5 0 0 0;
#X connect 5 1 1 0;
#X connect 6 0 5 1;
#X connect 8 0 5 0;
#X connect 9 0 11 0;
#X connect 10 0 12 0;
#X connect 13 0 14 0;
#X connect 14 0 9 0;
#X connect 14 1 10 0;
#X connect 15 0 14 0;
#X connect 16 0 14 0;
#X connect 22 0 5 0;
#X restore 3 66 pd split;
#N canvas 273 114 640 400 join 0;
#X obj 48 60 str join pig;
#X obj 48 108 str to_list;
#X obj 206 -4 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X obj 13 -32 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X obj 198 15 str 32 the 32 end;
#X obj 13 -13 str This 32 is;
#X msg 10 31 set That 32 was;
#X floatatom 198 -27 5 0 0 0 - - -;
#X obj 48 130 print joined;
#X obj 10 51 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X text 175 60 [str join]: Set the string to be appended either with
a [set( message to the first inlet or by sending a string to the second
inlet.;
#X msg 43 -34 elephant;
#X floatatom 106 7 5 0 0 0 - - -;
#X floatatom 312 36 5 0 0 0 - - -;
#X floatatom 127 82 5 0 0 0 - - -;
#X obj 43 259 str add abc;
#X floatatom 43 217 5 0 0 0 - - -;
#X obj 17 233 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X obj 43 303 str to_list;
#X obj 115 200 str;
#X floatatom 88 159 5 0 0 0 - - -;
#X msg 115 176 whoa;
#X msg 55 236 set;
#X text 84 237 [set( message without arguments clears the string.;
#X text 133 259 [str add] adds input to the end of the string until
banged.;
#X floatatom 129 221 5 0 0 0 - - -;
#X floatatom 115 282 5 0 0 0 - - -;
#X text 158 282 string length;
#X obj 43 324 print added;
#X connect 0 0 1 0;
#X connect 0 1 14 0;
#X connect 1 0 8 0;
#X connect 2 0 4 0;
#X connect 3 0 5 0;
#X connect 4 0 0 1;
#X connect 4 1 13 0;
#X connect 5 0 0 0;
#X connect 5 1 12 0;
#X connect 6 0 0 0;
#X connect 7 0 4 0;
#X connect 9 0 0 0;
#X connect 11 0 0 0;
#X connect 15 0 18 0;
#X connect 15 1 26 0;
#X connect 16 0 15 0;
#X connect 17 0 15 0;
#X connect 18 0 28 0;
#X connect 19 0 15 1;
#X connect 19 1 25 0;
#X connect 20 0 19 0;
#X connect 21 0 19 0;
#X connect 22 0 15 0;
#X restore 3 99 pd join;
#X text 61 98 join and add;
#N canvas 0 0 771 248 compare 0;
#X obj 16 130 str compare This 32 is 32 the 32 end;
#X floatatom 16 153 5 0 0 0 - - -;
#X text 276 131 [str compare]: Set the reference string either with
a [set( message to the first inlet or by sending a string to the second
inlet.;
#X msg 67 102 set This 32 is That 32 was;
#X obj 263 62 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X obj 263 81 str 32 the 32 end;
#X floatatom 377 102 5 0 0 0 - - -;
#X text 19 179 Output is 1 only if the input string and the reference
string are identical.;
#X obj 30 37 str This 32 is 32 the 32 end;
#X obj 30 15 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X msg 37 64 32 the 32 end;
#X obj 45 103 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X connect 0 0 1 0;
#X connect 3 0 0 0;
#X connect 4 0 5 0;
#X connect 5 0 0 1;
#X connect 5 1 6 0;
#X connect 8 0 0 0;
#X connect 9 0 8 0;
#X connect 10 0 0 0;
#X connect 11 0 0 0;
#X restore 4 135 pd compare;
#X text 84 134 compare two strings;
#N canvas -4 -4 399 531 conversion 0;
#X obj 19 16 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -250685
-1;
#X obj 19 80 print;
#X obj 19 52 str to_symbol whichever 32 was it;
#X floatatom 47 16 5 0 0 0 - - -;
#X obj 22 152 str to_float 189.999;
#X floatatom 22 181 15 0 0 0 - - -;
#X obj 22 118 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -250685
-1;
#X floatatom 48 118 5 0 0 0 - - -;
#X msg 90 16 whatever I thought32 at 32 the 10 32 time;
#X msg 97 121 192.168.0.1;
#X msg 110 89 all32were wolves;
#X text 167 152 [str to_float] converts as much as possible of a string
to a single float.;
#X text 257 53 [str to_symbol] converts a string to a symbol as best
it can.;
#X obj 24 261 print;
#X obj 24 236 str to_list;
#X msg 24 212 tell 32 me 32 everything 10 13;
#X text 112 235 [str to_list] outputs the string as a list of floats.
;
#X msg 30 299 One 32 at 32 a 32 time 10 13;
#X obj 30 347 print;
#X obj 30 323 str drip trip 10 13;
#X obj -13 269 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -250685
-1;
#X floatatom 80 259 5 0 0 0 - - -;
#X floatatom 83 349 5 0 0 0 - - -;
#X obj 158 345 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -250685
-1;
#X obj 180 345 tgl 15 0 empty empty empty 17 7 0 10 -24198 -250685
-1 0 1;
#X floatatom 118 432 5 0 0 0 - - -;
#X msg 29 377 The nth character of this string will be output as a
float 10 13;
#X obj 60 450 str nth 5;
#X obj 22 422 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -250685
-1;
#X msg 98 410 set one;
#X text 160 411 [set( quietly sets the string to be analyzed.;
#X floatatom 118 490 5 0 0 0 - - -;
#X text 161 489 string length;
#X floatatom 60 491 5 0 0 0 - - -;
#X text 128 451 [str nth] emits the nth character if it exists \, otherwise
a bang will be emitted.;
#X text 162 431 set n;
#X text 202 322 [str drip] outputs the entire string one float at a
time. Outlet 2 bangs when end is reached.;
#X obj -12 289 until;
#X connect 0 0 2 0;
#X connect 2 0 1 0;
#X connect 3 0 2 0;
#X connect 4 0 5 0;
#X connect 6 0 4 0;
#X connect 7 0 4 0;
#X connect 8 0 2 0;
#X connect 9 0 4 0;
#X connect 10 0 4 0;
#X connect 14 0 13 0;
#X connect 14 0 21 0;
#X connect 15 0 14 0;
#X connect 17 0 19 0;
#X connect 19 0 18 0;
#X connect 19 0 22 0;
#X connect 19 1 23 0;
#X connect 19 1 37 1;
#X connect 20 0 37 0;
#X connect 23 0 24 0;
#X connect 25 0 27 1;
#X connect 26 0 27 0;
#X connect 27 0 33 0;
#X connect 27 1 31 0;
#X connect 28 0 27 0;
#X connect 29 0 27 0;
#X connect 37 0 19 0;
#X restore 4 172 pd conversion;
#X text 105 171 convert strings to other pd types;
#X text 75 30 the basic string;
#X text 69 65 split strings by character or position;

--- NEW FILE: str.c ---
/* str.c by Martin Peach, started 20061227 */
/* version 20070101 no more resizing memory */
/* The str object uses the t_string type */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "m_pd.h"

#ifndef t_string
#error "str needs t_string support in pd source"
#endif

typedef enum
{
    string,
    nsplit,
    csplit,
    join,
    compare,
    add,
    nth,
    drip,
    to_list,
    to_symbol,
    to_float,
    n_functions
} str_function;

char *str_function_names[] = {"string", "nsplit", "csplit", "join", "compare", "add", "nth", "drip", "to_list", "to_symbol", "to_float"};

typedef struct _str
{
    t_object        x_obj;
    t_float         x_nsplit;
    str_function    x_function;
    t_string        x_buf;
    t_string        x_string_in1;
    t_string        x_string_in2;
    t_string        x_string_out1;
    t_string        x_string_out2;
    t_atom          *x_atom_list;
    size_t          x_atom_list_end;
    size_t          x_buf_end;
    size_t          x_string_in1_end;/* the current end of the string. Must be less than x_string_in1.s_length */
    size_t          x_string_in2_end;
    size_t          x_string_out1_end;
    size_t          x_string_out2_end;
    t_outlet        *x_outlet_1;
    t_outlet        *x_outlet_2;
    t_inlet         *x_inlet_2;
    size_t          x_atom_list_length;
} t_str;

/*
* typedef struct _string //pointer to a string
* {
*     unsigned long s_length; // length of string in bytes
*     unsigned char *s_data; // pointer to 1st byte of string
* } t_string;
*/

static t_class *str_class;

void str_setup(void);
static void *str_new(t_symbol *s, int argc, t_atom *argv);
static void str_free(t_str *x);
static void str_do_out1(t_str *x);
static void str_do_out2(t_str *x);
static void str_do_out3(t_str *x);
static void str_do_string(t_str *x);
static void str_bang(t_str *x);
static void str_float(t_str *x, t_float f);
static void str_symbol(t_str *x, t_symbol *s);
static void str_list(t_str *x, t_symbol *s, int argc, t_atom *argv);
static void str_anything(t_str *x, t_symbol *s, int argc, t_atom *argv);
static void str_string(t_str *x, t_string *st);
static void str_set_string(t_string *dest, t_string *src, size_t *len);
static void str_buf_to_string(t_str *x, t_string *dest);
static void str_float_to_buf(t_str *x, t_float f);
static void str_str_to_buf (t_str *x, t_atom *a);
static void str_symbol_to_buf(t_str *x, t_atom *a);
static void str_list_to_buf(t_str *x, t_atom *a, int n);
static void str_set(t_str *x, t_symbol *s, int argc, t_atom *argv);
static void str_fread(t_str *x, t_symbol *s, int argc, t_atom *argv);
static void str_fwrite(t_str *x, t_symbol *s, int argc, t_atom *argv);
static void str_set_second(t_str *x, t_string *st);
static int str_equal(t_str *x);
static void str_join(t_str *x);
static void str_add(t_str *x);
static void str_drip(t_str *x);
static void str_nsplit(t_str *x);
static void str_csplit(t_str *x);
static t_symbol *str_to_symbol(t_str *x);
static t_float str_to_float(t_str *x);


static t_float str_to_float(t_str *x)
{/* return a float from an ASCII representation of a float at the start of the string, or the first character. */
    size_t  limit;
    t_float f = 0.0;

    limit = (x->x_string_in1.s_length-1 >= x->x_string_in1_end)? x->x_string_in1_end: x->x_string_in1.s_length-1;
    if (limit == f) return f;
    x->x_string_in1.s_data[limit] = '\0';
    if (sscanf((char *)x->x_string_in1.s_data, "%f", &f)) return f;
    return (f = x->x_string_in1.s_data[0]);
}

static t_symbol *str_to_symbol(t_str *x)
{
    size_t limit;

    limit = (x->x_string_in1.s_length-1 >= x->x_string_in1_end)? x->x_string_in1_end: x->x_string_in1.s_length-1;
    x->x_string_in1.s_data[limit] = '\0';
    return gensym((char *)x->x_string_in1.s_data);
}

static void str_csplit(t_str *x)
/* split input string 1 into output strings 1 and 2 at first occurrence of any character in input string 2 */
{
    size_t  i, j;

    /*post("str_csplit: x->x_string_in2_end is %lu", x->x_string_in2_end);*/
    for (i = 0; i < x->x_string_in1_end; ++i)
    {
        for (j = 0; j < x->x_string_in2_end; ++j )
        {
            if (x->x_string_in1.s_data[i] == x->x_string_in2.s_data[j])
            { /* found the first character, see if there are more */
                x->x_string_out1_end = x->x_buf_end = i;
                for (++i; i < x->x_string_in1_end; ++i)
                {
                    for (j = 0; j < x->x_string_in2_end; ++j )
                    {
                        if (x->x_string_in1.s_data[i] == x->x_string_in2.s_data[j])
                        break;
                    }
                    if(j == x->x_string_in2_end) goto found; /* 1st non-target character */
                }
            }
        }
        x->x_buf.s_data[i] = x->x_string_in1.s_data[i]; /* this string goes to the left outlet*/
    }
found:
    str_buf_to_string(x, &x->x_string_out1);
    j = i;
    for (i = 0; j < x->x_string_in1_end; ++i, ++j)
    {
       x->x_buf.s_data[i] = x->x_string_in1.s_data[j]; /* this string goes to the right outlet */
    }
    x->x_string_out2_end = x->x_buf_end = i;
    str_buf_to_string(x, &x->x_string_out2);
    return;
}

static void str_nsplit(t_str *x)
/* split input string 1 into output strings 1 and 2 at index x_nsplit */
{
    size_t len, i, j;

    if (x->x_nsplit >= 0)
    { /* split from start of data, no more than size of largest possible string */
        len = (unsigned long)x->x_nsplit;
        if (len > x->x_string_in1_end) len = x->x_string_in1_end;
        if (len > x->x_string_in1.s_length) len = x->x_string_in1.s_length;
    }
    else
    { /* split from the end */
        len = (unsigned long)-x->x_nsplit;
        if (len > x->x_string_in1_end) len = 0L;
        else len = x->x_string_in1_end - len;
    }
    for (i = 0; i < len; ++i) x->x_buf.s_data[i] = x->x_string_in1.s_data[i];
    x->x_string_out1_end = x->x_buf_end = len;
    str_buf_to_string(x, &x->x_string_out1);
    j = i;
    len = (len < x->x_string_in1_end)? x->x_string_in1_end - len: 0L;
    for (i = 0; i < len; ++i, ++j) x->x_buf.s_data[i] = x->x_string_in1.s_data[j];
    x->x_string_out2_end = x->x_buf_end = len;
    str_buf_to_string(x, &x->x_string_out2);
    x->x_buf_end = 0L;/* finished with x_buf */
    return;
}

static int str_equal(t_str *x)
/* If input string 1 is exactly equal to input string 2, return 1, else 0 */
{
    size_t len, i, j;

    if ((len = x->x_string_in1_end) != x->x_string_in2_end) return 0; /* not the same length */
    for (i = 0; i < len; ++i) if (x->x_string_in1.s_data[i] != x->x_string_in2.s_data[i]) return 0;
    return 1;

}

static void str_drip(t_str *x)
/* Send next character of input string 1 out outlet 1, bang outlet 2 if end of string */
{
    size_t              limit, i;
    unsigned char       c;

    limit = (x->x_string_in1_end > x->x_string_in1.s_length)? x->x_string_in1.s_length: x->x_string_in1_end;
    if (x->x_nsplit >= limit) x->x_nsplit = 0L;
    if (limit != 0)
    {/* x->x_nsplit points to the current output character */
        c = x->x_string_in1.s_data[(size_t)x->x_nsplit++];
        outlet_float(x->x_outlet_1, (float)c);
    }
    if (x->x_nsplit >= limit)
    { /* bang at end of string */
        x->x_nsplit = 0L;
        outlet_bang(x->x_outlet_2);
    }
}

static void str_add(t_str *x)
/* Append input string 1 to input string 2, result to input_string 2. Clear input string 1 */
{
    size_t len, i, j;

    len = x->x_string_in1_end + x->x_string_in2_end;
    if (len > x->x_string_in2.s_length) len = x->x_string_in2.s_length;
    for (i = 0, j = x->x_string_in2_end; ((i < x->x_string_in1_end) && (j < len)); ++i, ++j)
        x->x_string_in2.s_data[j] = x->x_string_in1.s_data[i];
    x->x_string_in2_end = j;
    x->x_string_in1_end = 0L;
    return;
}

static void str_join(t_str *x)
/* Append input string 1 to input string 2 in output string 1 */
{
    size_t len, i, j;

    len = x->x_string_in1_end + x->x_string_in2_end;
    if (len > x->x_string_out1.s_length) len = x->x_string_out1.s_length;
    for (i = 0; i < x->x_string_in1_end; ++i) x->x_string_out1.s_data[i] = x->x_string_in1.s_data[i];
    j = i;
    for (i = 0; i < x->x_string_in2_end; ++i, ++j) x->x_string_out1.s_data[j] = x->x_string_in2.s_data[i];
    x->x_string_out1_end = len;
    return;

}

static void str_list_to_buf(t_str *x, t_atom *a, int n)
/* Convert list of atoms to string in x->x_buf.s_data at offset x->x_buf_end,
* increment x->x_buf_end by the number of chars added to x->x_buf.s_data*/
{
    int     j;

    for (j = 0; j < n; ++j)
    { /* concatenate all arguments into a single string */
        if (a[j].a_type == A_STRING)
        { /* already a string */
            str_str_to_buf(x, &a[j]);
        }
        else if (a[j].a_type == A_SYMBOL)
        {
            str_symbol_to_buf(x, &a[j]);
        }
        else if (a[j].a_type == A_FLOAT)
        { /* integers on [0..255] are taken directly, otherwise converted to strings */
            str_float_to_buf(x, atom_getfloat(&a[j]));
        }
    }
 }

static void str_str_to_buf (t_str *x, t_atom *a)
/* Copy string to string in x->x_buf.s_data at offset x->x_buf_end,
* increment x->x_buf_end by the number of chars added to x->x_buf.s_data*/
{
    size_t len, limit, i, j;
    char *cP = (char *)x->x_buf.s_data + x->x_buf_end;
    t_string *str = atom_getstring(a);
    if (str == NULL)
    {
        post ("str_str_to_buf: null string. Need a string to point to....");
        return;
    }
    limit = x->x_buf.s_length - x->x_buf_end;
    len = (str->s_length > limit)? limit: str->s_length;
    for (i = 0, j = x->x_buf_end; ((i < len)&&(j < x->x_buf.s_length)); ++i, ++j)
        x->x_buf.s_data[j] = str->s_data[i];
    x->x_buf_end = j;
}

static void str_symbol_to_buf(t_str *x, t_atom *a)
/* Convert symbol to string in x->x_buf.s_data at offset x->x_buf_end,
* increment x->x_buf_end by the number of chars added to x->x_buf.s_data*/
{                                                                                                                               char *cP = (char *)x->x_buf.s_data + x->x_buf_end;
    atom_string(a, cP, x->x_buf.s_length-x->x_buf_end);
    x->x_buf_end += strlen(cP);
}

static void str_float_to_buf(t_str *x, t_float f)
/* Convert float to characters in x->x_buf.s_data at offset x->x_buf_end,
* increment x->x_buf_end by the number of chars added to x->x_buf.s_data. */
{
    long i;
    char j;

    if (x->x_buf_end > x->x_buf.s_length-20) /* what's the longest float? */
    {
        error("str_float_to_buf: string too long.");
        return;
    }
    /* A float is either an ascii character number or a floating-point string */
    i = (long)f;
    j = i & 0x0FF;
    if ((f == i)&&(i < 256)&&(i > -129)) /* is f an integer on [-128..255] */
        x->x_buf.s_data[x->x_buf_end++] = j;
    else
        x->x_buf_end += sprintf((char *)&x->x_buf.s_data[x->x_buf_end], "%f", f);
 }

static void str_buf_to_string(t_str *x, t_string *dest)
/* copy x->x_buf_end bytes of x->x_buf.s_data into dest */
{
    size_t      i, limit;

    limit = (dest->s_length < x->x_buf.s_length)? dest->s_length: x->x_buf.s_length;
    if (limit > x->x_buf_end) limit = x->x_buf_end;/* normally the case */
/*    post("str_buf_to_string: limit %lu", limit); */
    for (i = 0; i < limit; ++i)
    {
        dest->s_data[i] = x->x_buf.s_data[i];
    }
/*    post("str_buf_to_string: new length %lu", dest->s_length); */
    return;
}

static void str_set_string(t_string *dest, t_string *src, size_t *len)
/* Copy src into dest up to the shorter of dest->s_length and src->s_length
*  and set len to number of bytes copied */
{
    size_t i, limit;

    *len = (dest->s_length < src->s_length)? dest->s_length: src->s_length;
    for (i = 0; i < *len; ++i) dest->s_data[i] = src->s_data[i];
}

static void str_fread(t_str *x, t_symbol *s, int argc, t_atom *argv)
{
 /* a [file_read( message can have any type */
    FILE    *fp = NULL;
    size_t  limit = 0L;
    int     err = 0;

    x->x_buf_end = limit;
    post("str_fread: argc %d", argc);
    str_list_to_buf(x, argv, argc);
    limit = (x->x_buf_end >= x->x_buf.s_length)? x->x_buf.s_length-1: x->x_buf_end;
    x->x_buf.s_data[limit] = '\0'; /* make buf a c string */
    if (0 == limit)
    {
        post ("str file_read: no path.");
        return;
    }
    errno = 0;
    fp = fopen((char *)x->x_buf.s_data, "rb");
    if(NULL == fp)
    {
        post ("str file_read: error opening file \"%s\": %d", x->x_buf.s_data, errno);
        return;
    }
    limit = x->x_string_in1.s_length;
    limit = fread(x->x_string_in1.s_data, 1L, limit, fp);
    if (0 != (err = ferror(fp)))
    {
        post ("str file_read: error reading file \"%s\": %d", x->x_buf.s_data, errno);
        x->x_string_in1_end = 0L;
    }
    else
    {
        x->x_string_in1_end = limit;
        post ("str file_read: read %lu bytes", limit);
    }
    fclose(fp);
    return;
}

static void str_fwrite(t_str *x, t_symbol *s, int argc, t_atom *argv)
{
 /* a [file_write( message can have any type */
    FILE    *fp = NULL;
    size_t  limit = 0L;
    int     err = 0;

    if (0 == x->x_string_in1_end)
    {
        post ("str file_write: nothing to write");
        return;
    }
    x->x_buf_end = limit;
    post("str_fwrite: argc %d", argc);
    str_list_to_buf(x, argv, argc);
    limit = (x->x_buf_end >= x->x_buf.s_length)? x->x_buf.s_length: x->x_buf_end;
    if (0 == limit)
    {
        post ("str file_write: no path.");
        return;
    }
    errno = 0;
    fp = fopen((char *)x->x_buf.s_data, "wb");
    if(NULL == fp)
    {
        post ("str file_write: error opening file \"%s\": %d", x->x_buf.s_data, errno);
        return;
    }
    rewind(fp);
    limit = x->x_string_in1_end;
    limit = fwrite(x->x_string_in1.s_data, 1L, limit, fp);
    if (0 != (err = ferror(fp)))
        post ("str file_write: error writing file \"%s\": %d", x->x_buf.s_data, errno);
    else post ("str file_write: wrote %lu bytes to \"%s\"", limit, x->x_buf.s_data);
    fclose(fp);
    return;
}

static void str_set(t_str *x, t_symbol *s, int argc, t_atom *argv)
{ /* a [set( message can have any type */
    x->x_buf_end = 0L;
    /*post("str_set: argc %d", argc);*/
    str_list_to_buf(x, argv, argc);
    if ((x->x_function == csplit) || (x->x_function == compare) || (x->x_function == join) || (x->x_function == add))
    {
        x->x_string_in2_end = x->x_buf_end;
        str_buf_to_string(x, &x->x_string_in2);
    }
    else
    {
        x->x_string_in1_end = x->x_buf_end;
        str_buf_to_string(x, &x->x_string_in1);
    }
    if ((x->x_function == add)||(x->x_function == join)) outlet_float(x->x_outlet_2, x->x_string_in2_end);
    else if ((x->x_function == nth) || (x->x_function == string)) outlet_float(x->x_outlet_2, x->x_string_in1_end);
}

static void str_set_second(t_str *x, t_string *st)
{ /* Inlet 2 accepts strings only: Set string_in2 */
    /*post("x=%p str_set_second(%p): %s %p %lu",
        x, &str_set_second, str_function_names[x->x_function], st, st->s_length);*/
    str_set_string(&x->x_string_in2, st, &x->x_string_in2_end);
    if ((x->x_function == add)||(x->x_function == join)) outlet_float(x->x_outlet_2, x->x_string_in2_end);
}

static void str_string(t_str *x, t_string *st)
{
    /*post("x=%p str_string (%p) string %p %lu", x, &str_string, st, st->s_length);*/
    str_set_string(&x->x_string_in1, st, &x->x_string_in1_end);
    if (x->x_function == drip) x->x_nsplit = 0L;
    str_do_string(x);
}

static void str_anything(t_str *x, t_symbol *s, int argc, t_atom *argv)
{
/*    post("str_anything"); */
    x->x_buf_end = sprintf((char *)x->x_buf.s_data, "%s", s->s_name); /* the selector is just another word... */
    str_list_to_buf(x, argv, argc);
    x->x_string_in1_end = x->x_buf_end;
    str_buf_to_string(x, &x->x_string_in1);
    if (x->x_function == drip) x->x_nsplit = 0L;
    str_do_string(x);
}

static void str_list(t_str *x, t_symbol *s, int argc, t_atom *argv)
{
/*    post("str_list"); */
    x->x_buf_end = 0L;
    str_list_to_buf(x, argv, argc);
    x->x_string_in1_end = x->x_buf_end;
    str_buf_to_string(x, &x->x_string_in1);
    if (x->x_function == drip) x->x_nsplit = 0L;
    str_do_string(x);
}

static void str_symbol(t_str *x, t_symbol *s)
{
/*    post("str_symbol");*/
    x->x_buf_end = sprintf((char *)x->x_buf.s_data, "%s", s->s_name);
    x->x_string_in1_end = x->x_buf_end;
    str_buf_to_string(x, &x->x_string_in1);
    if (x->x_function == drip) x->x_nsplit = 0L;
    str_do_string(x);
}

static void str_float(t_str *x, t_float f)
{
    x->x_buf_end = 0L;

/*    post("str_float");*/
    str_float_to_buf(x, f);
    x->x_string_in1_end = x->x_buf_end;
    str_buf_to_string(x, &x->x_string_in1);
    if (x->x_function == drip) x->x_nsplit = 0L;
    str_do_string(x);
}

static void str_bang(t_str *x)
{
/*    post("str_bang");*/
    if((x->x_function == add) && (x->x_string_in2_end != 0))str_do_out3(x);
    else str_do_string(x);
}

/* Send string_in1 through outlet_1 */
static void str_do_out0(t_str *x)
{
/* The receiver needs to know the length of the actual data, not the size of our buffer */
/* so we temporarily replace s_length with string end. */
    size_t  true_length = x->x_string_in1.s_length;
    x->x_string_in1.s_length = x->x_string_in1_end;
/*    post("str_do_out0: x->x_string_in1.s_data[0] = %d", x->x_string_in1.s_data[0]);*/
    outlet_string(x->x_outlet_1, &x->x_string_in1);
    x->x_string_in1.s_length = true_length;
}

 /* send string_out_1 through outlet_1 */
 static void str_do_out1(t_str *x)
{
   size_t  true_length = x->x_string_out1.s_length;
    x->x_string_out1.s_length = x->x_string_out1_end;
/*    post("str_do_out1: x->x_string_out1.s_data[0] = %d", x->x_string_out1.s_data[0]);*/
    outlet_string(x->x_outlet_1, &x->x_string_out1);
    x->x_string_out1.s_length = true_length;
}

/* send string_out_2 through outlet_2 */
static void str_do_out2(t_str *x)
{
    size_t  true_length = x->x_string_out2.s_length;
    x->x_string_out2.s_length = x->x_string_out2_end;
/*    post("str_do_out2: x->x_string_out2.s_data[0] = %d", x->x_string_out2.s_data[0]);*/
    outlet_string(x->x_outlet_2, &x->x_string_out2);
    x->x_string_out2.s_length = true_length;
}

/* Send string_in2 through outlet_1 */
static void str_do_out3(t_str *x)
{
/* The receiver needs to know the length of the actual data, not the size of the buffer */
/* so we temporarily replace s_length with string end. */
    size_t  true_length = x->x_string_in2.s_length;
    x->x_string_in2.s_length = x->x_string_in2_end;
    outlet_string(x->x_outlet_1, &x->x_string_in2);
    x->x_string_in2.s_length = true_length;
}

/* Perform the string function and emit the result */
static void str_do_string(t_str *x)
{
    size_t          i;
    float           f;
    unsigned char   c;

    switch (x->x_function)
    {
        case string:
            outlet_float(x->x_outlet_2, x->x_string_in1_end);
            if(x->x_string_in1_end != 0) str_do_out0(x);
            break;
        case join:
            str_join(x);
            outlet_float(x->x_outlet_2, x->x_string_out1_end);
            if(x->x_string_out1_end != 0) str_do_out1(x);
            break;
        case add:
            str_add(x);/* no output until banged */
            outlet_float(x->x_outlet_2, x->x_string_in2_end);
            break;
        case drip:
            if (x->x_string_in1_end != 0) str_drip(x);
            break;
        case nth:
            outlet_float(x->x_outlet_2, x->x_string_in1_end);
            i = x->x_nsplit; /* output the nth character as a float, or bang if none. */
            if ((x->x_string_in1_end != 0) && (i < x->x_string_in1_end))
                outlet_float(x->x_outlet_1, x->x_string_in1.s_data[i]);
            else
                outlet_bang(x->x_outlet_1);
            break;
        case compare:
            outlet_float(x->x_outlet_1, str_equal(x));
            break;
        case nsplit:
            str_nsplit(x);
            if(x->x_string_out2_end != 0) str_do_out2(x);
            if(x->x_string_out1_end != 0) str_do_out1(x);
            break;
        case csplit:
            str_csplit(x);
            if(x->x_string_out2_end != 0) str_do_out2(x);
            if(x->x_string_out1_end != 0) str_do_out1(x);
            break;
        case to_float:
            if (x->x_string_in1_end != 0)
                outlet_float(x->x_outlet_1, str_to_float(x));
            break;
        case to_symbol:
            if (x->x_string_in1_end != 0)
                outlet_symbol(x->x_outlet_1, str_to_symbol(x));
            break;
        case to_list:
            x->x_atom_list_end = (sizeof(t_atom))*(x->x_string_in1.s_length);
            if (x->x_atom_list_end > x->x_atom_list_length) x->x_atom_list_end = x->x_atom_list_length;
            for (i = 0; i < x->x_string_in1_end; ++i)
            {
                c = x->x_string_in1.s_data[i];
                f = (float)c;
                SETFLOAT(&x->x_atom_list[i], f);
            }
            if (x->x_string_in1_end != 0)
                outlet_list(x->x_outlet_1, &s_list, x->x_string_in1_end, x->x_atom_list);
            break;
    }
}

static void str_free(t_str *x)
{
/*    post("str_free");*/
    freebytes(x->x_string_out1.s_data, x->x_string_out1.s_length);
    freebytes(x->x_string_out2.s_data, x->x_string_out2.s_length);
    freebytes(x->x_string_in1.s_data, x->x_string_in1.s_length);
    freebytes(x->x_string_in2.s_data, x->x_string_in2.s_length);
    freebytes(x->x_buf.s_data, x->x_buf.s_length);
    freebytes(x->x_atom_list, x->x_atom_list_length);
}

static void *str_new(t_symbol *s, int argc, t_atom *argv)
{
    t_str           *x;
    unsigned long   i, next;
    size_t          cLen = MAXPDSTRING;
    unsigned int    u;
    t_float         f;

    x = (t_str *)pd_new(str_class);
    if (x == NULL) return (x);
    x->x_outlet_1 = outlet_new((t_object *)x, &s_anything);
    /* This is the only place we allocate string storage */
    x->x_buf.s_data = getbytes(cLen);
    x->x_buf.s_length = cLen;
    x->x_buf_end = 0L;
    x->x_string_in1.s_data = getbytes(cLen);
    x->x_string_in1.s_length = cLen;
    x->x_string_in1_end = 0L;/* the current end of the string. Must be less than x_string_in1.s_length */
    x->x_string_in2.s_data = getbytes(cLen);
    x->x_string_in2.s_length = cLen;
    x->x_string_in2_end = 0L;
    x->x_string_out1.s_data = getbytes(cLen);
    x->x_string_out1.s_length = cLen;
    x->x_string_out1_end = 0L;
    x->x_string_out2.s_data = getbytes(cLen);
    x->x_string_out2.s_length = cLen;
    x->x_string_out2_end = 0L;
    x->x_atom_list = getbytes(cLen);
    x->x_atom_list_length = cLen;
    x->x_atom_list_end = 0L;
    x->x_function = 0; /* default = string */
    x->x_nsplit = 0L;
    next = 0; /* index of next argument */
    if (argv[0].a_type == A_SYMBOL)
    { /* the first argument may be a selector */
        atom_string(&argv[0], (char *)x->x_buf.s_data, MAXPDSTRING);
        for (i = 0; i < n_functions; ++i)
        {
            if (strcmp((char *)x->x_buf.s_data, str_function_names[i]) == 0)
            {
                x->x_function = i;
/*                post("str_new: x_function is %s", str_function_names[x->x_function]);*/
                next = 1;
                if ((x->x_function == nsplit) || (x->x_function == csplit))
                    x->x_outlet_2 = outlet_new((t_object *)x, &s_anything);
                break;
            }
        }
    }
    if ((x->x_function == string)||(x->x_function == nth)||(x->x_function == add)||(x->x_function == join)
    || (x->x_function == drip))
       x->x_outlet_2 = outlet_new((t_object *)x, &s_anything); /* an outlet for the string length or bang */
    if ((x->x_function == nsplit)||(x->x_function == nth))
    { /* single argument must be a float, add a float inlet */
        x->x_nsplit = atom_getfloat(&argv[next]);
        x->x_inlet_2 = floatinlet_new((t_object *)x, &x->x_nsplit);
    }
    else if (x->x_function == csplit)
    { /* argument goes to string_in2 */
        str_list_to_buf(x, &argv[next], argc-next);
        x->x_string_in2_end = x->x_buf_end;
        str_buf_to_string(x, &x->x_string_in2);
    }
    else if ((x->x_function == join)||(x->x_function == compare)||(x->x_function == add))
    { /* argument goes to string_in2, add a string inlet */
        x->x_inlet_2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_string, gensym("")); /* gensym("string") */
        str_list_to_buf(x, &argv[next], argc-next);
        x->x_string_in2_end = x->x_buf_end;
        str_buf_to_string(x, &x->x_string_in2);
    }
    else
    { /* argument goes to string_in1 */
        str_list_to_buf(x, &argv[next], argc-next);
        x->x_string_in1_end = x->x_buf_end;
        str_buf_to_string(x, &x->x_string_in1);
    }
    return (x);
}

void str_setup(void)
{
    str_class = class_new(gensym("str"),
                    (t_newmethod)str_new,
                    (t_method)str_free,
                    sizeof(t_str), 0, A_GIMME, 0);
    class_addbang(str_class, str_bang);
    class_addfloat(str_class, str_float);
    class_addsymbol(str_class, str_symbol);
    class_addlist(str_class, str_list);
    class_addanything(str_class, str_anything);
    class_addstring(str_class, str_string);
    class_addmethod(str_class, (t_method)str_set, gensym("set"), A_GIMME, 0);
    class_addmethod(str_class, (t_method)str_fread, gensym("file_read"), A_GIMME, 0);
    class_addmethod(str_class, (t_method)str_fwrite, gensym("file_write"), A_GIMME, 0);
    class_addmethod(str_class, (t_method)str_set_second, gensym(""), A_STRING, 0);
}
/* end str.c */


--- NEW FILE: str-to-comport.pd ---
#N canvas 574 0 450 300 10;
#X obj 98 81 comport 0 9600;
#X msg 98 30 Tell 32 me 32 again 10 13;
#X obj 94 124 print a;
#X obj 184 127 print b;
#X msg 107 8 info;
#X obj 30 111 float;
#X obj 32 147 + 1;
#X floatatom 6 132 5 0 0 0 - - -;
#X obj 47 84 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X msg 16 73 0;
#X obj 96 54 str drip what????;
#X obj 210 80 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X obj 210 105 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
1;
#X obj 24 7 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
;
#X obj 24 30 metro 10;
#X obj 56 8 until;
#X obj 55 -14 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X connect 0 0 2 0;
#X connect 0 1 3 0;
#X connect 1 0 10 0;
#X connect 4 0 0 0;
#X connect 5 0 6 0;
#X connect 5 0 7 0;
#X connect 6 0 5 1;
#X connect 8 0 5 0;
#X connect 9 0 5 1;
#X connect 10 0 0 0;
#X connect 10 0 8 0;
#X connect 10 1 11 0;
#X connect 10 1 15 1;
#X connect 11 0 12 0;
#X connect 13 0 14 0;
#X connect 14 0 10 0;
#X connect 15 0 10 0;
#X connect 16 0 15 0;





More information about the Pd-cvs mailing list