/*
* NAME: vartext.c
* DESCRIPTION: variable-to-text translators
*/
inherit "/std/string";
inherit "/std/eefun";
# include "vartext.h"
# include <dgd/type.h>
/*
* NAME: type_str()
* DESCRIPTION: return a string indicating value type
*/
static
string type_str(mixed var)
{
switch (typeof(var))
{
case T_INT:
return "int";
case T_FLOAT:
return "float";
case T_STRING:
return "string";
case T_OBJECT:
return "object";
case T_ARRAY:
return "mixed *";
case T_MAPPING:
return "mapping";
default:
error("Unknown return value from typeof()");
}
}
/*
* NAME: elements_of_arr()
* DESCRIPTION: return a string representing the elements of an array
*/
private
string elements_of_arr(mixed *var)
{
int i, sz;
string str;
str = "";
for (i = 0, sz = sizeof(var); i < sz; ++i)
str += " " + var2str(var[i]) + (i < sz - 1 ? "," : "");
return str;
}
/*
* NAME: elements_of_map()
* DESCRIPTION: return a string representing the elements of a mapping
*/
private
string elements_of_map(mapping var)
{
mixed *keys, *values;
int i, sz;
string str;
keys = map_indices(var);
values = map_values(var);
str = "";
for (i = 0, sz = sizeof(keys); i < sz; ++i)
str += " " + var2str(keys[i]) + " : " + var2str(values[i]) +
(i < sz - 1 ? "," : "");
return str;
}
/*
* NAME: var2str()
* DESCRIPTION: given a variable of any type, return a string representation
*/
static
string var2str(mixed var)
{
switch (typeof(var))
{
case T_INT:
return (string) var;
case T_FLOAT:
return flt2str(var);
case T_STRING:
return "\"" + escape_str(var) + "\"";
case T_OBJECT:
return object_name(var);
case T_ARRAY:
return "({" + elements_of_arr((mixed *) var) + " })";
case T_MAPPING:
return "([" + elements_of_map(var) + " ])";
default:
return "#unknown";
}
}
/*
* NAME: tokenize()
* DESCRIPTION: convert a string into an array of tokens
*/
private
mixed **tokenize(string str)
{
mixed **tokens;
int i, j, sz, val, neg, flt;
float flval;
tokens = ({ });
for (i = 0, sz = strlen(str); i < sz; ++i)
switch (str[i])
{
case ' ': case '\t': case '\n':
continue;
case ',':
tokens += ({ ({ ',' }) });
break;
case ':':
tokens += ({ ({ ':' }) });
break;
case '-': case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (neg = (str[i] == '-'))
{
if (i == sz - 1)
break;
++i;
}
if (str[i] == '.')
{
val = 0;
--i;
}
else
val = str[i] - '0';
while (++i < sz && str[i] >= '0' && str[i] <= '9')
val = 10 * val + str[i] - '0';
if (i < sz && str[i] == '.')
{
int hund;
flt = 1;
flval = (float) val;
hund = 1;
while (++i < sz && str[i] >= '0' && str[i] <= '9')
flval += (1.0 / ((float) (hund *= 10))) * (float) (str[i] - '0');
}
else
flt = 0;
if (i < sz - 1)
--i;
if (flt)
{
if (neg)
flval = -flval;
tokens += ({ ({ '.', flval }) });
}
else
{
if (neg)
val = -val;
tokens += ({ ({ '1', val }) });
}
break;
case '\"':
if (i == sz - 1)
continue;
for (j = i + 1; j < sz; ++j)
{
if (str[j] == '\\')
{
++j;
continue;
}
if (str[j] == '\"')
break;
}
tokens += ({ ({ '\"', unescape_str(str[i + 1 .. j - 1]) }) });
i = j;
break;
case '/':
case '#':
for (j = i + 1; j < sz; ++j)
{
if (str[j] == ' ' || str[j] == ',' || str[j] == ':' ||
str[j] == '}' || str[j] == ']')
break;
}
if (str[i] == '/')
tokens += ({ ({ '/', find_object(str[i .. j - 1]) }) });
i = j - 1;
break;
case '(':
if (i == sz - 1)
continue;
if (str[++i] == '{')
tokens += ({ ({ '{' }) });
else if (str[i] == '[')
tokens += ({ ({ '[' }) });
break;
case ']':
if (i == sz - 1)
continue;
if (str[++i] == ')')
tokens += ({ ({ ']' }) });
break;
case '}':
if (i == sz - 1)
continue;
if (str[++i] == ')')
tokens += ({ ({ '}' }) });
break;
}
return tokens;
}
/*
* NAME: parse_element()
* DESCRIPTION: given an array of tokens, parse the first data element
* RETURNS: ({ element, next_token_index })
*/
private
mixed *parse_element(mixed **tokens, int item)
{
int i, sz;
mixed *arr, *elem, *key;
mapping map;
sz = sizeof(tokens);
if (sz == 0 || item >= sz)
return ({ 0, item });
switch (tokens[item][0])
{
case '1':
case '.':
case '\"':
case '/':
return ({ tokens[item][1], item + 1 });
case '{':
arr = ({ });
for (i = item + 1; i < sz; ++i)
{
switch (tokens[i][0])
{
case ',':
continue;
case '}':
break;
default:
elem = parse_element(tokens, i);
arr += ({ elem[0] });
i = elem[1] - 1;
continue;
}
break;
}
return ({ arr, i + 1 });
case '[':
map = ([ ]);
for (i = item + 1; i < sz; ++i)
{
if (tokens[i][0] == ':')
{
elem = parse_element(tokens, i + 1);
if (key != 0)
{
map[key[0]] = elem[0];
key = 0;
}
i = elem[1] - 1;
continue;
}
if (tokens[i][0] == ',')
continue;
if (tokens[i][0] == ']')
break;
key = parse_element(tokens, i);
i = key[1] - 1;
}
return ({ map, i + 1 });
}
return ({ 0, item + 1 });
}
/*
* NAME: str2var()
* DESCRIPTION: given a string representing a value, return that value
*/
static
mixed str2var(string str)
{
if (str == 0)
return 0;
return parse_element(tokenize(str), 0)[0];
}