Add a new incremental parsing API

Change-Id: I6b921766836d58df0281fb23b2add3f62a478e14
This commit is contained in:
Michael Bradshaw 2016-06-14 16:53:56 -07:00
parent 900d322cc8
commit cb8ce0b4b5
752 changed files with 21329 additions and 0 deletions

319
webm_parser/README.md Normal file
View File

@ -0,0 +1,319 @@
# WebM Parser {#mainpage}
# Introduction
This WebM parser is a C++11-based parser that aims to be a safe and complete
parser for WebM. It supports all WebM elements (from the old deprecated ones to
the newest ones like `Colour`), including recursive elements like `ChapterAtom`
and `SimpleTag`. It supports incremental parsing; parsing may be stopped at any
point and resumed later as needed. It also supports starting at an arbitrary
WebM element, so parsing need not start from the beginning of the file.
The parser (`WebmParser`) works by being fed input data from a data source (an
instance of `Reader`) that represents a WebM file. The parser will parse the
WebM data into various data structures that represent the encoded WebM elements,
and then call corresponding `Callback` event methods as the data structures are
parsed.
# Building
CMake support will be be added, but for now the parser may be build into a
static library using the following commands:
```.sh
c++ -Iinclude -std=c++11 -c src/*.cc
ar rcs libwebm.a *.o
```
# Using the parser
There are 3 basic components in the parser that are used: `Reader`, `Callback`,
and `WebmParser`.
## `Reader`
The `Reader` interface acts as a data source for the parser. You may subclass it
and implement your own data source if you wish. Alternatively, use the
`FileReader`, `IstreamReader`, or `BufferReader` if you wish to read from a
`FILE*`, `std::istream`, or `std::vector<std::uint8_t>`, respectively.
The parser supports `Reader` implementations that do short reads. If
`Reader::Skip()` or `Reader::Read()` do a partial read (returning
`Status::kOkPartial`), the parser will call them again in an attempt to read
more data. If no data is available, the `Reader` may return some other status
(like `Status::kWouldBlock`) to indicate that no data is available. In this
situation, the parser will stop parsing and return the status it received.
Parsing may be resumed later when more data is available.
When the `Reader` has reached the end of the WebM document and no more data is
available, it should return `Status::kEndOfFile`. This will cause parsing to
stop. If the file ends at a valid location (that is, there aren't any elements
that have specified a size that indicates the file ended prematurely), the
parser will translate `Status::kEndOfFile` into `Status::kOkCompleted` and
return it. If the file ends prematurely, the parser will return
`Status::kEndOfFile` to indicate that.
Note that if the WebM file contains elements that have an unknown size (or a
seek has been performed and the parser doesn't know the size of the root
element(s)), and the parser is parsing them and hits end-of-file, the parser may
still call `Reader::Read()`/`Reader::Skip()` multiple times (even though they've
already reported `Status::kEndOfFile`) as nested parsers terminate parsing.
Because of this, `Reader::Read()`/`Reader::Skip()` implementations should be
able to handle being called multiple times after the file's end has been
reached, and they should consistently return `Status::kEndOfFile`.
The three provided readers (`FileReader`, `IstreamReader`, and `BufferReader`)
are blocking implementations (they won't return `Status::kWouldBlock`), so if
you're using them the parser will run until it entirely consumes all their data
(unless, of course, you request the parser to stop via `Callback`... see the
next section).
## `Callback`
As the parser progresses through the file, it builds objects (see
`webm/dom_types.h`) that represent parsed data structures. The parser then
notifies the `Callback` implementation as objects complete parsing. For some
data structures (like frames or Void elements), the parser notifies the
`Callback` and requests it to consume the data directly from the `Reader` (this
is done for structures that can be large/frequent binary blobs in order to allow
you to read the data directly into the object/type of your choice, rather than
just reading them into a `std::vector<std::uint8_t>` and making you copy it into
a different object if you wanted to work with something other than
`std::vector<std::uint8_t>`).
The parser was designed to parse the data into objects that are small enough
that the `Callback` can be quickly and frequently notified as soon as the object
is ready, but large enough that the objects received by the `Callback` are still
useful. Having `Callback` events for every tiny integer/float/string/etc.
element would require too much assembly and work to be useful to most users, and
pasing the file into a single DOM tree (or a small handful of large conglomerate
structures) would unnecessarily delay video playback or consume too much memory
on smaller devices.
The parser may call the following methods while nearly anywhere in the file:
- `Callback::OnElementBegin()`: This is called for every element that the
parser encounters. This is primarily useful if you want to skip some
elements or build a map of every element in the file.
- `Callback::OnUnknownElement()`: This is called when an element is either not
a valid/recognized WebM element, or it is a WebM element but is improperly
nested (e.g. an EBMLVersion element inside of a Segment element). The parser
doesn't know how to handle the element; it could just skip it but instead
defers to the `Callback` to decide how it should be handled. The default
implementation just skips the element.
- `Callback::OnVoid()`: Void elements can appear anywhere in any master
element. This method will be called to handle the Void element.
The parser may call the following methods in the proper nesting order, as shown
in the list. A `*Begin()` method will always be matched up with its
corresponding `*End()` method (unless a seek has been performed). The parser
will only call the methods in the proper nesting order as specified in the WebM
DOM. For example, `Callback::OnEbml()` will never be called in between
`Callback::OnSegmentBegin()`/`Callback::OnSegmentEnd()` (since the EBML element
is not a child of the Segment element), and `Callback::OnTrackEntry()` will only
ever be called in between
`Callback::OnSegmentBegin()`/`Callback::OnSegmentEnd()` (since the TrackEntry
element is a (grand-)child of the Segment element and must be contained by a
Segment element). `Callback::OnFrame()` is listed twice because it will be
called to handle frames contained in both SimpleBlock and Block elements.
- `Callback::OnEbml()`
- `Callback::OnSegmentBegin()`
- `Callback::OnSeek()`
- `Callback::OnInfo()`
- `Callback::OnClusterBegin()`
- `Callback::OnSimpleBlockBegin()`
- `Callback::OnFrame()`
- `Callback::OnSimpleBlockEnd()`
- `Callback::OnBlockGroupBegin()`
- `Callback::OnBlockBegin()`
- `Callback::OnFrame()`
- `Callback::OnBlockEnd()`
- `Callback::OnBlockGroupEnd()`
- `Callback::OnClusterEnd()`
- `Callback::OnTrackEntry()`
- `Callback::OnCuePoint()`
- `Callback::OnEditionEntry()`
- `Callback::OnTag()`
- `Callback::OnSegmentEnd()`
Only `Callback::OnFrame()` (and no other `Callback` methods) will be called in
between `Callback::OnSimpleBlockBegin()`/`Callback::OnSimpleBlockEnd()` or
`Callback::OnBlockBegin()`/`Callback::OnBlockEnd()`, since the SimpleBlock and
Block elements are not master elements only contain frames.
Note that seeking into the middle of the file may cause the parser to skip some
`*Begin()` methods. For example, if a seek is performed to a SimpleBlock
element, `Callback::OnSegmentBegin()` and `Callback::OnClusterBegin()` will not
be called. In this situation, the full sequence of callback events would be
(assuming the file ended after the SimpleBlock):
`Callback::OnSimpleBlockBegin()`, `Callback::OnFrame()` (for every frame in the
SimpleBlock), `Callback::OnSimpleBlockEnd()`, `Callback::OnClusterEnd()`, and
`Callback::OnSegmentEnd()`. Since the Cluster and Segment elements were skipped,
the `Cluster` DOM object may have some members marked as absent, and the
`*End()` events for the Cluster and Segment elements will have metadata with
unknown header position, header length, and body size (see `kUnknownHeaderSize`,
`kUnknownElementSize`, and `kUnknownElementPosition`).
When a `Callback` method has completed, it should return `Status::kOkCompleted`
to allow parsing to continue. If you would like parsing to stop, return any
other status code (except `Status::kEndOfFile`, since that's treated somewhat
specially and is intended for `Reader`s to use), which the parser will return.
If you return a non-parsing-error status code (.e.g. `Status::kOkPartial`,
`Status::kWouldBlock`, etc. or your own status code with a value > 0), parsing
may be resumed again. When parsing is resumed, the parser will call the same
callback method again (and once again, you may return `Status::kOkCompleted` to
let parsing continue or some other value to stop parsing).
You may subclass the `Callback` element and override methods which you are
interested in receiving events for. By default, methods taking an `Action`
parameter will set it to `Action::kRead` so the entire file is parsed. The
`Callback::OnFrame()` method will just skip over the frame bytes by default.
## `WebmParser`
The actual parsing work is done with `WebmParser`. Simply construct a
`WebmParser` and call `WebmParser::Feed()` (providing it a `Callback` and
`Reader` instance) to parse a file. It will return `Status::kOkCompleted` when
the entire file has been successfully parsed. `WebmParser::Feed()` doesn't store
any internal references to the `Callback` or `Reader`.
If you wish to start parsing from the middle of a file, call
`WebmParser::DidSeek()` before calling `WebmParser::Feed()` to prepare the
parser to receive data starting at an arbitrary point in the file. When seeking,
you should seek to the beginning of a WebM element; seeking to a location that
is not the start of a WebM element (e.g. seeking to a frame, rather than its
containing SimpleBlock/Block element) will cause parsing to fail. Calling
`WebmParser::DidSeek()` will reset the state of the parser and clear any
internal errors, so a `WebmParser` instance may be reused (even if it has
previously failed to parse a file).
## Building your program
The following program is a small program that completely parses a file from
stdin:
```.cc
#include <webm/callback.h>
#include <webm/file_reader.h>
#include <webm/webm_parser.h>
int main() {
video_webm_parser::Callback callback;
video_webm_parser::FileReader reader(std::freopen(nullptr, "rb", stdin));
video_webm_parser::WebmParser parser;
parser.Feed(&callback, &reader);
}
```
It completely parses the input file, but we need to make a new class that
derives from `Callback` if we want to receive any parsing events. So if we
change it to:
```.cc
#include <iomanip>
#include <iostream>
#include <webm/callback.h>
#include <webm/file_reader.h>
#include <webm/status.h>
#include <webm/webm_parser.h>
class MyCallback : public video_webm_parser::Callback {
public:
video_webm_parser::Status OnElementBegin(const video_webm_parser::ElementMetadata& metadata,
video_webm_parser::Action* action) override {
std::cout << "Element ID = 0x"
<< std::hex << static_cast<std::uint32_t>(metadata.id);
std::cout << std::dec; // Reset to decimal mode.
std::cout << " at position ";
if (metadata.position == video_webm_parser::kUnknownElementPosition) {
// The position will only be unknown if we've done a seek. But since we
// aren't seeking in this demo, this will never be the case. However, this
// if-statement is included for completeness.
std::cout << "<unknown>";
} else {
std::cout << metadata.position;
}
std::cout << " with header size ";
if (metadata.header_size == video_webm_parser::kUnknownHeaderSize) {
// The header size will only be unknown if we've done a seek. But since we
// aren't seeking in this demo, this will never be the case. However, this
// if-statement is included for completeness.
std::cout << "<unknown>";
} else {
std::cout << metadata.header_size;
}
std::cout << " and body size ";
if (metadata.size == video_webm_parser::kUnknownElementSize) {
// WebM master elements may have an unknown size, though this is rare.
std::cout << "<unknown>";
} else {
std::cout << metadata.size;
}
std::cout << '\n';
*action = video_webm_parser::Action::kRead;
return video_webm_parser::Status(video_webm_parser::Status::kOkCompleted);
}
};
int main() {
MyCallback callback;
video_webm_parser::FileReader reader(std::freopen(nullptr, "rb", stdin));
video_webm_parser::WebmParser parser;
video_webm_parser::Status status = parser.Feed(&callback, &reader);
if (status.completed_ok()) {
std::cout << "Parsing successfully completed\n";
} else {
std::cout << "Parsing failed with status code: " << status.code << '\n';
}
}
```
This will output information about every element in the entire file: it's ID,
position, header size, and body size. The status of the parse is also checked
and reported.
For a more complete example, see `demo/demo.cc`, which parses an entire file and
prints out all of its information. That example overrides every `Callback`
method to show exactly what information is available while parsing and how to
access it. The example is verbose, but that's primarily due to pretty-printing
and string formatting operations.
When compiling your program, add the `include` directory to your compiler's
header search paths and link to the compiled library. Be sure your compiler has
C++11 mode enabled (`-std=c++11` in clang++ or g++).
# Testing
Unit tests are located in the `tests` directory. Google Test and Google Mock are
used as testing frameworks. Building and running the tests will be supported in
the upcoming CMake scripts, but they can currently be built and run by manually
compiling them (and linking to Google Test and Google Mock).
# Fuzzing
The parser has been fuzzed with [AFL](http://lcamtuf.coredump.cx/afl/) and
[libFuzzer](http://llvm.org/docs/LibFuzzer.html). If you wish to fuzz the parser
with AFL or libFuzzer but don't want to write an executable that exercises the
parsing API, you may use `fuzzing/webm_fuzzer.cc`.
When compiling for fuzzing, define the macro
`WEBM_FUZZER_BYTE_ELEMENT_SIZE_LIMIT` to be some integer in order to limit the
maximum size of ASCII/UTF-8/binary elements. It's too easy for the fuzzer to
generate elements that claim to have a ridiculously massive size, which will
cause allocations to fail or the program to allocate too much memory. AFL will
terminate the process if it allocates too much memory (by default, 50 MB), and
the [Address Sanitizer doesn't throw `std::bad_alloc` when an allocation fails]
(https://github.com/google/sanitizers/issues/295). Defining
`WEBM_FUZZER_BYTE_ELEMENT_SIZE_LIMIT` to a low number (say, 1024) will cause the
ASCII/UTF-8/binary element parsers to return `Status::kNotEnoughMemory` if the
element's size exceeds `WEBM_FUZZER_BYTE_ELEMENT_SIZE_LIMIT`, which will avoid
false positives when fuzzing. The parser expects `std::string` and `std::vector`
to throw `std::bad_alloc` when an allocation fails, which doesn't necessarily
happen due to the fuzzers' limitations.
You may also define the macro `WEBM_FUZZER_SEEK_FIRST` to have
`fuzzing/webm_fuzzer.cc` call `WebmParser::DidSeek()` before doing any parsing.
This will test the seeking code paths.

View File

@ -0,0 +1,91 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IndentCaseLabels: true
IndentWidth: 2
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 8
UseTab: Never
...

1124
webm_parser/demo/demo.cc Normal file

File diff suppressed because it is too large Load Diff

319
webm_parser/doxygen.config Normal file
View File

@ -0,0 +1,319 @@
# Doxyfile 1.8.11
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "WebM Parser"
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 2
ALIASES = MatroskaID{1}="[\1](https://www.webmproject.org/docs/container/#\1) ([Matroska definition](https://matroska.org/technical/specs/index.html#\1))" \
WebMID{1}="[\1](https://www.webmproject.org/docs/container/#\1)" \
WebMTable{7}="| Type | Level | Mandatory | Multiple | Recursive | Value range | Default value |\n| ---- | ----- | --------- | -------- | --------- | ----------- | ------------- |\n| \1 | \2 | \3 | \4 | \5 | \6 | \7 |\n"
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = README.md include/webm
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE = README.md
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P1<50>S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P5<50>G<EFBFBD><47><EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>c<EFBFBD><63>!

View File

@ -0,0 +1 @@
S<>g<EFBFBD>C<>u<EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P3<50>

View File

@ -0,0 +1 @@
SЂgђC¶u ‰Ћ‡и…Мѓ

View File

@ -0,0 +1 @@
S€g<E282AC>Tÿk†à®ˆTº„<C2BA>ÿ

View File

@ -0,0 +1 @@
S€gŽC§p‰E¹†¶„VT<56>!

View File

@ -0,0 +1 @@
S<>g<EFBFBD>S<>k<EFBFBD><6B><EFBFBD><EFBFBD><EFBFBD><01><><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S€g<E282AC>TÃg˜ss•gÈE£€Dz€D„€D‡€D…€gÈ€

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P5<50>G<EFBFBD><47>!S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>

View File

@ -0,0 +1 @@
u<EFBFBD>

View File

@ -0,0 +1 @@
T<EFBFBD><EFBFBD>€€

View File

@ -0,0 +1 @@
S<>g<EFBFBD>S<>k<EFBFBD><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>C<>u<EFBFBD><75><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>́<01><><EFBFBD>́

View File

@ -0,0 +1 @@
S€gœC§p—E¹”¶Ä€aT€€€€€€€€€€€€€ƒèÌ<C3A8>

View File

@ -0,0 +1 @@
S€g€

View File

@ -0,0 +1 @@
S<>g<EFBFBD>C<>u<EFBFBD><75><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P5<50><35><EFBFBD>G<EFBFBD><47>G<EFBFBD><47>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>SЛk<D09B>Л<EFBFBD>З<EFBFBD>В<EFBFBD>

View File

@ -0,0 +1 @@
S€g”T®i<C2AE>®<EFBFBD>m€b@‡P5„Gâ<47>!S€gŠT®k…®ƒ¹<C692>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>C<>u<EFBFBD><75><EFBFBD>u<EFBFBD><75><EFBFBD><EFBFBD><EFBFBD><EFBFBD><02><><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>g<EFBFBD>ss<73>gȄD<C884><44><EFBFBD>

View File

@ -0,0 +1 @@
!EߣˆB@webmS€g£Mt€I©f€C¶u€TS€gŒT®k‡®…®k€Sჟ<C692>»k€C§p€TÃg€

View File

@ -0,0 +1 @@
(<28>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P5<50>G<EFBFBD><47>!S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>%<25><><EFBFBD>!

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P5<50>G<EFBFBD><47>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>g<EFBFBD>ss<73>gȆD<C886><44>

View File

@ -0,0 +1 @@
S€g½C§p¸E¹µ¶³sÄ<73>VT<56>A@…@B€@”@C¶@<73>¶@<73>¶@<73>¶@<73>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P5<50>G<EFBFBD><47>!

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD><EFBFBD><E1839F>

View File

@ -0,0 +1 @@
S€g<E282AC>C§pŠE¹‡¶…€ƒ…<C692>!

View File

@ -0,0 +1 @@
S€g¼C§p·E¹´¶“|°…@hello€€€€€€€€€…@B€@…@C¶@ sÄ€€€€€€„€

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P5<50>G<EFBFBD><47>!S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>b@<40>P5<50>G<EFBFBD><47>!S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD>;S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD>m<EFBFBD><6D>

View File

@ -0,0 +1 @@
S€g¼C§p·E¹´¶²€ …@helloC|…lang0C~…area0C}…lang€…S|1CT®k®<E28098>m€Œb@‰P2€ÿ†G*lang2C~ƒGè…€ara1

View File

@ -0,0 +1 @@
T<EFBFBD><EFBFBD>g<EFBFBD>C<>u<EFBFBD><75><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S€g<E282AC>C§pˆE¹…¶ƒ<C692>

View File

@ -0,0 +1 @@
S€g<E282AC>C§pˆ¶†€„C|<7C>

View File

@ -0,0 +1 @@
S€gT®kŒ®Šàˆ#ƒã„@Û

View File

@ -0,0 +1 @@
Sg€„IŒû@D‰ÉÛ

View File

@ -0,0 +1 @@
S€gĽC§p·Eą´˛€°…@helloC|…lang0C|…area0C|…lang1C|…lang2C|…area1

View File

@ -0,0 +1 @@
bdT°gŒT®‡®…ᇟ<E280A1>

View File

@ -0,0 +1 @@
S€g<E282AC>T®kˆ®†à„T²<54>

View File

@ -0,0 +1 @@
<1A>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>SЛk<D09B>Л<EFBFBD>З<EFBFBD>В<EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>C<>u<EFBFBD><75><EFBFBD>u<EFBFBD><75><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>g<EFBFBD>ss<73>c<EFBFBD><63>hg<68>

View File

@ -0,0 +1 @@
S€g£I©f€I©f€I©f€C¶u€T®k€)S»k€ÿ

View File

@ -0,0 +1 @@
S€g<E282AC>T®kˆ®†à„S¸<53>ÿ

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>S<>k<EFBFBD><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S<>g<EFBFBD>S<>k<EFBFBD><6B><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
EߣˆB@webmS€g©C¶u¤ç@«@£…¾Eß#Z

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>k<EFBFBD><6B><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
S<>TŠggÀss‡g„D…<44>!

View File

@ -0,0 +1 @@
S<>g<EFBFBD>T<>g<EFBFBD>ss<73>c<EFBFBD><63>hʀcʀcŀ

View File

@ -0,0 +1 @@
S<>g<EFBFBD>C<>u<EFBFBD><75><EFBFBD>u<EFBFBD><75><EFBFBD><EFBFBD><EFBFBD><EFBFBD><02><><EFBFBD><EFBFBD>

Some files were not shown because too many files have changed in this diff Show More