Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
yaml-cpp
Commits
9b4db068
Commit
9b4db068
authored
Mar 22, 2014
by
Jesse Beder
Browse files
Run clang-format
parent
e40ed4f9
Changes
78
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2733 additions
and
2763 deletions
+2733
-2763
src/collectionstack.h
src/collectionstack.h
+34
-23
src/contrib/graphbuilder.cpp
src/contrib/graphbuilder.cpp
+9
-10
src/contrib/graphbuilderadapter.cpp
src/contrib/graphbuilderadapter.cpp
+80
-87
src/contrib/graphbuilderadapter.h
src/contrib/graphbuilderadapter.h
+55
-57
src/directives.cpp
src/directives.cpp
+19
-21
src/directives.h
src/directives.h
+17
-17
src/emitfromevents.cpp
src/emitfromevents.cpp
+80
-93
src/emitter.cpp
src/emitter.cpp
+879
-924
src/emitterstate.cpp
src/emitterstate.cpp
+341
-378
src/emitterstate.h
src/emitterstate.h
+196
-172
src/emitterutils.cpp
src/emitterutils.cpp
+431
-413
src/emitterutils.h
src/emitterutils.h
+36
-23
src/exp.cpp
src/exp.cpp
+113
-96
src/exp.h
src/exp.h
+187
-175
src/indentation.h
src/indentation.h
+26
-25
src/null.cpp
src/null.cpp
+2
-3
src/ostream_wrapper.cpp
src/ostream_wrapper.cpp
+43
-51
src/parser.cpp
src/parser.cpp
+115
-129
src/ptr_stack.h
src/ptr_stack.h
+37
-34
src/ptr_vector.h
src/ptr_vector.h
+33
-32
No files found.
src/collectionstack.h
View file @
9b4db068
#ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <stack>
#include <cassert>
namespace
YAML
{
struct
CollectionType
{
enum
value
{
None
,
BlockMap
,
BlockSeq
,
FlowMap
,
FlowSeq
,
CompactMap
};
};
namespace
YAML
{
struct
CollectionType
{
enum
value
{
None
,
BlockMap
,
BlockSeq
,
FlowMap
,
FlowSeq
,
CompactMap
};
};
class
CollectionStack
{
public:
CollectionType
::
value
GetCurCollectionType
()
const
{
if
(
collectionStack
.
empty
())
return
CollectionType
::
None
;
return
collectionStack
.
top
();
}
void
PushCollectionType
(
CollectionType
::
value
type
)
{
collectionStack
.
push
(
type
);
}
void
PopCollectionType
(
CollectionType
::
value
type
)
{
assert
(
type
==
GetCurCollectionType
());
collectionStack
.
pop
();
}
class
CollectionStack
{
public:
CollectionType
::
value
GetCurCollectionType
()
const
{
if
(
collectionStack
.
empty
())
return
CollectionType
::
None
;
return
collectionStack
.
top
();
}
void
PushCollectionType
(
CollectionType
::
value
type
)
{
collectionStack
.
push
(
type
);
}
void
PopCollectionType
(
CollectionType
::
value
type
)
{
assert
(
type
==
GetCurCollectionType
());
collectionStack
.
pop
();
}
private:
std
::
stack
<
CollectionType
::
value
>
collectionStack
;
};
private:
std
::
stack
<
CollectionType
::
value
>
collectionStack
;
};
}
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif
// COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/contrib/graphbuilder.cpp
View file @
9b4db068
...
...
@@ -2,15 +2,14 @@
#include "yaml-cpp/contrib/graphbuilder.h"
#include "graphbuilderadapter.h"
namespace
YAML
{
void
*
BuildGraphOfNextDocument
(
Parser
&
parser
,
GraphBuilderInterface
&
graphBuilder
)
{
GraphBuilderAdapter
eventHandler
(
graphBuilder
);
if
(
parser
.
HandleNextDocument
(
eventHandler
))
{
return
eventHandler
.
RootNode
();
}
else
{
return
NULL
;
}
namespace
YAML
{
void
*
BuildGraphOfNextDocument
(
Parser
&
parser
,
GraphBuilderInterface
&
graphBuilder
)
{
GraphBuilderAdapter
eventHandler
(
graphBuilder
);
if
(
parser
.
HandleNextDocument
(
eventHandler
))
{
return
eventHandler
.
RootNode
();
}
else
{
return
NULL
;
}
}
}
src/contrib/graphbuilderadapter.cpp
View file @
9b4db068
#include "graphbuilderadapter.h"
namespace
YAML
{
int
GraphBuilderAdapter
::
ContainerFrame
::
sequenceMarker
;
void
GraphBuilderAdapter
::
OnNull
(
const
Mark
&
mark
,
anchor_t
anchor
)
{
void
*
pParent
=
GetCurrentParent
();
void
*
pNode
=
m_builder
.
NewNull
(
mark
,
pParent
);
RegisterAnchor
(
anchor
,
pNode
);
DispositionNode
(
pNode
);
}
void
GraphBuilderAdapter
::
OnAlias
(
const
Mark
&
mark
,
anchor_t
anchor
)
{
void
*
pReffedNode
=
m_anchors
.
Get
(
anchor
);
DispositionNode
(
m_builder
.
AnchorReference
(
mark
,
pReffedNode
));
}
void
GraphBuilderAdapter
::
OnScalar
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
,
const
std
::
string
&
value
)
{
void
*
pParent
=
GetCurrentParent
();
void
*
pNode
=
m_builder
.
NewScalar
(
mark
,
tag
,
pParent
,
value
);
RegisterAnchor
(
anchor
,
pNode
);
DispositionNode
(
pNode
);
}
void
GraphBuilderAdapter
::
OnSequenceStart
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
void
*
pNode
=
m_builder
.
NewSequence
(
mark
,
tag
,
GetCurrentParent
());
m_containers
.
push
(
ContainerFrame
(
pNode
));
RegisterAnchor
(
anchor
,
pNode
);
}
void
GraphBuilderAdapter
::
OnSequenceEnd
()
{
void
*
pSequence
=
m_containers
.
top
().
pContainer
;
m_containers
.
pop
();
DispositionNode
(
pSequence
);
}
void
GraphBuilderAdapter
::
OnMapStart
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
void
*
pNode
=
m_builder
.
NewMap
(
mark
,
tag
,
GetCurrentParent
());
m_containers
.
push
(
ContainerFrame
(
pNode
,
m_pKeyNode
));
m_pKeyNode
=
NULL
;
RegisterAnchor
(
anchor
,
pNode
);
}
void
GraphBuilderAdapter
::
OnMapEnd
()
{
void
*
pMap
=
m_containers
.
top
().
pContainer
;
m_pKeyNode
=
m_containers
.
top
().
pPrevKeyNode
;
m_containers
.
pop
();
DispositionNode
(
pMap
);
namespace
YAML
{
int
GraphBuilderAdapter
::
ContainerFrame
::
sequenceMarker
;
void
GraphBuilderAdapter
::
OnNull
(
const
Mark
&
mark
,
anchor_t
anchor
)
{
void
*
pParent
=
GetCurrentParent
();
void
*
pNode
=
m_builder
.
NewNull
(
mark
,
pParent
);
RegisterAnchor
(
anchor
,
pNode
);
DispositionNode
(
pNode
);
}
void
GraphBuilderAdapter
::
OnAlias
(
const
Mark
&
mark
,
anchor_t
anchor
)
{
void
*
pReffedNode
=
m_anchors
.
Get
(
anchor
);
DispositionNode
(
m_builder
.
AnchorReference
(
mark
,
pReffedNode
));
}
void
GraphBuilderAdapter
::
OnScalar
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
,
const
std
::
string
&
value
)
{
void
*
pParent
=
GetCurrentParent
();
void
*
pNode
=
m_builder
.
NewScalar
(
mark
,
tag
,
pParent
,
value
);
RegisterAnchor
(
anchor
,
pNode
);
DispositionNode
(
pNode
);
}
void
GraphBuilderAdapter
::
OnSequenceStart
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
void
*
pNode
=
m_builder
.
NewSequence
(
mark
,
tag
,
GetCurrentParent
());
m_containers
.
push
(
ContainerFrame
(
pNode
));
RegisterAnchor
(
anchor
,
pNode
);
}
void
GraphBuilderAdapter
::
OnSequenceEnd
()
{
void
*
pSequence
=
m_containers
.
top
().
pContainer
;
m_containers
.
pop
();
DispositionNode
(
pSequence
);
}
void
GraphBuilderAdapter
::
OnMapStart
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
void
*
pNode
=
m_builder
.
NewMap
(
mark
,
tag
,
GetCurrentParent
());
m_containers
.
push
(
ContainerFrame
(
pNode
,
m_pKeyNode
));
m_pKeyNode
=
NULL
;
RegisterAnchor
(
anchor
,
pNode
);
}
void
GraphBuilderAdapter
::
OnMapEnd
()
{
void
*
pMap
=
m_containers
.
top
().
pContainer
;
m_pKeyNode
=
m_containers
.
top
().
pPrevKeyNode
;
m_containers
.
pop
();
DispositionNode
(
pMap
);
}
void
*
GraphBuilderAdapter
::
GetCurrentParent
()
const
{
if
(
m_containers
.
empty
())
{
return
NULL
;
}
void
*
GraphBuilderAdapter
::
GetCurrentParent
()
const
{
if
(
m_containers
.
empty
())
{
return
NULL
;
}
return
m_containers
.
top
().
pContainer
;
return
m_containers
.
top
().
pContainer
;
}
void
GraphBuilderAdapter
::
RegisterAnchor
(
anchor_t
anchor
,
void
*
pNode
)
{
if
(
anchor
)
{
m_anchors
.
Register
(
anchor
,
pNode
);
}
void
GraphBuilderAdapter
::
RegisterAnchor
(
anchor_t
anchor
,
void
*
pNode
)
{
if
(
anchor
)
{
m_anchors
.
Register
(
anchor
,
pNode
)
;
}
}
void
GraphBuilderAdapter
::
DispositionNode
(
void
*
pNode
)
{
if
(
m_containers
.
empty
()
)
{
m_pRootNode
=
pNode
;
return
;
}
void
GraphBuilderAdapter
::
DispositionNode
(
void
*
pNode
)
{
if
(
m_containers
.
empty
())
{
m_pRootNode
=
pNode
;
return
;
}
void
*
pContainer
=
m_containers
.
top
().
pContainer
;
if
(
m_containers
.
top
().
isMap
())
{
if
(
m_pKeyNode
)
{
m_builder
.
AssignInMap
(
pContainer
,
m_pKeyNode
,
pNode
);
m_pKeyNode
=
NULL
;
}
else
{
m_pKeyNode
=
pNode
;
}
void
*
pContainer
=
m_containers
.
top
().
pContainer
;
if
(
m_containers
.
top
().
isMap
())
{
if
(
m_pKeyNode
)
{
m_builder
.
AssignInMap
(
pContainer
,
m_pKeyNode
,
pNode
);
m_pKeyNode
=
NULL
;
}
else
{
m_
builder
.
AppendToSequence
(
pContainer
,
pNode
)
;
m_
pKeyNode
=
pNode
;
}
}
else
{
m_builder
.
AppendToSequence
(
pContainer
,
pNode
);
}
}
}
src/contrib/graphbuilderadapter.h
View file @
9b4db068
#ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
...
...
@@ -12,62 +14,58 @@
#include "yaml-cpp/contrib/anchordict.h"
#include "yaml-cpp/contrib/graphbuilder.h"
namespace
YAML
{
class
GraphBuilderAdapter
:
public
EventHandler
{
public:
GraphBuilderAdapter
(
GraphBuilderInterface
&
builder
)
:
m_builder
(
builder
),
m_pRootNode
(
NULL
),
m_pKeyNode
(
NULL
)
{
}
virtual
void
OnDocumentStart
(
const
Mark
&
mark
)
{(
void
)
mark
;}
virtual
void
OnDocumentEnd
()
{}
virtual
void
OnNull
(
const
Mark
&
mark
,
anchor_t
anchor
);
virtual
void
OnAlias
(
const
Mark
&
mark
,
anchor_t
anchor
);
virtual
void
OnScalar
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
,
const
std
::
string
&
value
);
virtual
void
OnSequenceStart
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
);
virtual
void
OnSequenceEnd
();
virtual
void
OnMapStart
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
);
virtual
void
OnMapEnd
();
void
*
RootNode
()
const
{
return
m_pRootNode
;}
private:
struct
ContainerFrame
{
ContainerFrame
(
void
*
pSequence
)
:
pContainer
(
pSequence
),
pPrevKeyNode
(
&
sequenceMarker
)
{}
ContainerFrame
(
void
*
pMap
,
void
*
pPrevKeyNode
)
:
pContainer
(
pMap
),
pPrevKeyNode
(
pPrevKeyNode
)
{}
void
*
pContainer
;
void
*
pPrevKeyNode
;
bool
isMap
()
const
{
return
pPrevKeyNode
!=
&
sequenceMarker
;}
private:
static
int
sequenceMarker
;
};
typedef
std
::
stack
<
ContainerFrame
>
ContainerStack
;
typedef
AnchorDict
<
void
*>
AnchorMap
;
GraphBuilderInterface
&
m_builder
;
ContainerStack
m_containers
;
AnchorMap
m_anchors
;
void
*
m_pRootNode
;
void
*
m_pKeyNode
;
void
*
GetCurrentParent
()
const
;
void
RegisterAnchor
(
anchor_t
anchor
,
void
*
pNode
);
void
DispositionNode
(
void
*
pNode
);
namespace
YAML
{
class
GraphBuilderAdapter
:
public
EventHandler
{
public:
GraphBuilderAdapter
(
GraphBuilderInterface
&
builder
)
:
m_builder
(
builder
),
m_pRootNode
(
NULL
),
m_pKeyNode
(
NULL
)
{}
virtual
void
OnDocumentStart
(
const
Mark
&
mark
)
{
(
void
)
mark
;
}
virtual
void
OnDocumentEnd
()
{}
virtual
void
OnNull
(
const
Mark
&
mark
,
anchor_t
anchor
);
virtual
void
OnAlias
(
const
Mark
&
mark
,
anchor_t
anchor
);
virtual
void
OnScalar
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
,
const
std
::
string
&
value
);
virtual
void
OnSequenceStart
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
);
virtual
void
OnSequenceEnd
();
virtual
void
OnMapStart
(
const
Mark
&
mark
,
const
std
::
string
&
tag
,
anchor_t
anchor
);
virtual
void
OnMapEnd
();
void
*
RootNode
()
const
{
return
m_pRootNode
;
}
private:
struct
ContainerFrame
{
ContainerFrame
(
void
*
pSequence
)
:
pContainer
(
pSequence
),
pPrevKeyNode
(
&
sequenceMarker
)
{}
ContainerFrame
(
void
*
pMap
,
void
*
pPrevKeyNode
)
:
pContainer
(
pMap
),
pPrevKeyNode
(
pPrevKeyNode
)
{}
void
*
pContainer
;
void
*
pPrevKeyNode
;
bool
isMap
()
const
{
return
pPrevKeyNode
!=
&
sequenceMarker
;
}
private:
static
int
sequenceMarker
;
};
typedef
std
::
stack
<
ContainerFrame
>
ContainerStack
;
typedef
AnchorDict
<
void
*>
AnchorMap
;
GraphBuilderInterface
&
m_builder
;
ContainerStack
m_containers
;
AnchorMap
m_anchors
;
void
*
m_pRootNode
;
void
*
m_pKeyNode
;
void
*
GetCurrentParent
()
const
;
void
RegisterAnchor
(
anchor_t
anchor
,
void
*
pNode
);
void
DispositionNode
(
void
*
pNode
);
};
}
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif
// GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/directives.cpp
View file @
9b4db068
#include "directives.h"
namespace
YAML
{
Directives
::
Directives
()
{
// version
version
.
isDefault
=
true
;
version
.
major
=
1
;
version
.
minor
=
2
;
}
const
std
::
string
Directives
::
TranslateTagHandle
(
const
std
::
string
&
handle
)
const
{
std
::
map
<
std
::
string
,
std
::
string
>::
const_iterator
it
=
tags
.
find
(
handle
);
if
(
it
==
tags
.
end
())
{
if
(
handle
==
"!!"
)
return
"tag:yaml.org,2002:"
;
return
handle
;
}
return
it
->
second
;
}
namespace
YAML
{
Directives
::
Directives
()
{
// version
version
.
isDefault
=
true
;
version
.
major
=
1
;
version
.
minor
=
2
;
}
const
std
::
string
Directives
::
TranslateTagHandle
(
const
std
::
string
&
handle
)
const
{
std
::
map
<
std
::
string
,
std
::
string
>::
const_iterator
it
=
tags
.
find
(
handle
);
if
(
it
==
tags
.
end
())
{
if
(
handle
==
"!!"
)
return
"tag:yaml.org,2002:"
;
return
handle
;
}
return
it
->
second
;
}
}
src/directives.h
View file @
9b4db068
#ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <string>
#include <map>
namespace
YAML
{
struct
Version
{
bool
isDefault
;
int
major
,
minor
;
};
struct
Directives
{
Directives
();
const
std
::
string
TranslateTagHandle
(
const
std
::
string
&
handle
)
const
;
namespace
YAML
{
struct
Version
{
bool
isDefault
;
int
major
,
minor
;
};
struct
Directives
{
Directives
();
const
std
::
string
TranslateTagHandle
(
const
std
::
string
&
handle
)
const
;
Version
version
;
std
::
map
<
std
::
string
,
std
::
string
>
tags
;
};
Version
version
;
std
::
map
<
std
::
string
,
std
::
string
>
tags
;
};
}
#endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif
// DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/emitfromevents.cpp
View file @
9b4db068
...
...
@@ -5,101 +5,88 @@
#include <sstream>
namespace
{
std
::
string
ToString
(
YAML
::
anchor_t
anchor
)
{
std
::
stringstream
stream
;
stream
<<
anchor
;
return
stream
.
str
();
}
std
::
string
ToString
(
YAML
::
anchor_t
anchor
)
{
std
::
stringstream
stream
;
stream
<<
anchor
;
return
stream
.
str
();
}
}
namespace
YAML
{
EmitFromEvents
::
EmitFromEvents
(
Emitter
&
emitter
)
:
m_emitter
(
emitter
)
{}
void
EmitFromEvents
::
OnDocumentStart
(
const
Mark
&
)
{}
void
EmitFromEvents
::
OnDocumentEnd
()
{}
void
EmitFromEvents
::
OnNull
(
const
Mark
&
,
anchor_t
anchor
)
{
BeginNode
();
EmitProps
(
""
,
anchor
);
m_emitter
<<
Null
;
}
void
EmitFromEvents
::
OnAlias
(
const
Mark
&
,
anchor_t
anchor
)
{
BeginNode
();
m_emitter
<<
Alias
(
ToString
(
anchor
));
}
void
EmitFromEvents
::
OnScalar
(
const
Mark
&
,
const
std
::
string
&
tag
,
anchor_t
anchor
,
const
std
::
string
&
value
)
{
BeginNode
();
EmitProps
(
tag
,
anchor
);
m_emitter
<<
value
;
}
namespace
YAML
{
EmitFromEvents
::
EmitFromEvents
(
Emitter
&
emitter
)
:
m_emitter
(
emitter
)
{
}
void
EmitFromEvents
::
OnDocumentStart
(
const
Mark
&
)
{
}
void
EmitFromEvents
::
OnDocumentEnd
()
{
}
void
EmitFromEvents
::
OnNull
(
const
Mark
&
,
anchor_t
anchor
)
{
BeginNode
();
EmitProps
(
""
,
anchor
);
m_emitter
<<
Null
;
}
void
EmitFromEvents
::
OnAlias
(
const
Mark
&
,
anchor_t
anchor
)
{
BeginNode
();
m_emitter
<<
Alias
(
ToString
(
anchor
));
}
void
EmitFromEvents
::
OnScalar
(
const
Mark
&
,
const
std
::
string
&
tag
,
anchor_t
anchor
,
const
std
::
string
&
value
)
{
BeginNode
();
EmitProps
(
tag
,
anchor
);
m_emitter
<<
value
;
}
void
EmitFromEvents
::
OnSequenceStart
(
const
Mark
&
,
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
BeginNode
();
EmitProps
(
tag
,
anchor
);
m_emitter
<<
BeginSeq
;
m_stateStack
.
push
(
State
::
WaitingForSequenceEntry
);
}
void
EmitFromEvents
::
OnSequenceEnd
()
{
m_emitter
<<
EndSeq
;
assert
(
m_stateStack
.
top
()
==
State
::
WaitingForSequenceEntry
);
m_stateStack
.
pop
();
}
void
EmitFromEvents
::
OnMapStart
(
const
Mark
&
,
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
BeginNode
();
EmitProps
(
tag
,
anchor
);
m_emitter
<<
BeginMap
;
m_stateStack
.
push
(
State
::
WaitingForKey
);
}
void
EmitFromEvents
::
OnSequenceStart
(
const
Mark
&
,
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
BeginNode
();
EmitProps
(
tag
,
anchor
);
m_emitter
<<
BeginSeq
;
m_stateStack
.
push
(
State
::
WaitingForSequenceEntry
);
}
void
EmitFromEvents
::
OnSequenceEnd
()
{
m_emitter
<<
EndSeq
;
assert
(
m_stateStack
.
top
()
==
State
::
WaitingForSequenceEntry
);
m_stateStack
.
pop
();
}
void
EmitFromEvents
::
OnMapStart
(
const
Mark
&
,
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
BeginNode
();
EmitProps
(
tag
,
anchor
);
m_emitter
<<
BeginMap
;
m_stateStack
.
push
(
State
::
WaitingForKey
);
}
void
EmitFromEvents
::
OnMapEnd
()
{
m_emitter
<<
EndMap
;
assert
(
m_stateStack
.
top
()
==
State
::
WaitingForKey
);
m_stateStack
.
pop
();
}
void
EmitFromEvents
::
OnMapEnd
()
{
m_emitter
<<
EndMap
;
assert
(
m_stateStack
.
top
()
==
State
::
WaitingForKey
);
m_stateStack
.
pop
();
}
void
EmitFromEvents
::
BeginNode
()
{
if
(
m_stateStack
.
empty
())
return
;
void
EmitFromEvents
::
BeginNode
()
{
if
(
m_stateStack
.
empty
())
return
;
switch
(
m_stateStack
.
top
())
{
case
State
::
WaitingForKey
:
m_emitter
<<
Key
;
m_stateStack
.
top
()
=
State
::
WaitingForValue
;
break
;
case
State
::
WaitingForValue
:
m_emitter
<<
Value
;
m_stateStack
.
top
()
=
State
::
WaitingForKey
;
break
;
default:
break
;
}
}
void
EmitFromEvents
::
EmitProps
(
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
if
(
!
tag
.
empty
()
&&
tag
!=
"?"
)
m_emitter
<<
VerbatimTag
(
tag
);
if
(
anchor
)
m_emitter
<<
Anchor
(
ToString
(
anchor
));
}
switch
(
m_stateStack
.
top
())
{
case
State
::
WaitingForKey
:
m_emitter
<<
Key
;
m_stateStack
.
top
()
=
State
::
WaitingForValue
;
break
;
case
State
::
WaitingForValue
:
m_emitter
<<
Value
;
m_stateStack
.
top
()
=
State
::
WaitingForKey
;
break
;
default:
break
;
}
}
void
EmitFromEvents
::
EmitProps
(
const
std
::
string
&
tag
,
anchor_t
anchor
)
{
if
(
!
tag
.
empty
()
&&
tag
!=
"?"
)
m_emitter
<<
VerbatimTag
(
tag
);
if
(
anchor
)
m_emitter
<<
Anchor
(
ToString
(
anchor
));
}
}
src/emitter.cpp
View file @
9b4db068
...
...
@@ -5,947 +5,902 @@
#include "yaml-cpp/exceptions.h"
#include <sstream>
namespace
YAML
{
Emitter
::
Emitter
()
:
m_pState
(
new
EmitterState
)
{
}
Emitter
::
Emitter
(
std
::
ostream
&
stream
)
:
m_pState
(
new
EmitterState
),
m_stream
(
stream
)
{
}
Emitter
::~
Emitter
()
{
}
const
char
*
Emitter
::
c_str
()
const
{
return
m_stream
.
str
();
}
std
::
size_t
Emitter
::
size
()
const
{
return
m_stream
.
pos
();
}
// state checking
bool
Emitter
::
good
()
const
{
return
m_pState
->
good
();
}
const
std
::
string
Emitter
::
GetLastError
()
const
{
return
m_pState
->
GetLastError
();
}
// global setters
bool
Emitter
::
SetOutputCharset
(
EMITTER_MANIP
value
)
{
return
m_pState
->
SetOutputCharset
(
value
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetStringFormat
(
EMITTER_MANIP
value
)
{
return
m_pState
->
SetStringFormat
(
value
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetBoolFormat
(
EMITTER_MANIP
value
)
{
bool
ok
=
false
;
if
(
m_pState
->
SetBoolFormat
(
value
,
FmtScope
::
Global
))
ok
=
true
;
if
(
m_pState
->
SetBoolCaseFormat
(
value
,
FmtScope
::
Global
))
ok
=
true
;
if
(
m_pState
->
SetBoolLengthFormat
(
value
,
FmtScope
::
Global
))
ok
=
true
;
return
ok
;
}
bool
Emitter
::
SetIntBase
(
EMITTER_MANIP
value
)
{
return
m_pState
->
SetIntFormat
(
value
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetSeqFormat
(
EMITTER_MANIP
value
)
{
return
m_pState
->
SetFlowType
(
GroupType
::
Seq
,
value
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetMapFormat
(
EMITTER_MANIP
value
)
{
bool
ok
=
false
;
if
(
m_pState
->
SetFlowType
(
GroupType
::
Map
,
value
,
FmtScope
::
Global
))
ok
=
true
;
if
(
m_pState
->
SetMapKeyFormat
(
value
,
FmtScope
::
Global
))
ok
=
true
;
return
ok
;
}
bool
Emitter
::
SetIndent
(
unsigned
n
)
{
return
m_pState
->
SetIndent
(
n
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetPreCommentIndent
(
unsigned
n
)
{
return
m_pState
->
SetPreCommentIndent
(
n
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetPostCommentIndent
(
unsigned
n
)
{
return
m_pState
->
SetPostCommentIndent
(
n
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetFloatPrecision
(
unsigned
n
)
{
return
m_pState
->
SetFloatPrecision
(
n
,
FmtScope
::
Global
);
}
namespace
YAML
{
Emitter
::
Emitter
()
:
m_pState
(
new
EmitterState
)
{}
bool
Emitter
::
SetDoublePrecision
(
unsigned
n
)
{
return
m_pState
->
SetDoublePrecision
(
n
,
FmtScope
::
Global
);
}
Emitter
::
Emitter
(
std
::
ostream
&
stream
)
:
m_pState
(
new
EmitterState
),
m_stream
(
stream
)
{}
// SetLocalValue
// . Either start/end a group, or set a modifier locally
Emitter
&
Emitter
::
SetLocalValue
(
EMITTER_MANIP
value
)
{
if
(
!
good
())
return
*
this
;
switch
(
value
)
{
case
BeginDoc
:
EmitBeginDoc
();
break
;
case
EndDoc
:
EmitEndDoc
();
break
;
case
BeginSeq
:
EmitBeginSeq
();
break
;
case
EndSeq
:
EmitEndSeq
();
break
;
case
BeginMap
:
EmitBeginMap
();
break
;
case
EndMap
:
EmitEndMap
();
break
;
case
Key
:
case
Value
:
// deprecated (these can be deduced by the parity of nodes in a map)
break
;
case
TagByKind
:
EmitKindTag
();
break
;
case
Newline
:
EmitNewline
();
break
;
default:
m_pState
->
SetLocalValue
(
value
);
break
;
}
return
*
this
;
}
Emitter
&
Emitter
::
SetLocalIndent
(
const
_Indent
&
indent
)
{
m_pState
->
SetIndent
(
indent
.
value
,
FmtScope
::
Local
);
return
*
this
;
}
Emitter
&
Emitter
::
SetLocalPrecision
(
const
_Precision
&
precision
)
{
if
(
precision
.
floatPrecision
>=
0
)
m_pState
->
SetFloatPrecision
(
precision
.
floatPrecision
,
FmtScope
::
Local
);
if
(
precision
.
doublePrecision
>=
0
)
m_pState
->
SetDoublePrecision
(
precision
.
doublePrecision
,
FmtScope
::
Local
);
return
*
this
;
}
Emitter
::~
Emitter
()
{}
// EmitBeginDoc
void
Emitter
::
EmitBeginDoc
()
{
if
(
!
good
())
return
;
if
(
m_pState
->
CurGroupType
()
!=
GroupType
::
None
)
{
m_pState
->
SetError
(
"Unexpected begin document"
);
return
;
}
if
(
m_pState
->
HasAnchor
()
||
m_pState
->
HasTag
())
{
m_pState
->
SetError
(
"Unexpected begin document"
);
return
;
}
if
(
m_stream
.
col
()
>
0
)
m_stream
<<
"
\n
"
;
m_stream
<<
"---
\n
"
;
m_pState
->
StartedDoc
();
}
// EmitEndDoc
void
Emitter
::
EmitEndDoc
()
{
if
(
!
good
())
return
;
if
(
m_pState
->
CurGroupType
()
!=
GroupType
::
None
)
{
m_pState
->
SetError
(
"Unexpected begin document"
);
return
;
}
if
(
m_pState
->
HasAnchor
()
||
m_pState
->
HasTag
())
{
m_pState
->
SetError
(
"Unexpected begin document"
);
return
;
}
if
(
m_stream
.
col
()
>
0
)
m_stream
<<
"
\n
"
;
m_stream
<<
"...
\n
"
;
}
// EmitBeginSeq
void
Emitter
::
EmitBeginSeq
()
{
if
(
!
good
())
return
;
PrepareNode
(
m_pState
->
NextGroupType
(
GroupType
::
Seq
));
m_pState
->
StartedGroup
(
GroupType
::
Seq
);
}
// EmitEndSeq
void
Emitter
::
EmitEndSeq
()
{
if
(
!
good
())
return
;
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_pState
->
ForceFlow
();
if
(
m_pState
->
CurGroupFlowType
()
==
FlowType
::
Flow
)
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
m_pState
->
CurIndent
());
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"["
;
m_stream
<<
"]"
;
}
m_pState
->
EndedGroup
(
GroupType
::
Seq
);
}
// EmitBeginMap
void
Emitter
::
EmitBeginMap
()
{
if
(
!
good
())
return
;
PrepareNode
(
m_pState
->
NextGroupType
(
GroupType
::
Map
));
m_pState
->
StartedGroup
(
GroupType
::
Map
);
}
// EmitEndMap
void
Emitter
::
EmitEndMap
()
{
if
(
!
good
())
return
;
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_pState
->
ForceFlow
();
if
(
m_pState
->
CurGroupFlowType
()
==
FlowType
::
Flow
)
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
m_pState
->
CurIndent
());
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"{"
;
m_stream
<<
"}"
;
}
m_pState
->
EndedGroup
(
GroupType
::
Map
);
}
const
char
*
Emitter
::
c_str
()
const
{
return
m_stream
.
str
();
}
std
::
size_t
Emitter
::
size
()
const
{
return
m_stream
.
pos
();
}
// state checking
bool
Emitter
::
good
()
const
{
return
m_pState
->
good
();
}
const
std
::
string
Emitter
::
GetLastError
()
const
{
return
m_pState
->
GetLastError
();
}
// global setters
bool
Emitter
::
SetOutputCharset
(
EMITTER_MANIP
value
)
{
return
m_pState
->
SetOutputCharset
(
value
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetStringFormat
(
EMITTER_MANIP
value
)
{
return
m_pState
->
SetStringFormat
(
value
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetBoolFormat
(
EMITTER_MANIP
value
)
{
bool
ok
=
false
;
if
(
m_pState
->
SetBoolFormat
(
value
,
FmtScope
::
Global
))
ok
=
true
;
if
(
m_pState
->
SetBoolCaseFormat
(
value
,
FmtScope
::
Global
))
ok
=
true
;
if
(
m_pState
->
SetBoolLengthFormat
(
value
,
FmtScope
::
Global
))
ok
=
true
;
return
ok
;
}
bool
Emitter
::
SetIntBase
(
EMITTER_MANIP
value
)
{
return
m_pState
->
SetIntFormat
(
value
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetSeqFormat
(
EMITTER_MANIP
value
)
{
return
m_pState
->
SetFlowType
(
GroupType
::
Seq
,
value
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetMapFormat
(
EMITTER_MANIP
value
)
{
bool
ok
=
false
;
if
(
m_pState
->
SetFlowType
(
GroupType
::
Map
,
value
,
FmtScope
::
Global
))
ok
=
true
;
if
(
m_pState
->
SetMapKeyFormat
(
value
,
FmtScope
::
Global
))
ok
=
true
;
return
ok
;
}
bool
Emitter
::
SetIndent
(
unsigned
n
)
{
return
m_pState
->
SetIndent
(
n
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetPreCommentIndent
(
unsigned
n
)
{
return
m_pState
->
SetPreCommentIndent
(
n
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetPostCommentIndent
(
unsigned
n
)
{
return
m_pState
->
SetPostCommentIndent
(
n
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetFloatPrecision
(
unsigned
n
)
{
return
m_pState
->
SetFloatPrecision
(
n
,
FmtScope
::
Global
);
}
bool
Emitter
::
SetDoublePrecision
(
unsigned
n
)
{
return
m_pState
->
SetDoublePrecision
(
n
,
FmtScope
::
Global
);
}
// SetLocalValue
// . Either start/end a group, or set a modifier locally
Emitter
&
Emitter
::
SetLocalValue
(
EMITTER_MANIP
value
)
{
if
(
!
good
())
return
*
this
;
switch
(
value
)
{
case
BeginDoc
:
EmitBeginDoc
();
break
;
case
EndDoc
:
EmitEndDoc
();
break
;
case
BeginSeq
:
EmitBeginSeq
();
break
;
case
EndSeq
:
EmitEndSeq
();
break
;
case
BeginMap
:
EmitBeginMap
();
break
;
case
EndMap
:
EmitEndMap
();
break
;
case
Key
:
case
Value
:
// deprecated (these can be deduced by the parity of nodes in a map)
break
;
case
TagByKind
:
EmitKindTag
();
break
;
case
Newline
:
EmitNewline
();
break
;
default:
m_pState
->
SetLocalValue
(
value
);
break
;
}
return
*
this
;
}
Emitter
&
Emitter
::
SetLocalIndent
(
const
_Indent
&
indent
)
{
m_pState
->
SetIndent
(
indent
.
value
,
FmtScope
::
Local
);
return
*
this
;
}
Emitter
&
Emitter
::
SetLocalPrecision
(
const
_Precision
&
precision
)
{
if
(
precision
.
floatPrecision
>=
0
)
m_pState
->
SetFloatPrecision
(
precision
.
floatPrecision
,
FmtScope
::
Local
);
if
(
precision
.
doublePrecision
>=
0
)
m_pState
->
SetDoublePrecision
(
precision
.
doublePrecision
,
FmtScope
::
Local
);
return
*
this
;
}
// EmitBeginDoc
void
Emitter
::
EmitBeginDoc
()
{
if
(
!
good
())
return
;
if
(
m_pState
->
CurGroupType
()
!=
GroupType
::
None
)
{
m_pState
->
SetError
(
"Unexpected begin document"
);
return
;
}
if
(
m_pState
->
HasAnchor
()
||
m_pState
->
HasTag
())
{
m_pState
->
SetError
(
"Unexpected begin document"
);
return
;
}
if
(
m_stream
.
col
()
>
0
)
m_stream
<<
"
\n
"
;
m_stream
<<
"---
\n
"
;
m_pState
->
StartedDoc
();
}
// EmitEndDoc
void
Emitter
::
EmitEndDoc
()
{
if
(
!
good
())
return
;
if
(
m_pState
->
CurGroupType
()
!=
GroupType
::
None
)
{
m_pState
->
SetError
(
"Unexpected begin document"
);
return
;
}
if
(
m_pState
->
HasAnchor
()
||
m_pState
->
HasTag
())
{
m_pState
->
SetError
(
"Unexpected begin document"
);
return
;
}
// EmitNewline
void
Emitter
::
EmitNewline
()
{
if
(
!
good
())
return
;
PrepareNode
(
EmitterNodeType
::
None
);
if
(
m_stream
.
col
()
>
0
)
m_stream
<<
"
\n
"
;
m_stream
<<
"...
\n
"
;
}
// EmitBeginSeq
void
Emitter
::
EmitBeginSeq
()
{
if
(
!
good
())
return
;
PrepareNode
(
m_pState
->
NextGroupType
(
GroupType
::
Seq
));
m_pState
->
StartedGroup
(
GroupType
::
Seq
);
}
// EmitEndSeq
void
Emitter
::
EmitEndSeq
()
{
if
(
!
good
())
return
;
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_pState
->
ForceFlow
();
if
(
m_pState
->
CurGroupFlowType
()
==
FlowType
::
Flow
)
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
m_pState
->
CurIndent
());
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"["
;
m_stream
<<
"]"
;
}
m_pState
->
EndedGroup
(
GroupType
::
Seq
);
}
// EmitBeginMap
void
Emitter
::
EmitBeginMap
()
{
if
(
!
good
())
return
;
PrepareNode
(
m_pState
->
NextGroupType
(
GroupType
::
Map
));
m_pState
->
StartedGroup
(
GroupType
::
Map
);
}
// EmitEndMap
void
Emitter
::
EmitEndMap
()
{
if
(
!
good
())
return
;
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_pState
->
ForceFlow
();
if
(
m_pState
->
CurGroupFlowType
()
==
FlowType
::
Flow
)
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
m_pState
->
CurIndent
());
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"{"
;
m_stream
<<
"}"
;
}
m_pState
->
EndedGroup
(
GroupType
::
Map
);
}
// EmitNewline
void
Emitter
::
EmitNewline
()
{
if
(
!
good
())
return
;
PrepareNode
(
EmitterNodeType
::
None
);
m_stream
<<
"
\n
"
;
m_pState
->
SetNonContent
();
}
bool
Emitter
::
CanEmitNewline
()
const
{
return
true
;
}
// Put the stream in a state so we can simply write the next node
// E.g., if we're in a sequence, write the "- "
void
Emitter
::
PrepareNode
(
EmitterNodeType
::
value
child
)
{
switch
(
m_pState
->
CurGroupNodeType
())
{
case
EmitterNodeType
::
None
:
PrepareTopNode
(
child
);
break
;
case
EmitterNodeType
::
FlowSeq
:
FlowSeqPrepareNode
(
child
);
break
;
case
EmitterNodeType
::
BlockSeq
:
BlockSeqPrepareNode
(
child
);
break
;
case
EmitterNodeType
::
FlowMap
:
FlowMapPrepareNode
(
child
);
break
;
case
EmitterNodeType
::
BlockMap
:
BlockMapPrepareNode
(
child
);
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
assert
(
false
);
break
;
}
}
void
Emitter
::
PrepareTopNode
(
EmitterNodeType
::
value
child
)
{
if
(
child
==
EmitterNodeType
::
None
)
return
;
if
(
m_pState
->
CurGroupChildCount
()
>
0
&&
m_stream
.
col
()
>
0
)
{
if
(
child
!=
EmitterNodeType
::
None
)
EmitBeginDoc
();
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
// TODO: if we were writing null, and
// we wanted it blank, we wouldn't want a space
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
(),
0
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
if
(
m_pState
->
HasBegunNode
())
m_stream
<<
"
\n
"
;
m_pState
->
SetNonContent
();
}
bool
Emitter
::
CanEmitNewline
()
const
{
return
true
;
}
// Put the stream in a state so we can simply write the next node
// E.g., if we're in a sequence, write the "- "
void
Emitter
::
PrepareNode
(
EmitterNodeType
::
value
child
)
{
switch
(
m_pState
->
CurGroupNodeType
())
{
case
EmitterNodeType
::
None
:
PrepareTopNode
(
child
);
break
;
case
EmitterNodeType
::
FlowSeq
:
FlowSeqPrepareNode
(
child
);
break
;
case
EmitterNodeType
::
BlockSeq
:
BlockSeqPrepareNode
(
child
);
break
;
case
EmitterNodeType
::
FlowMap
:
FlowMapPrepareNode
(
child
);
break
;
case
EmitterNodeType
::
BlockMap
:
BlockMapPrepareNode
(
child
);
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
assert
(
false
);
break
;
}
}
void
Emitter
::
PrepareTopNode
(
EmitterNodeType
::
value
child
)
{
if
(
child
==
EmitterNodeType
::
None
)
return
;
if
(
m_pState
->
CurGroupChildCount
()
>
0
&&
m_stream
.
col
()
>
0
)
{
if
(
child
!=
EmitterNodeType
::
None
)
EmitBeginDoc
();
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
// TODO: if we were writing null, and
// we wanted it blank, we wouldn't want a space
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
(),
0
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
if
(
m_pState
->
HasBegunNode
())
m_stream
<<
"
\n
"
;
break
;
}
}
void
Emitter
::
FlowSeqPrepareNode
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"["
;
else
m_stream
<<
","
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
break
;
}
}
void
Emitter
::
BlockSeqPrepareNode
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
const
unsigned
nextIndent
=
curIndent
+
m_pState
->
CurGroupIndent
();
if
(
child
==
EmitterNodeType
::
None
)
return
;
if
(
!
m_pState
->
HasBegunContent
())
{
if
(
m_pState
->
CurGroupChildCount
()
>
0
||
m_stream
.
comment
())
{
m_stream
<<
"
\n
"
;
}
m_stream
<<
IndentTo
(
curIndent
);
m_stream
<<
"-"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
(),
nextIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
m_stream
<<
"
\n
"
;
break
;
case
EmitterNodeType
::
BlockMap
:
if
(
m_pState
->
HasBegunContent
()
||
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
break
;
}
}
void
Emitter
::
FlowMapPrepareNode
(
EmitterNodeType
::
value
child
)
{
if
(
m_pState
->
CurGroupChildCount
()
%
2
==
0
)
{
if
(
m_pState
->
GetMapKeyFormat
()
==
LongKey
)
m_pState
->
SetLongKey
();
if
(
m_pState
->
CurGroupLongKey
())
FlowMapPrepareLongKey
(
child
);
else
FlowMapPrepareSimpleKey
(
child
);
}
else
{
if
(
m_pState
->
CurGroupLongKey
())
FlowMapPrepareLongKeyValue
(
child
);
else
FlowMapPrepareSimpleKeyValue
(
child
);
}
}
void
Emitter
::
FlowSeqPrepareNode
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"["
;
else
m_stream
<<
","
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
void
Emitter
::
FlowMapPrepareLongKey
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"{ ?"
;
else
m_stream
<<
", ?"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
void
Emitter
::
FlowMapPrepareLongKeyValue
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
m_stream
<<
":"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
void
Emitter
::
FlowMapPrepareSimpleKey
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"{"
;
else
m_stream
<<
","
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
void
Emitter
::
FlowMapPrepareSimpleKeyValue
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
m_stream
<<
":"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
void
Emitter
::
BlockSeqPrepareNode
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
const
unsigned
nextIndent
=
curIndent
+
m_pState
->
CurGroupIndent
();
void
Emitter
::
BlockMapPrepareNode
(
EmitterNodeType
::
value
child
)
{
if
(
m_pState
->
CurGroupChildCount
()
%
2
==
0
)
{
if
(
m_pState
->
GetMapKeyFormat
()
==
LongKey
)
m_pState
->
SetLongKey
();
if
(
child
==
EmitterNodeType
::
BlockSeq
||
child
==
EmitterNodeType
::
BlockMap
)
m_pState
->
SetLongKey
();
if
(
m_pState
->
CurGroupLongKey
())
BlockMapPrepareLongKey
(
child
);
else
BlockMapPrepareSimpleKey
(
child
);
}
else
{
if
(
m_pState
->
CurGroupLongKey
())
BlockMapPrepareLongKeyValue
(
child
);
else
BlockMapPrepareSimpleKeyValue
(
child
);
}
}
void
Emitter
::
BlockMapPrepareLongKey
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
const
std
::
size_t
childCount
=
m_pState
->
CurGroupChildCount
();
if
(
child
==
EmitterNodeType
::
None
)
return
;
if
(
!
m_pState
->
HasBegunContent
())
{
if
(
childCount
>
0
)
{
m_stream
<<
"
\n
"
;
}
if
(
m_stream
.
comment
())
{
m_stream
<<
"
\n
"
;
}
m_stream
<<
IndentTo
(
curIndent
);
m_stream
<<
"?"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
true
,
curIndent
+
1
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
break
;
}
}
if
(
child
==
EmitterNodeType
::
None
)
return
;
void
Emitter
::
BlockMapPrepareLongKeyValue
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
if
(
child
==
EmitterNodeType
::
None
)
return
;
if
(
!
m_pState
->
HasBegunContent
())
{
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
curIndent
);
m_stream
<<
":"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
SpaceOrIndentTo
(
true
,
curIndent
+
1
);
break
;
}
if
(
!
m_pState
->
HasBegunContent
())
{
if
(
m_pState
->
CurGroupChildCount
()
>
0
||
m_stream
.
comment
())
{
m_stream
<<
"
\n
"
;
}
m_stream
<<
IndentTo
(
curIndent
);
m_stream
<<
"-"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
(),
nextIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
m_stream
<<
"
\n
"
;
break
;
case
EmitterNodeType
::
BlockMap
:
if
(
m_pState
->
HasBegunContent
()
||
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
break
;
}
}
void
Emitter
::
BlockMapPrepareSimpleKey
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
const
std
::
size_t
childCount
=
m_pState
->
CurGroupChildCount
();
if
(
child
==
EmitterNodeType
::
None
)
return
;
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
childCount
>
0
)
{
m_stream
<<
"
\n
"
;
}
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
(),
curIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
break
;
}
}
void
Emitter
::
BlockMapPrepareSimpleKeyValue
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
const
unsigned
nextIndent
=
curIndent
+
m_pState
->
CurGroupIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
m_stream
<<
":"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
true
,
nextIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
m_stream
<<
"
\n
"
;
break
;
}
void
Emitter
::
FlowMapPrepareNode
(
EmitterNodeType
::
value
child
)
{
if
(
m_pState
->
CurGroupChildCount
()
%
2
==
0
)
{
if
(
m_pState
->
GetMapKeyFormat
()
==
LongKey
)
m_pState
->
SetLongKey
();
if
(
m_pState
->
CurGroupLongKey
())
FlowMapPrepareLongKey
(
child
);
else
FlowMapPrepareSimpleKey
(
child
);
}
else
{
if
(
m_pState
->
CurGroupLongKey
())
FlowMapPrepareLongKeyValue
(
child
);
else
FlowMapPrepareSimpleKeyValue
(
child
);
}
}
void
Emitter
::
FlowMapPrepareLongKey
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"{ ?"
;
else
m_stream
<<
", ?"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
void
Emitter
::
FlowMapPrepareLongKeyValue
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
m_stream
<<
":"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
void
Emitter
::
FlowMapPrepareSimpleKey
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
if
(
m_pState
->
CurGroupChildCount
()
==
0
)
m_stream
<<
"{"
;
else
m_stream
<<
","
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
void
Emitter
::
FlowMapPrepareSimpleKeyValue
(
EmitterNodeType
::
value
child
)
{
const
unsigned
lastIndent
=
m_pState
->
LastIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
lastIndent
);
m_stream
<<
":"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
()
||
m_pState
->
CurGroupChildCount
()
>
0
,
lastIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
assert
(
false
);
break
;
}
}
void
Emitter
::
BlockMapPrepareNode
(
EmitterNodeType
::
value
child
)
{
if
(
m_pState
->
CurGroupChildCount
()
%
2
==
0
)
{
if
(
m_pState
->
GetMapKeyFormat
()
==
LongKey
)
m_pState
->
SetLongKey
();
if
(
child
==
EmitterNodeType
::
BlockSeq
||
child
==
EmitterNodeType
::
BlockMap
)
m_pState
->
SetLongKey
();
if
(
m_pState
->
CurGroupLongKey
())
BlockMapPrepareLongKey
(
child
);
else
BlockMapPrepareSimpleKey
(
child
);
}
else
{
if
(
m_pState
->
CurGroupLongKey
())
BlockMapPrepareLongKeyValue
(
child
);
else
BlockMapPrepareSimpleKeyValue
(
child
);
}
}
void
Emitter
::
BlockMapPrepareLongKey
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
const
std
::
size_t
childCount
=
m_pState
->
CurGroupChildCount
();
if
(
child
==
EmitterNodeType
::
None
)
return
;
if
(
!
m_pState
->
HasBegunContent
())
{
if
(
childCount
>
0
)
{
m_stream
<<
"
\n
"
;
}
// SpaceOrIndentTo
// . Prepares for some more content by proper spacing
void
Emitter
::
SpaceOrIndentTo
(
bool
requireSpace
,
unsigned
indent
)
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
if
(
m_stream
.
col
()
>
0
&&
requireSpace
)
m_stream
<<
" "
;
m_stream
<<
IndentTo
(
indent
);
if
(
m_stream
.
comment
())
{
m_stream
<<
"
\n
"
;
}
m_stream
<<
IndentTo
(
curIndent
);
m_stream
<<
"?"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
true
,
curIndent
+
1
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
break
;
}
}
void
Emitter
::
PrepareIntegralStream
(
std
::
stringstream
&
stream
)
const
{
switch
(
m_pState
->
GetIntFormat
())
{
case
Dec
:
stream
<<
std
::
dec
;
break
;
case
Hex
:
stream
<<
"0x"
;
stream
<<
std
::
hex
;
break
;
case
Oct
:
stream
<<
"0"
;
stream
<<
std
::
oct
;
break
;
default:
assert
(
false
);
}
}
void
Emitter
::
BlockMapPrepareLongKeyValue
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
if
(
child
==
EmitterNodeType
::
None
)
return
;
if
(
!
m_pState
->
HasBegunContent
())
{
m_stream
<<
"
\n
"
;
m_stream
<<
IndentTo
(
curIndent
);
m_stream
<<
":"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
SpaceOrIndentTo
(
true
,
curIndent
+
1
);
break
;
}
}
void
Emitter
::
StartedScalar
()
{
m_pState
->
StartedScalar
();
}
void
Emitter
::
BlockMapPrepareSimpleKey
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
const
std
::
size_t
childCount
=
m_pState
->
CurGroupChildCount
();
// *******************************************************************************************
// overloads of Write
Emitter
&
Emitter
::
Write
(
const
std
::
string
&
str
)
{
if
(
!
good
())
return
*
this
;
const
bool
escapeNonAscii
=
m_pState
->
GetOutputCharset
()
==
EscapeNonAscii
;
const
StringFormat
::
value
strFormat
=
Utils
::
ComputeStringFormat
(
str
,
m_pState
->
GetStringFormat
(),
m_pState
->
CurGroupFlowType
(),
escapeNonAscii
);
if
(
strFormat
==
StringFormat
::
Literal
)
m_pState
->
SetMapKeyFormat
(
YAML
::
LongKey
,
FmtScope
::
Local
);
PrepareNode
(
EmitterNodeType
::
Scalar
);
switch
(
strFormat
)
{
case
StringFormat
::
Plain
:
m_stream
<<
str
;
break
;
case
StringFormat
::
SingleQuoted
:
Utils
::
WriteSingleQuotedString
(
m_stream
,
str
);
break
;
case
StringFormat
::
DoubleQuoted
:
Utils
::
WriteDoubleQuotedString
(
m_stream
,
str
,
escapeNonAscii
);
break
;
case
StringFormat
::
Literal
:
Utils
::
WriteLiteralString
(
m_stream
,
str
,
m_pState
->
CurIndent
()
+
m_pState
->
GetIndent
());
break
;
}
StartedScalar
();
return
*
this
;
}
unsigned
Emitter
::
GetFloatPrecision
()
const
{
return
m_pState
->
GetFloatPrecision
();
}
unsigned
Emitter
::
GetDoublePrecision
()
const
{
return
m_pState
->
GetDoublePrecision
();
if
(
child
==
EmitterNodeType
::
None
)
return
;
if
(
!
m_pState
->
HasBegunNode
())
{
if
(
childCount
>
0
)
{
m_stream
<<
"
\n
"
;
}
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
m_pState
->
HasBegunContent
(),
curIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
break
;
}
}
void
Emitter
::
BlockMapPrepareSimpleKeyValue
(
EmitterNodeType
::
value
child
)
{
const
unsigned
curIndent
=
m_pState
->
CurIndent
();
const
unsigned
nextIndent
=
curIndent
+
m_pState
->
CurGroupIndent
();
if
(
!
m_pState
->
HasBegunNode
())
{
m_stream
<<
":"
;
}
switch
(
child
)
{
case
EmitterNodeType
::
None
:
break
;
case
EmitterNodeType
::
Property
:
case
EmitterNodeType
::
Scalar
:
case
EmitterNodeType
::
FlowSeq
:
case
EmitterNodeType
::
FlowMap
:
SpaceOrIndentTo
(
true
,
nextIndent
);
break
;
case
EmitterNodeType
::
BlockSeq
:
case
EmitterNodeType
::
BlockMap
:
m_stream
<<
"
\n
"
;
break
;
}
}
// SpaceOrIndentTo
// . Prepares for some more content by proper spacing
void
Emitter
::
SpaceOrIndentTo
(
bool
requireSpace
,
unsigned
indent
)
{
if
(
m_stream
.
comment
())
m_stream
<<
"
\n
"
;
if
(
m_stream
.
col
()
>
0
&&
requireSpace
)
m_stream
<<
" "
;
m_stream
<<
IndentTo
(
indent
);
}
void
Emitter
::
PrepareIntegralStream
(
std
::
stringstream
&
stream
)
const
{
switch
(
m_pState
->
GetIntFormat
())
{
case
Dec
:
stream
<<
std
::
dec
;
break
;
case
Hex
:
stream
<<
"0x"
;
stream
<<
std
::
hex
;
break
;
case
Oct
:
stream
<<
"0"
;
stream
<<
std
::
oct
;
break
;
default:
assert
(
false
);
}
}
void
Emitter
::
StartedScalar
()
{
m_pState
->
StartedScalar
();
}
// *******************************************************************************************
// overloads of Write
Emitter
&
Emitter
::
Write
(
const
std
::
string
&
str
)
{
if
(
!
good
())
return
*
this
;
const
bool
escapeNonAscii
=
m_pState
->
GetOutputCharset
()
==
EscapeNonAscii
;
const
StringFormat
::
value
strFormat
=
Utils
::
ComputeStringFormat
(
str
,
m_pState
->
GetStringFormat
(),
m_pState
->
CurGroupFlowType
(),
escapeNonAscii
);
if
(
strFormat
==
StringFormat
::
Literal
)
m_pState
->
SetMapKeyFormat
(
YAML
::
LongKey
,
FmtScope
::
Local
);
PrepareNode
(
EmitterNodeType
::
Scalar
);
switch
(
strFormat
)
{
case
StringFormat
::
Plain
:
m_stream
<<
str
;
break
;
case
StringFormat
::
SingleQuoted
:
Utils
::
WriteSingleQuotedString
(
m_stream
,
str
);
break
;
case
StringFormat
::
DoubleQuoted
:
Utils
::
WriteDoubleQuotedString
(
m_stream
,
str
,
escapeNonAscii
);
break
;
case
StringFormat
::
Literal
:
Utils
::
WriteLiteralString
(
m_stream
,
str
,
m_pState
->
CurIndent
()
+
m_pState
->
GetIndent
());
break
;
}
StartedScalar
();
return
*
this
;
}
unsigned
Emitter
::
GetFloatPrecision
()
const
{
return
m_pState
->
GetFloatPrecision
();
}
unsigned
Emitter
::
GetDoublePrecision
()
const
{
return
m_pState
->
GetDoublePrecision
();
}
const
char
*
Emitter
::
ComputeFullBoolName
(
bool
b
)
const
{
const
EMITTER_MANIP
mainFmt
=
(
m_pState
->
GetBoolLengthFormat
()
==
ShortBool
?
YesNoBool
:
m_pState
->
GetBoolFormat
());
const
EMITTER_MANIP
caseFmt
=
m_pState
->
GetBoolCaseFormat
();
switch
(
mainFmt
)
{
case
YesNoBool
:
switch
(
caseFmt
)
{
case
UpperCase
:
return
b
?
"YES"
:
"NO"
;
case
CamelCase
:
return
b
?
"Yes"
:
"No"
;
case
LowerCase
:
return
b
?
"yes"
:
"no"
;
default:
break
;
}
break
;
case
OnOffBool
:
switch
(
caseFmt
)
{
case
UpperCase
:
return
b
?
"ON"
:
"OFF"
;
case
CamelCase
:
return
b
?
"On"
:
"Off"
;
case
LowerCase
:
return
b
?
"on"
:
"off"
;
default:
break
;
}
break
;
case
TrueFalseBool
:
switch
(
caseFmt
)
{
case
UpperCase
:
return
b
?
"TRUE"
:
"FALSE"
;
case
CamelCase
:
return
b
?
"True"
:
"False"
;
case
LowerCase
:
return
b
?
"true"
:
"false"
;
default:
break
;
}
break
;
default:
break
;
}
return
b
?
"y"
:
"n"
;
// should never get here, but it can't hurt to give
// these answers
}
Emitter
&
Emitter
::
Write
(
bool
b
)
{
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
Scalar
);
const
char
*
name
=
ComputeFullBoolName
(
b
);
if
(
m_pState
->
GetBoolLengthFormat
()
==
ShortBool
)
m_stream
<<
name
[
0
];
else
m_stream
<<
name
;
StartedScalar
();
const
char
*
Emitter
::
ComputeFullBoolName
(
bool
b
)
const
{
const
EMITTER_MANIP
mainFmt
=
(
m_pState
->
GetBoolLengthFormat
()
==
ShortBool
?
YesNoBool
:
m_pState
->
GetBoolFormat
());
const
EMITTER_MANIP
caseFmt
=
m_pState
->
GetBoolCaseFormat
();
switch
(
mainFmt
)
{
case
YesNoBool
:
switch
(
caseFmt
)
{
case
UpperCase
:
return
b
?
"YES"
:
"NO"
;
case
CamelCase
:
return
b
?
"Yes"
:
"No"
;
case
LowerCase
:
return
b
?
"yes"
:
"no"
;
default:
break
;
}
break
;
case
OnOffBool
:
switch
(
caseFmt
)
{
case
UpperCase
:
return
b
?
"ON"
:
"OFF"
;
case
CamelCase
:
return
b
?
"On"
:
"Off"
;
case
LowerCase
:
return
b
?
"on"
:
"off"
;
default:
break
;
}
break
;
case
TrueFalseBool
:
switch
(
caseFmt
)
{
case
UpperCase
:
return
b
?
"TRUE"
:
"FALSE"
;
case
CamelCase
:
return
b
?
"True"
:
"False"
;
case
LowerCase
:
return
b
?
"true"
:
"false"
;
default:
break
;
}
break
;
default:
break
;
}
return
b
?
"y"
:
"n"
;
// should never get here, but it can't hurt to give these answers
}
Emitter
&
Emitter
::
Write
(
bool
b
)
{
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
Scalar
);
const
char
*
name
=
ComputeFullBoolName
(
b
);
if
(
m_pState
->
GetBoolLengthFormat
()
==
ShortBool
)
m_stream
<<
name
[
0
];
else
m_stream
<<
name
;
StartedScalar
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
char
ch
)
{
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
Scalar
);
Utils
::
WriteChar
(
m_stream
,
ch
);
StartedScalar
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
_Alias
&
alias
)
{
if
(
!
good
())
return
*
this
;
if
(
m_pState
->
HasAnchor
()
||
m_pState
->
HasTag
())
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_ALIAS
);
return
*
this
;
}
PrepareNode
(
EmitterNodeType
::
Scalar
);
if
(
!
Utils
::
WriteAlias
(
m_stream
,
alias
.
content
))
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_ALIAS
);
return
*
this
;
}
StartedScalar
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
_Anchor
&
anchor
)
{
if
(
!
good
())
return
*
this
;
if
(
m_pState
->
HasAnchor
())
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_ANCHOR
);
return
*
this
;
}
PrepareNode
(
EmitterNodeType
::
Property
);
if
(
!
Utils
::
WriteAnchor
(
m_stream
,
anchor
.
content
))
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_ANCHOR
);
return
*
this
;
}
m_pState
->
SetAnchor
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
_Tag
&
tag
)
{
if
(
!
good
())
return
*
this
;
if
(
m_pState
->
HasTag
())
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_TAG
);
return
*
this
;
}
PrepareNode
(
EmitterNodeType
::
Property
);
bool
success
=
false
;
if
(
tag
.
type
==
_Tag
::
Type
::
Verbatim
)
success
=
Utils
::
WriteTag
(
m_stream
,
tag
.
content
,
true
);
else
if
(
tag
.
type
==
_Tag
::
Type
::
PrimaryHandle
)
success
=
Utils
::
WriteTag
(
m_stream
,
tag
.
content
,
false
);
else
success
=
Utils
::
WriteTagWithPrefix
(
m_stream
,
tag
.
prefix
,
tag
.
content
);
if
(
!
success
)
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_TAG
);
return
*
this
;
}
m_pState
->
SetTag
();
return
*
this
;
}
void
Emitter
::
EmitKindTag
()
{
Write
(
LocalTag
(
""
));
}
Emitter
&
Emitter
::
Write
(
const
_Comment
&
comment
)
{
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
None
);
if
(
m_stream
.
col
()
>
0
)
m_stream
<<
Indentation
(
m_pState
->
GetPreCommentIndent
());
Utils
::
WriteComment
(
m_stream
,
comment
.
content
,
m_pState
->
GetPostCommentIndent
());
m_pState
->
SetNonContent
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
_Null
&
/*null*/
)
{
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
Scalar
);
m_stream
<<
"~"
;
StartedScalar
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
Binary
&
binary
)
{
Write
(
SecondaryTag
(
"binary"
));
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
Scalar
);
Utils
::
WriteBinary
(
m_stream
,
binary
);
StartedScalar
();
return
*
this
;
}
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
char
ch
)
{
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
Scalar
);
Utils
::
WriteChar
(
m_stream
,
ch
);
StartedScalar
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
_Alias
&
alias
)
{
if
(
!
good
())
return
*
this
;
if
(
m_pState
->
HasAnchor
()
||
m_pState
->
HasTag
())
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_ALIAS
);
return
*
this
;
}
PrepareNode
(
EmitterNodeType
::
Scalar
);
if
(
!
Utils
::
WriteAlias
(
m_stream
,
alias
.
content
))
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_ALIAS
);
return
*
this
;
}
StartedScalar
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
_Anchor
&
anchor
)
{
if
(
!
good
())
return
*
this
;
if
(
m_pState
->
HasAnchor
())
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_ANCHOR
);
return
*
this
;
}
PrepareNode
(
EmitterNodeType
::
Property
);
if
(
!
Utils
::
WriteAnchor
(
m_stream
,
anchor
.
content
))
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_ANCHOR
);
return
*
this
;
}
m_pState
->
SetAnchor
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
_Tag
&
tag
)
{
if
(
!
good
())
return
*
this
;
if
(
m_pState
->
HasTag
())
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_TAG
);
return
*
this
;
}
PrepareNode
(
EmitterNodeType
::
Property
);
bool
success
=
false
;
if
(
tag
.
type
==
_Tag
::
Type
::
Verbatim
)
success
=
Utils
::
WriteTag
(
m_stream
,
tag
.
content
,
true
);
else
if
(
tag
.
type
==
_Tag
::
Type
::
PrimaryHandle
)
success
=
Utils
::
WriteTag
(
m_stream
,
tag
.
content
,
false
);
else
success
=
Utils
::
WriteTagWithPrefix
(
m_stream
,
tag
.
prefix
,
tag
.
content
);
if
(
!
success
)
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_TAG
);
return
*
this
;
}
m_pState
->
SetTag
();
return
*
this
;
}
void
Emitter
::
EmitKindTag
()
{
Write
(
LocalTag
(
""
));
}
Emitter
&
Emitter
::
Write
(
const
_Comment
&
comment
)
{
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
None
);
if
(
m_stream
.
col
()
>
0
)
m_stream
<<
Indentation
(
m_pState
->
GetPreCommentIndent
());
Utils
::
WriteComment
(
m_stream
,
comment
.
content
,
m_pState
->
GetPostCommentIndent
());
m_pState
->
SetNonContent
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
_Null
&
/*null*/
)
{
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
Scalar
);
m_stream
<<
"~"
;
StartedScalar
();
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
Binary
&
binary
)
{
Write
(
SecondaryTag
(
"binary"
));
if
(
!
good
())
return
*
this
;
PrepareNode
(
EmitterNodeType
::
Scalar
);
Utils
::
WriteBinary
(
m_stream
,
binary
);
StartedScalar
();
return
*
this
;
}
}
src/emitterstate.cpp
View file @
9b4db068
...
...
@@ -2,383 +2,346 @@
#include "yaml-cpp/exceptions.h"
#include <limits>
namespace
YAML
{
EmitterState
::
EmitterState
()
:
m_isGood
(
true
),
m_curIndent
(
0
),
m_hasAnchor
(
false
),
m_hasTag
(
false
),
m_hasNonContent
(
false
),
m_docCount
(
0
)
{
// set default global manipulators
m_charset
.
set
(
EmitNonAscii
);
m_strFmt
.
set
(
Auto
);
m_boolFmt
.
set
(
TrueFalseBool
);
m_boolLengthFmt
.
set
(
LongBool
);
m_boolCaseFmt
.
set
(
LowerCase
);
m_intFmt
.
set
(
Dec
);
m_indent
.
set
(
2
);
m_preCommentIndent
.
set
(
2
);
m_postCommentIndent
.
set
(
1
);
m_seqFmt
.
set
(
Block
);
m_mapFmt
.
set
(
Block
);
m_mapKeyFmt
.
set
(
Auto
);
m_floatPrecision
.
set
(
std
::
numeric_limits
<
float
>::
digits10
+
1
);
m_doublePrecision
.
set
(
std
::
numeric_limits
<
double
>::
digits10
+
1
);
}
EmitterState
::~
EmitterState
()
{
}
// SetLocalValue
// . We blindly tries to set all possible formatters to this value
// . Only the ones that make sense will be accepted
void
EmitterState
::
SetLocalValue
(
EMITTER_MANIP
value
)
{
SetOutputCharset
(
value
,
FmtScope
::
Local
);
SetStringFormat
(
value
,
FmtScope
::
Local
);
SetBoolFormat
(
value
,
FmtScope
::
Local
);
SetBoolCaseFormat
(
value
,
FmtScope
::
Local
);
SetBoolLengthFormat
(
value
,
FmtScope
::
Local
);
SetIntFormat
(
value
,
FmtScope
::
Local
);
SetFlowType
(
GroupType
::
Seq
,
value
,
FmtScope
::
Local
);
SetFlowType
(
GroupType
::
Map
,
value
,
FmtScope
::
Local
);
SetMapKeyFormat
(
value
,
FmtScope
::
Local
);
}
void
EmitterState
::
SetAnchor
()
{
m_hasAnchor
=
true
;
}
void
EmitterState
::
SetTag
()
{
m_hasTag
=
true
;
}
void
EmitterState
::
SetNonContent
()
{
m_hasNonContent
=
true
;
}
void
EmitterState
::
SetLongKey
()
{
assert
(
!
m_groups
.
empty
());
if
(
m_groups
.
empty
())
return
;
assert
(
m_groups
.
top
().
type
==
GroupType
::
Map
);
m_groups
.
top
().
longKey
=
true
;
}
void
EmitterState
::
ForceFlow
()
{
assert
(
!
m_groups
.
empty
());
if
(
m_groups
.
empty
())
return
;
m_groups
.
top
().
flowType
=
FlowType
::
Flow
;
}
void
EmitterState
::
StartedNode
()
{
if
(
m_groups
.
empty
())
{
m_docCount
++
;
}
else
{
m_groups
.
top
().
childCount
++
;
if
(
m_groups
.
top
().
childCount
%
2
==
0
)
m_groups
.
top
().
longKey
=
false
;
}
m_hasAnchor
=
false
;
m_hasTag
=
false
;
m_hasNonContent
=
false
;
}
EmitterNodeType
::
value
EmitterState
::
NextGroupType
(
GroupType
::
value
type
)
const
{
if
(
type
==
GroupType
::
Seq
)
{
if
(
GetFlowType
(
type
)
==
Block
)
return
EmitterNodeType
::
BlockSeq
;
else
return
EmitterNodeType
::
FlowSeq
;
}
else
{
if
(
GetFlowType
(
type
)
==
Block
)
return
EmitterNodeType
::
BlockMap
;
else
return
EmitterNodeType
::
FlowMap
;
}
// can't happen
assert
(
false
);
return
EmitterNodeType
::
None
;
}
void
EmitterState
::
StartedDoc
()
{
m_hasAnchor
=
false
;
m_hasTag
=
false
;
m_hasNonContent
=
false
;
}
void
EmitterState
::
EndedDoc
()
{
m_hasAnchor
=
false
;
m_hasTag
=
false
;
m_hasNonContent
=
false
;
}
void
EmitterState
::
StartedScalar
()
{
StartedNode
();
ClearModifiedSettings
();
}
void
EmitterState
::
StartedGroup
(
GroupType
::
value
type
)
{
StartedNode
();
const
int
lastGroupIndent
=
(
m_groups
.
empty
()
?
0
:
m_groups
.
top
().
indent
);
m_curIndent
+=
lastGroupIndent
;
std
::
auto_ptr
<
Group
>
pGroup
(
new
Group
(
type
));
// transfer settings (which last until this group is done)
pGroup
->
modifiedSettings
=
m_modifiedSettings
;
// set up group
if
(
GetFlowType
(
type
)
==
Block
)
pGroup
->
flowType
=
FlowType
::
Block
;
else
pGroup
->
flowType
=
FlowType
::
Flow
;
pGroup
->
indent
=
GetIndent
();
m_groups
.
push
(
pGroup
);
}
void
EmitterState
::
EndedGroup
(
GroupType
::
value
type
)
{
if
(
m_groups
.
empty
())
{
if
(
type
==
GroupType
::
Seq
)
return
SetError
(
ErrorMsg
::
UNEXPECTED_END_SEQ
);
else
return
SetError
(
ErrorMsg
::
UNEXPECTED_END_MAP
);
}
// get rid of the current group
{
std
::
auto_ptr
<
Group
>
pFinishedGroup
=
m_groups
.
pop
();
if
(
pFinishedGroup
->
type
!=
type
)
return
SetError
(
ErrorMsg
::
UNMATCHED_GROUP_TAG
);
}
// reset old settings
unsigned
lastIndent
=
(
m_groups
.
empty
()
?
0
:
m_groups
.
top
().
indent
);
assert
(
m_curIndent
>=
lastIndent
);
m_curIndent
-=
lastIndent
;
// some global settings that we changed may have been overridden
// by a local setting we just popped, so we need to restore them
m_globalModifiedSettings
.
restore
();
ClearModifiedSettings
();
}
EmitterNodeType
::
value
EmitterState
::
CurGroupNodeType
()
const
{
if
(
m_groups
.
empty
())
return
EmitterNodeType
::
None
;
return
m_groups
.
top
().
NodeType
();
}
GroupType
::
value
EmitterState
::
CurGroupType
()
const
{
return
m_groups
.
empty
()
?
GroupType
::
None
:
m_groups
.
top
().
type
;
}
FlowType
::
value
EmitterState
::
CurGroupFlowType
()
const
{
return
m_groups
.
empty
()
?
FlowType
::
None
:
m_groups
.
top
().
flowType
;
}
int
EmitterState
::
CurGroupIndent
()
const
{
return
m_groups
.
empty
()
?
0
:
m_groups
.
top
().
indent
;
}
std
::
size_t
EmitterState
::
CurGroupChildCount
()
const
{
return
m_groups
.
empty
()
?
m_docCount
:
m_groups
.
top
().
childCount
;
}
bool
EmitterState
::
CurGroupLongKey
()
const
{
return
m_groups
.
empty
()
?
false
:
m_groups
.
top
().
longKey
;
}
int
EmitterState
::
LastIndent
()
const
{
if
(
m_groups
.
size
()
<=
1
)
return
0
;
return
m_curIndent
-
m_groups
.
top
(
-
1
).
indent
;
}
void
EmitterState
::
ClearModifiedSettings
()
{
m_modifiedSettings
.
clear
();
}
bool
EmitterState
::
SetOutputCharset
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
EmitNonAscii
:
case
EscapeNonAscii
:
_Set
(
m_charset
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetStringFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
Auto
:
case
SingleQuoted
:
case
DoubleQuoted
:
case
Literal
:
_Set
(
m_strFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetBoolFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
OnOffBool
:
case
TrueFalseBool
:
case
YesNoBool
:
_Set
(
m_boolFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetBoolLengthFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
LongBool
:
case
ShortBool
:
_Set
(
m_boolLengthFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetBoolCaseFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
UpperCase
:
case
LowerCase
:
case
CamelCase
:
_Set
(
m_boolCaseFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetIntFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
Dec
:
case
Hex
:
case
Oct
:
_Set
(
m_intFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetIndent
(
unsigned
value
,
FmtScope
::
value
scope
)
{
if
(
value
<=
1
)
return
false
;
_Set
(
m_indent
,
value
,
scope
);
return
true
;
}
bool
EmitterState
::
SetPreCommentIndent
(
unsigned
value
,
FmtScope
::
value
scope
)
{
if
(
value
==
0
)
return
false
;
_Set
(
m_preCommentIndent
,
value
,
scope
);
return
true
;
}
bool
EmitterState
::
SetPostCommentIndent
(
unsigned
value
,
FmtScope
::
value
scope
)
{
if
(
value
==
0
)
return
false
;
_Set
(
m_postCommentIndent
,
value
,
scope
);
return
true
;
}
bool
EmitterState
::
SetFlowType
(
GroupType
::
value
groupType
,
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
Block
:
case
Flow
:
_Set
(
groupType
==
GroupType
::
Seq
?
m_seqFmt
:
m_mapFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
EMITTER_MANIP
EmitterState
::
GetFlowType
(
GroupType
::
value
groupType
)
const
{
// force flow style if we're currently in a flow
if
(
CurGroupFlowType
()
==
FlowType
::
Flow
)
return
Flow
;
// otherwise, go with what's asked of us
return
(
groupType
==
GroupType
::
Seq
?
m_seqFmt
.
get
()
:
m_mapFmt
.
get
());
}
bool
EmitterState
::
SetMapKeyFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
Auto
:
case
LongKey
:
_Set
(
m_mapKeyFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetFloatPrecision
(
int
value
,
FmtScope
::
value
scope
)
{
if
(
value
<
0
||
value
>
std
::
numeric_limits
<
float
>::
digits10
+
1
)
return
false
;
_Set
(
m_floatPrecision
,
value
,
scope
);
return
true
;
}
bool
EmitterState
::
SetDoublePrecision
(
int
value
,
FmtScope
::
value
scope
)
{
if
(
value
<
0
||
value
>
std
::
numeric_limits
<
double
>::
digits10
+
1
)
return
false
;
_Set
(
m_doublePrecision
,
value
,
scope
);
return
true
;
}
namespace
YAML
{
EmitterState
::
EmitterState
()
:
m_isGood
(
true
),
m_curIndent
(
0
),
m_hasAnchor
(
false
),
m_hasTag
(
false
),
m_hasNonContent
(
false
),
m_docCount
(
0
)
{
// set default global manipulators
m_charset
.
set
(
EmitNonAscii
);
m_strFmt
.
set
(
Auto
);
m_boolFmt
.
set
(
TrueFalseBool
);
m_boolLengthFmt
.
set
(
LongBool
);
m_boolCaseFmt
.
set
(
LowerCase
);
m_intFmt
.
set
(
Dec
);
m_indent
.
set
(
2
);
m_preCommentIndent
.
set
(
2
);
m_postCommentIndent
.
set
(
1
);
m_seqFmt
.
set
(
Block
);
m_mapFmt
.
set
(
Block
);
m_mapKeyFmt
.
set
(
Auto
);
m_floatPrecision
.
set
(
std
::
numeric_limits
<
float
>::
digits10
+
1
);
m_doublePrecision
.
set
(
std
::
numeric_limits
<
double
>::
digits10
+
1
);
}
EmitterState
::~
EmitterState
()
{}
// SetLocalValue
// . We blindly tries to set all possible formatters to this value
// . Only the ones that make sense will be accepted
void
EmitterState
::
SetLocalValue
(
EMITTER_MANIP
value
)
{
SetOutputCharset
(
value
,
FmtScope
::
Local
);
SetStringFormat
(
value
,
FmtScope
::
Local
);
SetBoolFormat
(
value
,
FmtScope
::
Local
);
SetBoolCaseFormat
(
value
,
FmtScope
::
Local
);
SetBoolLengthFormat
(
value
,
FmtScope
::
Local
);
SetIntFormat
(
value
,
FmtScope
::
Local
);
SetFlowType
(
GroupType
::
Seq
,
value
,
FmtScope
::
Local
);
SetFlowType
(
GroupType
::
Map
,
value
,
FmtScope
::
Local
);
SetMapKeyFormat
(
value
,
FmtScope
::
Local
);
}
void
EmitterState
::
SetAnchor
()
{
m_hasAnchor
=
true
;
}
void
EmitterState
::
SetTag
()
{
m_hasTag
=
true
;
}
void
EmitterState
::
SetNonContent
()
{
m_hasNonContent
=
true
;
}
void
EmitterState
::
SetLongKey
()
{
assert
(
!
m_groups
.
empty
());
if
(
m_groups
.
empty
())
return
;
assert
(
m_groups
.
top
().
type
==
GroupType
::
Map
);
m_groups
.
top
().
longKey
=
true
;
}
void
EmitterState
::
ForceFlow
()
{
assert
(
!
m_groups
.
empty
());
if
(
m_groups
.
empty
())
return
;
m_groups
.
top
().
flowType
=
FlowType
::
Flow
;
}
void
EmitterState
::
StartedNode
()
{
if
(
m_groups
.
empty
())
{
m_docCount
++
;
}
else
{
m_groups
.
top
().
childCount
++
;
if
(
m_groups
.
top
().
childCount
%
2
==
0
)
m_groups
.
top
().
longKey
=
false
;
}
m_hasAnchor
=
false
;
m_hasTag
=
false
;
m_hasNonContent
=
false
;
}
EmitterNodeType
::
value
EmitterState
::
NextGroupType
(
GroupType
::
value
type
)
const
{
if
(
type
==
GroupType
::
Seq
)
{
if
(
GetFlowType
(
type
)
==
Block
)
return
EmitterNodeType
::
BlockSeq
;
else
return
EmitterNodeType
::
FlowSeq
;
}
else
{
if
(
GetFlowType
(
type
)
==
Block
)
return
EmitterNodeType
::
BlockMap
;
else
return
EmitterNodeType
::
FlowMap
;
}
// can't happen
assert
(
false
);
return
EmitterNodeType
::
None
;
}
void
EmitterState
::
StartedDoc
()
{
m_hasAnchor
=
false
;
m_hasTag
=
false
;
m_hasNonContent
=
false
;
}
void
EmitterState
::
EndedDoc
()
{
m_hasAnchor
=
false
;
m_hasTag
=
false
;
m_hasNonContent
=
false
;
}
void
EmitterState
::
StartedScalar
()
{
StartedNode
();
ClearModifiedSettings
();
}
void
EmitterState
::
StartedGroup
(
GroupType
::
value
type
)
{
StartedNode
();
const
int
lastGroupIndent
=
(
m_groups
.
empty
()
?
0
:
m_groups
.
top
().
indent
);
m_curIndent
+=
lastGroupIndent
;
std
::
auto_ptr
<
Group
>
pGroup
(
new
Group
(
type
));
// transfer settings (which last until this group is done)
pGroup
->
modifiedSettings
=
m_modifiedSettings
;
// set up group
if
(
GetFlowType
(
type
)
==
Block
)
pGroup
->
flowType
=
FlowType
::
Block
;
else
pGroup
->
flowType
=
FlowType
::
Flow
;
pGroup
->
indent
=
GetIndent
();
m_groups
.
push
(
pGroup
);
}
void
EmitterState
::
EndedGroup
(
GroupType
::
value
type
)
{
if
(
m_groups
.
empty
())
{
if
(
type
==
GroupType
::
Seq
)
return
SetError
(
ErrorMsg
::
UNEXPECTED_END_SEQ
);
else
return
SetError
(
ErrorMsg
::
UNEXPECTED_END_MAP
);
}
// get rid of the current group
{
std
::
auto_ptr
<
Group
>
pFinishedGroup
=
m_groups
.
pop
();
if
(
pFinishedGroup
->
type
!=
type
)
return
SetError
(
ErrorMsg
::
UNMATCHED_GROUP_TAG
);
}
// reset old settings
unsigned
lastIndent
=
(
m_groups
.
empty
()
?
0
:
m_groups
.
top
().
indent
);
assert
(
m_curIndent
>=
lastIndent
);
m_curIndent
-=
lastIndent
;
// some global settings that we changed may have been overridden
// by a local setting we just popped, so we need to restore them
m_globalModifiedSettings
.
restore
();
ClearModifiedSettings
();
}
EmitterNodeType
::
value
EmitterState
::
CurGroupNodeType
()
const
{
if
(
m_groups
.
empty
())
return
EmitterNodeType
::
None
;
return
m_groups
.
top
().
NodeType
();
}
GroupType
::
value
EmitterState
::
CurGroupType
()
const
{
return
m_groups
.
empty
()
?
GroupType
::
None
:
m_groups
.
top
().
type
;
}
FlowType
::
value
EmitterState
::
CurGroupFlowType
()
const
{
return
m_groups
.
empty
()
?
FlowType
::
None
:
m_groups
.
top
().
flowType
;
}
int
EmitterState
::
CurGroupIndent
()
const
{
return
m_groups
.
empty
()
?
0
:
m_groups
.
top
().
indent
;
}
std
::
size_t
EmitterState
::
CurGroupChildCount
()
const
{
return
m_groups
.
empty
()
?
m_docCount
:
m_groups
.
top
().
childCount
;
}
bool
EmitterState
::
CurGroupLongKey
()
const
{
return
m_groups
.
empty
()
?
false
:
m_groups
.
top
().
longKey
;
}
int
EmitterState
::
LastIndent
()
const
{
if
(
m_groups
.
size
()
<=
1
)
return
0
;
return
m_curIndent
-
m_groups
.
top
(
-
1
).
indent
;
}
void
EmitterState
::
ClearModifiedSettings
()
{
m_modifiedSettings
.
clear
();
}
bool
EmitterState
::
SetOutputCharset
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
EmitNonAscii
:
case
EscapeNonAscii
:
_Set
(
m_charset
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetStringFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
Auto
:
case
SingleQuoted
:
case
DoubleQuoted
:
case
Literal
:
_Set
(
m_strFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetBoolFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
OnOffBool
:
case
TrueFalseBool
:
case
YesNoBool
:
_Set
(
m_boolFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetBoolLengthFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
LongBool
:
case
ShortBool
:
_Set
(
m_boolLengthFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetBoolCaseFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
UpperCase
:
case
LowerCase
:
case
CamelCase
:
_Set
(
m_boolCaseFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetIntFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
Dec
:
case
Hex
:
case
Oct
:
_Set
(
m_intFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetIndent
(
unsigned
value
,
FmtScope
::
value
scope
)
{
if
(
value
<=
1
)
return
false
;
_Set
(
m_indent
,
value
,
scope
);
return
true
;
}
bool
EmitterState
::
SetPreCommentIndent
(
unsigned
value
,
FmtScope
::
value
scope
)
{
if
(
value
==
0
)
return
false
;
_Set
(
m_preCommentIndent
,
value
,
scope
);
return
true
;
}
bool
EmitterState
::
SetPostCommentIndent
(
unsigned
value
,
FmtScope
::
value
scope
)
{
if
(
value
==
0
)
return
false
;
_Set
(
m_postCommentIndent
,
value
,
scope
);
return
true
;
}
bool
EmitterState
::
SetFlowType
(
GroupType
::
value
groupType
,
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
Block
:
case
Flow
:
_Set
(
groupType
==
GroupType
::
Seq
?
m_seqFmt
:
m_mapFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
EMITTER_MANIP
EmitterState
::
GetFlowType
(
GroupType
::
value
groupType
)
const
{
// force flow style if we're currently in a flow
if
(
CurGroupFlowType
()
==
FlowType
::
Flow
)
return
Flow
;
// otherwise, go with what's asked of us
return
(
groupType
==
GroupType
::
Seq
?
m_seqFmt
.
get
()
:
m_mapFmt
.
get
());
}
bool
EmitterState
::
SetMapKeyFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
)
{
switch
(
value
)
{
case
Auto
:
case
LongKey
:
_Set
(
m_mapKeyFmt
,
value
,
scope
);
return
true
;
default:
return
false
;
}
}
bool
EmitterState
::
SetFloatPrecision
(
int
value
,
FmtScope
::
value
scope
)
{
if
(
value
<
0
||
value
>
std
::
numeric_limits
<
float
>::
digits10
+
1
)
return
false
;
_Set
(
m_floatPrecision
,
value
,
scope
);
return
true
;
}
bool
EmitterState
::
SetDoublePrecision
(
int
value
,
FmtScope
::
value
scope
)
{
if
(
value
<
0
||
value
>
std
::
numeric_limits
<
double
>::
digits10
+
1
)
return
false
;
_Set
(
m_doublePrecision
,
value
,
scope
);
return
true
;
}
}
src/emitterstate.h
View file @
9b4db068
#ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "ptr_stack.h"
#include "setting.h"
#include "yaml-cpp/emitterdef.h"
...
...
@@ -16,175 +17,198 @@
#include <memory>
#include <stdexcept>
namespace
YAML
{
struct
FmtScope
{
enum
value
{
Local
,
Global
};
};
struct
GroupType
{
enum
value
{
None
,
Seq
,
Map
};
};
struct
FlowType
{
enum
value
{
None
,
Flow
,
Block
};
};
class
EmitterState
{
public:
EmitterState
();
~
EmitterState
();
// basic state checking
bool
good
()
const
{
return
m_isGood
;
}
const
std
::
string
GetLastError
()
const
{
return
m_lastError
;
}
void
SetError
(
const
std
::
string
&
error
)
{
m_isGood
=
false
;
m_lastError
=
error
;
}
// node handling
void
SetAnchor
();
void
SetTag
();
void
SetNonContent
();
void
SetLongKey
();
void
ForceFlow
();
void
StartedDoc
();
void
EndedDoc
();
void
StartedScalar
();
void
StartedGroup
(
GroupType
::
value
type
);
void
EndedGroup
(
GroupType
::
value
type
);
EmitterNodeType
::
value
NextGroupType
(
GroupType
::
value
type
)
const
;
EmitterNodeType
::
value
CurGroupNodeType
()
const
;
GroupType
::
value
CurGroupType
()
const
;
FlowType
::
value
CurGroupFlowType
()
const
;
int
CurGroupIndent
()
const
;
std
::
size_t
CurGroupChildCount
()
const
;
bool
CurGroupLongKey
()
const
;
int
LastIndent
()
const
;
int
CurIndent
()
const
{
return
m_curIndent
;
}
bool
HasAnchor
()
const
{
return
m_hasAnchor
;
}
bool
HasTag
()
const
{
return
m_hasTag
;
}
bool
HasBegunNode
()
const
{
return
m_hasAnchor
||
m_hasTag
||
m_hasNonContent
;
}
bool
HasBegunContent
()
const
{
return
m_hasAnchor
||
m_hasTag
;
}
void
ClearModifiedSettings
();
// formatters
void
SetLocalValue
(
EMITTER_MANIP
value
);
bool
SetOutputCharset
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetOutputCharset
()
const
{
return
m_charset
.
get
();
}
bool
SetStringFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetStringFormat
()
const
{
return
m_strFmt
.
get
();
}
bool
SetBoolFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetBoolFormat
()
const
{
return
m_boolFmt
.
get
();
}
bool
SetBoolLengthFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetBoolLengthFormat
()
const
{
return
m_boolLengthFmt
.
get
();
}
bool
SetBoolCaseFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetBoolCaseFormat
()
const
{
return
m_boolCaseFmt
.
get
();
}
bool
SetIntFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetIntFormat
()
const
{
return
m_intFmt
.
get
();
}
bool
SetIndent
(
unsigned
value
,
FmtScope
::
value
scope
);
int
GetIndent
()
const
{
return
m_indent
.
get
();
}
bool
SetPreCommentIndent
(
unsigned
value
,
FmtScope
::
value
scope
);
int
GetPreCommentIndent
()
const
{
return
m_preCommentIndent
.
get
();
}
bool
SetPostCommentIndent
(
unsigned
value
,
FmtScope
::
value
scope
);
int
GetPostCommentIndent
()
const
{
return
m_postCommentIndent
.
get
();
}
bool
SetFlowType
(
GroupType
::
value
groupType
,
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetFlowType
(
GroupType
::
value
groupType
)
const
;
bool
SetMapKeyFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetMapKeyFormat
()
const
{
return
m_mapKeyFmt
.
get
();
}
bool
SetFloatPrecision
(
int
value
,
FmtScope
::
value
scope
);
unsigned
GetFloatPrecision
()
const
{
return
m_floatPrecision
.
get
();
}
bool
SetDoublePrecision
(
int
value
,
FmtScope
::
value
scope
);
unsigned
GetDoublePrecision
()
const
{
return
m_doublePrecision
.
get
();
}
private:
template
<
typename
T
>
void
_Set
(
Setting
<
T
>&
fmt
,
T
value
,
FmtScope
::
value
scope
);
void
StartedNode
();
private:
// basic state ok?
bool
m_isGood
;
std
::
string
m_lastError
;
// other state
Setting
<
EMITTER_MANIP
>
m_charset
;
Setting
<
EMITTER_MANIP
>
m_strFmt
;
Setting
<
EMITTER_MANIP
>
m_boolFmt
;
Setting
<
EMITTER_MANIP
>
m_boolLengthFmt
;
Setting
<
EMITTER_MANIP
>
m_boolCaseFmt
;
Setting
<
EMITTER_MANIP
>
m_intFmt
;
Setting
<
unsigned
>
m_indent
;
Setting
<
unsigned
>
m_preCommentIndent
,
m_postCommentIndent
;
Setting
<
EMITTER_MANIP
>
m_seqFmt
;
Setting
<
EMITTER_MANIP
>
m_mapFmt
;
Setting
<
EMITTER_MANIP
>
m_mapKeyFmt
;
Setting
<
int
>
m_floatPrecision
;
Setting
<
int
>
m_doublePrecision
;
SettingChanges
m_modifiedSettings
;
SettingChanges
m_globalModifiedSettings
;
struct
Group
{
explicit
Group
(
GroupType
::
value
type_
)
:
type
(
type_
),
indent
(
0
),
childCount
(
0
),
longKey
(
false
)
{}
GroupType
::
value
type
;
FlowType
::
value
flowType
;
int
indent
;
std
::
size_t
childCount
;
bool
longKey
;
SettingChanges
modifiedSettings
;
EmitterNodeType
::
value
NodeType
()
const
{
if
(
type
==
GroupType
::
Seq
)
{
if
(
flowType
==
FlowType
::
Flow
)
return
EmitterNodeType
::
FlowSeq
;
else
return
EmitterNodeType
::
BlockSeq
;
}
else
{
if
(
flowType
==
FlowType
::
Flow
)
return
EmitterNodeType
::
FlowMap
;
else
return
EmitterNodeType
::
BlockMap
;
}
// can't get here
assert
(
false
);
return
EmitterNodeType
::
None
;
}
};
ptr_stack
<
Group
>
m_groups
;
unsigned
m_curIndent
;
bool
m_hasAnchor
;
bool
m_hasTag
;
bool
m_hasNonContent
;
std
::
size_t
m_docCount
;
};
template
<
typename
T
>
void
EmitterState
::
_Set
(
Setting
<
T
>&
fmt
,
T
value
,
FmtScope
::
value
scope
)
{
switch
(
scope
)
{
case
FmtScope
::
Local
:
m_modifiedSettings
.
push
(
fmt
.
set
(
value
));
break
;
case
FmtScope
::
Global
:
fmt
.
set
(
value
);
m_globalModifiedSettings
.
push
(
fmt
.
set
(
value
));
// this pushes an identity set, so when we restore,
// it restores to the value here, and not the previous one
break
;
default:
assert
(
false
);
}
}
namespace
YAML
{
struct
FmtScope
{
enum
value
{
Local
,
Global
};
};
struct
GroupType
{
enum
value
{
None
,
Seq
,
Map
};
};
struct
FlowType
{
enum
value
{
None
,
Flow
,
Block
};
};
class
EmitterState
{
public:
EmitterState
();
~
EmitterState
();
// basic state checking
bool
good
()
const
{
return
m_isGood
;
}
const
std
::
string
GetLastError
()
const
{
return
m_lastError
;
}
void
SetError
(
const
std
::
string
&
error
)
{
m_isGood
=
false
;
m_lastError
=
error
;
}
// node handling
void
SetAnchor
();
void
SetTag
();
void
SetNonContent
();
void
SetLongKey
();
void
ForceFlow
();
void
StartedDoc
();
void
EndedDoc
();
void
StartedScalar
();
void
StartedGroup
(
GroupType
::
value
type
);
void
EndedGroup
(
GroupType
::
value
type
);
EmitterNodeType
::
value
NextGroupType
(
GroupType
::
value
type
)
const
;
EmitterNodeType
::
value
CurGroupNodeType
()
const
;
GroupType
::
value
CurGroupType
()
const
;
FlowType
::
value
CurGroupFlowType
()
const
;
int
CurGroupIndent
()
const
;
std
::
size_t
CurGroupChildCount
()
const
;
bool
CurGroupLongKey
()
const
;
int
LastIndent
()
const
;
int
CurIndent
()
const
{
return
m_curIndent
;
}
bool
HasAnchor
()
const
{
return
m_hasAnchor
;
}
bool
HasTag
()
const
{
return
m_hasTag
;
}
bool
HasBegunNode
()
const
{
return
m_hasAnchor
||
m_hasTag
||
m_hasNonContent
;
}
bool
HasBegunContent
()
const
{
return
m_hasAnchor
||
m_hasTag
;
}
void
ClearModifiedSettings
();
// formatters
void
SetLocalValue
(
EMITTER_MANIP
value
);
bool
SetOutputCharset
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetOutputCharset
()
const
{
return
m_charset
.
get
();
}
bool
SetStringFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetStringFormat
()
const
{
return
m_strFmt
.
get
();
}
bool
SetBoolFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetBoolFormat
()
const
{
return
m_boolFmt
.
get
();
}
bool
SetBoolLengthFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetBoolLengthFormat
()
const
{
return
m_boolLengthFmt
.
get
();
}
bool
SetBoolCaseFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetBoolCaseFormat
()
const
{
return
m_boolCaseFmt
.
get
();
}
bool
SetIntFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetIntFormat
()
const
{
return
m_intFmt
.
get
();
}
bool
SetIndent
(
unsigned
value
,
FmtScope
::
value
scope
);
int
GetIndent
()
const
{
return
m_indent
.
get
();
}
bool
SetPreCommentIndent
(
unsigned
value
,
FmtScope
::
value
scope
);
int
GetPreCommentIndent
()
const
{
return
m_preCommentIndent
.
get
();
}
bool
SetPostCommentIndent
(
unsigned
value
,
FmtScope
::
value
scope
);
int
GetPostCommentIndent
()
const
{
return
m_postCommentIndent
.
get
();
}
bool
SetFlowType
(
GroupType
::
value
groupType
,
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetFlowType
(
GroupType
::
value
groupType
)
const
;
bool
SetMapKeyFormat
(
EMITTER_MANIP
value
,
FmtScope
::
value
scope
);
EMITTER_MANIP
GetMapKeyFormat
()
const
{
return
m_mapKeyFmt
.
get
();
}
bool
SetFloatPrecision
(
int
value
,
FmtScope
::
value
scope
);
unsigned
GetFloatPrecision
()
const
{
return
m_floatPrecision
.
get
();
}
bool
SetDoublePrecision
(
int
value
,
FmtScope
::
value
scope
);
unsigned
GetDoublePrecision
()
const
{
return
m_doublePrecision
.
get
();
}
private:
template
<
typename
T
>
void
_Set
(
Setting
<
T
>&
fmt
,
T
value
,
FmtScope
::
value
scope
);
void
StartedNode
();
private:
// basic state ok?
bool
m_isGood
;
std
::
string
m_lastError
;
// other state
Setting
<
EMITTER_MANIP
>
m_charset
;
Setting
<
EMITTER_MANIP
>
m_strFmt
;
Setting
<
EMITTER_MANIP
>
m_boolFmt
;
Setting
<
EMITTER_MANIP
>
m_boolLengthFmt
;
Setting
<
EMITTER_MANIP
>
m_boolCaseFmt
;
Setting
<
EMITTER_MANIP
>
m_intFmt
;
Setting
<
unsigned
>
m_indent
;
Setting
<
unsigned
>
m_preCommentIndent
,
m_postCommentIndent
;
Setting
<
EMITTER_MANIP
>
m_seqFmt
;
Setting
<
EMITTER_MANIP
>
m_mapFmt
;
Setting
<
EMITTER_MANIP
>
m_mapKeyFmt
;
Setting
<
int
>
m_floatPrecision
;
Setting
<
int
>
m_doublePrecision
;
SettingChanges
m_modifiedSettings
;
SettingChanges
m_globalModifiedSettings
;
struct
Group
{
explicit
Group
(
GroupType
::
value
type_
)
:
type
(
type_
),
indent
(
0
),
childCount
(
0
),
longKey
(
false
)
{}
GroupType
::
value
type
;
FlowType
::
value
flowType
;
int
indent
;
std
::
size_t
childCount
;
bool
longKey
;
SettingChanges
modifiedSettings
;
EmitterNodeType
::
value
NodeType
()
const
{
if
(
type
==
GroupType
::
Seq
)
{
if
(
flowType
==
FlowType
::
Flow
)
return
EmitterNodeType
::
FlowSeq
;
else
return
EmitterNodeType
::
BlockSeq
;
}
else
{
if
(
flowType
==
FlowType
::
Flow
)
return
EmitterNodeType
::
FlowMap
;
else
return
EmitterNodeType
::
BlockMap
;
}
// can't get here
assert
(
false
);
return
EmitterNodeType
::
None
;
}
};
ptr_stack
<
Group
>
m_groups
;
unsigned
m_curIndent
;
bool
m_hasAnchor
;
bool
m_hasTag
;
bool
m_hasNonContent
;
std
::
size_t
m_docCount
;
};
template
<
typename
T
>
void
EmitterState
::
_Set
(
Setting
<
T
>&
fmt
,
T
value
,
FmtScope
::
value
scope
)
{
switch
(
scope
)
{
case
FmtScope
::
Local
:
m_modifiedSettings
.
push
(
fmt
.
set
(
value
));
break
;
case
FmtScope
::
Global
:
fmt
.
set
(
value
);
m_globalModifiedSettings
.
push
(
fmt
.
set
(
value
));
// this pushes an identity set, so when we restore,
// it restores to the value here, and not the previous one
break
;
default:
assert
(
false
);
}
}
}
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif
// EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/emitterutils.cpp
View file @
9b4db068
...
...
@@ -7,418 +7,436 @@
#include <sstream>
#include <iomanip>
namespace
YAML
{
namespace
Utils
{
namespace
{
enum
{
REPLACEMENT_CHARACTER
=
0xFFFD
};
bool
IsAnchorChar
(
int
ch
)
{
// test for ns-anchor-char
switch
(
ch
)
{
case
','
:
case
'['
:
case
']'
:
case
'{'
:
case
'}'
:
// c-flow-indicator
case
' '
:
case
'\t'
:
// s-white
case
0xFEFF
:
// c-byte-order-mark
case
0xA
:
case
0xD
:
// b-char
return
false
;
case
0x85
:
return
true
;
}
if
(
ch
<
0x20
)
return
false
;
if
(
ch
<
0x7E
)
return
true
;
if
(
ch
<
0xA0
)
return
false
;
if
(
ch
>=
0xD800
&&
ch
<=
0xDFFF
)
return
false
;
if
((
ch
&
0xFFFE
)
==
0xFFFE
)
return
false
;
if
((
ch
>=
0xFDD0
)
&&
(
ch
<=
0xFDEF
))
return
false
;
if
(
ch
>
0x10FFFF
)
return
false
;
return
true
;
}
int
Utf8BytesIndicated
(
char
ch
)
{
int
byteVal
=
static_cast
<
unsigned
char
>
(
ch
);
switch
(
byteVal
>>
4
)
{
case
0
:
case
1
:
case
2
:
case
3
:
case
4
:
case
5
:
case
6
:
case
7
:
return
1
;
case
12
:
case
13
:
return
2
;
case
14
:
return
3
;
case
15
:
return
4
;
default:
return
-
1
;
}
}
bool
IsTrailingByte
(
char
ch
)
{
return
(
ch
&
0xC0
)
==
0x80
;
}
bool
GetNextCodePointAndAdvance
(
int
&
codePoint
,
std
::
string
::
const_iterator
&
first
,
std
::
string
::
const_iterator
last
)
{
if
(
first
==
last
)
return
false
;
int
nBytes
=
Utf8BytesIndicated
(
*
first
);
if
(
nBytes
<
1
)
{
// Bad lead byte
++
first
;
codePoint
=
REPLACEMENT_CHARACTER
;
return
true
;
}
if
(
nBytes
==
1
)
{
codePoint
=
*
first
++
;
return
true
;
}
// Gather bits from trailing bytes
codePoint
=
static_cast
<
unsigned
char
>
(
*
first
)
&
~
(
0xFF
<<
(
7
-
nBytes
));
++
first
;
--
nBytes
;
for
(;
nBytes
>
0
;
++
first
,
--
nBytes
)
{
if
((
first
==
last
)
||
!
IsTrailingByte
(
*
first
))
{
codePoint
=
REPLACEMENT_CHARACTER
;
break
;
}
codePoint
<<=
6
;
codePoint
|=
*
first
&
0x3F
;
}
// Check for illegal code points
if
(
codePoint
>
0x10FFFF
)
codePoint
=
REPLACEMENT_CHARACTER
;
else
if
(
codePoint
>=
0xD800
&&
codePoint
<=
0xDFFF
)
codePoint
=
REPLACEMENT_CHARACTER
;
else
if
((
codePoint
&
0xFFFE
)
==
0xFFFE
)
codePoint
=
REPLACEMENT_CHARACTER
;
else
if
(
codePoint
>=
0xFDD0
&&
codePoint
<=
0xFDEF
)
codePoint
=
REPLACEMENT_CHARACTER
;
return
true
;
}
void
WriteCodePoint
(
ostream_wrapper
&
out
,
int
codePoint
)
{
if
(
codePoint
<
0
||
codePoint
>
0x10FFFF
)
{
codePoint
=
REPLACEMENT_CHARACTER
;
}
if
(
codePoint
<
0x7F
)
{
out
<<
static_cast
<
char
>
(
codePoint
);
}
else
if
(
codePoint
<
0x7FF
)
{
out
<<
static_cast
<
char
>
(
0xC0
|
(
codePoint
>>
6
))
<<
static_cast
<
char
>
(
0x80
|
(
codePoint
&
0x3F
));
}
else
if
(
codePoint
<
0xFFFF
)
{
out
<<
static_cast
<
char
>
(
0xE0
|
(
codePoint
>>
12
))
<<
static_cast
<
char
>
(
0x80
|
((
codePoint
>>
6
)
&
0x3F
))
<<
static_cast
<
char
>
(
0x80
|
(
codePoint
&
0x3F
));
}
else
{
out
<<
static_cast
<
char
>
(
0xF0
|
(
codePoint
>>
18
))
<<
static_cast
<
char
>
(
0x80
|
((
codePoint
>>
12
)
&
0x3F
))
<<
static_cast
<
char
>
(
0x80
|
((
codePoint
>>
6
)
&
0x3F
))
<<
static_cast
<
char
>
(
0x80
|
(
codePoint
&
0x3F
));
}
}
bool
IsValidPlainScalar
(
const
std
::
string
&
str
,
FlowType
::
value
flowType
,
bool
allowOnlyAscii
)
{
if
(
str
.
empty
())
return
false
;
// first check the start
const
RegEx
&
start
=
(
flowType
==
FlowType
::
Flow
?
Exp
::
PlainScalarInFlow
()
:
Exp
::
PlainScalar
());
if
(
!
start
.
Matches
(
str
))
return
false
;
// and check the end for plain whitespace (which can't be faithfully kept in a plain scalar)
if
(
!
str
.
empty
()
&&
*
str
.
rbegin
()
==
' '
)
return
false
;
// then check until something is disallowed
const
RegEx
&
disallowed
=
(
flowType
==
FlowType
::
Flow
?
Exp
::
EndScalarInFlow
()
:
Exp
::
EndScalar
())
||
(
Exp
::
BlankOrBreak
()
+
Exp
::
Comment
())
||
Exp
::
NotPrintable
()
||
Exp
::
Utf8_ByteOrderMark
()
||
Exp
::
Break
()
||
Exp
::
Tab
();
StringCharSource
buffer
(
str
.
c_str
(),
str
.
size
());
while
(
buffer
)
{
if
(
disallowed
.
Matches
(
buffer
))
return
false
;
if
(
allowOnlyAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
buffer
[
0
])))
return
false
;
++
buffer
;
}
return
true
;
}
bool
IsValidSingleQuotedScalar
(
const
std
::
string
&
str
,
bool
escapeNonAscii
)
{
// TODO: check for non-printable characters?
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
if
(
escapeNonAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
str
[
i
])))
return
false
;
if
(
str
[
i
]
==
'\n'
)
return
false
;
}
return
true
;
}
bool
IsValidLiteralScalar
(
const
std
::
string
&
str
,
FlowType
::
value
flowType
,
bool
escapeNonAscii
)
{
if
(
flowType
==
FlowType
::
Flow
)
return
false
;
// TODO: check for non-printable characters?
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
if
(
escapeNonAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
str
[
i
])))
return
false
;
}
return
true
;
}
void
WriteDoubleQuoteEscapeSequence
(
ostream_wrapper
&
out
,
int
codePoint
)
{
static
const
char
hexDigits
[]
=
"0123456789abcdef"
;
out
<<
"
\\
"
;
int
digits
=
8
;
if
(
codePoint
<
0xFF
)
{
out
<<
"x"
;
digits
=
2
;
}
else
if
(
codePoint
<
0xFFFF
)
{
out
<<
"u"
;
digits
=
4
;
}
else
{
out
<<
"U"
;
digits
=
8
;
}
// Write digits into the escape sequence
for
(;
digits
>
0
;
--
digits
)
out
<<
hexDigits
[(
codePoint
>>
(
4
*
(
digits
-
1
)))
&
0xF
];
}
bool
WriteAliasName
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
)
{
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());
)
{
if
(
!
IsAnchorChar
(
codePoint
))
return
false
;
WriteCodePoint
(
out
,
codePoint
);
}
return
true
;
}
}
StringFormat
::
value
ComputeStringFormat
(
const
std
::
string
&
str
,
EMITTER_MANIP
strFormat
,
FlowType
::
value
flowType
,
bool
escapeNonAscii
)
{
switch
(
strFormat
)
{
case
Auto
:
if
(
IsValidPlainScalar
(
str
,
flowType
,
escapeNonAscii
))
return
StringFormat
::
Plain
;
return
StringFormat
::
DoubleQuoted
;
case
SingleQuoted
:
if
(
IsValidSingleQuotedScalar
(
str
,
escapeNonAscii
))
return
StringFormat
::
SingleQuoted
;
return
StringFormat
::
DoubleQuoted
;
case
DoubleQuoted
:
return
StringFormat
::
DoubleQuoted
;
case
Literal
:
if
(
IsValidLiteralScalar
(
str
,
flowType
,
escapeNonAscii
))
return
StringFormat
::
Literal
;
return
StringFormat
::
DoubleQuoted
;
default:
break
;
}
return
StringFormat
::
DoubleQuoted
;
}
bool
WriteSingleQuotedString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
)
{
out
<<
"'"
;
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());
)
{
if
(
codePoint
==
'\n'
)
return
false
;
// We can't handle a new line and the attendant indentation yet
if
(
codePoint
==
'\''
)
out
<<
"''"
;
else
WriteCodePoint
(
out
,
codePoint
);
}
out
<<
"'"
;
return
true
;
}
bool
WriteDoubleQuotedString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
bool
escapeNonAscii
)
{
out
<<
"
\"
"
;
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());
)
{
switch
(
codePoint
)
{
case
'\"'
:
out
<<
"
\\\"
"
;
break
;
case
'\\'
:
out
<<
"
\\\\
"
;
break
;
case
'\n'
:
out
<<
"
\\
n"
;
break
;
case
'\t'
:
out
<<
"
\\
t"
;
break
;
case
'\r'
:
out
<<
"
\\
r"
;
break
;
case
'\b'
:
out
<<
"
\\
b"
;
break
;
default:
if
(
codePoint
<
0x20
||
(
codePoint
>=
0x80
&&
codePoint
<=
0xA0
))
// Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
else
if
(
codePoint
==
0xFEFF
)
// Byte order marks (ZWNS) should be escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
else
if
(
escapeNonAscii
&&
codePoint
>
0x7E
)
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
else
WriteCodePoint
(
out
,
codePoint
);
}
}
out
<<
"
\"
"
;
return
true
;
}
bool
WriteLiteralString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
int
indent
)
{
out
<<
"|
\n
"
;
out
<<
IndentTo
(
indent
);
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());
)
{
if
(
codePoint
==
'\n'
)
out
<<
"
\n
"
<<
IndentTo
(
indent
);
else
WriteCodePoint
(
out
,
codePoint
);
}
return
true
;
}
bool
WriteChar
(
ostream_wrapper
&
out
,
char
ch
)
{
if
((
'a'
<=
ch
&&
ch
<=
'z'
)
||
(
'A'
<=
ch
&&
ch
<=
'Z'
))
out
<<
ch
;
else
if
((
0x20
<=
ch
&&
ch
<=
0x7e
)
||
ch
==
' '
)
out
<<
"
\"
"
<<
ch
<<
"
\"
"
;
else
if
(
ch
==
'\t'
)
out
<<
"
\"\\
t
\"
"
;
else
if
(
ch
==
'\n'
)
out
<<
"
\"\\
n
\"
"
;
else
if
(
ch
==
'\b'
)
out
<<
"
\"\\
b
\"
"
;
else
{
out
<<
"
\"
"
;
WriteDoubleQuoteEscapeSequence
(
out
,
ch
);
out
<<
"
\"
"
;
}
return
true
;
}
bool
WriteComment
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
int
postCommentIndent
)
{
const
unsigned
curIndent
=
out
.
col
();
out
<<
"#"
<<
Indentation
(
postCommentIndent
);
out
.
set_comment
();
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());
)
{
if
(
codePoint
==
'\n'
)
{
out
<<
"
\n
"
<<
IndentTo
(
curIndent
)
<<
"#"
<<
Indentation
(
postCommentIndent
);
out
.
set_comment
();
}
else
{
WriteCodePoint
(
out
,
codePoint
);
}
}
return
true
;
}
bool
WriteAlias
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
)
{
out
<<
"*"
;
return
WriteAliasName
(
out
,
str
);
}
bool
WriteAnchor
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
)
{
out
<<
"&"
;
return
WriteAliasName
(
out
,
str
);
}
bool
WriteTag
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
bool
verbatim
)
{
out
<<
(
verbatim
?
"!<"
:
"!"
);
StringCharSource
buffer
(
str
.
c_str
(),
str
.
size
());
const
RegEx
&
reValid
=
verbatim
?
Exp
::
URI
()
:
Exp
::
Tag
();
while
(
buffer
)
{
int
n
=
reValid
.
Match
(
buffer
);
if
(
n
<=
0
)
return
false
;
while
(
--
n
>=
0
)
{
out
<<
buffer
[
0
];
++
buffer
;
}
}
if
(
verbatim
)
out
<<
">"
;
return
true
;
}
bool
WriteTagWithPrefix
(
ostream_wrapper
&
out
,
const
std
::
string
&
prefix
,
const
std
::
string
&
tag
)
{
out
<<
"!"
;
StringCharSource
prefixBuffer
(
prefix
.
c_str
(),
prefix
.
size
());
while
(
prefixBuffer
)
{
int
n
=
Exp
::
URI
().
Match
(
prefixBuffer
);
if
(
n
<=
0
)
return
false
;
while
(
--
n
>=
0
)
{
out
<<
prefixBuffer
[
0
];
++
prefixBuffer
;
}
}
out
<<
"!"
;
StringCharSource
tagBuffer
(
tag
.
c_str
(),
tag
.
size
());
while
(
tagBuffer
)
{
int
n
=
Exp
::
Tag
().
Match
(
tagBuffer
);
if
(
n
<=
0
)
return
false
;
while
(
--
n
>=
0
)
{
out
<<
tagBuffer
[
0
];
++
tagBuffer
;
}
}
return
true
;
}
bool
WriteBinary
(
ostream_wrapper
&
out
,
const
Binary
&
binary
)
{
WriteDoubleQuotedString
(
out
,
EncodeBase64
(
binary
.
data
(),
binary
.
size
()),
false
);
return
true
;
}
}
namespace
YAML
{
namespace
Utils
{
namespace
{
enum
{
REPLACEMENT_CHARACTER
=
0xFFFD
};
bool
IsAnchorChar
(
int
ch
)
{
// test for ns-anchor-char
switch
(
ch
)
{
case
','
:
case
'['
:
case
']'
:
case
'{'
:
case
'}'
:
// c-flow-indicator
case
' '
:
case
'\t'
:
// s-white
case
0xFEFF
:
// c-byte-order-mark
case
0xA
:
case
0xD
:
// b-char
return
false
;
case
0x85
:
return
true
;
}
if
(
ch
<
0x20
)
return
false
;
if
(
ch
<
0x7E
)
return
true
;
if
(
ch
<
0xA0
)
return
false
;
if
(
ch
>=
0xD800
&&
ch
<=
0xDFFF
)
return
false
;
if
((
ch
&
0xFFFE
)
==
0xFFFE
)
return
false
;
if
((
ch
>=
0xFDD0
)
&&
(
ch
<=
0xFDEF
))
return
false
;
if
(
ch
>
0x10FFFF
)
return
false
;
return
true
;
}
int
Utf8BytesIndicated
(
char
ch
)
{
int
byteVal
=
static_cast
<
unsigned
char
>
(
ch
);
switch
(
byteVal
>>
4
)
{
case
0
:
case
1
:
case
2
:
case
3
:
case
4
:
case
5
:
case
6
:
case
7
:
return
1
;
case
12
:
case
13
:
return
2
;
case
14
:
return
3
;
case
15
:
return
4
;
default:
return
-
1
;
}
}
bool
IsTrailingByte
(
char
ch
)
{
return
(
ch
&
0xC0
)
==
0x80
;
}
bool
GetNextCodePointAndAdvance
(
int
&
codePoint
,
std
::
string
::
const_iterator
&
first
,
std
::
string
::
const_iterator
last
)
{
if
(
first
==
last
)
return
false
;
int
nBytes
=
Utf8BytesIndicated
(
*
first
);
if
(
nBytes
<
1
)
{
// Bad lead byte
++
first
;
codePoint
=
REPLACEMENT_CHARACTER
;
return
true
;
}
if
(
nBytes
==
1
)
{
codePoint
=
*
first
++
;
return
true
;
}
// Gather bits from trailing bytes
codePoint
=
static_cast
<
unsigned
char
>
(
*
first
)
&
~
(
0xFF
<<
(
7
-
nBytes
));
++
first
;
--
nBytes
;
for
(;
nBytes
>
0
;
++
first
,
--
nBytes
)
{
if
((
first
==
last
)
||
!
IsTrailingByte
(
*
first
))
{
codePoint
=
REPLACEMENT_CHARACTER
;
break
;
}
codePoint
<<=
6
;
codePoint
|=
*
first
&
0x3F
;
}
// Check for illegal code points
if
(
codePoint
>
0x10FFFF
)
codePoint
=
REPLACEMENT_CHARACTER
;
else
if
(
codePoint
>=
0xD800
&&
codePoint
<=
0xDFFF
)
codePoint
=
REPLACEMENT_CHARACTER
;
else
if
((
codePoint
&
0xFFFE
)
==
0xFFFE
)
codePoint
=
REPLACEMENT_CHARACTER
;
else
if
(
codePoint
>=
0xFDD0
&&
codePoint
<=
0xFDEF
)
codePoint
=
REPLACEMENT_CHARACTER
;
return
true
;
}
void
WriteCodePoint
(
ostream_wrapper
&
out
,
int
codePoint
)
{
if
(
codePoint
<
0
||
codePoint
>
0x10FFFF
)
{
codePoint
=
REPLACEMENT_CHARACTER
;
}
if
(
codePoint
<
0x7F
)
{
out
<<
static_cast
<
char
>
(
codePoint
);
}
else
if
(
codePoint
<
0x7FF
)
{
out
<<
static_cast
<
char
>
(
0xC0
|
(
codePoint
>>
6
))
<<
static_cast
<
char
>
(
0x80
|
(
codePoint
&
0x3F
));
}
else
if
(
codePoint
<
0xFFFF
)
{
out
<<
static_cast
<
char
>
(
0xE0
|
(
codePoint
>>
12
))
<<
static_cast
<
char
>
(
0x80
|
((
codePoint
>>
6
)
&
0x3F
))
<<
static_cast
<
char
>
(
0x80
|
(
codePoint
&
0x3F
));
}
else
{
out
<<
static_cast
<
char
>
(
0xF0
|
(
codePoint
>>
18
))
<<
static_cast
<
char
>
(
0x80
|
((
codePoint
>>
12
)
&
0x3F
))
<<
static_cast
<
char
>
(
0x80
|
((
codePoint
>>
6
)
&
0x3F
))
<<
static_cast
<
char
>
(
0x80
|
(
codePoint
&
0x3F
));
}
}
bool
IsValidPlainScalar
(
const
std
::
string
&
str
,
FlowType
::
value
flowType
,
bool
allowOnlyAscii
)
{
if
(
str
.
empty
())
return
false
;
// first check the start
const
RegEx
&
start
=
(
flowType
==
FlowType
::
Flow
?
Exp
::
PlainScalarInFlow
()
:
Exp
::
PlainScalar
());
if
(
!
start
.
Matches
(
str
))
return
false
;
// and check the end for plain whitespace (which can't be faithfully kept in a
// plain scalar)
if
(
!
str
.
empty
()
&&
*
str
.
rbegin
()
==
' '
)
return
false
;
// then check until something is disallowed
const
RegEx
&
disallowed
=
(
flowType
==
FlowType
::
Flow
?
Exp
::
EndScalarInFlow
()
:
Exp
::
EndScalar
())
||
(
Exp
::
BlankOrBreak
()
+
Exp
::
Comment
())
||
Exp
::
NotPrintable
()
||
Exp
::
Utf8_ByteOrderMark
()
||
Exp
::
Break
()
||
Exp
::
Tab
();
StringCharSource
buffer
(
str
.
c_str
(),
str
.
size
());
while
(
buffer
)
{
if
(
disallowed
.
Matches
(
buffer
))
return
false
;
if
(
allowOnlyAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
buffer
[
0
])))
return
false
;
++
buffer
;
}
return
true
;
}
bool
IsValidSingleQuotedScalar
(
const
std
::
string
&
str
,
bool
escapeNonAscii
)
{
// TODO: check for non-printable characters?
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
if
(
escapeNonAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
str
[
i
])))
return
false
;
if
(
str
[
i
]
==
'\n'
)
return
false
;
}
return
true
;
}
bool
IsValidLiteralScalar
(
const
std
::
string
&
str
,
FlowType
::
value
flowType
,
bool
escapeNonAscii
)
{
if
(
flowType
==
FlowType
::
Flow
)
return
false
;
// TODO: check for non-printable characters?
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
if
(
escapeNonAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
str
[
i
])))
return
false
;
}
return
true
;
}
void
WriteDoubleQuoteEscapeSequence
(
ostream_wrapper
&
out
,
int
codePoint
)
{
static
const
char
hexDigits
[]
=
"0123456789abcdef"
;
out
<<
"
\\
"
;
int
digits
=
8
;
if
(
codePoint
<
0xFF
)
{
out
<<
"x"
;
digits
=
2
;
}
else
if
(
codePoint
<
0xFFFF
)
{
out
<<
"u"
;
digits
=
4
;
}
else
{
out
<<
"U"
;
digits
=
8
;
}
// Write digits into the escape sequence
for
(;
digits
>
0
;
--
digits
)
out
<<
hexDigits
[(
codePoint
>>
(
4
*
(
digits
-
1
)))
&
0xF
];
}
bool
WriteAliasName
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
)
{
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
if
(
!
IsAnchorChar
(
codePoint
))
return
false
;
WriteCodePoint
(
out
,
codePoint
);
}
return
true
;
}
}
StringFormat
::
value
ComputeStringFormat
(
const
std
::
string
&
str
,
EMITTER_MANIP
strFormat
,
FlowType
::
value
flowType
,
bool
escapeNonAscii
)
{
switch
(
strFormat
)
{
case
Auto
:
if
(
IsValidPlainScalar
(
str
,
flowType
,
escapeNonAscii
))
return
StringFormat
::
Plain
;
return
StringFormat
::
DoubleQuoted
;
case
SingleQuoted
:
if
(
IsValidSingleQuotedScalar
(
str
,
escapeNonAscii
))
return
StringFormat
::
SingleQuoted
;
return
StringFormat
::
DoubleQuoted
;
case
DoubleQuoted
:
return
StringFormat
::
DoubleQuoted
;
case
Literal
:
if
(
IsValidLiteralScalar
(
str
,
flowType
,
escapeNonAscii
))
return
StringFormat
::
Literal
;
return
StringFormat
::
DoubleQuoted
;
default:
break
;
}
return
StringFormat
::
DoubleQuoted
;
}
bool
WriteSingleQuotedString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
)
{
out
<<
"'"
;
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
if
(
codePoint
==
'\n'
)
return
false
;
// We can't handle a new line and the attendant indentation
// yet
if
(
codePoint
==
'\''
)
out
<<
"''"
;
else
WriteCodePoint
(
out
,
codePoint
);
}
out
<<
"'"
;
return
true
;
}
bool
WriteDoubleQuotedString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
bool
escapeNonAscii
)
{
out
<<
"
\"
"
;
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
switch
(
codePoint
)
{
case
'\"'
:
out
<<
"
\\\"
"
;
break
;
case
'\\'
:
out
<<
"
\\\\
"
;
break
;
case
'\n'
:
out
<<
"
\\
n"
;
break
;
case
'\t'
:
out
<<
"
\\
t"
;
break
;
case
'\r'
:
out
<<
"
\\
r"
;
break
;
case
'\b'
:
out
<<
"
\\
b"
;
break
;
default:
if
(
codePoint
<
0x20
||
(
codePoint
>=
0x80
&&
codePoint
<=
0xA0
))
// Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
else
if
(
codePoint
==
0xFEFF
)
// Byte order marks (ZWNS) should be
// escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
else
if
(
escapeNonAscii
&&
codePoint
>
0x7E
)
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
else
WriteCodePoint
(
out
,
codePoint
);
}
}
out
<<
"
\"
"
;
return
true
;
}
bool
WriteLiteralString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
int
indent
)
{
out
<<
"|
\n
"
;
out
<<
IndentTo
(
indent
);
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
if
(
codePoint
==
'\n'
)
out
<<
"
\n
"
<<
IndentTo
(
indent
);
else
WriteCodePoint
(
out
,
codePoint
);
}
return
true
;
}
bool
WriteChar
(
ostream_wrapper
&
out
,
char
ch
)
{
if
((
'a'
<=
ch
&&
ch
<=
'z'
)
||
(
'A'
<=
ch
&&
ch
<=
'Z'
))
out
<<
ch
;
else
if
((
0x20
<=
ch
&&
ch
<=
0x7e
)
||
ch
==
' '
)
out
<<
"
\"
"
<<
ch
<<
"
\"
"
;
else
if
(
ch
==
'\t'
)
out
<<
"
\"\\
t
\"
"
;
else
if
(
ch
==
'\n'
)
out
<<
"
\"\\
n
\"
"
;
else
if
(
ch
==
'\b'
)
out
<<
"
\"\\
b
\"
"
;
else
{
out
<<
"
\"
"
;
WriteDoubleQuoteEscapeSequence
(
out
,
ch
);
out
<<
"
\"
"
;
}
return
true
;
}
bool
WriteComment
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
int
postCommentIndent
)
{
const
unsigned
curIndent
=
out
.
col
();
out
<<
"#"
<<
Indentation
(
postCommentIndent
);
out
.
set_comment
();
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
if
(
codePoint
==
'\n'
)
{
out
<<
"
\n
"
<<
IndentTo
(
curIndent
)
<<
"#"
<<
Indentation
(
postCommentIndent
);
out
.
set_comment
();
}
else
{
WriteCodePoint
(
out
,
codePoint
);
}
}
return
true
;
}
bool
WriteAlias
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
)
{
out
<<
"*"
;
return
WriteAliasName
(
out
,
str
);
}
bool
WriteAnchor
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
)
{
out
<<
"&"
;
return
WriteAliasName
(
out
,
str
);
}
bool
WriteTag
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
bool
verbatim
)
{
out
<<
(
verbatim
?
"!<"
:
"!"
);
StringCharSource
buffer
(
str
.
c_str
(),
str
.
size
());
const
RegEx
&
reValid
=
verbatim
?
Exp
::
URI
()
:
Exp
::
Tag
();
while
(
buffer
)
{
int
n
=
reValid
.
Match
(
buffer
);
if
(
n
<=
0
)
return
false
;
while
(
--
n
>=
0
)
{
out
<<
buffer
[
0
];
++
buffer
;
}
}
if
(
verbatim
)
out
<<
">"
;
return
true
;
}
bool
WriteTagWithPrefix
(
ostream_wrapper
&
out
,
const
std
::
string
&
prefix
,
const
std
::
string
&
tag
)
{
out
<<
"!"
;
StringCharSource
prefixBuffer
(
prefix
.
c_str
(),
prefix
.
size
());
while
(
prefixBuffer
)
{
int
n
=
Exp
::
URI
().
Match
(
prefixBuffer
);
if
(
n
<=
0
)
return
false
;
while
(
--
n
>=
0
)
{
out
<<
prefixBuffer
[
0
];
++
prefixBuffer
;
}
}
out
<<
"!"
;
StringCharSource
tagBuffer
(
tag
.
c_str
(),
tag
.
size
());
while
(
tagBuffer
)
{
int
n
=
Exp
::
Tag
().
Match
(
tagBuffer
);
if
(
n
<=
0
)
return
false
;
while
(
--
n
>=
0
)
{
out
<<
tagBuffer
[
0
];
++
tagBuffer
;
}
}
return
true
;
}
bool
WriteBinary
(
ostream_wrapper
&
out
,
const
Binary
&
binary
)
{
WriteDoubleQuotedString
(
out
,
EncodeBase64
(
binary
.
data
(),
binary
.
size
()),
false
);
return
true
;
}
}
}
src/emitterutils.h
View file @
9b4db068
#ifndef EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "emitterstate.h"
#include "yaml-cpp/ostream_wrapper.h"
#include <string>
namespace
YAML
{
class
Binary
;
struct
StringFormat
{
enum
value
{
Plain
,
SingleQuoted
,
DoubleQuoted
,
Literal
};
};
namespace
YAML
{
class
Binary
;
struct
StringFormat
{
enum
value
{
Plain
,
SingleQuoted
,
DoubleQuoted
,
Literal
};
};
namespace
Utils
{
StringFormat
::
value
ComputeStringFormat
(
const
std
::
string
&
str
,
EMITTER_MANIP
strFormat
,
FlowType
::
value
flowType
,
bool
escapeNonAscii
);
bool
WriteSingleQuotedString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
);
bool
WriteDoubleQuotedString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
bool
escapeNonAscii
);
bool
WriteLiteralString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
int
indent
);
bool
WriteChar
(
ostream_wrapper
&
out
,
char
ch
);
bool
WriteComment
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
int
postCommentIndent
);
bool
WriteAlias
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
);
bool
WriteAnchor
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
);
bool
WriteTag
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
bool
verbatim
);
bool
WriteTagWithPrefix
(
ostream_wrapper
&
out
,
const
std
::
string
&
prefix
,
const
std
::
string
&
tag
);
bool
WriteBinary
(
ostream_wrapper
&
out
,
const
Binary
&
binary
);
}
namespace
Utils
{
StringFormat
::
value
ComputeStringFormat
(
const
std
::
string
&
str
,
EMITTER_MANIP
strFormat
,
FlowType
::
value
flowType
,
bool
escapeNonAscii
);
bool
WriteSingleQuotedString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
);
bool
WriteDoubleQuotedString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
bool
escapeNonAscii
);
bool
WriteLiteralString
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
int
indent
);
bool
WriteChar
(
ostream_wrapper
&
out
,
char
ch
);
bool
WriteComment
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
int
postCommentIndent
);
bool
WriteAlias
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
);
bool
WriteAnchor
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
);
bool
WriteTag
(
ostream_wrapper
&
out
,
const
std
::
string
&
str
,
bool
verbatim
);
bool
WriteTagWithPrefix
(
ostream_wrapper
&
out
,
const
std
::
string
&
prefix
,
const
std
::
string
&
tag
);
bool
WriteBinary
(
ostream_wrapper
&
out
,
const
Binary
&
binary
);
}
}
#endif // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif
// EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/exp.cpp
View file @
9b4db068
...
...
@@ -2,112 +2,129 @@
#include "yaml-cpp/exceptions.h"
#include <sstream>
namespace
YAML
{
namespace
Exp
{
unsigned
ParseHex
(
const
std
::
string
&
str
,
const
Mark
&
mark
)
{
unsigned
value
=
0
;
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
char
ch
=
str
[
i
];
int
digit
=
0
;
if
(
'a'
<=
ch
&&
ch
<=
'f'
)
digit
=
ch
-
'a'
+
10
;
else
if
(
'A'
<=
ch
&&
ch
<=
'F'
)
digit
=
ch
-
'A'
+
10
;
else
if
(
'0'
<=
ch
&&
ch
<=
'9'
)
digit
=
ch
-
'0'
;
else
throw
ParserException
(
mark
,
ErrorMsg
::
INVALID_HEX
);
namespace
YAML
{
namespace
Exp
{
unsigned
ParseHex
(
const
std
::
string
&
str
,
const
Mark
&
mark
)
{
unsigned
value
=
0
;
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
char
ch
=
str
[
i
];
int
digit
=
0
;
if
(
'a'
<=
ch
&&
ch
<=
'f'
)
digit
=
ch
-
'a'
+
10
;
else
if
(
'A'
<=
ch
&&
ch
<=
'F'
)
digit
=
ch
-
'A'
+
10
;
else
if
(
'0'
<=
ch
&&
ch
<=
'9'
)
digit
=
ch
-
'0'
;
else
throw
ParserException
(
mark
,
ErrorMsg
::
INVALID_HEX
);
value
=
(
value
<<
4
)
+
digit
;
}
value
=
(
value
<<
4
)
+
digit
;
}
return
value
;
}
return
value
;
}
std
::
string
Str
(
unsigned
ch
)
{
return
std
::
string
(
1
,
static_cast
<
char
>
(
ch
));
}
std
::
string
Str
(
unsigned
ch
)
{
return
std
::
string
(
1
,
static_cast
<
char
>
(
ch
));
}
// Escape
// . Translates the next 'codeLength' characters into a hex number and returns
the result.
//
. Throws if it's not actually hex
.
std
::
string
Escape
(
Stream
&
in
,
int
codeLength
)
{
// grab string
std
::
string
str
;
for
(
int
i
=
0
;
i
<
codeLength
;
i
++
)
str
+=
in
.
get
();
// Escape
// . Translates the next 'codeLength' characters into a hex number and returns
//
the result
.
// . Throws if it's not actually hex.
std
::
string
Escape
(
Stream
&
in
,
int
codeLength
)
{
// grab string
std
::
string
str
;
for
(
int
i
=
0
;
i
<
codeLength
;
i
++
)
str
+=
in
.
get
();
// get the value
unsigned
value
=
ParseHex
(
str
,
in
.
mark
());
// get the value
unsigned
value
=
ParseHex
(
str
,
in
.
mark
());
// legal unicode?
if
((
value
>=
0xD800
&&
value
<=
0xDFFF
)
||
value
>
0x10FFFF
)
{
std
::
stringstream
msg
;
msg
<<
ErrorMsg
::
INVALID_UNICODE
<<
value
;
throw
ParserException
(
in
.
mark
(),
msg
.
str
());
}
// legal unicode?
if
((
value
>=
0xD800
&&
value
<=
0xDFFF
)
||
value
>
0x10FFFF
)
{
std
::
stringstream
msg
;
msg
<<
ErrorMsg
::
INVALID_UNICODE
<<
value
;
throw
ParserException
(
in
.
mark
(),
msg
.
str
());
}
// now break it up into chars
if
(
value
<=
0x7F
)
return
Str
(
value
);
else
if
(
value
<=
0x7FF
)
return
Str
(
0xC0
+
(
value
>>
6
))
+
Str
(
0x80
+
(
value
&
0x3F
));
else
if
(
value
<=
0xFFFF
)
return
Str
(
0xE0
+
(
value
>>
12
))
+
Str
(
0x80
+
((
value
>>
6
)
&
0x3F
))
+
Str
(
0x80
+
(
value
&
0x3F
));
else
return
Str
(
0xF0
+
(
value
>>
18
))
+
Str
(
0x80
+
((
value
>>
12
)
&
0x3F
))
+
Str
(
0x80
+
((
value
>>
6
)
&
0x3F
))
+
Str
(
0x80
+
(
value
&
0x3F
));
}
// now break it up into chars
if
(
value
<=
0x7F
)
return
Str
(
value
);
else
if
(
value
<=
0x7FF
)
return
Str
(
0xC0
+
(
value
>>
6
))
+
Str
(
0x80
+
(
value
&
0x3F
));
else
if
(
value
<=
0xFFFF
)
return
Str
(
0xE0
+
(
value
>>
12
))
+
Str
(
0x80
+
((
value
>>
6
)
&
0x3F
))
+
Str
(
0x80
+
(
value
&
0x3F
));
else
return
Str
(
0xF0
+
(
value
>>
18
))
+
Str
(
0x80
+
((
value
>>
12
)
&
0x3F
))
+
Str
(
0x80
+
((
value
>>
6
)
&
0x3F
))
+
Str
(
0x80
+
(
value
&
0x3F
));
}
// Escape
// . Escapes the sequence starting 'in' (it must begin with a '\' or single
quote)
//
and returns the result.
//
. Throws if it's an unknown escape character
.
std
::
string
Escape
(
Stream
&
in
)
{
// eat slash
char
escape
=
in
.
get
();
// Escape
// . Escapes the sequence starting 'in' (it must begin with a '\' or single
//
quote)
//
and returns the result
.
// . Throws if it's an unknown escape character.
std
::
string
Escape
(
Stream
&
in
)
{
// eat slash
char
escape
=
in
.
get
();
// switch on escape character
char
ch
=
in
.
get
();
// switch on escape character
char
ch
=
in
.
get
();
// first do single quote, since it's easier
if
(
escape
==
'\''
&&
ch
==
'\''
)
return
"
\'
"
;
// first do single quote, since it's easier
if
(
escape
==
'\''
&&
ch
==
'\''
)
return
"
\'
"
;
// now do the slash (we're not gonna check if it's a slash - you better pass one!)
switch
(
ch
)
{
case
'0'
:
return
std
::
string
(
1
,
'\x00'
);
case
'a'
:
return
"
\x07
"
;
case
'b'
:
return
"
\x08
"
;
case
't'
:
case
'\t'
:
return
"
\x09
"
;
case
'n'
:
return
"
\x0A
"
;
case
'v'
:
return
"
\x0B
"
;
case
'f'
:
return
"
\x0C
"
;
case
'r'
:
return
"
\x0D
"
;
case
'e'
:
return
"
\x1B
"
;
case
' '
:
return
"
\x20
"
;
case
'\"'
:
return
"
\"
"
;
case
'\''
:
return
"
\'
"
;
case
'\\'
:
return
"
\\
"
;
case
'/'
:
return
"/"
;
case
'N'
:
return
"
\x85
"
;
case
'_'
:
return
"
\xA0
"
;
case
'L'
:
return
"
\xE2\x80\xA8
"
;
// LS (#x2028)
case
'P'
:
return
"
\xE2\x80\xA9
"
;
// PS (#x2029)
case
'x'
:
return
Escape
(
in
,
2
);
case
'u'
:
return
Escape
(
in
,
4
);
case
'U'
:
return
Escape
(
in
,
8
);
}
// now do the slash (we're not gonna check if it's a slash - you better pass
// one!)
switch
(
ch
)
{
case
'0'
:
return
std
::
string
(
1
,
'\x00'
);
case
'a'
:
return
"
\x07
"
;
case
'b'
:
return
"
\x08
"
;
case
't'
:
case
'\t'
:
return
"
\x09
"
;
case
'n'
:
return
"
\x0A
"
;
case
'v'
:
return
"
\x0B
"
;
case
'f'
:
return
"
\x0C
"
;
case
'r'
:
return
"
\x0D
"
;
case
'e'
:
return
"
\x1B
"
;
case
' '
:
return
"
\x20
"
;
case
'\"'
:
return
"
\"
"
;
case
'\''
:
return
"
\'
"
;
case
'\\'
:
return
"
\\
"
;
case
'/'
:
return
"/"
;
case
'N'
:
return
"
\x85
"
;
case
'_'
:
return
"
\xA0
"
;
case
'L'
:
return
"
\xE2\x80\xA8
"
;
// LS (#x2028)
case
'P'
:
return
"
\xE2\x80\xA9
"
;
// PS (#x2029)
case
'x'
:
return
Escape
(
in
,
2
);
case
'u'
:
return
Escape
(
in
,
4
);
case
'U'
:
return
Escape
(
in
,
8
);
}
std
::
stringstream
msg
;
throw
ParserException
(
in
.
mark
(),
std
::
string
(
ErrorMsg
::
INVALID_ESCAPE
)
+
ch
);
}
}
std
::
stringstream
msg
;
throw
ParserException
(
in
.
mark
(),
std
::
string
(
ErrorMsg
::
INVALID_ESCAPE
)
+
ch
);
}
}
}
src/exp.h
View file @
9b4db068
#ifndef EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "regex.h"
#include <string>
#include <ios>
#include "stream.h"
namespace
YAML
{
////////////////////////////////////////////////////////////////////////////////
//
Here we store a bunch of expressions for matching different parts of the
file.
namespace
YAML
{
////////////////////////////////////////////////////////////////////////////////
// Here we store a bunch of expressions for matching different parts of the
// file.
namespace
Exp
{
// misc
inline
const
RegEx
&
Space
()
{
static
const
RegEx
e
=
RegEx
(
' '
);
return
e
;
}
inline
const
RegEx
&
Tab
()
{
static
const
RegEx
e
=
RegEx
(
'\t'
);
return
e
;
}
inline
const
RegEx
&
Blank
()
{
static
const
RegEx
e
=
Space
()
||
Tab
();
return
e
;
}
inline
const
RegEx
&
Break
()
{
static
const
RegEx
e
=
RegEx
(
'\n'
)
||
RegEx
(
"
\r\n
"
);
return
e
;
}
inline
const
RegEx
&
BlankOrBreak
()
{
static
const
RegEx
e
=
Blank
()
||
Break
();
return
e
;
}
inline
const
RegEx
&
Digit
()
{
static
const
RegEx
e
=
RegEx
(
'0'
,
'9'
);
return
e
;
}
inline
const
RegEx
&
Alpha
()
{
static
const
RegEx
e
=
RegEx
(
'a'
,
'z'
)
||
RegEx
(
'A'
,
'Z'
);
return
e
;
}
inline
const
RegEx
&
AlphaNumeric
()
{
static
const
RegEx
e
=
Alpha
()
||
Digit
();
return
e
;
}
inline
const
RegEx
&
Word
()
{
static
const
RegEx
e
=
AlphaNumeric
()
||
RegEx
(
'-'
);
return
e
;
}
inline
const
RegEx
&
Hex
()
{
static
const
RegEx
e
=
Digit
()
||
RegEx
(
'A'
,
'F'
)
||
RegEx
(
'a'
,
'f'
);
return
e
;
}
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1)
inline
const
RegEx
&
NotPrintable
()
{
static
const
RegEx
e
=
RegEx
(
0
)
||
RegEx
(
"
\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F
"
,
REGEX_OR
)
||
RegEx
(
0x0E
,
0x1F
)
||
(
RegEx
(
'\xC2'
)
+
(
RegEx
(
'\x80'
,
'\x84'
)
||
RegEx
(
'\x86'
,
'\x9F'
)));
return
e
;
}
inline
const
RegEx
&
Utf8_ByteOrderMark
()
{
static
const
RegEx
e
=
RegEx
(
"
\xEF\xBB\xBF
"
);
return
e
;
}
namespace
Exp
{
// misc
inline
const
RegEx
&
Space
()
{
static
const
RegEx
e
=
RegEx
(
' '
);
return
e
;
}
inline
const
RegEx
&
Tab
()
{
static
const
RegEx
e
=
RegEx
(
'\t'
);
return
e
;
}
inline
const
RegEx
&
Blank
()
{
static
const
RegEx
e
=
Space
()
||
Tab
();
return
e
;
}
inline
const
RegEx
&
Break
()
{
static
const
RegEx
e
=
RegEx
(
'\n'
)
||
RegEx
(
"
\r\n
"
);
return
e
;
}
inline
const
RegEx
&
BlankOrBreak
()
{
static
const
RegEx
e
=
Blank
()
||
Break
();
return
e
;
}
inline
const
RegEx
&
Digit
()
{
static
const
RegEx
e
=
RegEx
(
'0'
,
'9'
);
return
e
;
}
inline
const
RegEx
&
Alpha
()
{
static
const
RegEx
e
=
RegEx
(
'a'
,
'z'
)
||
RegEx
(
'A'
,
'Z'
);
return
e
;
}
inline
const
RegEx
&
AlphaNumeric
()
{
static
const
RegEx
e
=
Alpha
()
||
Digit
();
return
e
;
}
inline
const
RegEx
&
Word
()
{
static
const
RegEx
e
=
AlphaNumeric
()
||
RegEx
(
'-'
);
return
e
;
}
inline
const
RegEx
&
Hex
()
{
static
const
RegEx
e
=
Digit
()
||
RegEx
(
'A'
,
'F'
)
||
RegEx
(
'a'
,
'f'
);
return
e
;
}
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec.
// 5.1)
inline
const
RegEx
&
NotPrintable
()
{
static
const
RegEx
e
=
RegEx
(
0
)
||
RegEx
(
"
\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F
"
,
REGEX_OR
)
||
RegEx
(
0x0E
,
0x1F
)
||
(
RegEx
(
'\xC2'
)
+
(
RegEx
(
'\x80'
,
'\x84'
)
||
RegEx
(
'\x86'
,
'\x9F'
)));
return
e
;
}
inline
const
RegEx
&
Utf8_ByteOrderMark
()
{
static
const
RegEx
e
=
RegEx
(
"
\xEF\xBB\xBF
"
);
return
e
;
}
// actual tags
// actual tags
inline
const
RegEx
&
DocStart
()
{
static
const
RegEx
e
=
RegEx
(
"---"
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
DocEnd
()
{
static
const
RegEx
e
=
RegEx
(
"..."
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
DocIndicator
()
{
static
const
RegEx
e
=
DocStart
()
||
DocEnd
();
return
e
;
}
inline
const
RegEx
&
BlockEntry
()
{
static
const
RegEx
e
=
RegEx
(
'-'
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
Key
()
{
static
const
RegEx
e
=
RegEx
(
'?'
)
+
BlankOrBreak
();
return
e
;
}
inline
const
RegEx
&
KeyInFlow
()
{
static
const
RegEx
e
=
RegEx
(
'?'
)
+
BlankOrBreak
();
return
e
;
}
inline
const
RegEx
&
Value
()
{
static
const
RegEx
e
=
RegEx
(
':'
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
ValueInFlow
()
{
static
const
RegEx
e
=
RegEx
(
':'
)
+
(
BlankOrBreak
()
||
RegEx
(
",}"
,
REGEX_OR
));
return
e
;
}
inline
const
RegEx
&
ValueInJSONFlow
()
{
static
const
RegEx
e
=
RegEx
(
':'
);
return
e
;
}
inline
const
RegEx
Comment
()
{
static
const
RegEx
e
=
RegEx
(
'#'
);
return
e
;
}
inline
const
RegEx
&
Anchor
()
{
static
const
RegEx
e
=
!
(
RegEx
(
"[]{},"
,
REGEX_OR
)
||
BlankOrBreak
());
return
e
;
}
inline
const
RegEx
&
AnchorEnd
()
{
static
const
RegEx
e
=
RegEx
(
"?:,]}%@`"
,
REGEX_OR
)
||
BlankOrBreak
();
return
e
;
}
inline
const
RegEx
&
URI
()
{
static
const
RegEx
e
=
Word
()
||
RegEx
(
"#;/?:@&=+$,_.!~*'()[]"
,
REGEX_OR
)
||
(
RegEx
(
'%'
)
+
Hex
()
+
Hex
());
return
e
;
}
inline
const
RegEx
&
Tag
()
{
static
const
RegEx
e
=
Word
()
||
RegEx
(
"#;/?:@&=+$_.~*'"
,
REGEX_OR
)
||
(
RegEx
(
'%'
)
+
Hex
()
+
Hex
());
return
e
;
}
inline
const
RegEx
&
DocStart
()
{
static
const
RegEx
e
=
RegEx
(
"---"
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
DocEnd
()
{
static
const
RegEx
e
=
RegEx
(
"..."
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
DocIndicator
()
{
static
const
RegEx
e
=
DocStart
()
||
DocEnd
();
return
e
;
}
inline
const
RegEx
&
BlockEntry
()
{
static
const
RegEx
e
=
RegEx
(
'-'
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
Key
()
{
static
const
RegEx
e
=
RegEx
(
'?'
)
+
BlankOrBreak
();
return
e
;
}
inline
const
RegEx
&
KeyInFlow
()
{
static
const
RegEx
e
=
RegEx
(
'?'
)
+
BlankOrBreak
();
return
e
;
}
inline
const
RegEx
&
Value
()
{
static
const
RegEx
e
=
RegEx
(
':'
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
ValueInFlow
()
{
static
const
RegEx
e
=
RegEx
(
':'
)
+
(
BlankOrBreak
()
||
RegEx
(
",}"
,
REGEX_OR
));
return
e
;
}
inline
const
RegEx
&
ValueInJSONFlow
()
{
static
const
RegEx
e
=
RegEx
(
':'
);
return
e
;
}
inline
const
RegEx
Comment
()
{
static
const
RegEx
e
=
RegEx
(
'#'
);
return
e
;
}
inline
const
RegEx
&
Anchor
()
{
static
const
RegEx
e
=
!
(
RegEx
(
"[]{},"
,
REGEX_OR
)
||
BlankOrBreak
());
return
e
;
}
inline
const
RegEx
&
AnchorEnd
()
{
static
const
RegEx
e
=
RegEx
(
"?:,]}%@`"
,
REGEX_OR
)
||
BlankOrBreak
();
return
e
;
}
inline
const
RegEx
&
URI
()
{
static
const
RegEx
e
=
Word
()
||
RegEx
(
"#;/?:@&=+$,_.!~*'()[]"
,
REGEX_OR
)
||
(
RegEx
(
'%'
)
+
Hex
()
+
Hex
());
return
e
;
}
inline
const
RegEx
&
Tag
()
{
static
const
RegEx
e
=
Word
()
||
RegEx
(
"#;/?:@&=+$_.~*'"
,
REGEX_OR
)
||
(
RegEx
(
'%'
)
+
Hex
()
+
Hex
());
return
e
;
}
// Plain scalar rules:
// . Cannot start with a blank.
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
// . In the block context - ? : must be not be followed with a space.
// . In the flow context ? is illegal and : and - must not be followed with a space.
inline
const
RegEx
&
PlainScalar
()
{
static
const
RegEx
e
=
!
(
BlankOrBreak
()
||
RegEx
(
",[]{}#&*!|>
\'\"
%@`"
,
REGEX_OR
)
||
(
RegEx
(
"-?:"
,
REGEX_OR
)
+
(
BlankOrBreak
()
||
RegEx
())));
return
e
;
}
inline
const
RegEx
&
PlainScalarInFlow
()
{
static
const
RegEx
e
=
!
(
BlankOrBreak
()
||
RegEx
(
"?,[]{}#&*!|>
\'\"
%@`"
,
REGEX_OR
)
||
(
RegEx
(
"-:"
,
REGEX_OR
)
+
Blank
()));
return
e
;
}
inline
const
RegEx
&
EndScalar
()
{
static
const
RegEx
e
=
RegEx
(
':'
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
EndScalarInFlow
()
{
static
const
RegEx
e
=
(
RegEx
(
':'
)
+
(
BlankOrBreak
()
||
RegEx
()
||
RegEx
(
",]}"
,
REGEX_OR
)))
||
RegEx
(
",?[]{}"
,
REGEX_OR
);
return
e
;
}
// Plain scalar rules:
// . Cannot start with a blank.
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
// . In the block context - ? : must be not be followed with a space.
// . In the flow context ? is illegal and : and - must not be followed with a
// space.
inline
const
RegEx
&
PlainScalar
()
{
static
const
RegEx
e
=
!
(
BlankOrBreak
()
||
RegEx
(
",[]{}#&*!|>
\'\"
%@`"
,
REGEX_OR
)
||
(
RegEx
(
"-?:"
,
REGEX_OR
)
+
(
BlankOrBreak
()
||
RegEx
())));
return
e
;
}
inline
const
RegEx
&
PlainScalarInFlow
()
{
static
const
RegEx
e
=
!
(
BlankOrBreak
()
||
RegEx
(
"?,[]{}#&*!|>
\'\"
%@`"
,
REGEX_OR
)
||
(
RegEx
(
"-:"
,
REGEX_OR
)
+
Blank
()));
return
e
;
}
inline
const
RegEx
&
EndScalar
()
{
static
const
RegEx
e
=
RegEx
(
':'
)
+
(
BlankOrBreak
()
||
RegEx
());
return
e
;
}
inline
const
RegEx
&
EndScalarInFlow
()
{
static
const
RegEx
e
=
(
RegEx
(
':'
)
+
(
BlankOrBreak
()
||
RegEx
()
||
RegEx
(
",]}"
,
REGEX_OR
)))
||
RegEx
(
",?[]{}"
,
REGEX_OR
);
return
e
;
}
inline
const
RegEx
&
EscSingleQuote
()
{
static
const
RegEx
e
=
RegEx
(
"
\'\'
"
);
return
e
;
}
inline
const
RegEx
&
EscBreak
()
{
static
const
RegEx
e
=
RegEx
(
'\\'
)
+
Break
();
return
e
;
}
inline
const
RegEx
&
EscSingleQuote
()
{
static
const
RegEx
e
=
RegEx
(
"
\'\'
"
);
return
e
;
}
inline
const
RegEx
&
EscBreak
()
{
static
const
RegEx
e
=
RegEx
(
'\\'
)
+
Break
();
return
e
;
}
inline
const
RegEx
&
ChompIndicator
()
{
static
const
RegEx
e
=
RegEx
(
"+-"
,
REGEX_OR
);
return
e
;
}
inline
const
RegEx
&
Chomp
()
{
static
const
RegEx
e
=
(
ChompIndicator
()
+
Digit
())
||
(
Digit
()
+
ChompIndicator
())
||
ChompIndicator
()
||
Digit
();
return
e
;
}
inline
const
RegEx
&
ChompIndicator
()
{
static
const
RegEx
e
=
RegEx
(
"+-"
,
REGEX_OR
);
return
e
;
}
inline
const
RegEx
&
Chomp
()
{
static
const
RegEx
e
=
(
ChompIndicator
()
+
Digit
())
||
(
Digit
()
+
ChompIndicator
())
||
ChompIndicator
()
||
Digit
();
return
e
;
}
// and some functions
std
::
string
Escape
(
Stream
&
in
);
}
// and some functions
std
::
string
Escape
(
Stream
&
in
);
}
namespace
Keys
{
const
char
Directive
=
'%'
;
const
char
FlowSeqStart
=
'['
;
const
char
FlowSeqEnd
=
']'
;
const
char
FlowMapStart
=
'{'
;
const
char
FlowMapEnd
=
'}'
;
const
char
FlowEntry
=
','
;
const
char
Alias
=
'*'
;
const
char
Anchor
=
'&'
;
const
char
Tag
=
'!'
;
const
char
LiteralScalar
=
'|'
;
const
char
FoldedScalar
=
'>'
;
const
char
VerbatimTagStart
=
'<'
;
const
char
VerbatimTagEnd
=
'>'
;
}
namespace
Keys
{
const
char
Directive
=
'%'
;
const
char
FlowSeqStart
=
'['
;
const
char
FlowSeqEnd
=
']'
;
const
char
FlowMapStart
=
'{'
;
const
char
FlowMapEnd
=
'}'
;
const
char
FlowEntry
=
','
;
const
char
Alias
=
'*'
;
const
char
Anchor
=
'&'
;
const
char
Tag
=
'!'
;
const
char
LiteralScalar
=
'|'
;
const
char
FoldedScalar
=
'>'
;
const
char
VerbatimTagStart
=
'<'
;
const
char
VerbatimTagEnd
=
'>'
;
}
}
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif
// EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/indentation.h
View file @
9b4db068
#ifndef INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/ostream_wrapper.h"
#include <iostream>
namespace
YAML
{
struct
Indentation
{
Indentation
(
unsigned
n_
)
:
n
(
n_
)
{}
unsigned
n
;
};
inline
ostream_wrapper
&
operator
<<
(
ostream_wrapper
&
out
,
const
Indentation
&
indent
)
{
for
(
unsigned
i
=
0
;
i
<
indent
.
n
;
i
++
)
out
<<
' '
;
return
out
;
}
namespace
YAML
{
struct
Indentation
{
Indentation
(
unsigned
n_
)
:
n
(
n_
)
{}
unsigned
n
;
};
struct
IndentTo
{
IndentTo
(
unsigned
n_
)
:
n
(
n_
)
{}
unsigned
n
;
};
inline
ostream_wrapper
&
operator
<<
(
ostream_wrapper
&
out
,
const
IndentTo
&
indent
)
{
while
(
out
.
col
()
<
indent
.
n
)
out
<<
' '
;
return
out
;
}
inline
ostream_wrapper
&
operator
<<
(
ostream_wrapper
&
out
,
const
Indentation
&
indent
)
{
for
(
unsigned
i
=
0
;
i
<
indent
.
n
;
i
++
)
out
<<
' '
;
return
out
;
}
struct
IndentTo
{
IndentTo
(
unsigned
n_
)
:
n
(
n_
)
{}
unsigned
n
;
};
inline
ostream_wrapper
&
operator
<<
(
ostream_wrapper
&
out
,
const
IndentTo
&
indent
)
{
while
(
out
.
col
()
<
indent
.
n
)
out
<<
' '
;
return
out
;
}
}
#endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif
// INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/null.cpp
View file @
9b4db068
#include "yaml-cpp/null.h"
namespace
YAML
{
_Null
Null
;
namespace
YAML
{
_Null
Null
;
}
src/ostream_wrapper.cpp
View file @
9b4db068
...
...
@@ -2,55 +2,47 @@
#include <cstring>
#include <iostream>
namespace
YAML
{
ostream_wrapper
::
ostream_wrapper
()
:
m_pStream
(
0
),
m_pos
(
0
),
m_row
(
0
),
m_col
(
0
),
m_comment
(
false
)
{
}
ostream_wrapper
::
ostream_wrapper
(
std
::
ostream
&
stream
)
:
m_pStream
(
&
stream
),
m_pos
(
0
),
m_row
(
0
),
m_col
(
0
),
m_comment
(
false
)
{
}
ostream_wrapper
::~
ostream_wrapper
()
{
}
void
ostream_wrapper
::
write
(
const
std
::
string
&
str
)
{
if
(
m_pStream
)
{
m_pStream
->
write
(
str
.
c_str
(),
str
.
size
());
}
else
{
m_buffer
.
resize
(
std
::
max
(
m_buffer
.
size
(),
m_pos
+
str
.
size
()
+
1
));
std
::
copy
(
str
.
begin
(),
str
.
end
(),
&
m_buffer
[
m_pos
]);
}
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
update_pos
(
str
[
i
]);
}
void
ostream_wrapper
::
write
(
const
char
*
str
,
std
::
size_t
size
)
{
if
(
m_pStream
)
{
m_pStream
->
write
(
str
,
size
);
}
else
{
m_buffer
.
resize
(
std
::
max
(
m_buffer
.
size
(),
m_pos
+
size
+
1
));
std
::
copy
(
str
,
str
+
size
,
&
m_buffer
[
m_pos
]);
}
for
(
std
::
size_t
i
=
0
;
i
<
size
;
i
++
)
update_pos
(
str
[
i
]);
}
void
ostream_wrapper
::
update_pos
(
char
ch
)
{
m_pos
++
;
m_col
++
;
if
(
ch
==
'\n'
)
{
m_row
++
;
m_col
=
0
;
m_comment
=
false
;
}
}
namespace
YAML
{
ostream_wrapper
::
ostream_wrapper
()
:
m_pStream
(
0
),
m_pos
(
0
),
m_row
(
0
),
m_col
(
0
),
m_comment
(
false
)
{}
ostream_wrapper
::
ostream_wrapper
(
std
::
ostream
&
stream
)
:
m_pStream
(
&
stream
),
m_pos
(
0
),
m_row
(
0
),
m_col
(
0
),
m_comment
(
false
)
{}
ostream_wrapper
::~
ostream_wrapper
()
{}
void
ostream_wrapper
::
write
(
const
std
::
string
&
str
)
{
if
(
m_pStream
)
{
m_pStream
->
write
(
str
.
c_str
(),
str
.
size
());
}
else
{
m_buffer
.
resize
(
std
::
max
(
m_buffer
.
size
(),
m_pos
+
str
.
size
()
+
1
));
std
::
copy
(
str
.
begin
(),
str
.
end
(),
&
m_buffer
[
m_pos
]);
}
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
update_pos
(
str
[
i
]);
}
void
ostream_wrapper
::
write
(
const
char
*
str
,
std
::
size_t
size
)
{
if
(
m_pStream
)
{
m_pStream
->
write
(
str
,
size
);
}
else
{
m_buffer
.
resize
(
std
::
max
(
m_buffer
.
size
(),
m_pos
+
size
+
1
));
std
::
copy
(
str
,
str
+
size
,
&
m_buffer
[
m_pos
]);
}
for
(
std
::
size_t
i
=
0
;
i
<
size
;
i
++
)
update_pos
(
str
[
i
]);
}
void
ostream_wrapper
::
update_pos
(
char
ch
)
{
m_pos
++
;
m_col
++
;
if
(
ch
==
'\n'
)
{
m_row
++
;
m_col
=
0
;
m_comment
=
false
;
}
}
}
src/parser.cpp
View file @
9b4db068
...
...
@@ -9,133 +9,119 @@
#include <sstream>
#include <cstdio>
namespace
YAML
{
Parser
::
Parser
()
{
}
Parser
::
Parser
(
std
::
istream
&
in
)
{
Load
(
in
);
}
Parser
::~
Parser
()
{
}
Parser
::
operator
bool
()
const
{
return
m_pScanner
.
get
()
&&
!
m_pScanner
->
empty
();
}
void
Parser
::
Load
(
std
::
istream
&
in
)
{
m_pScanner
.
reset
(
new
Scanner
(
in
));
m_pDirectives
.
reset
(
new
Directives
);
}
// HandleNextDocument
// . Handles the next document
// . Throws a ParserException on error.
// . Returns false if there are no more documents
bool
Parser
::
HandleNextDocument
(
EventHandler
&
eventHandler
)
{
if
(
!
m_pScanner
.
get
())
return
false
;
ParseDirectives
();
if
(
m_pScanner
->
empty
())
return
false
;
SingleDocParser
sdp
(
*
m_pScanner
,
*
m_pDirectives
);
sdp
.
HandleDocument
(
eventHandler
);
return
true
;
}
// ParseDirectives
// . Reads any directives that are next in the queue.
void
Parser
::
ParseDirectives
()
{
bool
readDirective
=
false
;
while
(
1
)
{
if
(
m_pScanner
->
empty
())
break
;
Token
&
token
=
m_pScanner
->
peek
();
if
(
token
.
type
!=
Token
::
DIRECTIVE
)
break
;
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if
(
!
readDirective
)
m_pDirectives
.
reset
(
new
Directives
);
readDirective
=
true
;
HandleDirective
(
token
);
m_pScanner
->
pop
();
}
}
void
Parser
::
HandleDirective
(
const
Token
&
token
)
{
if
(
token
.
value
==
"YAML"
)
HandleYamlDirective
(
token
);
else
if
(
token
.
value
==
"TAG"
)
HandleTagDirective
(
token
);
}
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
void
Parser
::
HandleYamlDirective
(
const
Token
&
token
)
{
if
(
token
.
params
.
size
()
!=
1
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
YAML_DIRECTIVE_ARGS
);
if
(
!
m_pDirectives
->
version
.
isDefault
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
REPEATED_YAML_DIRECTIVE
);
std
::
stringstream
str
(
token
.
params
[
0
]);
str
>>
m_pDirectives
->
version
.
major
;
str
.
get
();
str
>>
m_pDirectives
->
version
.
minor
;
if
(
!
str
||
str
.
peek
()
!=
EOF
)
throw
ParserException
(
token
.
mark
,
std
::
string
(
ErrorMsg
::
YAML_VERSION
)
+
token
.
params
[
0
]);
if
(
m_pDirectives
->
version
.
major
>
1
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
YAML_MAJOR_VERSION
);
m_pDirectives
->
version
.
isDefault
=
false
;
// TODO: warning on major == 1, minor > 2?
}
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
void
Parser
::
HandleTagDirective
(
const
Token
&
token
)
{
if
(
token
.
params
.
size
()
!=
2
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
TAG_DIRECTIVE_ARGS
);
const
std
::
string
&
handle
=
token
.
params
[
0
];
const
std
::
string
&
prefix
=
token
.
params
[
1
];
if
(
m_pDirectives
->
tags
.
find
(
handle
)
!=
m_pDirectives
->
tags
.
end
())
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
REPEATED_TAG_DIRECTIVE
);
m_pDirectives
->
tags
[
handle
]
=
prefix
;
}
void
Parser
::
PrintTokens
(
std
::
ostream
&
out
)
{
if
(
!
m_pScanner
.
get
())
return
;
while
(
1
)
{
if
(
m_pScanner
->
empty
())
break
;
out
<<
m_pScanner
->
peek
()
<<
"
\n
"
;
m_pScanner
->
pop
();
}
}
namespace
YAML
{
Parser
::
Parser
()
{}
Parser
::
Parser
(
std
::
istream
&
in
)
{
Load
(
in
);
}
Parser
::~
Parser
()
{}
Parser
::
operator
bool
()
const
{
return
m_pScanner
.
get
()
&&
!
m_pScanner
->
empty
();
}
void
Parser
::
Load
(
std
::
istream
&
in
)
{
m_pScanner
.
reset
(
new
Scanner
(
in
));
m_pDirectives
.
reset
(
new
Directives
);
}
// HandleNextDocument
// . Handles the next document
// . Throws a ParserException on error.
// . Returns false if there are no more documents
bool
Parser
::
HandleNextDocument
(
EventHandler
&
eventHandler
)
{
if
(
!
m_pScanner
.
get
())
return
false
;
ParseDirectives
();
if
(
m_pScanner
->
empty
())
return
false
;
SingleDocParser
sdp
(
*
m_pScanner
,
*
m_pDirectives
);
sdp
.
HandleDocument
(
eventHandler
);
return
true
;
}
// ParseDirectives
// . Reads any directives that are next in the queue.
void
Parser
::
ParseDirectives
()
{
bool
readDirective
=
false
;
while
(
1
)
{
if
(
m_pScanner
->
empty
())
break
;
Token
&
token
=
m_pScanner
->
peek
();
if
(
token
.
type
!=
Token
::
DIRECTIVE
)
break
;
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if
(
!
readDirective
)
m_pDirectives
.
reset
(
new
Directives
);
readDirective
=
true
;
HandleDirective
(
token
);
m_pScanner
->
pop
();
}
}
void
Parser
::
HandleDirective
(
const
Token
&
token
)
{
if
(
token
.
value
==
"YAML"
)
HandleYamlDirective
(
token
);
else
if
(
token
.
value
==
"TAG"
)
HandleTagDirective
(
token
);
}
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
void
Parser
::
HandleYamlDirective
(
const
Token
&
token
)
{
if
(
token
.
params
.
size
()
!=
1
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
YAML_DIRECTIVE_ARGS
);
if
(
!
m_pDirectives
->
version
.
isDefault
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
REPEATED_YAML_DIRECTIVE
);
std
::
stringstream
str
(
token
.
params
[
0
]);
str
>>
m_pDirectives
->
version
.
major
;
str
.
get
();
str
>>
m_pDirectives
->
version
.
minor
;
if
(
!
str
||
str
.
peek
()
!=
EOF
)
throw
ParserException
(
token
.
mark
,
std
::
string
(
ErrorMsg
::
YAML_VERSION
)
+
token
.
params
[
0
]);
if
(
m_pDirectives
->
version
.
major
>
1
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
YAML_MAJOR_VERSION
);
m_pDirectives
->
version
.
isDefault
=
false
;
// TODO: warning on major == 1, minor > 2?
}
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to
// 'prefix' in the file.
void
Parser
::
HandleTagDirective
(
const
Token
&
token
)
{
if
(
token
.
params
.
size
()
!=
2
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
TAG_DIRECTIVE_ARGS
);
const
std
::
string
&
handle
=
token
.
params
[
0
];
const
std
::
string
&
prefix
=
token
.
params
[
1
];
if
(
m_pDirectives
->
tags
.
find
(
handle
)
!=
m_pDirectives
->
tags
.
end
())
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
REPEATED_TAG_DIRECTIVE
);
m_pDirectives
->
tags
[
handle
]
=
prefix
;
}
void
Parser
::
PrintTokens
(
std
::
ostream
&
out
)
{
if
(
!
m_pScanner
.
get
())
return
;
while
(
1
)
{
if
(
m_pScanner
->
empty
())
break
;
out
<<
m_pScanner
->
peek
()
<<
"
\n
"
;
m_pScanner
->
pop
();
}
}
}
src/ptr_stack.h
View file @
9b4db068
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
...
...
@@ -12,38 +14,39 @@
#include <vector>
template
<
typename
T
>
class
ptr_stack
:
private
YAML
::
noncopyable
{
public:
ptr_stack
()
{}
~
ptr_stack
()
{
clear
();
}
void
clear
()
{
for
(
unsigned
i
=
0
;
i
<
m_data
.
size
();
i
++
)
delete
m_data
[
i
];
m_data
.
clear
();
}
std
::
size_t
size
()
const
{
return
m_data
.
size
();
}
bool
empty
()
const
{
return
m_data
.
empty
();
}
void
push
(
std
::
auto_ptr
<
T
>
t
)
{
m_data
.
push_back
(
NULL
);
m_data
.
back
()
=
t
.
release
();
}
std
::
auto_ptr
<
T
>
pop
()
{
std
::
auto_ptr
<
T
>
t
(
m_data
.
back
());
m_data
.
pop_back
();
return
t
;
}
T
&
top
()
{
return
*
m_data
.
back
();
}
const
T
&
top
()
const
{
return
*
m_data
.
back
();
}
T
&
top
(
std
::
ptrdiff_t
diff
)
{
return
**
(
m_data
.
end
()
-
1
+
diff
);
}
const
T
&
top
(
std
::
ptrdiff_t
diff
)
const
{
return
**
(
m_data
.
end
()
-
1
+
diff
);
}
private:
std
::
vector
<
T
*>
m_data
;
class
ptr_stack
:
private
YAML
::
noncopyable
{
public:
ptr_stack
()
{}
~
ptr_stack
()
{
clear
();
}
void
clear
()
{
for
(
unsigned
i
=
0
;
i
<
m_data
.
size
();
i
++
)
delete
m_data
[
i
];
m_data
.
clear
();
}
std
::
size_t
size
()
const
{
return
m_data
.
size
();
}
bool
empty
()
const
{
return
m_data
.
empty
();
}
void
push
(
std
::
auto_ptr
<
T
>
t
)
{
m_data
.
push_back
(
NULL
);
m_data
.
back
()
=
t
.
release
();
}
std
::
auto_ptr
<
T
>
pop
()
{
std
::
auto_ptr
<
T
>
t
(
m_data
.
back
());
m_data
.
pop_back
();
return
t
;
}
T
&
top
()
{
return
*
m_data
.
back
();
}
const
T
&
top
()
const
{
return
*
m_data
.
back
();
}
T
&
top
(
std
::
ptrdiff_t
diff
)
{
return
**
(
m_data
.
end
()
-
1
+
diff
);
}
const
T
&
top
(
std
::
ptrdiff_t
diff
)
const
{
return
**
(
m_data
.
end
()
-
1
+
diff
);
}
private:
std
::
vector
<
T
*>
m_data
;
};
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif
// PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/ptr_vector.h
View file @
9b4db068
#ifndef PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
...
...
@@ -12,36 +14,35 @@
#include <vector>
namespace
YAML
{
template
<
typename
T
>
class
ptr_vector
:
private
YAML
::
noncopyable
{
public:
ptr_vector
()
{}
~
ptr_vector
()
{
clear
();
}
void
clear
()
{
for
(
unsigned
i
=
0
;
i
<
m_data
.
size
();
i
++
)
delete
m_data
[
i
];
m_data
.
clear
();
}
std
::
size_t
size
()
const
{
return
m_data
.
size
();
}
bool
empty
()
const
{
return
m_data
.
empty
();
}
void
push_back
(
std
::
auto_ptr
<
T
>
t
)
{
m_data
.
push_back
(
NULL
);
m_data
.
back
()
=
t
.
release
();
}
T
&
operator
[](
std
::
size_t
i
)
{
return
*
m_data
[
i
];
}
const
T
&
operator
[](
std
::
size_t
i
)
const
{
return
*
m_data
[
i
];
}
T
&
back
()
{
return
*
m_data
.
back
();
}
const
T
&
back
()
const
{
return
*
m_data
.
back
();
}
private:
std
::
vector
<
T
*>
m_data
;
};
template
<
typename
T
>
class
ptr_vector
:
private
YAML
::
noncopyable
{
public:
ptr_vector
()
{}
~
ptr_vector
()
{
clear
();
}
void
clear
()
{
for
(
unsigned
i
=
0
;
i
<
m_data
.
size
();
i
++
)
delete
m_data
[
i
];
m_data
.
clear
();
}
std
::
size_t
size
()
const
{
return
m_data
.
size
();
}
bool
empty
()
const
{
return
m_data
.
empty
();
}
void
push_back
(
std
::
auto_ptr
<
T
>
t
)
{
m_data
.
push_back
(
NULL
);
m_data
.
back
()
=
t
.
release
();
}
T
&
operator
[](
std
::
size_t
i
)
{
return
*
m_data
[
i
];
}
const
T
&
operator
[](
std
::
size_t
i
)
const
{
return
*
m_data
[
i
];
}
T
&
back
()
{
return
*
m_data
.
back
();
}
const
T
&
back
()
const
{
return
*
m_data
.
back
();
}
private:
std
::
vector
<
T
*>
m_data
;
};
}
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif
// PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
Prev
1
2
3
4
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment