ultimatepp/uppsrc/ide/Debuggers/MIValue.cpp
micio f7679cc1c8 Ide/Debuggers : fixed some bugs in Gdb_MI2 frontend -- removed Asynchronous break because of problems
git-svn-id: svn://ultimatepp.org/upp/trunk@5152 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2012-07-08 16:12:17 +00:00

401 lines
6.7 KiB
C++

#include "MIValue.h"
static MIValue &NullMIValue(void)
{
static MIValue v;
return v;
}
static MIValue &ErrorMIValue(String const &msg)
{
static MIValue v;
v.SetError(msg);
return v;
}
int MIValue::ParsePair(String &name, MIValue &val, String const &s, int i)
{
name.Clear();
val.Clear();
while(s[i] && (s[i] != '=') && s[i] != ']' && s[i] != '}')
name.Cat(s[i++]);
if(s[i] != '=')
return i;
i++;
switch(s[i])
{
case '"':
{
i = val.ParseString(s, i);
break;
}
break;
case '[':
i = val.ParseArray(s, i);
break;
case '{':
i = val.ParseTuple(s, i);
break;
default:
NEVER();
}
return i;
}
int MIValue::ParseTuple(String const &s, int i)
{
Clear();
type = MITuple;
// drop opening delimiter
if(s[i] != '{')
{
SetError(Format("Expected '{' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
while(s[i] && s[i] != '}')
{
String name;
MIValue val;
i = ParsePair(name, val, s, i);
tuple.Add(name, val);
if(s[i] == '}')
break;
if(s[i] != ',')
{
SetError(Format("Expected ',' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
}
return i + 1;
}
int MIValue::ParseArray(String const &s, int i)
{
Clear();
type = MIArray;
// drop opening delimiter
if(s[i] != '[')
{
SetError(Format("Expected '[' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
while(s[i] && s[i] != ']')
{
String name;
MIValue val;
if(s[i] == '[')
i = val.ParseArray(s, i);
else if(s[i] == '{')
i = val.ParseTuple(s, i);
else if(s[i] == '"')
i = val.ParseString(s, i);
else
i = ParsePair(name, val, s, i);
array.Add(val);
if(s[i] == ']')
break;
if(s[i] != ',')
{
SetError(Format("Expected ',' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
}
return i + 1;
}
int MIValue::ParseString(String const &s, int i)
{
Clear();
type = MIString;
char c;
if(s[i] != '"')
{
SetError(Format("Expected '\"' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
while( (c = s[i++]) != 0)
{
// verbatim if escaped
if(c == '\\')
string.Cat(s[i++]);
else if(c == '"')
break;
else
string.Cat(c);
}
if(c != '"')
{
SetError(Format("Expected '\"' at pos %d in '%s'", i, s));
return s.GetCount();
}
return i;
}
int MIValue::Parse(String const &s, int i)
{
// if starts with '"', it's a string
// if starts with '[', it's an array
// if starts with '{', it's a tuple
// otherwise, it can be a sequence of pair name="value" which is stored like a tuple
// latter case is an example o bad design of MI interface....
Clear();
if(s[i] == '"')
return ParseString(s, i);
else if(s[i] == '[')
return ParseArray(s, i);
else if(s[i] == '{')
return ParseTuple(s, i);
else
{
String name;
MIValue val;
type = MITuple;
while(s[i])
{
i = ParsePair(name, val, s, i);
tuple.Add(name, val);
if(s[i] != ',')
break;
i++;
}
return i;
}
}
MIValue &MIValue::operator=(pick_ MIValue &v)
{
Clear();
type = v.type;
switch(type)
{
case MIString:
string = v.string;
break;
case MIArray:
array = v.array;
break;
case MITuple:
tuple = v.tuple;
break;
default:
SetError("Unknown MIValue type");
}
return *this;
}
MIValue::MIValue()
{
Clear();
}
MIValue::MIValue(MIValue pick_ &v)
{
Clear();
type = v.type;
switch(type)
{
case MIString:
string = v.string;
break;
case MIArray:
array = v.array;
break;
case MITuple:
tuple = v.tuple;
break;
default:
SetError("Unknown MIValue type");
}
}
MIValue::MIValue(String const &s)
{
Parse(s);
}
MIValue &MIValue::operator=(String const &s)
{
Parse(s);
return *this;
}
void MIValue::Clear()
{
type = MIString;
string = "";
array.Clear();
tuple.Clear();
}
// sets value to an error condition
MIValue &MIValue::SetError(String const &msg)
{
type = MIString;
string = "error:" + msg;
return *this;
}
// check if value contains an error
bool MIValue::IsError(void) const
{
return type == MIString && string.StartsWith("error:");
}
// check for emptyness
bool MIValue::IsEmpty(void) const
{
return type == MIString && string == "";
}
// simple accessors
int MIValue::GetCount(void) const
{
if(IsError())
return 0;
if(type == MIArray)
return array.GetCount();
else if(type == MITuple)
return tuple.GetCount();
else
return string.GetCount();
}
int MIValue::Find(const char *key) const
{
if(type != MITuple)
return -1;
return tuple.Find(key);
}
MIValue &MIValue::Get(int i)
{
if(IsError())
return *this;
if(type != MIArray)
return ErrorMIValue("Not an Array value type");
return array[i];
}
MIValue &MIValue::Get(const char *key)
{
if(type != MITuple)
return ErrorMIValue("Not a Tuple value type");
return tuple.Get(key);
}
String &MIValue::Get(void)
{
if(type != MIString)
return ErrorMIValue("Not a String value type");
return string;
}
String const &MIValue::Get(void) const
{
if(type != MIString)
return ErrorMIValue("Not a String value type");
return string;
}
// tuple string member accessor with default value if not found
String MIValue::Get(const char *key, const char *def) const
{
if(type != MITuple)
return ErrorMIValue("Not a Tuple value type");
int i = tuple.Find(key);
if(i >= 0)
{
if(tuple[i].type != MIString)
return def;
return tuple[i].Get();
}
else
return def;
}
// data dump
String MIValue::Dump(int level) const
{
String spacer(' ', level);
switch(type)
{
case MIString:
return spacer + string;
case MITuple:
{
String s = spacer + "{\n";
level += 4;
spacer = String(' ', level);
for(int i = 0; i < tuple.GetCount(); i++)
{
String s1 = spacer + tuple.GetKey(i) + "=";
s += s1;
MIValue const &val = tuple[i];
if(val.type == MIString)
s += val.Dump();
else
{
s += '\n' + val.Dump(level + 4);
s = s.Left(s.GetCount()-1);
}
if(i < tuple.GetCount() - 1)
s += ',';
s += '\n';
}
level -= 4;
spacer = String(' ', level);
s += spacer + "}\n";
return s;
}
case MIArray:
{
String s = spacer + "[ \n";
level += 4;
for(int i = 0; i < array.GetCount(); i++)
{
MIValue const &val = array[i];
s += val.Dump(level);
if(val.type != MIString)
s = s.Left(s.GetCount()-1);
if(i < array.GetCount() - 1)
s += ',';
s += '\n';
}
s += spacer + "]\n";
return s;
}
default:
return spacer + "*UNKNOWN MIVALUE TYPE*";
}
}
// finds breakpoint data given file and line
MIValue &MIValue::FindBreakpoint(String const &file, int line)
{
MIValue &body = Get("body");
if(body.IsError() || !body.IsArray())
return NullMIValue();
for(int i = 0; i < body.GetCount(); i++)
{
MIValue &bp = body[i];
if(bp.IsError() || !bp.IsTuple())
return NullMIValue();
if(bp["file"] == file && atoi(bp["line"].Get()) == line)
return bp;
}
return NullMIValue();
}