diff options
author | Martin Peach <mrpeach@users.sourceforge.net> | 2007-01-28 21:21:59 +0000 |
---|---|---|
committer | Martin Peach <mrpeach@users.sourceforge.net> | 2007-01-28 21:21:59 +0000 |
commit | 1e8707c613a83a0fc506eae10a7fda33db0e6991 (patch) | |
tree | 3096743aeb56635d4569b989307efb417f7ddff2 /str/str.c | |
parent | a747b301849a7660f1dd6202f50372c67b771db1 (diff) |
An external that uses the string type. PD needs to be patched for this...
svn path=/trunk/externals/mrpeach/; revision=7390
Diffstat (limited to 'str/str.c')
-rwxr-xr-x | str/str.c | 727 |
1 files changed, 727 insertions, 0 deletions
diff --git a/str/str.c b/str/str.c new file mode 100755 index 0000000..2f4e2f1 --- /dev/null +++ b/str/str.c @@ -0,0 +1,727 @@ +/* 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 */ + |