13 Jan, 2013, Scandum wrote in the 1st comment:
Votes: 0
I wrote an MSDP 2 JSON function in C for client developers who are comfortable with JSON. The code is public domain.

As input it assumes the string 'src' contains: IAC SB MSDP <data> IAC SE. If the string just contains the data (so no IAC SB MSDP) you need to use i = 0 and properly check for a string terminator. The integer srclen contains the length of src, this isn't entirely necessary as MSDP data should never contain a string terminator, so depending on the implementation you can strip it out.

This functions translates an MSDP data string to JSON data strings, and it indicates where you need to raise events. The events should contain the 'var' (variable) and 'val' (value) strings.

Ideally, for each variable, you'd raise a generic "MSDP" event that contains 'var' and 'val'. People would use this to handle sets of variables that have a lot in common and can use the same functions. In addition you want to raise a "MSDP <var>" event so people can respond to receiving a specific variable. In addition you can raise an event at the end of receiving an MSDP subnegotiation so people can refresh their interface and/or carry out other generic activities.

I tested it and as far as I know it's bug free.

#define     MSDP_VAR              1
#define MSDP_VAL 2
#define MSDP_TABLE_OPEN 3
#define MSDP_TABLE_CLOSE 4
#define MSDP_ARRAY_OPEN 5
#define MSDP_ARRAY_CLOSE 6

#define BUFFER_SIZE 20000

void msdp2json(unsigned char *src, int srclen)
{
char var[BUFFER_SIZE], val[BUFFER_SIZE], *pto;
int i, nest, last;

var[0] = val[0] = nest = last = 0;

i = 3; // skip past IAC SB MSDP

pto = var;

while (i < srclen)
{
if (src[i] == IAC && src[i+1] == SE)
{
break;
}

switch (src[i])
{
case MSDP_TABLE_OPEN:
*pto++ = '{';
nest++;
last = MSDP_TABLE_OPEN;
break;

case MSDP_TABLE_CLOSE:
if (last == MSDP_VAL || last == MSDP_VAR)
{
*pto++ = '"';
}
if (nest)
{
nest–;
}
*pto++ = '}';
last = MSDP_TABLE_CLOSE;
break;

case MSDP_ARRAY_OPEN:
*pto++ = '[';
nest++;
last = MSDP_ARRAY_OPEN;
break;

case MSDP_ARRAY_CLOSE:
if (last == MSDP_VAL || last == MSDP_VAR)
{
*pto++ = '"';
}
if (nest)
{
nest–;
}
*pto++ = ']';
last = MSDP_ARRAY_CLOSE;
break;

case MSDP_VAR:
if (nest)
{
if (last == MSDP_VAL || last == MSDP_VAR)
{
*pto++ = '"';
}
if (last == MSDP_VAL || last == MSDP_VAR || last == MSDP_TABLE_CLOSE || last == MSDP_ARRAY_CLOSE)
{
*pto++ = ',';
}
*pto++ = '"';
}
else
{
*pto = 0;

if (last)
{
// raise an "MSDP var" event containing the 'val' string.
// raise an "MSDP" event containing the 'var' and 'val' strings.
}
pto = var;
}
last = MSDP_VAR;
break;

case MSDP_VAL:
if (nest)
{
if (last == MSDP_VAR)
{
*pto++ = '"';
*pto++ = ':';
}
if (last == MSDP_VAL)
{
*pto++ = '"';
*pto++ = ',';
}

if (src[i+1] != MSDP_TABLE_OPEN && src[i+1] != MSDP_ARRAY_OPEN)
{
*pto++ = '"';
}
}
else
{
*pto = 0;

if (last != MSDP_VAR)
{
// raise an "MSDP var" event containing the 'val' string.
// raise an "MSDP" event containing the 'var' and 'val' strings.
}
pto = val;
}
last = MSDP_VAL;
break;

case '\\':
*pto++ = '\\';
*pto++ = '\\';
break;

case '"':
*pto++ = '\\';
*pto++ = '"';
break;

default:
*pto++ = src[i];
break;
}
i++;
}

if (src[i] == IAC)
{
*pto = 0;

if (last)
{
// raise an "MSDP var" event containing the 'val' string.
// raise an "MSDP" event containing the 'var' and 'val' strings.
}
i++;
}

// raise an "MSDP SE" event to signal the end of an MSDP subnegotiation.
}
17 Jan, 2013, Heiko wrote in the 2nd comment:
Votes: 0
I'm thinking about changing this to directly setup Lua tables instead as using JSON has a negative performance impact here. I have a couple of questions, but I prefer email contact. Can you send me another PM with your email address pleas. Thank you.
18 Jan, 2013, Scandum wrote in the 3rd comment:
Votes: 0
Alright.

For those interested.

To make this work for Lua you would:

1) Edit line 101 and change ':' to '='
2) Edit line 50 and change '[' to '{'
3) Edit line 64 and change ']' to '}'

I think that's all, though quotes may have to be omitted for variable names? Right now it would use:

{ "var" = "val" }

This could be change to

{ var = "val" }

or

{ ["var"] = "val" }

I can update the specification to disallow the use of spaces in variable names, and it's probably for the best to ban anything else that's incompatible with json, lua, and jscript. This way quotes can be omitted for variable names inside tables.

I'm not sure if variable names should be allowed to contain a . and brackets [] to directly update nested data. This seems like useful behavior, but I'm not sure if that's going to create implementation difficulties on other platforms, like browser based clients.
19 Jan, 2013, quixadhal wrote in the 4th comment:
Votes: 0
Just as a general FYI, JSON and LPC object formats (IE: mudmode sockets) are also very similar. AFAIK, there isn't a general LPC implementation of the JSON API (there is for DGD, but it relies on parse_string(), which is DGD specific).

Essentially, arrays are ({ }) instead of [ ], mappings are ([ "a" : "b" ]) instead of { "a" : "b" }, and the NUL byte is \0 instead of \u0000.
0.0/4