/* $Header$ */
/*
* Copyright © 1988-2004 Keith Packard and Bart Massey.
* All Rights Reserved. See the file COPYING in this directory
* for licensing information.
*/
/*
* string.c
*
* provide builtin functions for the String namespace
*/
#include <ctype.h>
#include <strings.h>
#include <time.h>
#include "builtin.h"
NamespacePtr StringNamespace;
void
import_String_namespace()
{
ENTER ();
static const struct fbuiltin_1 funcs_1[] = {
{ do_String_length, "length", "i", "s", "\n"
" int length (string s)\n"
"\n"
" Return the number of characters in 's'.\n" },
{ do_String_new, "new", "s", "p", "\n"
" string new (int c)\n"
" string new (int[*] a)\n"
"\n"
" With 'c', return a single character string containing it.\n"
" With 'a', return a string constructed from the list of\n"
" characters in 'a'.\n" },
{ 0 }
};
static const struct fbuiltin_2 funcs_2[] = {
{ do_String_index, "index", "i", "ss", "\n"
" int index (string str, string substr)\n"
"\n"
" Return the index of the first location of 'substr'\n"
" within 'str', -1 if not found.\n" },
{ 0 }
};
static const struct fbuiltin_3 funcs_3[] = {
{ do_String_substr, "substr", "s", "sii", "\n"
" string substr (string str, int first, int len)\n"
"\n"
" Return a string containing characters in 'str' starting at\n"
" 'first' for 'len' characters.\n" },
{ 0 }
};
StringNamespace = BuiltinNamespace (/*parent*/ 0, "String")->namespace.namespace;
BuiltinFuncs1 (&StringNamespace, funcs_1);
BuiltinFuncs2 (&StringNamespace, funcs_2);
BuiltinFuncs3 (&StringNamespace, funcs_3);
EXIT ();
}
Value
do_String_length (Value av)
{
ENTER();
Value ret;
ret = NewInt(StringLength(StringChars(&av->string), av->string.length));
RETURN (ret);
}
Value
do_String_new (Value av)
{
ENTER ();
Value ret;
int len, i, size;
char *s;
if (ValueIsArray(av) && av->array.ndim == 1)
{
len = ArrayLimits(&av->array)[0];
size = 0;
for (i = 0; i < len; i++)
size += StringCharSize (IntPart (ArrayValue (&av->array, i),
"new: array element not integer"));
ret = NewString (size);
s = StringChars (&ret->string);
for (i = 0; i < len; i++)
{
s += StringPutChar (IntPart (ArrayValue (&av->array, i),
"new: array element not integer"),
s);
}
}
else
{
int c = IntPart (av, "new: argument not integer");
size = StringCharSize (c);
ret = NewString (size);
s = StringChars (&ret->string);
s += StringPutChar (c, s);
}
RETURN (ret);
}
Value
do_String_index (Value av, Value bv)
{
ENTER();
char *a, *b, *p;
long al;
Value ret;
int i;
a = StringChars(&av->string);
al = av->string.length;
b = StringChars(&bv->string);
p = strstr(a, b);
if (!p)
RETURN (NewInt(-1));
i = 0;
while (a < p)
{
unsigned c;
a = StringNextChar (a, &c, &al);
i++;
}
ret = NewInt(i);
RETURN (ret);
}
Value
do_String_substr (Value av, Value bv, Value cv)
{
ENTER();
char *a, *rchars, *e;
int b, c, al, size;
Value ret;
long alen = av->string.length;
long elen;
a = StringChars(&av->string);
al = StringLength (a, alen);
b = IntPart(bv, "substr: index not integer");
c = IntPart(cv, "substr: count not integer");
if (c < 0) {
b += c;
c = -c;
}
if (b < 0 || b > al)
{
RaiseStandardException (exception_invalid_argument,
"substr: index out of range",
2, NewInt (1), bv);
RETURN (av);
}
if (b + c > al)
{
RaiseStandardException (exception_invalid_argument,
"substr: count out of range",
2, NewInt (2), cv);
RETURN (av);
}
/*
* Find start of substring
*/
while (b > 0)
{
unsigned ch;
a = StringNextChar (a, &ch, &alen);
b--;
}
/*
* Find size of substring
*/
e = a;
elen = alen;
while (c > 0)
{
unsigned ch;
e = StringNextChar (e, &ch, &elen);
c--;
}
size = e - a;
ret = NewString(size);
rchars = StringChars(&ret->string);
memcpy (rchars, a, size);
RETURN (ret);
}
syntax highlighted by Code2HTML, v. 0.9.1