[llvm-commits] [llvm] r170019 - in /llvm/trunk: docs/YamlIO.rst docs/userguides.rst include/llvm/Support/YAMLTraits.h lib/Support/CMakeLists.txt lib/Support/YAMLTraits.cpp unittests/Support/CMakeLists.txt unittests/Support/YAMLIOTest.cpp
Chandler Carruth
chandlerc at google.com
Sun Jan 6 16:40:48 PST 2013
Yea, it was missing for a long time. Nick Lewycky recently revived it.
Thanks!
On Sun, Jan 6, 2013 at 4:18 PM, Nick Kledzik <kledzik at apple.com> wrote:
> Thanks. I'll take a look. I did not even realize the testers had a leak
> mode!
>
> -Nick
>
> On Jan 5, 2013, at 1:29 AM, Chandler Carruth wrote:
>
> Hey Nick, I just wanted to mention that YamlIO seems to be leaking memory:
>
> http://lab.llvm.org:8011/builders/llvm-x86_64-linux-vg_leak/builds/140
>
> There are other (unrelated) failures on that bot, the yamlio ones look
> like actual leaks to me?
>
>
> On Wed, Dec 12, 2012 at 12:46 PM, Nick Kledzik <kledzik at apple.com> wrote:
>
>> Author: kledzik
>> Date: Wed Dec 12 14:46:15 2012
>> New Revision: 170019
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=170019&view=rev
>> Log:
>> Initial implementation of a utility for converting native data
>> structures to and from YAML using traits. The first client will
>> be the test suite of lld. The documentation will show up at:
>>
>> http://llvm.org/docs/YamlIO.html
>>
>>
>>
>> Added:
>> llvm/trunk/docs/YamlIO.rst
>> llvm/trunk/include/llvm/Support/YAMLTraits.h
>> llvm/trunk/lib/Support/YAMLTraits.cpp
>> llvm/trunk/unittests/Support/YAMLIOTest.cpp
>> Modified:
>> llvm/trunk/docs/userguides.rst
>> llvm/trunk/lib/Support/CMakeLists.txt
>> llvm/trunk/unittests/Support/CMakeLists.txt
>>
>> Added: llvm/trunk/docs/YamlIO.rst
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/YamlIO.rst?rev=170019&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/docs/YamlIO.rst (added)
>> +++ llvm/trunk/docs/YamlIO.rst Wed Dec 12 14:46:15 2012
>> @@ -0,0 +1,862 @@
>> +.. _yamlio:
>> +
>> +=====================
>> +YAML I/O
>> +=====================
>> +
>> +.. contents::
>> + :local:
>> +
>> +Introduction to YAML
>> +====================
>> +
>> +YAML is a human readable data serialization language. The full YAML
>> language
>> +spec can be read at `yaml.org
>> +<http://www.yaml.org/spec/1.2/spec.html#Introduction>`_. The simplest
>> form of
>> +yaml is just "scalars", "mappings", and "sequences". A scalar is any
>> number
>> +or string. The pound/hash symbol (#) begins a comment line. A mapping
>> is
>> +a set of key-value pairs where the key ends with a colon. For example:
>> +
>> +.. code-block:: yaml
>> +
>> + # a mapping
>> + name: Tom
>> + hat-size: 7
>> +
>> +A sequence is a list of items where each item starts with a leading dash
>> ('-').
>> +For example:
>> +
>> +.. code-block:: yaml
>> +
>> + # a sequence
>> + - x86
>> + - x86_64
>> + - PowerPC
>> +
>> +You can combine mappings and sequences by indenting. For example a
>> sequence
>> +of mappings in which one of the mapping values is itself a sequence:
>> +
>> +.. code-block:: yaml
>> +
>> + # a sequence of mappings with one key's value being a sequence
>> + - name: Tom
>> + cpus:
>> + - x86
>> + - x86_64
>> + - name: Bob
>> + cpus:
>> + - x86
>> + - name: Dan
>> + cpus:
>> + - PowerPC
>> + - x86
>> +
>> +Sometime sequences are known to be short and the one entry per line is
>> too
>> +verbose, so YAML offers an alternate syntax for sequences called a "Flow
>> +Sequence" in which you put comma separated sequence elements into square
>> +brackets. The above example could then be simplified to :
>> +
>> +
>> +.. code-block:: yaml
>> +
>> + # a sequence of mappings with one key's value being a flow sequence
>> + - name: Tom
>> + cpus: [ x86, x86_64 ]
>> + - name: Bob
>> + cpus: [ x86 ]
>> + - name: Dan
>> + cpus: [ PowerPC, x86 ]
>> +
>> +
>> +Introduction to YAML I/O
>> +========================
>> +
>> +The use of indenting makes the YAML easy for a human to read and
>> understand,
>> +but having a program read and write YAML involves a lot of tedious
>> details.
>> +The YAML I/O library structures and simplifies reading and writing YAML
>> +documents.
>> +
>> +YAML I/O assumes you have some "native" data structures which you want
>> to be
>> +able to dump as YAML and recreate from YAML. The first step is to try
>> +writing example YAML for your data structures. You may find after
>> looking at
>> +possible YAML representations that a direct mapping of your data
>> structures
>> +to YAML is not very readable. Often the fields are not in the order that
>> +a human would find readable. Or the same information is replicated in
>> multiple
>> +locations, making it hard for a human to write such YAML correctly.
>> +
>> +In relational database theory there is a design step called
>> normalization in
>> +which you reorganize fields and tables. The same considerations need to
>> +go into the design of your YAML encoding. But, you may not want to
>> change
>> +your exisiting native data structures. Therefore, when writing out YAML
>> +there may be a normalization step, and when reading YAML there would be a
>> +corresponding denormalization step.
>> +
>> +YAML I/O uses a non-invasive, traits based design. YAML I/O defines some
>> +abstract base templates. You specialize those templates on your data
>> types.
>> +For instance, if you have an eumerated type FooBar you could specialize
>> +ScalarEnumerationTraits on that type and define the enumeration() method:
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::ScalarEnumerationTraits;
>> + using llvm::yaml::IO;
>> +
>> + template <>
>> + struct ScalarEnumerationTraits<FooBar> {
>> + static void enumeration(IO &io, FooBar &value) {
>> + ...
>> + }
>> + };
>> +
>> +
>> +As with all YAML I/O template specializations, the
>> ScalarEnumerationTraits is used for
>> +both reading and writing YAML. That is, the mapping between in-memory
>> enum
>> +values and the YAML string representation is only in place.
>> +This assures that the code for writing and parsing of YAML stays in sync.
>> +
>> +To specify a YAML mappings, you define a specialization on
>> +llvm::yaml::MapppingTraits.
>> +If your native data structure happens to be a struct that is already
>> normalized,
>> +then the specialization is simple. For example:
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::MapppingTraits;
>> + using llvm::yaml::IO;
>> +
>> + template <>
>> + struct MapppingTraits<Person> {
>> + static void mapping(IO &io, Person &info) {
>> + io.mapRequired("name", info.name);
>> + io.mapOptional("hat-size", info.hatSize);
>> + }
>> + };
>> +
>> +
>> +A YAML sequence is automatically infered if you data type has
>> begin()/end()
>> +iterators and a push_back() method. Therefore any of the STL containers
>> +(such as std::vector<>) will automatically translate to YAML sequences.
>> +
>> +Once you have defined specializations for your data types, you can
>> +programmatically use YAML I/O to write a YAML document:
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::Output;
>> +
>> + Person tom;
>> + tom.name = "Tom";
>> + tom.hatSize = 8;
>> + Person dan;
>> + dan.name = "Dan";
>> + dan.hatSize = 7;
>> + std::vector<Person> persons;
>> + persons.push_back(tom);
>> + persons.push_back(dan);
>> +
>> + Output yout(llvm::outs());
>> + yout << persons;
>> +
>> +This would write the following:
>> +
>> +.. code-block:: yaml
>> +
>> + - name: Tom
>> + hat-size: 8
>> + - name: Dan
>> + hat-size: 7
>> +
>> +And you can also read such YAML documents with the following code:
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::Input;
>> +
>> + typedef std::vector<Person> PersonList;
>> + std::vector<PersonList> docs;
>> +
>> + Input yin(document.getBuffer());
>> + yin >> docs;
>> +
>> + if ( yin.error() )
>> + return;
>> +
>> + // Process read document
>> + for ( PersonList &pl : docs ) {
>> + for ( Person &person : pl ) {
>> + cout << "name=" << person.name;
>> + }
>> + }
>> +
>> +One other feature of YAML is the ability to define multiple documents in
>> a
>> +single file. That is why reading YAML produces a vector of your
>> document type.
>> +
>> +
>> +
>> +Error Handling
>> +==============
>> +
>> +When parsing a YAML document, if the input does not match your schema (as
>> +expressed in your XxxTraits<> specializations). YAML I/O
>> +will print out an error message and your Input object's error() method
>> will
>> +return true. For instance the following document:
>> +
>> +.. code-block:: yaml
>> +
>> + - name: Tom
>> + shoe-size: 12
>> + - name: Dan
>> + hat-size: 7
>> +
>> +Has a key (shoe-size) that is not defined in the schema. YAML I/O will
>> +automatically generate this error:
>> +
>> +.. code-block:: yaml
>> +
>> + YAML:2:2: error: unknown key 'shoe-size'
>> + shoe-size: 12
>> + ^~~~~~~~~
>> +
>> +Similar errors are produced for other input not conforming to the schema.
>> +
>> +
>> +Scalars
>> +=======
>> +
>> +YAML scalars are just strings (i.e. not a sequence or mapping). The
>> YAML I/O
>> +library provides support for translating between YAML scalars and
>> specific
>> +C++ types.
>> +
>> +
>> +Built-in types
>> +--------------
>> +The following types have built-in support in YAML I/O:
>> +
>> +* bool
>> +* float
>> +* double
>> +* StringRef
>> +* int64_t
>> +* int32_t
>> +* int16_t
>> +* int8_t
>> +* uint64_t
>> +* uint32_t
>> +* uint16_t
>> +* uint8_t
>> +
>> +That is, you can use those types in fields of MapppingTraits or as
>> element type
>> +in sequence. When reading, YAML I/O will validate that the string found
>> +is convertible to that type and error out if not.
>> +
>> +
>> +Unique types
>> +------------
>> +Given that YAML I/O is trait based, the selection of how to convert your
>> data
>> +to YAML is based on the type of your data. But in C++ type matching,
>> typedefs
>> +do not generate unique type names. That means if you have two typedefs
>> of
>> +unsigned int, to YAML I/O both types look exactly like unsigned int. To
>> +facilitate make unique type names, YAML I/O provides a macro which is
>> used
>> +like a typedef on built-in types, but expands to create a class with
>> conversion
>> +operators to and from the base type. For example:
>> +
>> +.. code-block:: c++
>> +
>> + LLVM_YAML_STRONG_TYPEDEF(uint32_t, MyFooFlags)
>> + LLVM_YAML_STRONG_TYPEDEF(uint32_t, MyBarFlags)
>> +
>> +This generates two classes MyFooFlags and MyBarFlags which you can use
>> in your
>> +native data structures instead of uint32_t. They are implicitly
>> +converted to and from uint32_t. The point of creating these unique types
>> +is that you can now specify traits on them to get different YAML
>> conversions.
>> +
>> +Hex types
>> +---------
>> +An example use of a unique type is that YAML I/O provides fixed sized
>> unsigned
>> +integers that are written with YAML I/O as hexadecimal instead of the
>> decimal
>> +format used by the built-in integer types:
>> +
>> +* Hex64
>> +* Hex32
>> +* Hex16
>> +* Hex8
>> +
>> +You can use llvm::yaml::Hex32 instead of uint32_t and the only different
>> will
>> +be that when YAML I/O writes out that type it will be formatted in
>> hexadecimal.
>> +
>> +
>> +ScalarEnumerationTraits
>> +-----------------------
>> +YAML I/O supports translating between in-memory enumerations and a set
>> of string
>> +values in YAML documents. This is done by specializing
>> ScalarEnumerationTraits<>
>> +on your enumeration type and define a enumeration() method.
>> +For instance, suppose you had an enumeration of CPUs and a struct with
>> it as
>> +a field:
>> +
>> +.. code-block:: c++
>> +
>> + enum CPUs {
>> + cpu_x86_64 = 5,
>> + cpu_x86 = 7,
>> + cpu_PowerPC = 8
>> + };
>> +
>> + struct Info {
>> + CPUs cpu;
>> + uint32_t flags;
>> + };
>> +
>> +To support reading and writing of this enumeration, you can define a
>> +ScalarEnumerationTraits specialization on CPUs, which can then be used
>> +as a field type:
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::ScalarEnumerationTraits;
>> + using llvm::yaml::MapppingTraits;
>> + using llvm::yaml::IO;
>> +
>> + template <>
>> + struct ScalarEnumerationTraits<CPUs> {
>> + static void enumeration(IO &io, CPUs &value) {
>> + io.enumCase(value, "x86_64", cpu_x86_64);
>> + io.enumCase(value, "x86", cpu_x86);
>> + io.enumCase(value, "PowerPC", cpu_PowerPC);
>> + }
>> + };
>> +
>> + template <>
>> + struct MapppingTraits<Info> {
>> + static void mapping(IO &io, Info &info) {
>> + io.mapRequired("cpu", info.cpu);
>> + io.mapOptional("flags", info.flags, 0);
>> + }
>> + };
>> +
>> +When reading YAML, if the string found does not match any of the the
>> strings
>> +specified by enumCase() methods, an error is automatically generated.
>> +When writing YAML, if the value being written does not match any of the
>> values
>> +specified by the enumCase() methods, a runtime assertion is triggered.
>> +
>> +
>> +BitValue
>> +--------
>> +Another common data structure in C++ is a field where each bit has a
>> unique
>> +meaning. This is often used in a "flags" field. YAML I/O has support
>> for
>> +converting such fields to a flow sequence. For instance suppose you
>> +had the following bit flags defined:
>> +
>> +.. code-block:: c++
>> +
>> + enum {
>> + flagsPointy = 1
>> + flagsHollow = 2
>> + flagsFlat = 4
>> + flagsRound = 8
>> + };
>> +
>> + LLVM_YAML_UNIQUE_TYPE(MyFlags, uint32_t)
>> +
>> +To support reading and writing of MyFlags, you specialize
>> ScalarBitSetTraits<>
>> +on MyFlags and provide the bit values and their names.
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::ScalarBitSetTraits;
>> + using llvm::yaml::MapppingTraits;
>> + using llvm::yaml::IO;
>> +
>> + template <>
>> + struct ScalarBitSetTraits<MyFlags> {
>> + static void bitset(IO &io, MyFlags &value) {
>> + io.bitSetCase(value, "hollow", flagHollow);
>> + io.bitSetCase(value, "flat", flagFlat);
>> + io.bitSetCase(value, "round", flagRound);
>> + io.bitSetCase(value, "pointy", flagPointy);
>> + }
>> + };
>> +
>> + struct Info {
>> + StringRef name;
>> + MyFlags flags;
>> + };
>> +
>> + template <>
>> + struct MapppingTraits<Info> {
>> + static void mapping(IO &io, Info& info) {
>> + io.mapRequired("name", info.name);
>> + io.mapRequired("flags", info.flags);
>> + }
>> + };
>> +
>> +With the above, YAML I/O (when writing) will test mask each value in the
>> +bitset trait against the flags field, and each that matches will
>> +cause the corresponding string to be added to the flow sequence. The
>> opposite
>> +is done when reading and any unknown string values will result in a
>> error. With
>> +the above schema, a same valid YAML document is:
>> +
>> +.. code-block:: yaml
>> +
>> + name: Tom
>> + flags: [ pointy, flat ]
>> +
>> +
>> +Custom Scalar
>> +-------------
>> +Sometimes for readability a scalar needs to be formatted in a custom
>> way. For
>> +instance your internal data structure may use a integer for time
>> (seconds since
>> +some epoch), but in YAML it would be much nicer to express that integer
>> in
>> +some time format (e.g. 4-May-2012 10:30pm). YAML I/O has a way to
>> support
>> +custom formatting and parsing of scalar types by specializing
>> ScalarTraits<> on
>> +your data type. When writing, YAML I/O will provide the native type and
>> +your specialization must create a temporary llvm::StringRef. When
>> reading,
>> +YAML I/O will provide a llvm::StringRef of scalar and your specialization
>> +must convert that to your native data type. An outline of a custom
>> scalar type
>> +looks like:
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::ScalarTraits;
>> + using llvm::yaml::IO;
>> +
>> + template <>
>> + struct ScalarTraits<MyCustomType> {
>> + static void output(const T &value, llvm::raw_ostream &out) {
>> + out << value; // do custom formatting here
>> + }
>> + static StringRef input(StringRef scalar, T &value) {
>> + // do custom parsing here. Return the empty string on success,
>> + // or an error message on failure.
>> + return StringRef();
>> + }
>> + };
>> +
>> +
>> +Mappings
>> +========
>> +
>> +To be translated to or from a YAML mapping for your type T you must
>> specialize
>> +llvm::yaml::MapppingTraits on T and implement the "void mapping(IO &io,
>> T&)"
>> +method. If your native data structures use pointers to a class
>> everywhere,
>> +you can specialize on the class pointer. Examples:
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::MapppingTraits;
>> + using llvm::yaml::IO;
>> +
>> + // Example of struct Foo which is used by value
>> + template <>
>> + struct MapppingTraits<Foo> {
>> + static void mapping(IO &io, Foo &foo) {
>> + io.mapOptional("size", foo.size);
>> + ...
>> + }
>> + };
>> +
>> + // Example of struct Bar which is natively always a pointer
>> + template <>
>> + struct MapppingTraits<Bar*> {
>> + static void mapping(IO &io, Bar *&bar) {
>> + io.mapOptional("size", bar->size);
>> + ...
>> + }
>> + };
>> +
>> +
>> +No Normalization
>> +----------------
>> +
>> +The mapping() method is responsible, if needed, for normalizing and
>> +denormalizing. In a simple case where the native data structure requires
>> no
>> +normalization, the mapping method just uses mapOptional() or
>> mapRequired() to
>> +bind the struct's fields to YAML key names. For example:
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::MapppingTraits;
>> + using llvm::yaml::IO;
>> +
>> + template <>
>> + struct MapppingTraits<Person> {
>> + static void mapping(IO &io, Person &info) {
>> + io.mapRequired("name", info.name);
>> + io.mapOptional("hat-size", info.hatSize);
>> + }
>> + };
>> +
>> +
>> +Normalization
>> +----------------
>> +
>> +When [de]normalization is required, the mapping() method needs a way to
>> access
>> +normalized values as fields. To help with this, there is
>> +a template MappingNormalization<> which you can then use to automatically
>> +do the normalization and denormalization. The template is used to create
>> +a local variable in your mapping() method which contains the normalized
>> keys.
>> +
>> +Suppose you have native data type
>> +Polar which specifies a position in polar coordinates (distance, angle):
>> +
>> +.. code-block:: c++
>> +
>> + struct Polar {
>> + float distance;
>> + float angle;
>> + };
>> +
>> +but you've decided the normalized YAML for should be in x,y coordinates.
>> That
>> +is, you want the yaml to look like:
>> +
>> +.. code-block:: yaml
>> +
>> + x: 10.3
>> + y: -4.7
>> +
>> +You can support this by defining a MapppingTraits that normalizes the
>> polar
>> +coordinates to x,y coordinates when writing YAML and denormalizes x,y
>> +coordindates into polar when reading YAML.
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::MapppingTraits;
>> + using llvm::yaml::IO;
>> +
>> + template <>
>> + struct MapppingTraits<Polar> {
>> +
>> + class NormalizedPolar {
>> + public:
>> + NormalizedPolar(IO &io)
>> + : x(0.0), y(0.0) {
>> + }
>> + NormalizedPolar(IO &, Polar &polar)
>> + : x(polar.distance * cos(polar.angle)),
>> + y(polar.distance * sin(polar.angle)) {
>> + }
>> + Polar denormalize(IO &) {
>> + return Polar(sqrt(x*x+y*y, arctan(x,y));
>> + }
>> +
>> + float x;
>> + float y;
>> + };
>> +
>> + static void mapping(IO &io, Polar &polar) {
>> + MappingNormalization<NormalizedPolar, Polar> keys(io, polar);
>> +
>> + io.mapRequired("x", keys->x);
>> + io.mapRequired("y", keys->y);
>> + }
>> + };
>> +
>> +When writing YAML, the local variable "keys" will be a stack allocated
>> +instance of NormalizedPolar, constructed from the suppled polar object
>> which
>> +initializes it x and y fields. The mapRequired() methods then write out
>> the x
>> +and y values as key/value pairs.
>> +
>> +When reading YAML, the local variable "keys" will be a stack allocated
>> instance
>> +of NormalizedPolar, constructed by the empty constructor. The
>> mapRequired
>> +methods will find the matching key in the YAML document and fill in the
>> x and y
>> +fields of the NormalizedPolar object keys. At the end of the mapping()
>> method
>> +when the local keys variable goes out of scope, the denormalize() method
>> will
>> +automatically be called to convert the read values back to polar
>> coordinates,
>> +and then assigned back to the second parameter to mapping().
>> +
>> +In some cases, the normalized class may be a subclass of the native type
>> and
>> +could be returned by the denormalize() method, except that the temporary
>> +normalized instance is stack allocated. In these cases, the utility
>> template
>> +MappingNormalizationHeap<> can be used instead. It just like
>> +MappingNormalization<> except that it heap allocates the normalized
>> object
>> +when reading YAML. It never destroyes the normalized object. The
>> denormalize()
>> +method can this return "this".
>> +
>> +
>> +Default values
>> +--------------
>> +Within a mapping() method, calls to io.mapRequired() mean that that key
>> is
>> +required to exist when parsing YAML documents, otherwise YAML I/O will
>> issue an
>> +error.
>> +
>> +On the other hand, keys registered with io.mapOptional() are allowed to
>> not
>> +exist in the YAML document being read. So what value is put in the field
>> +for those optional keys?
>> +There are two steps to how those optional fields are filled in. First,
>> the
>> +second parameter to the mapping() method is a reference to a native
>> class. That
>> +native class must have a default constructor. Whatever value the default
>> +constructor initially sets for an optional field will be that field's
>> value.
>> +Second, the mapOptional() method has an optional third parameter. If
>> provided
>> +it is the value that mapOptional() should set that field to if the YAML
>> document
>> +does not have that key.
>> +
>> +There is one important difference between those two ways (default
>> constructor
>> +and third parameter to mapOptional). When YAML I/O generates a YAML
>> document,
>> +if the mapOptional() third parameter is used, if the actual value being
>> written
>> +is the same as (using ==) the default value, then that key/value is not
>> written.
>> +
>> +
>> +Order of Keys
>> +--------------
>> +
>> +When writing out a YAML document, the keys are written in the order that
>> the
>> +calls to mapRequired()/mapOptional() are made in the mapping() method.
>> This
>> +gives you a chance to write the fields in an order that a human reader of
>> +the YAML document would find natural. This may be different that the
>> order
>> +of the fields in the native class.
>> +
>> +When reading in a YAML document, the keys in the document can be in any
>> order,
>> +but they are processed in the order that the calls to
>> mapRequired()/mapOptional()
>> +are made in the mapping() method. That enables some interesting
>> +functionality. For instance, if the first field bound is the cpu and
>> the second
>> +field bound is flags, and the flags are cpu specific, you can
>> programmatically
>> +switch how the flags are converted to and from YAML based on the cpu.
>> +This works for both reading and writing. For example:
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::MapppingTraits;
>> + using llvm::yaml::IO;
>> +
>> + struct Info {
>> + CPUs cpu;
>> + uint32_t flags;
>> + };
>> +
>> + template <>
>> + struct MapppingTraits<Info> {
>> + static void mapping(IO &io, Info &info) {
>> + io.mapRequired("cpu", info.cpu);
>> + // flags must come after cpu for this to work when reading yaml
>> + if ( info.cpu == cpu_x86_64 )
>> + io.mapRequired("flags", *(My86_64Flags*)info.flags);
>> + else
>> + io.mapRequired("flags", *(My86Flags*)info.flags);
>> + }
>> + };
>> +
>> +
>> +Sequence
>> +========
>> +
>> +To be translated to or from a YAML sequence for your type T you must
>> specialize
>> +llvm::yaml::SequenceTraits on T and implement two methods:
>> +“size_t size(IO &io, T&)†and “T::value_type& element(IO &io, T&,
>> size_t indx)†.
>> +For example:
>> +
>> +.. code-block:: c++
>> +
>> + template <>
>> + struct SequenceTraits<MySeq> {
>> + static size_t size(IO &io, MySeq &list) { ... }
>> + static MySeqEl element(IO &io, MySeq &list, size_t index) { ... }
>> + };
>> +
>> +The size() method returns how many elements are currently in your
>> sequence.
>> +The element() method returns a reference to the i'th element in the
>> sequence.
>> +When parsing YAML, the element() method may be called with an index one
>> bigger
>> +than the current size. Your element() method should allocate space for
>> one
>> +more element (using default constructor if element is a C++ object) and
>> returns
>> +a reference to that new allocated space.
>> +
>> +
>> +Flow Sequence
>> +-------------
>> +A YAML "flow sequence" is a sequence that when written to YAML it uses
>> the
>> +inline notation (e.g [ foo, bar ] ). To specify that a sequence type
>> should
>> +be written in YAML as a flow sequence, your SequenceTraits
>> specialization should
>> +add "static const bool flow = true;". For instance:
>> +
>> +.. code-block:: c++
>> +
>> + template <>
>> + struct SequenceTraits<MyList> {
>> + static size_t size(IO &io, MyList &list) { ... }
>> + static MyListEl element(IO &io, MyList &list, size_t index) { ... }
>> +
>> + // The existence of this member causes YAML I/O to use a flow
>> sequence
>> + static const bool flow = true;
>> + };
>> +
>> +With the above, if you used MyList as the data type in your native data
>> +strucutures, then then when converted to YAML, a flow sequence of
>> integers
>> +will be used (e.g. [ 10, -3, 4 ]).
>> +
>> +
>> +Utility Macros
>> +--------------
>> +Since a common source of sequences is std::vector<>, YAML I/O provids
>> macros:
>> +LLVM_YAML_IS_SEQUENCE_VECTOR() and LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR()
>> which
>> +can be used to easily specify SequenceTraits<> on a std::vector type.
>> YAML
>> +I/O does not partial specialize SequenceTraits on std::vector<> because
>> that
>> +would force all vectors to be sequences. An example use of the macros:
>> +
>> +.. code-block:: c++
>> +
>> + std::vector<MyType1>;
>> + std::vector<MyType2>;
>> + LLVM_YAML_IS_SEQUENCE_VECTOR(MyType1)
>> + LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyType2)
>> +
>> +
>> +
>> +Document List
>> +=============
>> +
>> +YAML allows you to define multiple "documents" in a single YAML file.
>> Each
>> +new document starts with a left aligned "---" token. The end of all
>> documents
>> +is denoted with a left aligned "..." token. Many users of YAML will
>> never
>> +have need for multiple documents. The top level node in their YAML
>> schema
>> +will be a mapping or sequence. For those cases, the following is not
>> needed.
>> +But for cases where you do want multiple documents, you can specify a
>> +trait for you document list type. The trait has the same methods as
>> +SequenceTraits but is named DocumentListTraits. For example:
>> +
>> +.. code-block:: c++
>> +
>> + template <>
>> + struct DocumentListTraits<MyDocList> {
>> + static size_t size(IO &io, MyDocList &list) { ... }
>> + static MyDocType element(IO &io, MyDocList &list, size_t index) {
>> ... }
>> + };
>> +
>> +
>> +User Context Data
>> +=================
>> +When an llvm::yaml::Input or llvm::yaml::Output object is created their
>> +constructors take an optional "context" parameter. This is a pointer to
>> +whatever state information you might need.
>> +
>> +For instance, in a previous example we showed how the conversion type
>> for a
>> +flags field could be determined at runtime based on the value of another
>> field
>> +in the mapping. But what if an inner mapping needs to know some field
>> value
>> +of an outer mapping? That is where the "context" parameter comes in. You
>> +can set values in the context in the outer map's mapping() method and
>> +retrieve those values in the inner map's mapping() method.
>> +
>> +The context value is just a void*. All your traits which use the context
>> +and operate on your native data types, need to agree what the context
>> value
>> +actually is. It could be a pointer to an object or struct which your
>> various
>> +traits use to shared context sensitive information.
>> +
>> +
>> +Output
>> +======
>> +
>> +The llvm::yaml::Output class is used to generate a YAML document from
>> your
>> +in-memory data structures, using traits defined on your data types.
>> +To instantiate an Output object you need an llvm::raw_ostream, and
>> optionally
>> +a context pointer:
>> +
>> +.. code-block:: c++
>> +
>> + class Output : public IO {
>> + public:
>> + Output(llvm::raw_ostream &, void *context=NULL);
>> +
>> +Once you have an Output object, you can use the C++ stream operator on it
>> +to write your native data as YAML. One thing to recall is that a YAML
>> file
>> +can contain multiple "documents". If the top level data structure you
>> are
>> +streaming as YAML is a mapping, scalar, or sequence, then Output assumes
>> you
>> +are generating one document and wraps the mapping output
>> +with "``---``" and trailing "``...``".
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::Output;
>> +
>> + void dumpMyMapDoc(const MyMapType &info) {
>> + Output yout(llvm::outs());
>> + yout << info;
>> + }
>> +
>> +The above could produce output like:
>> +
>> +.. code-block:: yaml
>> +
>> + ---
>> + name: Tom
>> + hat-size: 7
>> + ...
>> +
>> +On the other hand, if the top level data structure you are streaming as
>> YAML
>> +has a DocumentListTraits specialization, then Output walks through each
>> element
>> +of your DocumentList and generates a "---" before the start of each
>> element
>> +and ends with a "...".
>> +
>> +.. code-block:: c++
>> +
>> + using llvm::yaml::Output;
>> +
>> + void dumpMyMapDoc(const MyDocListType &docList) {
>> + Output yout(llvm::outs());
>> + yout << docList;
>> + }
>> +
>> +The above could produce output like:
>> +
>> +.. code-block:: yaml
>> +
>> + ---
>> + name: Tom
>> + hat-size: 7
>> + ---
>> + name: Tom
>> + shoe-size: 11
>> + ...
>> +
>> +Input
>> +=====
>> +
>> +The llvm::yaml::Input class is used to parse YAML document(s) into your
>> native
>> +data structures. To instantiate an Input
>> +object you need a StringRef to the entire YAML file, and optionally a
>> context
>> +pointer:
>> +
>> +.. code-block:: c++
>> +
>> + class Input : public IO {
>> + public:
>> + Input(StringRef inputContent, void *context=NULL);
>> +
>> +Once you have an Input object, you can use the C++ stream operator to
>> read
>> +the document(s). If you expect there might be multiple YAML documents in
>> +one file, you'll need to specialize DocumentListTraits on a list of your
>> +document type and stream in that document list type. Otherwise you can
>> +just stream in the document type. Also, you can check if there was
>> +any syntax errors in the YAML be calling the error() method on the Input
>> +object. For example:
>> +
>> +.. code-block:: c++
>> +
>> + // Reading a single document
>> + using llvm::yaml::Input;
>> +
>> + Input yin(mb.getBuffer());
>> +
>> + // Parse the YAML file
>> + MyDocType theDoc;
>> + yin >> theDoc;
>> +
>> + // Check for error
>> + if ( yin.error() )
>> + return;
>> +
>> +
>> +.. code-block:: c++
>> +
>> + // Reading multiple documents in one file
>> + using llvm::yaml::Input;
>> +
>> + LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(std::vector<MyDocType>)
>> +
>> + Input yin(mb.getBuffer());
>> +
>> + // Parse the YAML file
>> + std::vector<MyDocType> theDocList;
>> + yin >> theDocList;
>> +
>> + // Check for error
>> + if ( yin.error() )
>> + return;
>> +
>> +
>>
>> Modified: llvm/trunk/docs/userguides.rst
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/userguides.rst?rev=170019&r1=170018&r2=170019&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/docs/userguides.rst (original)
>> +++ llvm/trunk/docs/userguides.rst Wed Dec 12 14:46:15 2012
>> @@ -24,6 +24,7 @@
>> tutorial/index
>> ReleaseNotes
>> Passes
>> + YamlIO
>>
>> * :ref:`getting_started`
>>
>> @@ -100,6 +101,10 @@
>>
>> Instructions for adding new builder to LLVM buildbot master.
>>
>> +* :ref:`yamlio`
>> +
>> + A reference guide for using LLVM's YAML I/O library.
>> +
>> * **IRC** -- You can probably find help on the unofficial LLVM IRC.
>>
>> We often are on irc.oftc.net in the #llvm channel. If you are using
>> the
>>
>> Added: llvm/trunk/include/llvm/Support/YAMLTraits.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/YAMLTraits.h?rev=170019&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Support/YAMLTraits.h (added)
>> +++ llvm/trunk/include/llvm/Support/YAMLTraits.h Wed Dec 12 14:46:15 2012
>> @@ -0,0 +1,1114 @@
>> +//===- llvm/Supporrt/YAMLTraits.h -------------------------------*- C++
>> -*-===//
>> +//
>> +// The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_YAML_TRAITS_H_
>> +#define LLVM_YAML_TRAITS_H_
>> +
>> +
>> +#include "llvm/ADT/DenseMap.h"
>> +#include "llvm/ADT/DenseMapInfo.h"
>> +#include "llvm/ADT/SmallVector.h"
>> +#include "llvm/ADT/StringExtras.h"
>> +#include "llvm/ADT/StringRef.h"
>> +#include "llvm/ADT/StringSwitch.h"
>> +#include "llvm/ADT/Twine.h"
>> +#include "llvm/Support/Compiler.h"
>> +#include "llvm/Support/SourceMgr.h"
>> +#include "llvm/Support/system_error.h"
>> +#include "llvm/Support/type_traits.h"
>> +#include "llvm/Support/YAMLParser.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +
>> +
>> +namespace llvm {
>> +namespace yaml {
>> +
>> +
>> +/// This class should be specialized by any type that needs to be
>> converted
>> +/// to/from a YAML mapping. For example:
>> +///
>> +/// struct ScalarBitSetTraits<MyStruct> {
>> +/// static void mapping(IO &io, MyStruct &s) {
>> +/// io.mapRequired("name", s.name);
>> +/// io.mapRequired("size", s.size);
>> +/// io.mapOptional("age", s.age);
>> +/// }
>> +/// };
>> +template<class T>
>> +struct MappingTraits {
>> + // Must provide:
>> + // static void mapping(IO &io, T &fields);
>> +};
>> +
>> +
>> +/// This class should be specialized by any integral type that converts
>> +/// to/from a YAML scalar where there is a one-to-one mapping between
>> +/// in-memory values and a string in YAML. For example:
>> +///
>> +/// struct ScalarEnumerationTraits<Colors> {
>> +/// static void enumeration(IO &io, Colors &value) {
>> +/// io.enumCase(value, "red", cRed);
>> +/// io.enumCase(value, "blue", cBlue);
>> +/// io.enumCase(value, "green", cGreen);
>> +/// }
>> +/// };
>> +template<typename T>
>> +struct ScalarEnumerationTraits {
>> + // Must provide:
>> + // static void enumeration(IO &io, T &value);
>> +};
>> +
>> +
>> +/// This class should be specialized by any integer type that is a union
>> +/// of bit values and the YAML representation is a flow sequence of
>> +/// strings. For example:
>> +///
>> +/// struct ScalarBitSetTraits<MyFlags> {
>> +/// static void bitset(IO &io, MyFlags &value) {
>> +/// io.bitSetCase(value, "big", flagBig);
>> +/// io.bitSetCase(value, "flat", flagFlat);
>> +/// io.bitSetCase(value, "round", flagRound);
>> +/// }
>> +/// };
>> +template<typename T>
>> +struct ScalarBitSetTraits {
>> + // Must provide:
>> + // static void bitset(IO &io, T &value);
>> +};
>> +
>> +
>> +/// This class should be specialized by type that requires custom
>> conversion
>> +/// to/from a yaml scalar. For example:
>> +///
>> +/// template<>
>> +/// struct ScalarTraits<MyType> {
>> +/// static void output(const MyType &val, void*, llvm::raw_ostream
>> &out) {
>> +/// // stream out custom formatting
>> +/// out << llvm::format("%x", val);
>> +/// }
>> +/// static StringRef input(StringRef scalar, void*, MyType &value) {
>> +/// // parse scalar and set `value`
>> +/// // return empty string on success, or error string
>> +/// return StringRef();
>> +/// }
>> +/// };
>> +template<typename T>
>> +struct ScalarTraits {
>> + // Must provide:
>> + //
>> + // Function to write the value as a string:
>> + //static void output(const T &value, void *ctxt, llvm::raw_ostream
>> &out);
>> + //
>> + // Function to convert a string to a value. Returns the empty
>> + // StringRef on success or an error string if string is malformed:
>> + //static StringRef input(StringRef scalar, void *ctxt, T &value);
>> +};
>> +
>> +
>> +/// This class should be specialized by any type that needs to be
>> converted
>> +/// to/from a YAML sequence. For example:
>> +///
>> +/// template<>
>> +/// struct SequenceTraits< std::vector<MyType> > {
>> +/// static size_t size(IO &io, std::vector<MyType> &seq) {
>> +/// return seq.size();
>> +/// }
>> +/// static MyType& element(IO &, std::vector<MyType> &seq, size_t
>> index) {
>> +/// if ( index >= seq.size() )
>> +/// seq.resize(index+1);
>> +/// return seq[index];
>> +/// }
>> +/// };
>> +template<typename T>
>> +struct SequenceTraits {
>> + // Must provide:
>> + // static size_t size(IO &io, T &seq);
>> + // static T::value_type& element(IO &io, T &seq, size_t index);
>> + //
>> + // The following is option and will cause generated YAML to use
>> + // a flow sequence (e.g. [a,b,c]).
>> + // static const bool flow = true;
>> +};
>> +
>> +
>> +/// This class should be specialized by any type that needs to be
>> converted
>> +/// to/from a list of YAML documents.
>> +template<typename T>
>> +struct DocumentListTraits {
>> + // Must provide:
>> + // static size_t size(IO &io, T &seq);
>> + // static T::value_type& element(IO &io, T &seq, size_t index);
>> +};
>> +
>> +
>> +// Only used by compiler if both template types are the same
>> +template <typename T, T>
>> +struct SameType;
>> +
>> +// Only used for better diagnostics of missing traits
>> +template <typename T>
>> +struct MissingTrait;
>> +
>> +
>> +
>> +// Test if ScalarEnumerationTraits<T> is defined on type T.
>> +template <class T>
>> +struct has_ScalarEnumerationTraits
>> +{
>> + typedef void (*Signature_enumeration)(class IO&, T&);
>> +
>> + template <typename U>
>> + static char test(SameType<Signature_enumeration, &U::enumeration>*);
>> +
>> + template <typename U>
>> + static double test(...);
>> +
>> +public:
>> + static bool const value = (sizeof(test<ScalarEnumerationTraits<T>
>> >(0)) == 1);
>> +};
>> +
>> +
>> +// Test if ScalarBitSetTraits<T> is defined on type T.
>> +template <class T>
>> +struct has_ScalarBitSetTraits
>> +{
>> + typedef void (*Signature_bitset)(class IO&, T&);
>> +
>> + template <typename U>
>> + static char test(SameType<Signature_bitset, &U::bitset>*);
>> +
>> + template <typename U>
>> + static double test(...);
>> +
>> +public:
>> + static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(0)) ==
>> 1);
>> +};
>> +
>> +
>> +// Test if ScalarTraits<T> is defined on type T.
>> +template <class T>
>> +struct has_ScalarTraits
>> +{
>> + typedef llvm::StringRef (*Signature_input)(llvm::StringRef, void*, T&);
>> + typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&);
>> +
>> + template <typename U>
>> + static char test(SameType<Signature_input, &U::input>*,
>> + SameType<Signature_output, &U::output>*);
>> +
>> + template <typename U>
>> + static double test(...);
>> +
>> +public:
>> + static bool const value = (sizeof(test<ScalarTraits<T> >(0,0)) == 1);
>> +};
>> +
>> +
>> +// Test if MappingTraits<T> is defined on type T.
>> +template <class T>
>> +struct has_MappingTraits
>> +{
>> + typedef void (*Signature_mapping)(class IO&, T&);
>> +
>> + template <typename U>
>> + static char test(SameType<Signature_mapping, &U::mapping>*);
>> +
>> + template <typename U>
>> + static double test(...);
>> +
>> +public:
>> + static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 1);
>> +};
>> +
>> +
>> +// Test if SequenceTraits<T> is defined on type T
>> +// and SequenceTraits<T>::flow is *not* defined.
>> +template <class T>
>> +struct has_SequenceTraits
>> +{
>> + typedef size_t (*Signature_size)(class IO&, T&);
>> +
>> + template <typename U>
>> + static char test(SameType<Signature_size, &U::size>*);
>> +
>> + template <typename U>
>> + static double test(...);
>> +
>> + template <typename U> static
>> + char flowtest( char[sizeof(&U::flow)] ) ;
>> +
>> + template <typename U>
>> + static double flowtest(...);
>> +
>> +public:
>> + static bool const value = (sizeof(test<SequenceTraits<T> >(0)) == 1)
>> + && (sizeof(flowtest<T>(0)) != 1);
>> +};
>> +
>> +
>> +// Test if SequenceTraits<T> is defined on type T
>> +// and SequenceTraits<T>::flow is defined.
>> +template <class T>
>> +struct has_FlowSequenceTraits
>> +{
>> + typedef size_t (*Signature_size)(class IO&, T&);
>> +
>> + template <typename U>
>> + static char test(SameType<Signature_size, &U::size>*);
>> +
>> + template <typename U>
>> + static double test(...);
>> +
>> + template <typename U> static
>> + char flowtest( char[sizeof(&U::flow)] ) ;
>> +
>> + template <typename U>
>> + static double flowtest(...);
>> +
>> +public:
>> + static bool const value = (sizeof(test<SequenceTraits<T> >(0)) == 1)
>> + && (sizeof(flowtest<T>(0)) == 1);
>> +};
>> +
>> +
>> +// Test if DocumentListTraits<T> is defined on type T
>> +template <class T>
>> +struct has_DocumentListTraits
>> +{
>> + typedef size_t (*Signature_size)(class IO&, T&);
>> +
>> + template <typename U>
>> + static char test(SameType<Signature_size, &U::size>*);
>> +
>> + template <typename U>
>> + static double test(...);
>> +
>> +public:
>> + static bool const value = (sizeof(test<DocumentListTraits<T> >(0)) ==
>> 1);
>> +};
>> +
>> +
>> +
>> +
>> +template<typename T>
>> +struct missingTraits : public llvm::integral_constant<bool,
>> +
>> !has_ScalarEnumerationTraits<T>::value
>> + &&
>> !has_ScalarBitSetTraits<T>::value
>> + && !has_ScalarTraits<T>::value
>> + && !has_MappingTraits<T>::value
>> + && !has_SequenceTraits<T>::value
>> + &&
>> !has_FlowSequenceTraits<T>::value
>> + &&
>> !has_DocumentListTraits<T>::value > {};
>> +
>> +
>> +// Base class for Input and Output.
>> +class IO {
>> +public:
>> +
>> + IO(void *Ctxt=NULL);
>> + virtual ~IO();
>> +
>> + virtual bool outputting() = 0;
>> +
>> + virtual unsigned beginSequence() = 0;
>> + virtual bool preflightElement(unsigned, void *&) = 0;
>> + virtual void postflightElement(void*) = 0;
>> + virtual void endSequence() = 0;
>> +
>> + virtual unsigned beginFlowSequence() = 0;
>> + virtual bool preflightFlowElement(unsigned, void *&) = 0;
>> + virtual void postflightFlowElement(void*) = 0;
>> + virtual void endFlowSequence() = 0;
>> +
>> + virtual void beginMapping() = 0;
>> + virtual void endMapping() = 0;
>> + virtual bool preflightKey(const char*, bool, bool, bool &, void *&) =
>> 0;
>> + virtual void postflightKey(void*) = 0;
>> +
>> + virtual void beginEnumScalar() = 0;
>> + virtual bool matchEnumScalar(const char*, bool) = 0;
>> + virtual void endEnumScalar() = 0;
>> +
>> + virtual bool beginBitSetScalar(bool &) = 0;
>> + virtual bool bitSetMatch(const char*, bool) = 0;
>> + virtual void endBitSetScalar() = 0;
>> +
>> + virtual void scalarString(StringRef &) = 0;
>> +
>> + virtual void setError(const Twine &) = 0;
>> +
>> + template <typename T>
>> + void enumCase(T &Val, const char* Str, const T ConstVal) {
>> + if ( matchEnumScalar(Str, (Val == ConstVal)) ) {
>> + Val = ConstVal;
>> + }
>> + }
>> +
>> + // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
>> + template <typename T>
>> + void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
>> + if ( matchEnumScalar(Str, (Val == static_cast<T>(ConstVal))) ) {
>> + Val = ConstVal;
>> + }
>> + }
>> +
>> + template <typename T>
>> + void bitSetCase(T &Val, const char* Str, const T ConstVal) {
>> + if ( bitSetMatch(Str, ((Val & ConstVal) == ConstVal)) ) {
>> + Val = Val | ConstVal;
>> + }
>> + }
>> +
>> + // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
>> + template <typename T>
>> + void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
>> + if ( bitSetMatch(Str, ((Val & ConstVal) == ConstVal)) ) {
>> + Val = Val | ConstVal;
>> + }
>> + }
>> +
>> + void *getContext();
>> + void setContext(void *);
>> +
>> + template <typename T>
>> + void mapRequired(const char* Key, T& Val) {
>> + this->processKey(Key, Val, true);
>> + }
>> +
>> + template <typename T>
>> + typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type
>> + mapOptional(const char* Key, T& Val) {
>> + // omit key/value instead of outputting empty sequence
>> + if ( this->outputting() && !(Val.begin() != Val.end()) )
>> + return;
>> + this->processKey(Key, Val, false);
>> + }
>> +
>> + template <typename T>
>> + typename llvm::enable_if_c<!has_SequenceTraits<T>::value,void>::type
>> + mapOptional(const char* Key, T& Val) {
>> + this->processKey(Key, Val, false);
>> + }
>> +
>> + template <typename T>
>> + void mapOptional(const char* Key, T& Val, const T& Default) {
>> + this->processKeyWithDefault(Key, Val, Default, false);
>> + }
>> +
>> +
>> +private:
>> + template <typename T>
>> + void processKeyWithDefault(const char *Key, T &Val, const T&
>> DefaultValue,
>> + bool
>> Required) {
>> + void *SaveInfo;
>> + bool UseDefault;
>> + const bool sameAsDefault = (Val == DefaultValue);
>> + if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
>> +
>> SaveInfo) ) {
>> + yamlize(*this, Val, Required);
>> + this->postflightKey(SaveInfo);
>> + }
>> + else {
>> + if ( UseDefault )
>> + Val = DefaultValue;
>> + }
>> + }
>> +
>> + template <typename T>
>> + void processKey(const char *Key, T &Val, bool Required) {
>> + void *SaveInfo;
>> + bool UseDefault;
>> + if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo)
>> ) {
>> + yamlize(*this, Val, Required);
>> + this->postflightKey(SaveInfo);
>> + }
>> + }
>> +
>> +private:
>> + void *Ctxt;
>> +};
>> +
>> +
>> +
>> +template<typename T>
>> +typename
>> llvm::enable_if_c<has_ScalarEnumerationTraits<T>::value,void>::type
>> +yamlize(IO &io, T &Val, bool) {
>> + io.beginEnumScalar();
>> + ScalarEnumerationTraits<T>::enumeration(io, Val);
>> + io.endEnumScalar();
>> +}
>> +
>> +template<typename T>
>> +typename llvm::enable_if_c<has_ScalarBitSetTraits<T>::value,void>::type
>> +yamlize(IO &io, T &Val, bool) {
>> + bool DoClear;
>> + if ( io.beginBitSetScalar(DoClear) ) {
>> + if ( DoClear )
>> + Val = static_cast<T>(0);
>> + ScalarBitSetTraits<T>::bitset(io, Val);
>> + io.endBitSetScalar();
>> + }
>> +}
>> +
>> +
>> +template<typename T>
>> +typename llvm::enable_if_c<has_ScalarTraits<T>::value,void>::type
>> +yamlize(IO &io, T &Val, bool) {
>> + if ( io.outputting() ) {
>> + std::string Storage;
>> + llvm::raw_string_ostream Buffer(Storage);
>> + ScalarTraits<T>::output(Val, io.getContext(), Buffer);
>> + StringRef Str = Buffer.str();
>> + io.scalarString(Str);
>> + }
>> + else {
>> + StringRef Str;
>> + io.scalarString(Str);
>> + StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
>> + if ( !Result.empty() ) {
>> + io.setError(llvm::Twine(Result));
>> + }
>> + }
>> +}
>> +
>> +
>> +template<typename T>
>> +typename llvm::enable_if_c<has_MappingTraits<T>::value, void>::type
>> +yamlize(IO &io, T &Val, bool) {
>> + io.beginMapping();
>> + MappingTraits<T>::mapping(io, Val);
>> + io.endMapping();
>> +}
>> +
>> +#ifndef BUILDING_YAMLIO
>> +template<typename T>
>> +typename llvm::enable_if_c<missingTraits<T>::value, void>::type
>> +yamlize(IO &io, T &Val, bool) {
>> + char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
>> +}
>> +#endif
>> +
>> +template<typename T>
>> +typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type
>> +yamlize(IO &io, T &Seq, bool) {
>> + unsigned incount = io.beginSequence();
>> + unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) :
>> incount;
>> + for(unsigned i=0; i < count; ++i) {
>> + void *SaveInfo;
>> + if ( io.preflightElement(i, SaveInfo) ) {
>> + yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
>> + io.postflightElement(SaveInfo);
>> + }
>> + }
>> + io.endSequence();
>> +}
>> +
>> +template<typename T>
>> +typename llvm::enable_if_c<has_FlowSequenceTraits<T>::value,void>::type
>> +yamlize(IO &io, T &Seq, bool) {
>> + unsigned incount = io.beginFlowSequence();
>> + unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) :
>> incount;
>> + for(unsigned i=0; i < count; ++i) {
>> + void *SaveInfo;
>> + if ( io.preflightFlowElement(i, SaveInfo) ) {
>> + yamlize(io, SequenceTraits<T>::element(io, Seq, i), true);
>> + io.postflightFlowElement(SaveInfo);
>> + }
>> + }
>> + io.endFlowSequence();
>> +}
>> +
>> +
>> +
>> +// Clients of YAML I/O only see declaration of the traits for built-in
>> +// types. The implementation is in the LLVM Support library. Without
>> +// this #ifdef, every client would get a copy of the implementation of
>> +// these traits.
>> +#ifndef BUILDING_YAMLIO
>> +template<>
>> +struct ScalarTraits<bool> {
>> + static void output(const bool &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, bool &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<StringRef> {
>> + static void output(const StringRef &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, StringRef &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<uint8_t> {
>> + static void output(const uint8_t &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, uint8_t &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<uint16_t> {
>> + static void output(const uint16_t &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, uint16_t &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<uint32_t> {
>> + static void output(const uint32_t &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, uint32_t &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<uint64_t> {
>> + static void output(const uint64_t &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, uint64_t &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<int8_t> {
>> + static void output(const int8_t &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, int8_t &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<int16_t> {
>> + static void output(const int16_t &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, int16_t &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<int32_t> {
>> + static void output(const int32_t &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, int32_t &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<int64_t> {
>> + static void output(const int64_t &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, int64_t &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<float> {
>> + static void output(const float &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, float &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<double> {
>> + static void output(const double &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, double &);
>> +};
>> +#endif
>> +
>> +
>> +
>> +// Utility for use within MappingTraits<>::mapping() method
>> +// to [de]normalize an object for use with YAML conversion.
>> +template <typename TNorm, typename TFinal>
>> +struct MappingNormalization {
>> + MappingNormalization(IO &i_o, TFinal &Obj)
>> + : io(i_o), BufPtr(NULL), Result(Obj) {
>> + if ( io.outputting() ) {
>> + BufPtr = new (&Buffer) TNorm(io, Obj);
>> + }
>> + else {
>> + BufPtr = new (&Buffer) TNorm(io);
>> + }
>> + }
>> +
>> + ~MappingNormalization() {
>> + if ( ! io.outputting() ) {
>> + Result = BufPtr->denormalize(io);
>> + }
>> + BufPtr->~TNorm();
>> + }
>> +
>> + TNorm* operator->() { return BufPtr; }
>> +
>> +private:
>> + typedef typename llvm::AlignedCharArrayUnion<TNorm> Storage;
>> +
>> + Storage Buffer;
>> + IO &io;
>> + TNorm *BufPtr;
>> + TFinal &Result;
>> +};
>> +
>> +
>> +
>> +// Utility for use within MappingTraits<>::mapping() method
>> +// to [de]normalize an object for use with YAML conversion.
>> +template <typename TNorm, typename TFinal>
>> +struct MappingNormalizationHeap {
>> + MappingNormalizationHeap(IO &i_o, TFinal &Obj)
>> + : io(i_o), BufPtr(NULL), Result(Obj) {
>> + if ( io.outputting() ) {
>> + BufPtr = new (&Buffer) TNorm(io, Obj);
>> + }
>> + else {
>> + BufPtr = new TNorm(io);
>> + }
>> + }
>> +
>> + ~MappingNormalizationHeap() {
>> + if ( io.outputting() ) {
>> + BufPtr->~TNorm();
>> + }
>> + else {
>> + Result = BufPtr->denormalize(io);
>> + }
>> + }
>> +
>> + TNorm* operator->() { return BufPtr; }
>> +
>> +private:
>> + typedef typename llvm::AlignedCharArrayUnion<TNorm> Storage;
>> +
>> + Storage Buffer;
>> + IO &io;
>> + TNorm *BufPtr;
>> + TFinal &Result;
>> +};
>> +
>> +
>> +
>> +///
>> +/// The Input class is used to parse a yaml document into in-memory
>> structs
>> +/// and vectors.
>> +///
>> +/// It works by using YAMLParser to do a syntax parse of the entire yaml
>> +/// document, then the Input class builds a graph of HNodes which wraps
>> +/// each yaml Node. The extra layer is buffering. The low level yaml
>> +/// parser only lets you look at each node once. The buffering layer
>> lets
>> +/// you search and interate multiple times. This is necessary because
>> +/// the mapRequired() method calls may not be in the same order
>> +/// as the keys in the document.
>> +///
>> +class Input : public IO {
>> +public:
>> + // Construct a yaml Input object from a StringRef and optional
>> user-data.
>> + Input(StringRef InputContent, void *Ctxt=NULL);
>> +
>> + // Check if there was an syntax or semantic error during parsing.
>> + llvm::error_code error();
>> +
>> + // To set alternate error reporting.
>> + void setDiagHandler(llvm::SourceMgr::DiagHandlerTy Handler, void *Ctxt
>> = 0);
>> +
>> +private:
>> + virtual bool outputting();
>> + virtual void beginMapping();
>> + virtual void endMapping();
>> + virtual bool preflightKey(const char *, bool, bool, bool &, void *&);
>> + virtual void postflightKey(void *);
>> + virtual unsigned beginSequence();
>> + virtual void endSequence();
>> + virtual bool preflightElement(unsigned index, void *&);
>> + virtual void postflightElement(void *);
>> + virtual unsigned beginFlowSequence();
>> + virtual bool preflightFlowElement(unsigned , void *&);
>> + virtual void postflightFlowElement(void *);
>> + virtual void endFlowSequence();
>> + virtual void beginEnumScalar();
>> + virtual bool matchEnumScalar(const char*, bool);
>> + virtual void endEnumScalar();
>> + virtual bool beginBitSetScalar(bool &);
>> + virtual bool bitSetMatch(const char *, bool );
>> + virtual void endBitSetScalar();
>> + virtual void scalarString(StringRef &);
>> + virtual void setError(const Twine &message);
>> +
>> + class HNode {
>> + public:
>> + HNode(Node *n) : _node(n) { }
>> + static inline bool classof(const HNode *) { return true; }
>> +
>> + Node *_node;
>> + };
>> +
>> + class EmptyHNode : public HNode {
>> + public:
>> + EmptyHNode(Node *n) : HNode(n) { }
>> + static inline bool classof(const HNode *n) {
>> + return NullNode::classof(n->_node);
>> + }
>> + static inline bool classof(const EmptyHNode *) { return true; }
>> + };
>> +
>> + class ScalarHNode : public HNode {
>> + public:
>> + ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
>> +
>> + StringRef value() const { return _value; }
>> +
>> + static inline bool classof(const HNode *n) {
>> + return ScalarNode::classof(n->_node);
>> + }
>> + static inline bool classof(const ScalarHNode *) { return true; }
>> + protected:
>> + StringRef _value;
>> + };
>> +
>> + class MapHNode : public HNode {
>> + public:
>> + MapHNode(Node *n) : HNode(n) { }
>> +
>> + static inline bool classof(const HNode *n) {
>> + return MappingNode::classof(n->_node);
>> + }
>> + static inline bool classof(const MapHNode *) { return true; }
>> +
>> + struct StrMappingInfo {
>> + static StringRef getEmptyKey() { return StringRef(); }
>> + static StringRef getTombstoneKey() { return StringRef(" ", 0); }
>> + static unsigned getHashValue(StringRef const val) {
>> + return
>> llvm::HashString(val); }
>> + static bool isEqual(StringRef const lhs,
>> + StringRef const rhs) { return lhs.equals(rhs);
>> }
>> + };
>> + typedef llvm::DenseMap<StringRef, HNode*, StrMappingInfo> NameToNode;
>> +
>> + bool isValidKey(StringRef key);
>> +
>> + NameToNode Mapping;
>> + llvm::SmallVector<const char*, 6> ValidKeys;
>> + };
>> +
>> + class SequenceHNode : public HNode {
>> + public:
>> + SequenceHNode(Node *n) : HNode(n) { }
>> +
>> + static inline bool classof(const HNode *n) {
>> + return SequenceNode::classof(n->_node);
>> + }
>> + static inline bool classof(const SequenceHNode *) { return true; }
>> +
>> + std::vector<HNode*> Entries;
>> + };
>> +
>> + Input::HNode *createHNodes(Node *node);
>> + void setError(HNode *hnode, const Twine &message);
>> + void setError(Node *node, const Twine &message);
>> +
>> +
>> +public:
>> + // These are only used by operator>>. They could be private
>> + // if those templated things could be made friends.
>> + bool setCurrentDocument();
>> + void nextDocument();
>> +
>> +private:
>> + llvm::yaml::Stream *Strm;
>> + llvm::SourceMgr SrcMgr;
>> + llvm::error_code EC;
>> + llvm::BumpPtrAllocator Allocator;
>> + llvm::yaml::document_iterator DocIterator;
>> + std::vector<bool> BitValuesUsed;
>> + HNode *CurrentNode;
>> + bool ScalarMatchFound;
>> +};
>> +
>> +
>> +
>> +
>> +///
>> +/// The Output class is used to generate a yaml document from in-memory
>> structs
>> +/// and vectors.
>> +///
>> +class Output : public IO {
>> +public:
>> + Output(llvm::raw_ostream &, void *Ctxt=NULL);
>> + virtual ~Output();
>> +
>> + virtual bool outputting();
>> + virtual void beginMapping();
>> + virtual void endMapping();
>> + virtual bool preflightKey(const char *key, bool, bool, bool &, void
>> *&);
>> + virtual void postflightKey(void *);
>> + virtual unsigned beginSequence();
>> + virtual void endSequence();
>> + virtual bool preflightElement(unsigned, void *&);
>> + virtual void postflightElement(void *);
>> + virtual unsigned beginFlowSequence();
>> + virtual bool preflightFlowElement(unsigned, void *&);
>> + virtual void postflightFlowElement(void *);
>> + virtual void endFlowSequence();
>> + virtual void beginEnumScalar();
>> + virtual bool matchEnumScalar(const char*, bool);
>> + virtual void endEnumScalar();
>> + virtual bool beginBitSetScalar(bool &);
>> + virtual bool bitSetMatch(const char *, bool );
>> + virtual void endBitSetScalar();
>> + virtual void scalarString(StringRef &);
>> + virtual void setError(const Twine &message);
>> +
>> +public:
>> + // These are only used by operator<<. They could be private
>> + // if that templated operator could be made a friend.
>> + void beginDocuments();
>> + bool preflightDocument(unsigned);
>> + void postflightDocument();
>> + void endDocuments();
>> +
>> +private:
>> + void output(StringRef s);
>> + void outputUpToEndOfLine(StringRef s);
>> + void newLineCheck();
>> + void outputNewLine();
>> + void paddedKey(StringRef key);
>> +
>> + enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey };
>> +
>> + llvm::raw_ostream &Out;
>> + SmallVector<InState, 8> StateStack;
>> + int Column;
>> + int ColumnAtFlowStart;
>> + bool NeedBitValueComma;
>> + bool NeedFlowSequenceComma;
>> + bool EnumerationMatchFound;
>> + bool NeedsNewLine;
>> +};
>> +
>> +
>> +
>> +
>> +/// YAML I/O does conversion based on types. But often native data types
>> +/// are just a typedef of built in intergral types (e.g. int). But the
>> C++
>> +/// type matching system sees through the typedef and all the typedefed
>> types
>> +/// look like a built in type. This will cause the generic YAML I/O
>> conversion
>> +/// to be used. To provide better control over the YAML conversion, you
>> can
>> +/// use this macro instead of typedef. It will create a class with one
>> field
>> +/// and automatic conversion operators to and from the base type.
>> +/// Based on BOOST_STRONG_TYPEDEF
>> +#define LLVM_YAML_STRONG_TYPEDEF(_base, _type)
>> \
>> + struct _type {
>> \
>> + _type() { }
>> \
>> + _type(const _base v) : value(v) { }
>> \
>> + _type(const _type &v) : value(v.value) {}
>> \
>> + _type &operator=(const _type &rhs) { value = rhs.value; return
>> *this; }\
>> + _type &operator=(const _base &rhs) { value = rhs; return *this;
>> } \
>> + operator const _base & () const { return value; }
>> \
>> + bool operator==(const _type &rhs) const { return value ==
>> rhs.value; } \
>> + bool operator==(const _base &rhs) const { return value == rhs; }
>> \
>> + bool operator<(const _type &rhs) const { return value <
>> rhs.value; } \
>> + _base value;
>> \
>> + };
>> +
>> +
>> +
>> +///
>> +/// Use these types instead of uintXX_t in any mapping to have
>> +/// its yaml output formatted as hexadecimal.
>> +///
>> +LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
>> +LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
>> +LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
>> +LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
>> +
>> +
>> +// Clients of YAML I/O only see declaration of the traits for Hex*
>> +// types. The implementation is in the LLVM Support library. Without
>> +// this #ifdef, every client would get a copy of the implementation of
>> +// these traits.
>> +#ifndef BUILDING_YAMLIO
>> +template<>
>> +struct ScalarTraits<Hex8> {
>> + static void output(const Hex8 &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, Hex8 &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<Hex16> {
>> + static void output(const Hex16 &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, Hex16 &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<Hex32> {
>> + static void output(const Hex32 &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, Hex32 &);
>> +};
>> +
>> +template<>
>> +struct ScalarTraits<Hex64> {
>> + static void output(const Hex64 &, void*, llvm::raw_ostream &);
>> + static llvm::StringRef input(llvm::StringRef , void*, Hex64 &);
>> +};
>> +#endif
>> +
>> +
>> +// Define non-member operator>> so that Input can stream in a document
>> list.
>> +template <typename T>
>> +inline
>> +typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Input
>> &>::type
>> +operator>>(Input &yin, T &docList) {
>> + int i = 0;
>> + while ( yin.setCurrentDocument() ) {
>> + yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true);
>> + if ( yin.error() )
>> + return yin;
>> + yin.nextDocument();
>> + ++i;
>> + }
>> + return yin;
>> +}
>> +
>> +// Define non-member operator>> so that Input can stream in a map as a
>> document.
>> +template <typename T>
>> +inline
>> +typename llvm::enable_if_c<has_MappingTraits<T>::value,Input &>::type
>> +operator>>(Input &yin, T &docMap) {
>> + yin.setCurrentDocument();
>> + yamlize(yin, docMap, true);
>> + return yin;
>> +}
>> +
>> +// Define non-member operator>> so that Input can stream in a sequence as
>> +// a document.
>> +template <typename T>
>> +inline
>> +typename llvm::enable_if_c<has_SequenceTraits<T>::value,Input &>::type
>> +operator>>(Input &yin, T &docSeq) {
>> + yin.setCurrentDocument();
>> + yamlize(yin, docSeq, true);
>> + return yin;
>> +}
>> +
>> +#ifndef BUILDING_YAMLIO
>> +// Provide better error message about types missing a trait
>> specialization
>> +template <typename T>
>> +inline
>> +typename llvm::enable_if_c<missingTraits<T>::value,Input &>::type
>> +operator>>(Input &yin, T &docSeq) {
>> + char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
>> + return yin;
>> +}
>> +#endif
>> +
>> +
>> +// Define non-member operator<< so that Output can stream out document
>> list.
>> +template <typename T>
>> +inline
>> +typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Output
>> &>::type
>> +operator<<(Output &yout, T &docList) {
>> + yout.beginDocuments();
>> + const size_t count = DocumentListTraits<T>::size(yout, docList);
>> + for(size_t i=0; i < count; ++i) {
>> + if ( yout.preflightDocument(i) ) {
>> + yamlize(yout, DocumentListTraits<T>::element(yout, docList, i),
>> true);
>> + yout.postflightDocument();
>> + }
>> + }
>> + yout.endDocuments();
>> + return yout;
>> +}
>> +
>> +// Define non-member operator<< so that Output can stream out a map.
>> +template <typename T>
>> +inline
>> +typename llvm::enable_if_c<has_MappingTraits<T>::value,Output &>::type
>> +operator<<(Output &yout, T &map) {
>> + yout.beginDocuments();
>> + if ( yout.preflightDocument(0) ) {
>> + yamlize(yout, map, true);
>> + yout.postflightDocument();
>> + }
>> + yout.endDocuments();
>> + return yout;
>> +}
>> +
>> +// Define non-member operator<< so that Output can stream out a sequence.
>> +template <typename T>
>> +inline
>> +typename llvm::enable_if_c<has_SequenceTraits<T>::value,Output &>::type
>> +operator<<(Output &yout, T &seq) {
>> + yout.beginDocuments();
>> + if ( yout.preflightDocument(0) ) {
>> + yamlize(yout, seq, true);
>> + yout.postflightDocument();
>> + }
>> + yout.endDocuments();
>> + return yout;
>> +}
>> +
>> +#ifndef BUILDING_YAMLIO
>> +// Provide better error message about types missing a trait
>> specialization
>> +template <typename T>
>> +inline
>> +typename llvm::enable_if_c<missingTraits<T>::value,Output &>::type
>> +operator<<(Output &yout, T &seq) {
>> + char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
>> + return yout;
>> +}
>> +#endif
>> +
>> +
>> +} // namespace yaml
>> +} // namespace llvm
>> +
>> +
>> +/// Utility for declaring that a std::vector of a particular type
>> +/// should be considered a YAML sequence.
>> +#define LLVM_YAML_IS_SEQUENCE_VECTOR(_type)
>> \
>> + namespace llvm {
>> \
>> + namespace yaml {
>> \
>> + template<>
>> \
>> + struct SequenceTraits< std::vector<_type> > {
>> \
>> + static size_t size(IO &io, std::vector<_type> &seq) {
>> \
>> + return seq.size();
>> \
>> + }
>> \
>> + static _type& element(IO &io, std::vector<_type> &seq, size_t
>> index) {\
>> + if ( index >= seq.size() )
>> \
>> + seq.resize(index+1);
>> \
>> + return seq[index];
>> \
>> + }
>> \
>> + };
>> \
>> + }
>> \
>> + }
>> +
>> +/// Utility for declaring that a std::vector of a particular type
>> +/// should be considered a YAML flow sequence.
>> +#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type)
>> \
>> + namespace llvm {
>> \
>> + namespace yaml {
>> \
>> + template<>
>> \
>> + struct SequenceTraits< std::vector<_type> > {
>> \
>> + static size_t size(IO &io, std::vector<_type> &seq) {
>> \
>> + return seq.size();
>> \
>> + }
>> \
>> + static _type& element(IO &io, std::vector<_type> &seq, size_t
>> index) {\
>> + if ( index >= seq.size() )
>> \
>> + seq.resize(index+1);
>> \
>> + return seq[index];
>> \
>> + }
>> \
>> + static const bool flow = true;
>> \
>> + };
>> \
>> + }
>> \
>> + }
>> +
>> +/// Utility for declaring that a std::vector of a particular type
>> +/// should be considered a YAML document list.
>> +#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type)
>> \
>> + namespace llvm {
>> \
>> + namespace yaml {
>> \
>> + template<>
>> \
>> + struct DocumentListTraits< std::vector<_type> > {
>> \
>> + static size_t size(IO &io, std::vector<_type> &seq) {
>> \
>> + return seq.size();
>> \
>> + }
>> \
>> + static _type& element(IO &io, std::vector<_type> &seq, size_t
>> index) {\
>> + if ( index >= seq.size() )
>> \
>> + seq.resize(index+1);
>> \
>> + return seq[index];
>> \
>> + }
>> \
>> + };
>> \
>> + }
>> \
>> + }
>> +
>> +
>> +
>> +#endif // LLVM_YAML_TRAITS_H_
>>
>> Modified: llvm/trunk/lib/Support/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CMakeLists.txt?rev=170019&r1=170018&r2=170019&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Support/CMakeLists.txt (original)
>> +++ llvm/trunk/lib/Support/CMakeLists.txt Wed Dec 12 14:46:15 2012
>> @@ -50,6 +50,7 @@
>> Triple.cpp
>> Twine.cpp
>> YAMLParser.cpp
>> + YAMLTraits.cpp
>> raw_os_ostream.cpp
>> raw_ostream.cpp
>> regcomp.c
>>
>> Added: llvm/trunk/lib/Support/YAMLTraits.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/YAMLTraits.cpp?rev=170019&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Support/YAMLTraits.cpp (added)
>> +++ llvm/trunk/lib/Support/YAMLTraits.cpp Wed Dec 12 14:46:15 2012
>> @@ -0,0 +1,881 @@
>> +//===- lib/Support/YAMLTraits.cpp
>> -----------------------------------------===//
>> +//
>> +// The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#define BUILDING_YAMLIO
>> +#include "llvm/Support/YAMLTraits.h"
>> +
>> +#include "llvm/ADT/Twine.h"
>> +#include "llvm/Support/Casting.h"
>> +#include "llvm/Support/ErrorHandling.h"
>> +#in
>
> ...
>
> [Message clipped]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130106/908175c0/attachment.html>
More information about the llvm-commits
mailing list