Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
39d3d35c
Commit
39d3d35c
authored
May 18, 2009
by
hjk
Browse files
debugger: add a primitive json parser (copied and trimmed from the mi parser)
parent
14241725
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/plugins/debugger/gdbmi.cpp
View file @
39d3d35c
...
...
@@ -52,7 +52,7 @@ void GdbMi::parseResultOrValue(const char *&from, const char *to)
//qDebug() << "parseResultOrValue: " << QByteArray(from, to - from);
parseValue
(
from
,
to
);
if
(
isValid
())
{
//qDebug() << "no valid result in " << QByteArray
::fromLatin1
(from, to - from);
//qDebug() << "no valid result in " << QByteArray(from, to - from);
return
;
}
if
(
from
==
to
||
*
from
==
'('
)
...
...
@@ -73,7 +73,7 @@ void GdbMi::parseResultOrValue(const char *&from, const char *to)
QByteArray
GdbMi
::
parseCString
(
const
char
*&
from
,
const
char
*
to
)
{
QByteArray
result
;
//qDebug() << "parseCString: " << QByteArray
::fromUtf16
(from, to - from);
//qDebug() << "parseCString: " << QByteArray(from, to - from);
if
(
*
from
!=
'"'
)
{
qDebug
()
<<
"MI Parse Error, double quote expected"
;
++
from
;
// So we don't hang
...
...
@@ -152,7 +152,7 @@ QByteArray GdbMi::parseCString(const char *&from, const char *to)
void
GdbMi
::
parseValue
(
const
char
*&
from
,
const
char
*
to
)
{
//qDebug() << "parseValue: " << QByteArray
::fromUtf16
(from, to - from);
//qDebug() << "parseValue: " << QByteArray(from, to - from);
switch
(
*
from
)
{
case
'{'
:
parseTuple
(
from
,
to
);
...
...
@@ -172,7 +172,7 @@ void GdbMi::parseValue(const char *&from, const char *to)
void
GdbMi
::
parseTuple
(
const
char
*&
from
,
const
char
*
to
)
{
//qDebug() << "parseTuple: " << QByteArray
::fromUtf16
(from, to - from);
//qDebug() << "parseTuple: " << QByteArray(from, to - from);
QTC_ASSERT
(
*
from
==
'{'
,
/**/
);
++
from
;
parseTuple_helper
(
from
,
to
);
...
...
@@ -180,7 +180,7 @@ void GdbMi::parseTuple(const char *&from, const char *to)
void
GdbMi
::
parseTuple_helper
(
const
char
*&
from
,
const
char
*
to
)
{
//qDebug() << "parseTuple_helper: " << QByteArray
::fromUtf16
(from, to - from);
//qDebug() << "parseTuple_helper: " << QByteArray(from, to - from);
m_type
=
Tuple
;
while
(
from
<
to
)
{
if
(
*
from
==
'}'
)
{
...
...
@@ -200,7 +200,7 @@ void GdbMi::parseTuple_helper(const char *&from, const char *to)
void
GdbMi
::
parseList
(
const
char
*&
from
,
const
char
*
to
)
{
//qDebug() << "parseList: " << QByteArray
::fromUtf16
(from, to - from);
//qDebug() << "parseList: " << QByteArray(from, to - from);
QTC_ASSERT
(
*
from
==
'['
,
/**/
);
++
from
;
m_type
=
List
;
...
...
src/plugins/debugger/json.cpp
0 → 100644
View file @
39d3d35c
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#include "json.h"
#include <utils/qtcassert.h>
#include <QtCore/QByteArray>
#include <QtCore/QTextStream>
#include <ctype.h>
//#define DEBUG_JASON
#ifdef DEBUG_JASON
#define JDEBUG(s) qDebug() << s
#else
#define JDEBUG(s)
#endif
namespace
Debugger
{
namespace
Internal
{
static
void
skipSpaces
(
const
char
*&
from
,
const
char
*
to
)
{
while
(
from
!=
to
&&
isspace
(
*
from
))
++
from
;
}
QTextStream
&
operator
<<
(
QTextStream
&
os
,
const
JsonValue
&
mi
)
{
return
os
<<
mi
.
toString
();
}
void
JsonValue
::
parsePair
(
const
char
*&
from
,
const
char
*
to
)
{
skipSpaces
(
from
,
to
);
JDEBUG
(
"parsePair: "
<<
QByteArray
(
from
,
to
-
from
));
m_name
=
parseCString
(
from
,
to
);
skipSpaces
(
from
,
to
);
while
(
from
<
to
&&
*
from
!=
':'
)
{
JDEBUG
(
"not a colon"
<<
*
from
);
++
from
;
}
++
from
;
parseValue
(
from
,
to
);
skipSpaces
(
from
,
to
);
}
QByteArray
JsonValue
::
parseNumber
(
const
char
*&
from
,
const
char
*
to
)
{
QByteArray
result
;
while
(
from
<
to
&&
*
from
>=
'0'
&&
*
from
<=
'9'
)
result
.
append
(
*
from
++
);
return
result
;
}
QByteArray
JsonValue
::
parseCString
(
const
char
*&
from
,
const
char
*
to
)
{
QByteArray
result
;
JDEBUG
(
"parseCString: "
<<
QByteArray
(
from
,
to
-
from
));
if
(
*
from
!=
'"'
)
{
qDebug
()
<<
"JSON Parse Error, double quote expected"
;
++
from
;
// So we don't hang
return
QByteArray
();
}
const
char
*
ptr
=
from
;
++
ptr
;
while
(
ptr
<
to
)
{
if
(
*
ptr
==
'"'
)
{
++
ptr
;
result
=
QByteArray
(
from
+
1
,
ptr
-
from
-
2
);
break
;
}
if
(
*
ptr
==
'\\'
)
{
++
ptr
;
if
(
ptr
==
to
)
{
qDebug
()
<<
"JSON Parse Error, unterminated backslash escape"
;
from
=
ptr
;
// So we don't hang
return
QByteArray
();
}
}
++
ptr
;
}
from
=
ptr
;
int
idx
=
result
.
indexOf
(
'\\'
);
if
(
idx
>=
0
)
{
char
*
dst
=
result
.
data
()
+
idx
;
const
char
*
src
=
dst
+
1
,
*
end
=
result
.
data
()
+
result
.
length
();
do
{
char
c
=
*
src
++
;
switch
(
c
)
{
case
'a'
:
*
dst
++
=
'\a'
;
break
;
case
'b'
:
*
dst
++
=
'\b'
;
break
;
case
'f'
:
*
dst
++
=
'\f'
;
break
;
case
'n'
:
*
dst
++
=
'\n'
;
break
;
case
'r'
:
*
dst
++
=
'\r'
;
break
;
case
't'
:
*
dst
++
=
'\t'
;
break
;
case
'v'
:
*
dst
++
=
'\v'
;
break
;
case
'"'
:
*
dst
++
=
'"'
;
break
;
case
'\\'
:
*
dst
++
=
'\\'
;
break
;
default:
{
int
chars
=
0
;
uchar
prod
=
0
;
forever
{
if
(
c
<
'0'
||
c
>
'7'
)
{
--
src
;
break
;
}
prod
=
prod
*
8
+
c
-
'0'
;
if
(
++
chars
==
3
||
src
==
end
)
break
;
c
=
*
src
++
;
}
if
(
!
chars
)
{
qDebug
()
<<
"JSON Parse Error, unrecognized backslash escape"
;
return
QByteArray
();
}
*
dst
++
=
prod
;
}
}
while
(
src
!=
end
)
{
char
c
=
*
src
++
;
if
(
c
==
'\\'
)
break
;
*
dst
++
=
c
;
}
}
while
(
src
!=
end
);
*
dst
=
0
;
result
.
truncate
(
dst
-
result
.
data
());
}
JDEBUG
(
"parseCString, got "
<<
result
);
return
result
;
}
void
JsonValue
::
parseValue
(
const
char
*&
from
,
const
char
*
to
)
{
JDEBUG
(
"parseValue: "
<<
QByteArray
(
from
,
to
-
from
));
switch
(
*
from
)
{
case
'{'
:
parseObject
(
from
,
to
);
break
;
case
'['
:
parseArray
(
from
,
to
);
break
;
case
'"'
:
m_type
=
String
;
m_data
=
parseCString
(
from
,
to
);
break
;
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
m_type
=
Number
;
m_data
=
parseNumber
(
from
,
to
);
default:
break
;
}
}
void
JsonValue
::
parseObject
(
const
char
*&
from
,
const
char
*
to
)
{
JDEBUG
(
"parseObject: "
<<
QByteArray
(
from
,
to
-
from
));
QTC_ASSERT
(
*
from
==
'{'
,
/**/
);
++
from
;
m_type
=
Object
;
while
(
from
<
to
)
{
if
(
*
from
==
'}'
)
{
++
from
;
break
;
}
JsonValue
child
;
child
.
parsePair
(
from
,
to
);
if
(
!
child
.
isValid
())
return
;
m_children
+=
child
;
if
(
*
from
==
','
)
++
from
;
}
}
void
JsonValue
::
parseArray
(
const
char
*&
from
,
const
char
*
to
)
{
JDEBUG
(
"parseArray: "
<<
QByteArray
(
from
,
to
-
from
));
QTC_ASSERT
(
*
from
==
'['
,
/**/
);
++
from
;
m_type
=
Array
;
while
(
from
<
to
)
{
if
(
*
from
==
']'
)
{
++
from
;
break
;
}
JsonValue
child
;
child
.
parseValue
(
from
,
to
);
if
(
child
.
isValid
())
m_children
+=
child
;
if
(
*
from
==
','
)
++
from
;
}
}
void
JsonValue
::
setStreamOutput
(
const
QByteArray
&
name
,
const
QByteArray
&
content
)
{
if
(
content
.
isEmpty
())
return
;
JsonValue
child
;
child
.
m_type
=
String
;
child
.
m_name
=
name
;
child
.
m_data
=
content
;
m_children
+=
child
;
if
(
m_type
==
Invalid
)
m_type
=
Object
;
}
static
QByteArray
ind
(
int
indent
)
{
return
QByteArray
(
2
*
indent
,
' '
);
}
void
JsonValue
::
dumpChildren
(
QByteArray
*
str
,
bool
multiline
,
int
indent
)
const
{
for
(
int
i
=
0
;
i
<
m_children
.
size
();
++
i
)
{
if
(
i
!=
0
)
{
*
str
+=
','
;
if
(
multiline
)
*
str
+=
'\n'
;
}
if
(
multiline
)
*
str
+=
ind
(
indent
);
*
str
+=
m_children
.
at
(
i
).
toString
(
multiline
,
indent
);
}
}
class
MyString
:
public
QString
{
public:
ushort
at
(
int
i
)
const
{
return
constData
()[
i
].
unicode
();
}
};
template
<
class
ST
,
typename
CT
>
inline
ST
escapeCStringTpl
(
const
ST
&
ba
)
{
ST
ret
;
ret
.
reserve
(
ba
.
length
()
*
2
);
for
(
int
i
=
0
;
i
<
ba
.
length
();
++
i
)
{
CT
c
=
ba
.
at
(
i
);
switch
(
c
)
{
case
'\\'
:
ret
+=
"
\\\\
"
;
break
;
case
'\a'
:
ret
+=
"
\\
a"
;
break
;
case
'\b'
:
ret
+=
"
\\
b"
;
break
;
case
'\f'
:
ret
+=
"
\\
f"
;
break
;
case
'\n'
:
ret
+=
"
\\
n"
;
break
;
case
'\r'
:
ret
+=
"
\\
r"
;
break
;
case
'\t'
:
ret
+=
"
\\
t"
;
break
;
case
'\v'
:
ret
+=
"
\\
v"
;
break
;
case
'"'
:
ret
+=
"
\\\"
"
;
break
;
default:
if
(
c
<
32
||
c
==
127
)
{
ret
+=
'\\'
;
ret
+=
'0'
+
(
c
>>
6
);
ret
+=
'0'
+
((
c
>>
3
)
&
7
);
ret
+=
'0'
+
(
c
&
7
);
}
else
{
ret
+=
c
;
}
}
}
return
ret
;
}
QString
JsonValue
::
escapeCString
(
const
QString
&
ba
)
{
return
escapeCStringTpl
<
MyString
,
ushort
>
(
static_cast
<
const
MyString
&>
(
ba
));
}
QByteArray
JsonValue
::
escapeCString
(
const
QByteArray
&
ba
)
{
return
escapeCStringTpl
<
QByteArray
,
uchar
>
(
ba
);
}
QByteArray
JsonValue
::
toString
(
bool
multiline
,
int
indent
)
const
{
QByteArray
result
;
switch
(
m_type
)
{
case
Invalid
:
if
(
multiline
)
result
+=
ind
(
indent
)
+
"Invalid
\n
"
;
else
result
+=
"Invalid"
;
break
;
case
String
:
if
(
!
m_name
.
isEmpty
())
result
+=
m_name
+
"="
;
result
+=
'"'
+
escapeCString
(
m_data
)
+
'"'
;
break
;
case
Number
:
if
(
!
m_name
.
isEmpty
())
result
+=
'"'
+
m_name
+
"
\"
:"
;
result
+=
m_data
;
break
;
case
Object
:
if
(
!
m_name
.
isEmpty
())
result
+=
m_name
+
'='
;
if
(
multiline
)
{
result
+=
"{
\n
"
;
dumpChildren
(
&
result
,
multiline
,
indent
+
1
);
result
+=
'\n'
+
ind
(
indent
)
+
"}"
;
}
else
{
result
+=
"{"
;
dumpChildren
(
&
result
,
multiline
,
indent
+
1
);
result
+=
"}"
;
}
break
;
case
Array
:
if
(
!
m_name
.
isEmpty
())
result
+=
m_name
+
"="
;
if
(
multiline
)
{
result
+=
"[
\n
"
;
dumpChildren
(
&
result
,
multiline
,
indent
+
1
);
result
+=
'\n'
+
ind
(
indent
)
+
"]"
;
}
else
{
result
+=
"["
;
dumpChildren
(
&
result
,
multiline
,
indent
+
1
);
result
+=
"]"
;
}
break
;
}
return
result
;
}
void
JsonValue
::
fromString
(
const
QByteArray
&
ba
)
{
const
char
*
from
=
ba
.
constBegin
();
const
char
*
to
=
ba
.
constEnd
();
parseValue
(
from
,
to
);
}
JsonValue
JsonValue
::
findChild
(
const
char
*
name
)
const
{
for
(
int
i
=
0
;
i
<
m_children
.
size
();
++
i
)
if
(
m_children
.
at
(
i
).
m_name
==
name
)
return
m_children
.
at
(
i
);
return
JsonValue
();
}
}
// namespace Internal
}
// namespace Debugger
src/plugins/debugger/json.h
0 → 100644
View file @
39d3d35c
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#ifndef DEBUGGER_JSON_H
#define DEBUGGER_JSON_H
#include <QtCore/QByteArray>
#include <QtCore/QList>
namespace
Debugger
{
namespace
Internal
{
class
JsonValue
{
public:
JsonValue
()
:
m_type
(
Invalid
)
{}
explicit
JsonValue
(
const
QByteArray
&
str
)
{
fromString
(
str
);
}
QByteArray
m_name
;
QByteArray
m_data
;
QList
<
JsonValue
>
m_children
;
enum
Type
{
Invalid
,
String
,
Number
,
Object
,
Array
,
};
Type
m_type
;
inline
Type
type
()
const
{
return
m_type
;
}
inline
QByteArray
name
()
const
{
return
m_name
;
}
inline
bool
hasName
(
const
char
*
name
)
const
{
return
m_name
==
name
;
}
inline
bool
isValid
()
const
{
return
m_type
!=
Invalid
;
}
inline
bool
isNumber
()
const
{
return
m_type
==
Number
;
}
inline
bool
isString
()
const
{
return
m_type
==
String
;
}
inline
bool
isObject
()
const
{
return
m_type
==
Object
;
}
inline
bool
isArray
()
const
{
return
m_type
==
Array
;
}
inline
QByteArray
data
()
const
{
return
m_data
;
}
inline
const
QList
<
JsonValue
>
&
children
()
const
{
return
m_children
;
}
inline
int
childCount
()
const
{
return
m_children
.
size
();
}
const
JsonValue
&
childAt
(
int
index
)
const
{
return
m_children
[
index
];
}
JsonValue
&
childAt
(
int
index
)
{
return
m_children
[
index
];
}
JsonValue
findChild
(
const
char
*
name
)
const
;
QByteArray
toString
(
bool
multiline
=
false
,
int
indent
=
0
)
const
;
void
fromString
(
const
QByteArray
&
str
);
void
setStreamOutput
(
const
QByteArray
&
name
,
const
QByteArray
&
content
);
private:
static
QByteArray
parseCString
(
const
char
*&
from
,
const
char
*
to
);
static
QByteArray
parseNumber
(
const
char
*&
from
,
const
char
*
to
);
static
QByteArray
escapeCString
(
const
QByteArray
&
ba
);
static
QString
escapeCString
(
const
QString
&
ba
);
void
parsePair
(
const
char
*&
from
,
const
char
*
to
);
void
parseValue
(
const
char
*&
from
,
const
char
*
to
);
void
parseObject
(
const
char
*&
from
,
const
char
*
to
);
void
parseArray
(
const
char
*&
from
,
const
char
*
to
);
void
dumpChildren
(
QByteArray
*
str
,
bool
multiline
,
int
indent
)
const
;
};
}
// namespace Internal
}
// namespace Debugger
//Q_DECLARE_METATYPE(GdbDebugger::Internal::JsonValue);
#endif // DEBUGGER_JSON_H
src/plugins/debugger/tcfengine.cpp
View file @
39d3d35c
...
...
@@ -40,7 +40,7 @@
#include "watchhandler.h"
#include "watchutils.h"
#include "moduleshandler.h"
#include "
gdbmi
.h"
#include "
json
.h"
#include <utils/qtcassert.h>
...
...
@@ -92,18 +92,6 @@ QByteArray C(const QByteArray &ba1,
//#define USE_CONGESTION_CONTROL
///////////////////////////////////////////////////////////////////////
//
// TcfData
//
///////////////////////////////////////////////////////////////////////
TcfData
::
TcfData
(
const
QByteArray
&
data
)
{
fromString
(
data
);
}
///////////////////////////////////////////////////////////////////////
//
...
...
@@ -369,11 +357,11 @@ void TcfEngine::handleResponse(const QByteArray &response)
acknowledgeResult
();
int
token
=
parts
.
at
(
1
).
toInt
();
QByteArray
message
=
parts
.
at
(
2
);
TcfData
data
(
parts
.
at
(
3
));
JsonValue
data
(
parts
.
at
(
3
));
emit
tcfOutputAvailable
(
""
,
QString
::
number
(
token
)
+
"^"
+
quoteUnprintableLatin1
(
response
)
+
data
.
toString
());
TcfCommand
tcf
=
m_cookieForToken
[
token
];
TcfData
result
(
data
);
JsonValue
result
(
data
);
SDEBUG
(
"GOOD RESPONSE: "
<<
quoteUnprintableLatin1
(
response
));
if
(
tcf
.
callback
)
(
this
->*
(
tcf
.
callback
))(
result
,
tcf
.
cookie
);
...
...
@@ -384,13 +372,13 @@ void TcfEngine::handleResponse(const QByteArray &response)
}
else
if
(
n
==
4
&&
tag
==
"E"
)
{
// an event
QByteArray
service
=
parts
.
at
(
1
);
QByteArray
eventName
=
parts
.
at
(
2
);
TcfData
data
(
parts
.
at
(
3
));
JsonValue
data
(
parts
.
at
(
3
));
if
(
eventName
!=
"peerHeartBeat"
)
SDEBUG
(
_
(
"
\n
TCF EVENT:"
)
<<
quoteUnprintableLatin1
(
response
)
<<
data
.
toString
());
if
(
service
==
"Locator"
&&
eventName
==
"Hello"
)
{
m_services
.
clear
();
foreach
(
const
GdbMi
&
service
,
data
.
children
())
foreach
(
const
JsonValue
&
service
,
data
.
children
())
m_services
.
append
(
service
.
data
());
QTimer
::
singleShot
(
0
,
this
,
SLOT
(
startDebugging
()));
}
...
...
@@ -525,17 +513,17 @@ void TcfEngine::acknowledgeResult()
#endif
}
void
TcfEngine
::
handleRunControlSuspend
(
const
TcfData
&
data
,
const
QVariant
&
)
void
TcfEngine
::
handleRunControlSuspend
(
const
JsonValue
&
data
,
const
QVariant
&
)
{
SDEBUG
(
"HANDLE RESULT"
<<
data
.
toString
());
}
void
TcfEngine
::
handleRunControlGetChildren
(
const
TcfData
&
data
,
const
QVariant
&
)
void
TcfEngine
::
handleRunControlGetChildren
(
const
JsonValue
&
data
,
const
QVariant
&
)
{
SDEBUG
(
"HANDLE RUN CONTROL GET CHILDREN"
<<
data
.
toString
());
}
void
TcfEngine
::
handleSysMonitorGetChildren
(
const
TcfData
&
data
,
const
QVariant
&
)
void
TcfEngine
::
handleSysMonitorGetChildren
(
const
JsonValue
&
data
,
const
QVariant
&
)
{
SDEBUG
(
"HANDLE RUN CONTROL GET CHILDREN"
<<
data
.
toString
());
}
...
...
src/plugins/debugger/tcfengine.h
View file @
39d3d35c
...
...
@@ -49,7 +49,7 @@ QT_END_NAMESPACE
#include "idebuggerengine.h"
#include "debuggermanager.h"
#include "
gdbmi
.h"