Introduction

While it may not be intuitive and unlike general-purpose object-oriented languages such as C++ and Java, we can, in fact, do object-oriented programming in R. For starters, everything in R is an object: vectors are objects, functions are objects, data frame are objects. However, this tutorial attempts to clarify how to create user-defined objects with attributes and methods.

In a generic sense, an object is an abstract data structure containing attributes, and defining methods which process the attributes. A class can be thought of as a blueprint for the objects, defining the structure and definition of the attributes. An object is an instance of a class. The process of creating a new object from a class definition is generally called instantiation.

While most programming languages have a single mechanism for defining classes, R has actually three class systems: S3, S4 and the more recent Reference class system. Each has their own features and peculiarities. Choosing which to use is mostly a matter of personal preference.

S3 Class System

An S3 class is simple but somewhat primitive in nature. It lacks a formal definition of the class and instances of this class are created by simply by adding a class attribute to a list object. This simplicity is one of the reasons that it is widely used by R programmers. In fact, most of the R built-in classes are S3 classes.

S4 Class System

The S4 class system is stricter in the sense that it has a formal way to define classes and a uniform way to instantiate objects. This makes the process safer, more like object-oriented languages, and prevents programmers from defining objects incorrectly.

Reference Class System

The Reference class system in R is similar to the object-oriented programming structures common languages like C++, Java, Python, etc. Unlike S3 and S4 classes, methods belong to a class rather than being definitions of pre-defined generic functions. Reference classes are internally implemented as S4 classes with an environment surrounding them.

The remainder of this lesson will focus on reference classes.

Defining a Reference Class

Defining a reference class is done with the setRefClass() function.

Member variables (attributes) of a reference class must be included as part of the class definition. Member variables of reference class are referred to as fields. Fields are called member variables in C++, attributes in Java, and slots in ontology definitions.

The code below defines a class Instructor with three fields.

Instructor <- setRefClass("Instructor", 
                          fields = list(iid="numeric", 
                                        name="character", 
                                        rank="character")
                          )

Instantiating a Reference Class

Instantiating an object means that we allocate a chunk of memory to hold all the fields of the object. There are two ways in which we can instantiate a new instance of a reference class. Using the name of the reference as shown below, or by using the new operator if we have a method initialize in our reference class definition – we will not show the latter approach just yet.

Instantiating an object means creating an instance of the class and allocating memory for its fields. So, the terminology instance, instance of a class, and object are used interchangeably.

Instantiation is done with the name of the class used an a generator function as demonstrated below.

i <- Instructor(iid = 1, name = 'Jeff Alden', rank = 'FT-Associate')

The code above creates an instance of the class “Instructor”, or, said another way, it allocates an object of type “Instructor”. Since the class “Instructor” has three fields (iid, name, and rank) we need to supply their default values. Instantiation means allocation of memory. In this case R allocates memory for a number (iid) and memory for each of the character strings. Upon completion of the memory allocation, we get back a reference to the object (i.e., a “pointer” or “link” to the block of memory where the object was allocated). We must keep track of that reference to be able to do something with the object or call any of its methods.

print(i)
## Reference class object of class "Instructor"
## Field "iid":
## [1] 1
## Field "name":
## [1] "Jeff Alden"
## Field "rank":
## [1] "FT-Associate"

Accessing Fields

Similar to S3 classes, fields are accessed with the $ operator. They can also be modified that way. There is no notion of “private” fields or methods like there are in Java and C++. All members (fields and methods) are “public” in an R reference class object.

i <- Instructor(iid = 1, name = 'Jeff Alden', rank = 'FT-Associate')

# read a field's value
n <- i$name

# update a field's value
i$name <- 'Jeffrey Alden'

Objects are References

When instantiating a reference object, R generates an internal object in memory and returns a reference to the object (hence the name). So, assigning an object to another actually assigns the reference and does not make a copy. In the code below, i1 and i2 are references to the same object. This is similar to Java but unlike C++ when a copy constructor is defined.

i1 <- Instructor(iid = 1, name = 'Jeff Alden', rank = 'FT-Associate')
i2 <- i1

i2$name <- 'Xin Wang'

print(i1)
## Reference class object of class "Instructor"
## Field "iid":
## [1] 1
## Field "name":
## [1] "Xin Wang"
## Field "rank":
## [1] "FT-Associate"

In the code above, we create a new instance of the class Instructor and get a reference back which we store in the variable i1. We then assign i1 to i2 – but we are actually assigning the reference (or a pointer to) the object. Think of i1 being the location in memory where the object is stored. Any modification of the memory through the reference i2 modifies the same object that is pointed to by i1. So, caution…

To make an actual copy, use the inherited method copy().

i1 <- Instructor(iid = 1, name = 'Jeff Alden', rank = 'FT-Associate')

i2 <- i1$copy()

# modifying i2 does not modify i1
i2$name <- 'Susan Wollaston'

print(i1)
## Reference class object of class "Instructor"
## Field "iid":
## [1] 1
## Field "name":
## [1] "Jeff Alden"
## Field "rank":
## [1] "FT-Associate"

Defining Methods

All reference classes have a set of predefined methods inherited from the superclass envRefClass. This is similar to all Java classes being subclasses of the Object class.

New methods can be added inline in the separate list methods.

Notice the operator <<- used to access fields within a method. Using the simple assignment operator <- would have created a local variable called salary, which would lead to different behavior. Fortunately, R will issue a warning in such a case.

Also note the , after the } to separate the method function definitions.

Instructor <- setRefClass("Instructor", 
                          fields = list(iid="numeric", 
                                        name="character", 
                                        rank="character",
                                        salary="numeric"
                                        ),
                          methods = list(
                            getMonthlySalary = function() {
                              return (salary / 12)
                            },
                            
                            applyRaise = function(merit) {
                              salary <<- salary * (1 + merit)
                            }
                          ))

To make it clearer to the reader of our code when we access a field within a method and to avoid clashes when the name of a field is the same as the name of an argument to a method or a local variable, we can use .self which is a reference to the object on which the method is called. This is equivalent to the this pointer in Java and C++. The code below demonstrates this alternative.

Instructor <- setRefClass("Instructor", 
                          fields = list(iid="numeric", 
                                        name="character", 
                                        rank="character",
                                        salary="numeric"
                                        ),
                          methods = list(
                            getMonthlySalary = function() {
                              return (.self$salary / 12)
                            },
                            
                            applyRaise = function(merit) {
                              .self$salary <- .self$salary * (1 + merit)
                            }
                          ))

Here is what we mean by .self being a reference to the object on which the method is called. Consider the code fragment below where we instantiate two instances (objects) of “Instructor” and assign their references to two variables in this context: i and f. So, i is a reference to a block of memory that contains the fields {11, ‘Kaleb Ahmad’, ‘FT-Associate’} and f is a reference to a block of memory that contains the fields {476, ‘Leena Patel’, ‘PT’}. Remember that instantiation means allocation of memory for the object.

When we then call i$getMonthlySalary(), we call the method getMonthlySalary() on the object references by i and therefore inside of the function getMonthlySalary(), .self refers to the block of memory pointed at by i. So, .self$name would be ‘Kaleb Ahmad’. If we had called f$getMonthlySalary(), then .self$name would be ‘Leena Patel’ within getMonthlySalary(). So, .self within a method of an object is a always reference to the object on which the method is called.

The variable .self is automatically created and always initialized to be a reference to the object on which the method is called.

i <- Instructor(iid = 11, name = 'Kaleb Ahmad', 
                rank = 'FT-Associate', salary = 200000)
f <- Instructor(iid = 476, name = 'Leena Patel', 
                rank = 'PT', salary = 68000)

i$getMonthlySalary()
## [1] 16666.67

Accessing Methods

Methods are accessed the same way as fields – with the $ operator.

i <- Instructor(iid = 2, name = 'Dua Dipa', rank = 'T-Assistant', salary = 128000)

m.bef <- i$getMonthlySalary()
i$applyRaise(0.045)

m.aft <- i$getMonthlySalary()

cat("Salary raised from $", m.bef, "to $", m.aft, "per month")
## Salary raised from $ 10666.67 to $ 11146.67 per month

Inheritance

Inheritance is a key mechanism in object-oriented programming. It allows a programmer to define a new class (subclass or derived class) from an existing classes (superclass or base class). Derived classes can add new fields and methods. All fields and methods of the base class are automatically fields and methods of the derived class. This increases reusability of code and allows programmers to represent domain objects more accurately.

Inheritance is supported in all three class systems but is more like other object-oriented languages in the Reference class system. We will restrict ourselves to this class system.

In the example below, we have a base class Person with three fields and a method. We then define a derived class Instructor which extends Person with two additional fields and two methods by adding the base class Person name to the contains argument.

Person <- setRefClass("Person", 
                      fields = list(pid="numeric", 
                                    name="character",
                                    yob = "numeric"),
                      methods = list(
                        getAge = function() {
                          currYear <- as.numeric(format(Sys.time(), "%Y"))
                          return (currYear - yob)
                        }
                      ))

Instructor <- setRefClass("Instructor", 
                      contains = "Person",
                      fields = list(rank="character",
                                    salary="numeric"
                      ),
                      methods = list(
                        getMonthlySalary = function() {
                          return (salary / 12)
                        },
                        
                        applyRaise = function(merit) {
                          salary <<- salary * (1 + merit)
                        }
                      ))

We can then instantiate the derived class Instructor and find that it has all of the fields and methods of Person in addition to its additional fields and methods.

anInstructor <- Instructor(pid = 100, 
                           name = 'Raj Metha', 
                           rank = 'FT-Full',
                           yob = 1968,
                           salary = 182972)

anInstructor$getMonthlySalary()
## [1] 15247.67
anInstructor$getAge()
## [1] 56

Object Aggregation

In an aggregation relationship between objects, there is a whole/part or container/part hierarchy. In ontology terms, there is a partonomy. In an aggregation, one object “contains” other objects, although the containment does not have to be “physical”, i.e., the part objects do not have to be part of the same memory structure. The whole/part relationship can be by reference where the container object (whole or aggregate) contains references to the contained (part) objects.

Let’s implement the part hierarchy expressed by the UML Class Diagram below:

Member <- setRefClass("Member", fields = list(
  mID = "numeric", 
  name = "character",
  yearJoined = "numeric"))

Club <- setRefClass("Club", fields = list(
  name = "character",
  yearFounded = "numeric",
  maxMemID = "numeric",
  members = "list"),
                    
  methods = list(
    getNumMembers = function() {
      return (length(members))
    },
    
    addMember = function(m) {
      if (is.null(members))
          members <<- list(1024)
      
      # add a member ID for the new member
      m$mID <- maxMemID + 1
      maxMemID <<- maxMemID + 1
      
      # add the member to internal list
      members[[length(members)+1]] <<- m
      
      return (1)
    }
  ))

A few noteworthy points about the above code. The field members is a “private” member variable that keeps track of all of the members added to the club. It is an empty list when created, so right before the first member is added it must be allocated.

Now that we have the classes defined, let’s create some sample instances for testing. We won’t set a member ID for new members as those are assigned to them when they get added to the club.

# create a Club
aClub <- Club(name = 'DATA Club', 
              yearFounded = 2015,
              maxMemID = 0)

# create a few members and add them to the club
s <- aClub$addMember(
  Member(name = 'Jeff Garol', yearJoined = 2022))

s <- aClub$addMember(
  Member(name = 'Ursula Van Leiden', yearJoined = 2022))

s <- aClub$addMember(
  Member(name = 'Garrett Liew', yearJoined = 2022))

# number of club members should be correct
aClub$getNumMembers()
## [1] 3

Accessing Fields

Fields are instance variables; they have a value for each instance. For example, let’s initialize two instances of the class Club and let’s add them to a list so we have a way of keeping track of all the clubs – of course creating an aggregation class would be even better, perhaps calling that class Clubs. But, for now, we’ll just build a “free” list, in other words, a list that exists outside of any class:

# our list of clubs
clubs <- list(0)

# create club and add it to our list of clubs
clubs[[1]] <- Club(name = 'Volleyball Club', 
              yearFounded = 1997,
              maxMemID = 0)

# create club and add it to our list of clubs
clubs[[2]] <- Club(name = 'Tech Club', 
              yearFounded = 2018,
              maxMemID = 0)

# let's add a member to one of the clubs
clubs[[1]]$addMember(
  Member(name = 'Lesley Walter', yearJoined = 2020))
## [1] 1

Let’s inspect more closely what happens when we call a member function, i.e., when we call clubs[[1]]$addMember(Member(name = 'Lesley Walter', yearJoined = 2020)). The method addMember() is passed an instance of the class Member as an argument. To understand what occurs, let’s look at the code for that function by itself.

...

addMember = function(m) {
  if (is.null(members))
      members <<- list(1024)
  
  # add a member ID for the new member
  m$mID <- maxMemID + 1
  maxMemID <<- maxMemID + 1
  
  # add the member to internal list
  members[[length(members)+1]] <<- m
  
  return (1)
}

...

So, for the call clubs[[1]]$addMember(Member(name = 'Lesley Walter', yearJoined = 2020)), the object on which addMember() is called is clubs[[1]]. So, within the function addMember(), when referring to a field of the class Club, we refer to the values of those fields for the instance clubs[[1]]. To review, here is the code that created that instance of the club:

clubs[[1]] <- Club(name = 'Volleyball Club', 
              yearFounded = 1997,
              maxMemID = 0)

So, within addMember() for the call clubs[[1]]$addMember(Member(name = 'Lesley Walter', yearJoined = 2020)), maxMemberID would have the value 0 and yearFounded would be 1997. So, referring to those variables within addMember() would refer to those instance variables.

The .self Reference

.self is a pre-defined variable that refers to the object on which a method is called. So, if you called method M on an instance c of the class C having field X, then when calling c$M(), .self would be a reference to c. Notice the dot prefix. To refer to the field X of the instance on which you are calling a method, would be .self$X within a method. This is useful if you need to access a field that is “hidden” because you either have a parameter to the method M that called X or a local variable with M that is called X. Alternatively, programmers often use .self$X when referring to the field X to make it clear to the reader of the code that they intend to access a field rather than a local variable or an argument – it adds to code clarity.

We could therefore rewrite the code for addMember() using .self as follows:

...

addMember = function(m) {
  if (is.null(.self$members))
      .self$members <<- list(1024)
  
  # add a member ID for the new member
  m$mID <- .self$maxMemID + 1
  maxMemID <<- .self$maxMemID + 1
  
  # add the member to internal list
  .self$members[[length(.self$members)+1]] <- m
  
  return (1)
}

...

Instantiation with new

This section presents an alternative way to instantiate and initialize a reference class object. It is more like those mechanisms found in object-oriented languages like Java.

Initialization refers to the process of setting up an object when it is created. In the reference class system in R, this is done by defining an initialize method for a class. The initialize method is called automatically when a new object of the class is created, and it takes care of setting up the object’s internal state. In Java and C++, this function is referred to as the constructor.

For example, you might use the initialize method to set the initial values or attributes, load an object’s state from an external file or a database, or perform any other kind of initialization.

The example below adds an initialize method to our previous class Member and shows how that method is automatically invoked. Note that we now need to call the implicitly defined function new to instantiate an object.

Member <- setRefClass("Member", 
                      fields = list(
                        mID = "numeric", 
                        name = "character",
                        yearJoined = "numeric"),
                      
                      methods = list(
                        initialize = function(name, year) {
                          .self$name <- name
                          .self$yearJoined <- year
                        }
                      ))


# create an instance with implicit initialization
aMember <- Member$new('Liz Chao', 2023)

In this example, the initialize method takes two arguments, name and year, which are used to initialize the name and yearJoined fields of the object, respectively. When a new object of the class is created with new, the initialize() method is called automatically and the fields are initialized accordingly.

Tutorial I: Classes, Objects, and Instantiation

After having read the lesson above, watch the tutorial and revisit the various sections of the lesson and try the code yourself.

Container Objects

A container object, also known as a collection object, is a type of object that holds a collection of other objects.

In object-oriented programming, a container object is an object that is used to store and manage other objects. The idea behind a container object is to provide a convenient and efficient way of grouping and organizing related objects.

They are necessary for storing instances of classes as there are no “natural” containers. In the previous example, a Club object acted as a container for all Member objects. But what if we had more than one Club object? Who would keep track of all of those objects? Naturally, we could use a vector to store them – or, we could build a container class and create an instance of that class as a container object. The class would then have the usual methods of adding an object, removing an object, counting the objects, and finding objects based on different criteria. Some containers also provide iterators to iterate over the elements stored in the container.

Using container objects can be beneficial in several ways:

  • Abstraction: By using a container object, you can abstract away the details of how the elements are stored and manipulated, making your code more readable and easier to maintain.

  • Encapsulation: Container objects encapsulate the elements they contain, hiding their implementation details and making it easier to change the underlying implementation without affecting the rest of the code.

  • Reusability: Container objects can be used as building blocks in larger systems, allowing for code reuse and reducing duplication.

  • Performance: Container objects can often provide optimized implementations for common operations, such as adding or removing elements, making them more efficient than using basic data structures like vectors or lists.

Overall, container objects are a key aspect of object-oriented programming and can help to simplify and optimize the development of complex systems. They are necessary in all object-oriented programming languages, including Java and C++, and not just R.

Tutorial II: Object Aggregation & Container Objects

Conclusion

Object-orientation is a common way to create abstraction and structure complex information. While R is not a fully object-oriented language, many of the information abstraction mechanisms provided by classes, objects, and methods are supported by R, albeit in a way that may be unfamiliar to programmers coming to R from C++, Java, or similar languages. Unlike other languages, R has three distinct ways in which to define classes and objects, with the Reference Classes being the most similar to other object-oriented languages.


Files & Resources

All Files for Lesson 6.122

Errata

Let us know.

LS0tCnRpdGxlOiAiUmVmZXJlbmNlIENsYXNzZXMsIE9iamVjdHMsIGFuZCBNZXRob2RzIGluIFIiCnBhcmFtczoKICBjYXRlZ29yeTogNgogIG51bWJlcjogMTIyCiAgdGltZTogNDUKICBsZXZlbDogaW50ZXJtZWRpYXRlCiAgdGFnczogInIscHJpbWVyLG9iamVjdHMsbGlzdHMscmVmZXJlbmNlIGNsYXNzLGNsYXNzLG9vcCIKICBkZXNjcmlwdGlvbjogIlRoaXMgbGVzc29ucyBleHBsb3JlcyBvYmplY3QtYmFzZWQgcHJvZ3JhbW1pbmcgaW4gUiBhbmQgCiAgICAgICAgICAgICAgICBkZW1vbnN0cmF0ZXMgaG93IHRvIGRlZmluZSBjbGFzc2VzIHVzaW5nIHRoZSBSZWZlcmVuY2UgQ2xhc3MgU3lzdGVtLAogICAgICAgICAgICAgICAgb25lIG9mIHRocmVlIG9iamVjdC1vcmllbnRlZCBjbGFzcyBzeXN0ZW1zIGF2YWlsYWJsZSBpbiBSLiIKZGF0ZTogIjxzbWFsbD5gciBTeXMuRGF0ZSgpYDwvc21hbGw+IgphdXRob3I6ICI8c21hbGw+TWFydGluIFNjaGVkbGJhdWVyPC9zbWFsbD4iCmVtYWlsOiAibS5zY2hlZGxiYXVlckBuZXUuZWR1IgphZmZpbGl0YXRpb246ICJOb3J0aGVhc3Rlcm4gVW5pdmVyc2l0eSIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29sbGFwc2VkOiBmYWxzZQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IHNwYWNlbGFiCiAgICBoaWdobGlnaHQ6IHRhbmdvCi0tLQoKLS0tCnRpdGxlOiAiPHNtYWxsPmByIHBhcmFtcyRjYXRlZ29yeWAuYHIgcGFyYW1zJG51bWJlcmA8L3NtYWxsPjxici8+PHNwYW4gc3R5bGU9J2NvbG9yOiAjMkU0MDUzOyBmb250LXNpemU6IDAuOWVtJz5gciBybWFya2Rvd246Om1ldGFkYXRhJHRpdGxlYDwvc3Bhbj4iCi0tLQoKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2luc2VydDJEQi5SJykpLCBpbmNsdWRlID0gRkFMU0V9CmBgYAoKIyMgSW50cm9kdWN0aW9uCgpXaGlsZSBpdCBtYXkgbm90IGJlIGludHVpdGl2ZSBhbmQgdW5saWtlIGdlbmVyYWwtcHVycG9zZSBvYmplY3Qtb3JpZW50ZWQgbGFuZ3VhZ2VzIHN1Y2ggYXMgQysrIGFuZCBKYXZhLCB3ZSBjYW4sIGluIGZhY3QsIGRvIG9iamVjdC1vcmllbnRlZCBwcm9ncmFtbWluZyBpbiBSLiBGb3Igc3RhcnRlcnMsIGV2ZXJ5dGhpbmcgaW4gUiBpcyBhbiBvYmplY3Q6IHZlY3RvcnMgYXJlIG9iamVjdHMsIGZ1bmN0aW9ucyBhcmUgb2JqZWN0cywgZGF0YSBmcmFtZSBhcmUgb2JqZWN0cy4gSG93ZXZlciwgdGhpcyB0dXRvcmlhbCBhdHRlbXB0cyB0byBjbGFyaWZ5IGhvdyB0byBjcmVhdGUgdXNlci1kZWZpbmVkIG9iamVjdHMgd2l0aCBhdHRyaWJ1dGVzIGFuZCBtZXRob2RzLgoKSW4gYSBnZW5lcmljIHNlbnNlLCBhbiBvYmplY3QgaXMgYW4gYWJzdHJhY3QgZGF0YSBzdHJ1Y3R1cmUgY29udGFpbmluZyBhdHRyaWJ1dGVzLCBhbmQgZGVmaW5pbmcgbWV0aG9kcyB3aGljaCBwcm9jZXNzIHRoZSBhdHRyaWJ1dGVzLiBBIGNsYXNzIGNhbiBiZSB0aG91Z2h0IG9mIGFzIGEgYmx1ZXByaW50IGZvciB0aGUgb2JqZWN0cywgZGVmaW5pbmcgdGhlIHN0cnVjdHVyZSBhbmQgZGVmaW5pdGlvbiBvZiB0aGUgYXR0cmlidXRlcy4gQW4gb2JqZWN0IGlzIGFuIGluc3RhbmNlIG9mIGEgY2xhc3MuIFRoZSBwcm9jZXNzIG9mIGNyZWF0aW5nIGEgbmV3IG9iamVjdCBmcm9tIGEgY2xhc3MgZGVmaW5pdGlvbiBpcyBnZW5lcmFsbHkgY2FsbGVkICppbnN0YW50aWF0aW9uKi4KCldoaWxlIG1vc3QgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGhhdmUgYSBzaW5nbGUgbWVjaGFuaXNtIGZvciBkZWZpbmluZyBjbGFzc2VzLCBSIGhhcyBhY3R1YWxseSB0aHJlZSBjbGFzcyBzeXN0ZW1zOiAqUzMqLCAqUzQqIGFuZCB0aGUgbW9yZSByZWNlbnQgKlJlZmVyZW5jZSogY2xhc3Mgc3lzdGVtLiBFYWNoIGhhcyB0aGVpciBvd24gZmVhdHVyZXMgYW5kIHBlY3VsaWFyaXRpZXMuIENob29zaW5nIHdoaWNoIHRvIHVzZSBpcyBtb3N0bHkgYSBtYXR0ZXIgb2YgcGVyc29uYWwgcHJlZmVyZW5jZS4KCiMjIyBTMyBDbGFzcyBTeXN0ZW0KCkFuICpTMyogY2xhc3MgaXMgc2ltcGxlIGJ1dCBzb21ld2hhdCBwcmltaXRpdmUgaW4gbmF0dXJlLiBJdCBsYWNrcyBhIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZSBjbGFzcyBhbmQgaW5zdGFuY2VzIG9mIHRoaXMgY2xhc3MgYXJlIGNyZWF0ZWQgYnkgc2ltcGx5IGJ5IGFkZGluZyBhIGNsYXNzIGF0dHJpYnV0ZSB0byBhICpsaXN0KiBvYmplY3QuIFRoaXMgc2ltcGxpY2l0eSBpcyBvbmUgb2YgdGhlIHJlYXNvbnMgdGhhdCBpdCBpcyB3aWRlbHkgdXNlZCBieSBSIHByb2dyYW1tZXJzLiBJbiBmYWN0LCBtb3N0IG9mIHRoZSBSIGJ1aWx0LWluIGNsYXNzZXMgYXJlICpTMyogY2xhc3Nlcy4KCiMjIyBTNCBDbGFzcyBTeXN0ZW0KClRoZSAqUzQqIGNsYXNzIHN5c3RlbSBpcyBzdHJpY3RlciBpbiB0aGUgc2Vuc2UgdGhhdCBpdCBoYXMgYSBmb3JtYWwgd2F5IHRvIGRlZmluZSBjbGFzc2VzIGFuZCBhIHVuaWZvcm0gd2F5IHRvIGluc3RhbnRpYXRlIG9iamVjdHMuIFRoaXMgbWFrZXMgdGhlIHByb2Nlc3Mgc2FmZXIsIG1vcmUgbGlrZSBvYmplY3Qtb3JpZW50ZWQgbGFuZ3VhZ2VzLCBhbmQgcHJldmVudHMgcHJvZ3JhbW1lcnMgZnJvbSBkZWZpbmluZyBvYmplY3RzIGluY29ycmVjdGx5LgoKIyMjIFJlZmVyZW5jZSBDbGFzcyBTeXN0ZW0KClRoZSAqUmVmZXJlbmNlKiBjbGFzcyBzeXN0ZW0gaW4gUiBpcyBzaW1pbGFyIHRvIHRoZSBvYmplY3Qtb3JpZW50ZWQgcHJvZ3JhbW1pbmcgc3RydWN0dXJlcyBjb21tb24gbGFuZ3VhZ2VzIGxpa2UgQysrLCBKYXZhLCBQeXRob24sICpldGMqLiBVbmxpa2UgKlMzKiBhbmQgKlM0KiBjbGFzc2VzLCBtZXRob2RzIGJlbG9uZyB0byBhIGNsYXNzIHJhdGhlciB0aGFuIGJlaW5nIGRlZmluaXRpb25zIG9mIHByZS1kZWZpbmVkIGdlbmVyaWMgZnVuY3Rpb25zLiBSZWZlcmVuY2UgY2xhc3NlcyBhcmUgaW50ZXJuYWxseSBpbXBsZW1lbnRlZCBhcyBTNCBjbGFzc2VzIHdpdGggYW4gZW52aXJvbm1lbnQgc3Vycm91bmRpbmcgdGhlbS4KClRoZSByZW1haW5kZXIgb2YgdGhpcyBsZXNzb24gd2lsbCBmb2N1cyBvbiByZWZlcmVuY2UgY2xhc3Nlcy4KCiMjIERlZmluaW5nIGEgUmVmZXJlbmNlIENsYXNzCgpEZWZpbmluZyBhIHJlZmVyZW5jZSBjbGFzcyBpcyBkb25lIHdpdGggdGhlIDxjb2RlPnNldFJlZkNsYXNzKCk8L2NvZGU+IGZ1bmN0aW9uLgoKTWVtYmVyIHZhcmlhYmxlcyAoYXR0cmlidXRlcykgb2YgYSByZWZlcmVuY2UgY2xhc3MgbXVzdCBiZSBpbmNsdWRlZCBhcyBwYXJ0IG9mIHRoZSBjbGFzcyBkZWZpbml0aW9uLiBNZW1iZXIgdmFyaWFibGVzIG9mIHJlZmVyZW5jZSBjbGFzcyBhcmUgcmVmZXJyZWQgdG8gYXMgZmllbGRzLiBGaWVsZHMgYXJlIGNhbGxlZCBtZW1iZXIgdmFyaWFibGVzIGluIEMrKywgYXR0cmlidXRlcyBpbiBKYXZhLCBhbmQgc2xvdHMgaW4gb250b2xvZ3kgZGVmaW5pdGlvbnMuCgpUaGUgY29kZSBiZWxvdyBkZWZpbmVzIGEgY2xhc3MgSW5zdHJ1Y3RvciB3aXRoIHRocmVlIGZpZWxkcy4KCmBgYHtyIGRlZlJlZmVyZW5jZUNsYXNzfQpJbnN0cnVjdG9yIDwtIHNldFJlZkNsYXNzKCJJbnN0cnVjdG9yIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmllbGRzID0gbGlzdChpaWQ9Im51bWVyaWMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9ImNoYXJhY3RlciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuaz0iY2hhcmFjdGVyIikKICAgICAgICAgICAgICAgICAgICAgICAgICApCmBgYAoKIyMgSW5zdGFudGlhdGluZyBhIFJlZmVyZW5jZSBDbGFzcwoKSW5zdGFudGlhdGluZyBhbiBvYmplY3QgbWVhbnMgdGhhdCB3ZSBhbGxvY2F0ZSBhIGNodW5rIG9mIG1lbW9yeSB0byBob2xkIGFsbCB0aGUgZmllbGRzIG9mIHRoZSBvYmplY3QuIFRoZXJlIGFyZSB0d28gd2F5cyBpbiB3aGljaCB3ZSBjYW4gaW5zdGFudGlhdGUgYSBuZXcgaW5zdGFuY2Ugb2YgYSByZWZlcmVuY2UgY2xhc3MuIFVzaW5nIHRoZSBuYW1lIG9mIHRoZSByZWZlcmVuY2UgYXMgc2hvd24gYmVsb3csIG9yIGJ5IHVzaW5nIHRoZSBgbmV3YCBvcGVyYXRvciBpZiB3ZSBoYXZlIGEgbWV0aG9kIGBpbml0aWFsaXplYCBpbiBvdXIgcmVmZXJlbmNlIGNsYXNzIGRlZmluaXRpb24gLS0gd2Ugd2lsbCBub3Qgc2hvdyB0aGUgbGF0dGVyIGFwcHJvYWNoIGp1c3QgeWV0LgoKPiBJbnN0YW50aWF0aW5nIGFuIG9iamVjdCBtZWFucyBjcmVhdGluZyBhbiBpbnN0YW5jZSBvZiB0aGUgY2xhc3MgYW5kIGFsbG9jYXRpbmcgbWVtb3J5IGZvciBpdHMgZmllbGRzLiBTbywgdGhlIHRlcm1pbm9sb2d5IGluc3RhbmNlLCBpbnN0YW5jZSBvZiBhIGNsYXNzLCBhbmQgb2JqZWN0IGFyZSB1c2VkIGludGVyY2hhbmdlYWJseS4KCkluc3RhbnRpYXRpb24gaXMgZG9uZSB3aXRoIHRoZSBuYW1lIG9mIHRoZSBjbGFzcyB1c2VkIGFuIGEgZ2VuZXJhdG9yIGZ1bmN0aW9uIGFzIGRlbW9uc3RyYXRlZCBiZWxvdy4KCmBgYHtyIGNyZWF0ZUluc3RSZWZDbGFzc30KaSA8LSBJbnN0cnVjdG9yKGlpZCA9IDEsIG5hbWUgPSAnSmVmZiBBbGRlbicsIHJhbmsgPSAnRlQtQXNzb2NpYXRlJykKYGBgCgpUaGUgY29kZSBhYm92ZSBjcmVhdGVzIGFuIGluc3RhbmNlIG9mIHRoZSBjbGFzcyAiSW5zdHJ1Y3RvciIsIG9yLCBzYWlkIGFub3RoZXIgd2F5LCBpdCBhbGxvY2F0ZXMgYW4gb2JqZWN0IG9mIHR5cGUgIkluc3RydWN0b3IiLiBTaW5jZSB0aGUgY2xhc3MgIkluc3RydWN0b3IiIGhhcyB0aHJlZSBmaWVsZHMgKCppaWQqLCAqbmFtZSosIGFuZCAqcmFuayopIHdlIG5lZWQgdG8gc3VwcGx5IHRoZWlyIGRlZmF1bHQgdmFsdWVzLiBJbnN0YW50aWF0aW9uIG1lYW5zIGFsbG9jYXRpb24gb2YgbWVtb3J5LiBJbiB0aGlzIGNhc2UgUiBhbGxvY2F0ZXMgbWVtb3J5IGZvciBhIG51bWJlciAoKmlpZCopIGFuZCBtZW1vcnkgZm9yIGVhY2ggb2YgdGhlIGNoYXJhY3RlciBzdHJpbmdzLiBVcG9uIGNvbXBsZXRpb24gb2YgdGhlIG1lbW9yeSBhbGxvY2F0aW9uLCB3ZSBnZXQgYmFjayBhIHJlZmVyZW5jZSB0byB0aGUgb2JqZWN0ICgqaS5lLiosIGEgInBvaW50ZXIiIG9yICJsaW5rIiB0byB0aGUgYmxvY2sgb2YgbWVtb3J5IHdoZXJlIHRoZSBvYmplY3Qgd2FzIGFsbG9jYXRlZCkuIFdlIG11c3Qga2VlcCB0cmFjayBvZiB0aGF0IHJlZmVyZW5jZSB0byBiZSBhYmxlIHRvIGRvIHNvbWV0aGluZyB3aXRoIHRoZSBvYmplY3Qgb3IgY2FsbCBhbnkgb2YgaXRzIG1ldGhvZHMuCgpgYGB7ciBwcmludFJlZk9ian0KcHJpbnQoaSkKYGBgCgojIyBBY2Nlc3NpbmcgRmllbGRzCgpTaW1pbGFyIHRvICpTMyogY2xhc3NlcywgZmllbGRzIGFyZSBhY2Nlc3NlZCB3aXRoIHRoZSAqXCQqIG9wZXJhdG9yLiBUaGV5IGNhbiBhbHNvIGJlIG1vZGlmaWVkIHRoYXQgd2F5LiBUaGVyZSBpcyBubyBub3Rpb24gb2YgInByaXZhdGUiIGZpZWxkcyBvciBtZXRob2RzIGxpa2UgdGhlcmUgYXJlIGluIEphdmEgYW5kIEMrKy4gQWxsIG1lbWJlcnMgKGZpZWxkcyBhbmQgbWV0aG9kcykgYXJlICJwdWJsaWMiIGluIGFuIFIgcmVmZXJlbmNlIGNsYXNzIG9iamVjdC4KCmBgYHtyIGFjY1JlZk9iakZpZWxkc30KaSA8LSBJbnN0cnVjdG9yKGlpZCA9IDEsIG5hbWUgPSAnSmVmZiBBbGRlbicsIHJhbmsgPSAnRlQtQXNzb2NpYXRlJykKCiMgcmVhZCBhIGZpZWxkJ3MgdmFsdWUKbiA8LSBpJG5hbWUKCiMgdXBkYXRlIGEgZmllbGQncyB2YWx1ZQppJG5hbWUgPC0gJ0plZmZyZXkgQWxkZW4nCmBgYAoKIyMjIE9iamVjdHMgYXJlIFJlZmVyZW5jZXMKCldoZW4gaW5zdGFudGlhdGluZyBhIHJlZmVyZW5jZSBvYmplY3QsIFIgZ2VuZXJhdGVzIGFuIGludGVybmFsIG9iamVjdCBpbiBtZW1vcnkgYW5kIHJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhlIG9iamVjdCAoaGVuY2UgdGhlIG5hbWUpLiBTbywgYXNzaWduaW5nIGFuIG9iamVjdCB0byBhbm90aGVyIGFjdHVhbGx5IGFzc2lnbnMgdGhlIHJlZmVyZW5jZSBhbmQgZG9lcyBub3QgbWFrZSBhIGNvcHkuIEluIHRoZSBjb2RlIGJlbG93LCAqaTEqIGFuZCAqaTIqIGFyZSByZWZlcmVuY2VzIHRvIHRoZSBzYW1lIG9iamVjdC4gVGhpcyBpcyBzaW1pbGFyIHRvIEphdmEgYnV0IHVubGlrZSBDKysgd2hlbiBhIGNvcHkgY29uc3RydWN0b3IgaXMgZGVmaW5lZC4KCmBgYHtyIG9ianNBc1JlZmVyZW5jZXN9CmkxIDwtIEluc3RydWN0b3IoaWlkID0gMSwgbmFtZSA9ICdKZWZmIEFsZGVuJywgcmFuayA9ICdGVC1Bc3NvY2lhdGUnKQppMiA8LSBpMQoKaTIkbmFtZSA8LSAnWGluIFdhbmcnCgpwcmludChpMSkKYGBgCgpJbiB0aGUgY29kZSBhYm92ZSwgd2UgY3JlYXRlIGEgbmV3IGluc3RhbmNlIG9mIHRoZSBjbGFzcyBJbnN0cnVjdG9yIGFuZCBnZXQgYSByZWZlcmVuY2UgYmFjayB3aGljaCB3ZSBzdG9yZSBpbiB0aGUgdmFyaWFibGUgKmkxKi4gV2UgdGhlbiBhc3NpZ24gKmkxKiB0byAqaTIqIC0tIGJ1dCB3ZSBhcmUgYWN0dWFsbHkgYXNzaWduaW5nIHRoZSByZWZlcmVuY2UgKG9yIGEgcG9pbnRlciB0bykgdGhlIG9iamVjdC4gVGhpbmsgb2YgKmkxKiBiZWluZyB0aGUgbG9jYXRpb24gaW4gbWVtb3J5IHdoZXJlIHRoZSBvYmplY3QgaXMgc3RvcmVkLiBBbnkgbW9kaWZpY2F0aW9uIG9mIHRoZSBtZW1vcnkgdGhyb3VnaCB0aGUgcmVmZXJlbmNlICppMiogbW9kaWZpZXMgdGhlIHNhbWUgb2JqZWN0IHRoYXQgaXMgcG9pbnRlZCB0byBieSAqaTEqLiBTbywgY2F1dGlvbi4uLgoKVG8gbWFrZSBhbiBhY3R1YWwgY29weSwgdXNlIHRoZSBpbmhlcml0ZWQgbWV0aG9kIDxjb2RlPmNvcHkoKTwvY29kZT4uCgpgYGB7ciBjb3B5UmVmT2JqfQppMSA8LSBJbnN0cnVjdG9yKGlpZCA9IDEsIG5hbWUgPSAnSmVmZiBBbGRlbicsIHJhbmsgPSAnRlQtQXNzb2NpYXRlJykKCmkyIDwtIGkxJGNvcHkoKQoKIyBtb2RpZnlpbmcgaTIgZG9lcyBub3QgbW9kaWZ5IGkxCmkyJG5hbWUgPC0gJ1N1c2FuIFdvbGxhc3RvbicKCnByaW50KGkxKQpgYGAKCiMjIERlZmluaW5nIE1ldGhvZHMKCkFsbCByZWZlcmVuY2UgY2xhc3NlcyBoYXZlIGEgc2V0IG9mIHByZWRlZmluZWQgbWV0aG9kcyBpbmhlcml0ZWQgZnJvbSB0aGUgc3VwZXJjbGFzcyAqZW52UmVmQ2xhc3MqLiBUaGlzIGlzIHNpbWlsYXIgdG8gYWxsIEphdmEgY2xhc3NlcyBiZWluZyBzdWJjbGFzc2VzIG9mIHRoZSAqT2JqZWN0KiBjbGFzcy4KCk5ldyBtZXRob2RzIGNhbiBiZSBhZGRlZCBpbmxpbmUgaW4gdGhlIHNlcGFyYXRlIGxpc3QgKm1ldGhvZHMqLgoKTm90aWNlIHRoZSBvcGVyYXRvciAqXDxcPC0qIHVzZWQgdG8gYWNjZXNzIGZpZWxkcyB3aXRoaW4gYSBtZXRob2QuIFVzaW5nIHRoZSBzaW1wbGUgYXNzaWdubWVudCBvcGVyYXRvciAqXDwtKiB3b3VsZCBoYXZlIGNyZWF0ZWQgYSBsb2NhbCB2YXJpYWJsZSBjYWxsZWQgKnNhbGFyeSosIHdoaWNoIHdvdWxkIGxlYWQgdG8gZGlmZmVyZW50IGJlaGF2aW9yLiBGb3J0dW5hdGVseSwgUiB3aWxsIGlzc3VlIGEgd2FybmluZyBpbiBzdWNoIGEgY2FzZS4KCkFsc28gbm90ZSB0aGUgKiwqIGFmdGVyIHRoZSAqfSogdG8gc2VwYXJhdGUgdGhlIG1ldGhvZCBmdW5jdGlvbiBkZWZpbml0aW9ucy4KCmBgYHtyIGRpc3BSZWZPYmp9Ckluc3RydWN0b3IgPC0gc2V0UmVmQ2xhc3MoIkluc3RydWN0b3IiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHMgPSBsaXN0KGlpZD0ibnVtZXJpYyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iY2hhcmFjdGVyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5rPSJjaGFyYWN0ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FsYXJ5PSJudW1lcmljIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2RzID0gbGlzdCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1vbnRobHlTYWxhcnkgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChzYWxhcnkgLyAxMikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UmFpc2UgPSBmdW5jdGlvbihtZXJpdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYWxhcnkgPDwtIHNhbGFyeSAqICgxICsgbWVyaXQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgKSkKYGBgCgpUbyBtYWtlIGl0IGNsZWFyZXIgdG8gdGhlIHJlYWRlciBvZiBvdXIgY29kZSB3aGVuIHdlIGFjY2VzcyBhIGZpZWxkIHdpdGhpbiBhIG1ldGhvZCBhbmQgdG8gYXZvaWQgY2xhc2hlcyB3aGVuIHRoZSBuYW1lIG9mIGEgZmllbGQgaXMgdGhlIHNhbWUgYXMgdGhlIG5hbWUgb2YgYW4gYXJndW1lbnQgdG8gYSBtZXRob2Qgb3IgYSBsb2NhbCB2YXJpYWJsZSwgd2UgY2FuIHVzZSBgLnNlbGZgIHdoaWNoIGlzIGEgcmVmZXJlbmNlIHRvIHRoZSBvYmplY3Qgb24gd2hpY2ggdGhlIG1ldGhvZCBpcyBjYWxsZWQuIFRoaXMgaXMgZXF1aXZhbGVudCB0byB0aGUgYHRoaXNgIHBvaW50ZXIgaW4gSmF2YSBhbmQgQysrLiBUaGUgY29kZSBiZWxvdyBkZW1vbnN0cmF0ZXMgdGhpcyBhbHRlcm5hdGl2ZS4KCmBgYHtyIGRpc3BSZWZPYmpTZWxmUmVmLCBldmFsID0gVH0KSW5zdHJ1Y3RvciA8LSBzZXRSZWZDbGFzcygiSW5zdHJ1Y3RvciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkcyA9IGxpc3QoaWlkPSJudW1lcmljIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSJjaGFyYWN0ZXIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbms9ImNoYXJhY3RlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYWxhcnk9Im51bWVyaWMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZHMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TW9udGhseVNhbGFyeSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKC5zZWxmJHNhbGFyeSAvIDEyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlSYWlzZSA9IGZ1bmN0aW9uKG1lcml0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZWxmJHNhbGFyeSA8LSAuc2VsZiRzYWxhcnkgKiAoMSArIG1lcml0KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICkpCmBgYAoKSGVyZSBpcyB3aGF0IHdlIG1lYW4gYnkgYC5zZWxmYCBiZWluZyBhIHJlZmVyZW5jZSB0byB0aGUgb2JqZWN0IG9uIHdoaWNoIHRoZSBtZXRob2QgaXMgY2FsbGVkLiBDb25zaWRlciB0aGUgY29kZSBmcmFnbWVudCBiZWxvdyB3aGVyZSB3ZSBpbnN0YW50aWF0ZSB0d28gaW5zdGFuY2VzIChvYmplY3RzKSBvZiAiSW5zdHJ1Y3RvciIgYW5kIGFzc2lnbiB0aGVpciByZWZlcmVuY2VzIHRvIHR3byB2YXJpYWJsZXMgaW4gdGhpcyBjb250ZXh0OiAqaSogYW5kICpmKi4gU28sICppKiBpcyBhIHJlZmVyZW5jZSB0byBhIGJsb2NrIG9mIG1lbW9yeSB0aGF0IGNvbnRhaW5zIHRoZSBmaWVsZHMgezExLCAnS2FsZWIgQWhtYWQnLCAnRlQtQXNzb2NpYXRlJ30gYW5kICpmKiBpcyBhIHJlZmVyZW5jZSB0byBhIGJsb2NrIG9mIG1lbW9yeSB0aGF0IGNvbnRhaW5zIHRoZSBmaWVsZHMgezQ3NiwgJ0xlZW5hIFBhdGVsJywgJ1BUJ30uIFJlbWVtYmVyIHRoYXQgaW5zdGFudGlhdGlvbiBtZWFucyBhbGxvY2F0aW9uIG9mIG1lbW9yeSBmb3IgdGhlIG9iamVjdC4KCldoZW4gd2UgdGhlbiBjYWxsIGBpJGdldE1vbnRobHlTYWxhcnkoKWAsIHdlIGNhbGwgdGhlIG1ldGhvZCBgZ2V0TW9udGhseVNhbGFyeSgpYCBvbiB0aGUgb2JqZWN0IHJlZmVyZW5jZXMgYnkgKmkqIGFuZCB0aGVyZWZvcmUgaW5zaWRlIG9mIHRoZSBmdW5jdGlvbiBgZ2V0TW9udGhseVNhbGFyeSgpYCwgYC5zZWxmYCByZWZlcnMgdG8gdGhlIGJsb2NrIG9mIG1lbW9yeSBwb2ludGVkIGF0IGJ5ICppKi4gU28sIGAuc2VsZiRuYW1lYCB3b3VsZCBiZSAnS2FsZWIgQWhtYWQnLiBJZiB3ZSBoYWQgY2FsbGVkIGBmJGdldE1vbnRobHlTYWxhcnkoKWAsIHRoZW4gYC5zZWxmJG5hbWVgIHdvdWxkIGJlICdMZWVuYSBQYXRlbCcgd2l0aGluIGBnZXRNb250aGx5U2FsYXJ5KClgLiBTbywgYC5zZWxmYCB3aXRoaW4gYSBtZXRob2Qgb2YgYW4gb2JqZWN0IGlzIGEgYWx3YXlzIHJlZmVyZW5jZSB0byB0aGUgb2JqZWN0IG9uIHdoaWNoIHRoZSBtZXRob2QgaXMgY2FsbGVkLgoKPiBUaGUgdmFyaWFibGUgYC5zZWxmYCBpcyBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQgYW5kIGFsd2F5cyBpbml0aWFsaXplZCB0byBiZSBhIHJlZmVyZW5jZSB0byB0aGUgb2JqZWN0IG9uIHdoaWNoIHRoZSBtZXRob2QgaXMgY2FsbGVkLgoKYGBge3Igb2Jqc0FjY2Vzc1NlbGZ9CmkgPC0gSW5zdHJ1Y3RvcihpaWQgPSAxMSwgbmFtZSA9ICdLYWxlYiBBaG1hZCcsIAogICAgICAgICAgICAgICAgcmFuayA9ICdGVC1Bc3NvY2lhdGUnLCBzYWxhcnkgPSAyMDAwMDApCmYgPC0gSW5zdHJ1Y3RvcihpaWQgPSA0NzYsIG5hbWUgPSAnTGVlbmEgUGF0ZWwnLCAKICAgICAgICAgICAgICAgIHJhbmsgPSAnUFQnLCBzYWxhcnkgPSA2ODAwMCkKCmkkZ2V0TW9udGhseVNhbGFyeSgpCmBgYAoKIyMjIEFjY2Vzc2luZyBNZXRob2RzCgpNZXRob2RzIGFyZSBhY2Nlc3NlZCB0aGUgc2FtZSB3YXkgYXMgZmllbGRzIC0tIHdpdGggdGhlICpcJCogb3BlcmF0b3IuCgpgYGB7ciBhY2Nlc3NSZWZNZXRob2R9CmkgPC0gSW5zdHJ1Y3RvcihpaWQgPSAyLCBuYW1lID0gJ0R1YSBEaXBhJywgcmFuayA9ICdULUFzc2lzdGFudCcsIHNhbGFyeSA9IDEyODAwMCkKCm0uYmVmIDwtIGkkZ2V0TW9udGhseVNhbGFyeSgpCmkkYXBwbHlSYWlzZSgwLjA0NSkKCm0uYWZ0IDwtIGkkZ2V0TW9udGhseVNhbGFyeSgpCgpjYXQoIlNhbGFyeSByYWlzZWQgZnJvbSAkIiwgbS5iZWYsICJ0byAkIiwgbS5hZnQsICJwZXIgbW9udGgiKQpgYGAKCiMjIEluaGVyaXRhbmNlCgpJbmhlcml0YW5jZSBpcyBhIGtleSBtZWNoYW5pc20gaW4gb2JqZWN0LW9yaWVudGVkIHByb2dyYW1taW5nLiBJdCBhbGxvd3MgYSBwcm9ncmFtbWVyIHRvIGRlZmluZSBhIG5ldyBjbGFzcyAoKnN1YmNsYXNzKiBvciAqZGVyaXZlZCBjbGFzcyopIGZyb20gYW4gZXhpc3RpbmcgY2xhc3NlcyAoKnN1cGVyY2xhc3MqIG9yICpiYXNlIGNsYXNzKikuIERlcml2ZWQgY2xhc3NlcyBjYW4gYWRkIG5ldyBmaWVsZHMgYW5kIG1ldGhvZHMuIEFsbCBmaWVsZHMgYW5kIG1ldGhvZHMgb2YgdGhlIGJhc2UgY2xhc3MgYXJlIGF1dG9tYXRpY2FsbHkgZmllbGRzIGFuZCBtZXRob2RzIG9mIHRoZSBkZXJpdmVkIGNsYXNzLiBUaGlzIGluY3JlYXNlcyByZXVzYWJpbGl0eSBvZiBjb2RlIGFuZCBhbGxvd3MgcHJvZ3JhbW1lcnMgdG8gcmVwcmVzZW50IGRvbWFpbiBvYmplY3RzIG1vcmUgYWNjdXJhdGVseS4KCkluaGVyaXRhbmNlIGlzIHN1cHBvcnRlZCBpbiBhbGwgdGhyZWUgY2xhc3Mgc3lzdGVtcyBidXQgaXMgbW9yZSBsaWtlIG90aGVyIG9iamVjdC1vcmllbnRlZCBsYW5ndWFnZXMgaW4gdGhlICpSZWZlcmVuY2UqIGNsYXNzIHN5c3RlbS4gV2Ugd2lsbCByZXN0cmljdCBvdXJzZWx2ZXMgdG8gdGhpcyBjbGFzcyBzeXN0ZW0uCgpJbiB0aGUgZXhhbXBsZSBiZWxvdywgd2UgaGF2ZSBhIGJhc2UgY2xhc3MgKlBlcnNvbiogd2l0aCB0aHJlZSBmaWVsZHMgYW5kIGEgbWV0aG9kLiBXZSB0aGVuIGRlZmluZSBhIGRlcml2ZWQgY2xhc3MgKkluc3RydWN0b3IqIHdoaWNoIGV4dGVuZHMgKlBlcnNvbiogd2l0aCB0d28gYWRkaXRpb25hbCBmaWVsZHMgYW5kIHR3byBtZXRob2RzIGJ5IGFkZGluZyB0aGUgYmFzZSBjbGFzcyAqUGVyc29uKiBuYW1lIHRvIHRoZSAqY29udGFpbnMqIGFyZ3VtZW50LgoKYGBge3IgZGVmRGVyaXZlZENsYXNzfQpQZXJzb24gPC0gc2V0UmVmQ2xhc3MoIlBlcnNvbiIsIAogICAgICAgICAgICAgICAgICAgICAgZmllbGRzID0gbGlzdChwaWQ9Im51bWVyaWMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iY2hhcmFjdGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeW9iID0gIm51bWVyaWMiKSwKICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZHMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgICAgICBnZXRBZ2UgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyWWVhciA8LSBhcy5udW1lcmljKGZvcm1hdChTeXMudGltZSgpLCAiJVkiKSkKICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKGN1cnJZZWFyIC0geW9iKQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICApKQoKSW5zdHJ1Y3RvciA8LSBzZXRSZWZDbGFzcygiSW5zdHJ1Y3RvciIsIAogICAgICAgICAgICAgICAgICAgICAgY29udGFpbnMgPSAiUGVyc29uIiwKICAgICAgICAgICAgICAgICAgICAgIGZpZWxkcyA9IGxpc3QocmFuaz0iY2hhcmFjdGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FsYXJ5PSJudW1lcmljIgogICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZHMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgICAgICBnZXRNb250aGx5U2FsYXJ5ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChzYWxhcnkgLyAxMikKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UmFpc2UgPSBmdW5jdGlvbihtZXJpdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgIHNhbGFyeSA8PC0gc2FsYXJ5ICogKDEgKyBtZXJpdCkKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgKSkKYGBgCgpXZSBjYW4gdGhlbiBpbnN0YW50aWF0ZSB0aGUgZGVyaXZlZCBjbGFzcyAqSW5zdHJ1Y3RvciogYW5kIGZpbmQgdGhhdCBpdCBoYXMgYWxsIG9mIHRoZSBmaWVsZHMgYW5kIG1ldGhvZHMgb2YgKlBlcnNvbiogaW4gYWRkaXRpb24gdG8gaXRzIGFkZGl0aW9uYWwgZmllbGRzIGFuZCBtZXRob2RzLgoKYGBge3IgaW5zdERlckNsYXNzfQphbkluc3RydWN0b3IgPC0gSW5zdHJ1Y3RvcihwaWQgPSAxMDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gJ1JhaiBNZXRoYScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICByYW5rID0gJ0ZULUZ1bGwnLAogICAgICAgICAgICAgICAgICAgICAgICAgICB5b2IgPSAxOTY4LAogICAgICAgICAgICAgICAgICAgICAgICAgICBzYWxhcnkgPSAxODI5NzIpCgphbkluc3RydWN0b3IkZ2V0TW9udGhseVNhbGFyeSgpCmFuSW5zdHJ1Y3RvciRnZXRBZ2UoKQpgYGAKCiMjIE9iamVjdCBBZ2dyZWdhdGlvbgoKSW4gYW4gYWdncmVnYXRpb24gcmVsYXRpb25zaGlwIGJldHdlZW4gb2JqZWN0cywgdGhlcmUgaXMgYSB3aG9sZS9wYXJ0IG9yIGNvbnRhaW5lci9wYXJ0IGhpZXJhcmNoeS4gSW4gb250b2xvZ3kgdGVybXMsIHRoZXJlIGlzIGEgKnBhcnRvbm9teSouIEluIGFuIGFnZ3JlZ2F0aW9uLCBvbmUgb2JqZWN0ICJjb250YWlucyIgb3RoZXIgb2JqZWN0cywgYWx0aG91Z2ggdGhlIGNvbnRhaW5tZW50IGRvZXMgbm90IGhhdmUgdG8gYmUgInBoeXNpY2FsIiwgaS5lLiwgdGhlIHBhcnQgb2JqZWN0cyBkbyBub3QgaGF2ZSB0byBiZSBwYXJ0IG9mIHRoZSBzYW1lIG1lbW9yeSBzdHJ1Y3R1cmUuIFRoZSB3aG9sZS9wYXJ0IHJlbGF0aW9uc2hpcCBjYW4gYmUgYnkgcmVmZXJlbmNlIHdoZXJlIHRoZSBjb250YWluZXIgb2JqZWN0ICh3aG9sZSBvciBhZ2dyZWdhdGUpIGNvbnRhaW5zIHJlZmVyZW5jZXMgdG8gdGhlIGNvbnRhaW5lZCAocGFydCkgb2JqZWN0cy4KCkxldCdzIGltcGxlbWVudCB0aGUgcGFydCBoaWVyYXJjaHkgZXhwcmVzc2VkIGJ5IHRoZSBVTUwgQ2xhc3MgRGlhZ3JhbSBiZWxvdzoKCiFbXShVTUxDbGFzc0FnZ3JlZ2F0aW9uLmpwZyl7d2lkdGg9IjYwJSJ9CgpgYGB7ciBkZWZDbHViQ2xhc3Nlc30KTWVtYmVyIDwtIHNldFJlZkNsYXNzKCJNZW1iZXIiLCBmaWVsZHMgPSBsaXN0KAogIG1JRCA9ICJudW1lcmljIiwgCiAgbmFtZSA9ICJjaGFyYWN0ZXIiLAogIHllYXJKb2luZWQgPSAibnVtZXJpYyIpKQoKQ2x1YiA8LSBzZXRSZWZDbGFzcygiQ2x1YiIsIGZpZWxkcyA9IGxpc3QoCiAgbmFtZSA9ICJjaGFyYWN0ZXIiLAogIHllYXJGb3VuZGVkID0gIm51bWVyaWMiLAogIG1heE1lbUlEID0gIm51bWVyaWMiLAogIG1lbWJlcnMgPSAibGlzdCIpLAogICAgICAgICAgICAgICAgICAgIAogIG1ldGhvZHMgPSBsaXN0KAogICAgZ2V0TnVtTWVtYmVycyA9IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gKGxlbmd0aChtZW1iZXJzKSkKICAgIH0sCiAgICAKICAgIGFkZE1lbWJlciA9IGZ1bmN0aW9uKG0pIHsKICAgICAgaWYgKGlzLm51bGwobWVtYmVycykpCiAgICAgICAgICBtZW1iZXJzIDw8LSBsaXN0KDEwMjQpCiAgICAgIAogICAgICAjIGFkZCBhIG1lbWJlciBJRCBmb3IgdGhlIG5ldyBtZW1iZXIKICAgICAgbSRtSUQgPC0gbWF4TWVtSUQgKyAxCiAgICAgIG1heE1lbUlEIDw8LSBtYXhNZW1JRCArIDEKICAgICAgCiAgICAgICMgYWRkIHRoZSBtZW1iZXIgdG8gaW50ZXJuYWwgbGlzdAogICAgICBtZW1iZXJzW1tsZW5ndGgobWVtYmVycykrMV1dIDw8LSBtCiAgICAgIAogICAgICByZXR1cm4gKDEpCiAgICB9CiAgKSkKYGBgCgpBIGZldyBub3Rld29ydGh5IHBvaW50cyBhYm91dCB0aGUgYWJvdmUgY29kZS4gVGhlIGZpZWxkICptZW1iZXJzKiBpcyBhICJwcml2YXRlIiBtZW1iZXIgdmFyaWFibGUgdGhhdCBrZWVwcyB0cmFjayBvZiBhbGwgb2YgdGhlIG1lbWJlcnMgYWRkZWQgdG8gdGhlIGNsdWIuIEl0IGlzIGFuIGVtcHR5IGxpc3Qgd2hlbiBjcmVhdGVkLCBzbyByaWdodCBiZWZvcmUgdGhlIGZpcnN0IG1lbWJlciBpcyBhZGRlZCBpdCBtdXN0IGJlIGFsbG9jYXRlZC4KCk5vdyB0aGF0IHdlIGhhdmUgdGhlIGNsYXNzZXMgZGVmaW5lZCwgbGV0J3MgY3JlYXRlIHNvbWUgc2FtcGxlIGluc3RhbmNlcyBmb3IgdGVzdGluZy4gV2Ugd29uJ3Qgc2V0IGEgbWVtYmVyIElEIGZvciBuZXcgbWVtYmVycyBhcyB0aG9zZSBhcmUgYXNzaWduZWQgdG8gdGhlbSB3aGVuIHRoZXkgZ2V0IGFkZGVkIHRvIHRoZSBjbHViLgoKYGBge3IgY3JlYXRlQ2x1Yk9iamVjdHN9CiMgY3JlYXRlIGEgQ2x1YgphQ2x1YiA8LSBDbHViKG5hbWUgPSAnREFUQSBDbHViJywgCiAgICAgICAgICAgICAgeWVhckZvdW5kZWQgPSAyMDE1LAogICAgICAgICAgICAgIG1heE1lbUlEID0gMCkKCiMgY3JlYXRlIGEgZmV3IG1lbWJlcnMgYW5kIGFkZCB0aGVtIHRvIHRoZSBjbHViCnMgPC0gYUNsdWIkYWRkTWVtYmVyKAogIE1lbWJlcihuYW1lID0gJ0plZmYgR2Fyb2wnLCB5ZWFySm9pbmVkID0gMjAyMikpCgpzIDwtIGFDbHViJGFkZE1lbWJlcigKICBNZW1iZXIobmFtZSA9ICdVcnN1bGEgVmFuIExlaWRlbicsIHllYXJKb2luZWQgPSAyMDIyKSkKCnMgPC0gYUNsdWIkYWRkTWVtYmVyKAogIE1lbWJlcihuYW1lID0gJ0dhcnJldHQgTGlldycsIHllYXJKb2luZWQgPSAyMDIyKSkKCiMgbnVtYmVyIG9mIGNsdWIgbWVtYmVycyBzaG91bGQgYmUgY29ycmVjdAphQ2x1YiRnZXROdW1NZW1iZXJzKCkKYGBgCgojIyMgQWNjZXNzaW5nIEZpZWxkcwoKRmllbGRzIGFyZSAqaW5zdGFuY2UgdmFyaWFibGVzKjsgdGhleSBoYXZlIGEgdmFsdWUgZm9yIGVhY2ggaW5zdGFuY2UuIEZvciBleGFtcGxlLCBsZXQncyBpbml0aWFsaXplIHR3byBpbnN0YW5jZXMgb2YgdGhlIGNsYXNzICpDbHViKiBhbmQgbGV0J3MgYWRkIHRoZW0gdG8gYSBsaXN0IHNvIHdlIGhhdmUgYSB3YXkgb2Yga2VlcGluZyB0cmFjayBvZiBhbGwgdGhlIGNsdWJzIC0tIG9mIGNvdXJzZSBjcmVhdGluZyBhbiBhZ2dyZWdhdGlvbiBjbGFzcyB3b3VsZCBiZSBldmVuIGJldHRlciwgcGVyaGFwcyBjYWxsaW5nIHRoYXQgY2xhc3MgKkNsdWJzKi4gQnV0LCBmb3Igbm93LCB3ZSdsbCBqdXN0IGJ1aWxkIGEgImZyZWUiIGxpc3QsIGluIG90aGVyIHdvcmRzLCBhIGxpc3QgdGhhdCBleGlzdHMgb3V0c2lkZSBvZiBhbnkgY2xhc3M6CgpgYGB7cn0KIyBvdXIgbGlzdCBvZiBjbHVicwpjbHVicyA8LSBsaXN0KDApCgojIGNyZWF0ZSBjbHViIGFuZCBhZGQgaXQgdG8gb3VyIGxpc3Qgb2YgY2x1YnMKY2x1YnNbWzFdXSA8LSBDbHViKG5hbWUgPSAnVm9sbGV5YmFsbCBDbHViJywgCiAgICAgICAgICAgICAgeWVhckZvdW5kZWQgPSAxOTk3LAogICAgICAgICAgICAgIG1heE1lbUlEID0gMCkKCiMgY3JlYXRlIGNsdWIgYW5kIGFkZCBpdCB0byBvdXIgbGlzdCBvZiBjbHVicwpjbHVic1tbMl1dIDwtIENsdWIobmFtZSA9ICdUZWNoIENsdWInLCAKICAgICAgICAgICAgICB5ZWFyRm91bmRlZCA9IDIwMTgsCiAgICAgICAgICAgICAgbWF4TWVtSUQgPSAwKQoKIyBsZXQncyBhZGQgYSBtZW1iZXIgdG8gb25lIG9mIHRoZSBjbHVicwpjbHVic1tbMV1dJGFkZE1lbWJlcigKICBNZW1iZXIobmFtZSA9ICdMZXNsZXkgV2FsdGVyJywgeWVhckpvaW5lZCA9IDIwMjApKQpgYGAKCkxldCdzIGluc3BlY3QgbW9yZSBjbG9zZWx5IHdoYXQgaGFwcGVucyB3aGVuIHdlIGNhbGwgYSBtZW1iZXIgZnVuY3Rpb24sICppLmUuKiwgd2hlbiB3ZSBjYWxsIGBjbHVic1tbMV1dJGFkZE1lbWJlcihNZW1iZXIobmFtZSA9ICdMZXNsZXkgV2FsdGVyJywgeWVhckpvaW5lZCA9IDIwMjApKWAuIFRoZSBtZXRob2QgYGFkZE1lbWJlcigpYCBpcyBwYXNzZWQgYW4gaW5zdGFuY2Ugb2YgdGhlIGNsYXNzIE1lbWJlciBhcyBhbiBhcmd1bWVudC4gVG8gdW5kZXJzdGFuZCB3aGF0IG9jY3VycywgbGV0J3MgbG9vayBhdCB0aGUgY29kZSBmb3IgdGhhdCBmdW5jdGlvbiBieSBpdHNlbGYuCgpgYGB7ciBldmFsPUZ9Ci4uLgoKYWRkTWVtYmVyID0gZnVuY3Rpb24obSkgewogIGlmIChpcy5udWxsKG1lbWJlcnMpKQogICAgICBtZW1iZXJzIDw8LSBsaXN0KDEwMjQpCiAgCiAgIyBhZGQgYSBtZW1iZXIgSUQgZm9yIHRoZSBuZXcgbWVtYmVyCiAgbSRtSUQgPC0gbWF4TWVtSUQgKyAxCiAgbWF4TWVtSUQgPDwtIG1heE1lbUlEICsgMQogIAogICMgYWRkIHRoZSBtZW1iZXIgdG8gaW50ZXJuYWwgbGlzdAogIG1lbWJlcnNbW2xlbmd0aChtZW1iZXJzKSsxXV0gPDwtIG0KICAKICByZXR1cm4gKDEpCn0KCi4uLgpgYGAKClNvLCBmb3IgdGhlIGNhbGwgYGNsdWJzW1sxXV0kYWRkTWVtYmVyKE1lbWJlcihuYW1lID0gJ0xlc2xleSBXYWx0ZXInLCB5ZWFySm9pbmVkID0gMjAyMCkpYCwgdGhlIG9iamVjdCBvbiB3aGljaCBgYWRkTWVtYmVyKClgIGlzIGNhbGxlZCBpcyBgY2x1YnNbWzFdXWAuIFNvLCB3aXRoaW4gdGhlIGZ1bmN0aW9uIGBhZGRNZW1iZXIoKWAsIHdoZW4gcmVmZXJyaW5nIHRvIGEgZmllbGQgb2YgdGhlIGNsYXNzICpDbHViKiwgd2UgcmVmZXIgdG8gdGhlIHZhbHVlcyBvZiB0aG9zZSBmaWVsZHMgZm9yIHRoZSBpbnN0YW5jZSBgY2x1YnNbWzFdXWAuIFRvIHJldmlldywgaGVyZSBpcyB0aGUgY29kZSB0aGF0IGNyZWF0ZWQgdGhhdCBpbnN0YW5jZSBvZiB0aGUgY2x1YjoKCmBgYHtyfQpjbHVic1tbMV1dIDwtIENsdWIobmFtZSA9ICdWb2xsZXliYWxsIENsdWInLCAKICAgICAgICAgICAgICB5ZWFyRm91bmRlZCA9IDE5OTcsCiAgICAgICAgICAgICAgbWF4TWVtSUQgPSAwKQpgYGAKClNvLCB3aXRoaW4gYGFkZE1lbWJlcigpYCBmb3IgdGhlIGNhbGwgYGNsdWJzW1sxXV0kYWRkTWVtYmVyKE1lbWJlcihuYW1lID0gJ0xlc2xleSBXYWx0ZXInLCB5ZWFySm9pbmVkID0gMjAyMCkpYCwgKm1heE1lbWJlcklEKiB3b3VsZCBoYXZlIHRoZSB2YWx1ZSAwIGFuZCAqeWVhckZvdW5kZWQqIHdvdWxkIGJlIDE5OTcuIFNvLCByZWZlcnJpbmcgdG8gdGhvc2UgdmFyaWFibGVzIHdpdGhpbiBgYWRkTWVtYmVyKClgIHdvdWxkIHJlZmVyIHRvIHRob3NlIGluc3RhbmNlIHZhcmlhYmxlcy4KCiMjIyBUaGUgLnNlbGYgUmVmZXJlbmNlCgoqLnNlbGYqIGlzIGEgcHJlLWRlZmluZWQgdmFyaWFibGUgdGhhdCByZWZlcnMgdG8gdGhlIG9iamVjdCBvbiB3aGljaCBhIG1ldGhvZCBpcyBjYWxsZWQuIFNvLCBpZiB5b3UgY2FsbGVkIG1ldGhvZCAqTSogb24gYW4gaW5zdGFuY2UgKmMqIG9mIHRoZSBjbGFzcyAqQyogaGF2aW5nIGZpZWxkICpYKiwgdGhlbiB3aGVuIGNhbGxpbmcgYGMkTSgpYCwgKi5zZWxmKiB3b3VsZCBiZSBhIHJlZmVyZW5jZSB0byAqYyouIE5vdGljZSB0aGUgZG90IHByZWZpeC4gVG8gcmVmZXIgdG8gdGhlIGZpZWxkIFggb2YgdGhlIGluc3RhbmNlIG9uIHdoaWNoIHlvdSBhcmUgY2FsbGluZyBhIG1ldGhvZCwgd291bGQgYmUgYC5zZWxmJFhgIHdpdGhpbiBhIG1ldGhvZC4gVGhpcyBpcyB1c2VmdWwgaWYgeW91IG5lZWQgdG8gYWNjZXNzIGEgZmllbGQgdGhhdCBpcyAiaGlkZGVuIiBiZWNhdXNlIHlvdSBlaXRoZXIgaGF2ZSBhIHBhcmFtZXRlciB0byB0aGUgbWV0aG9kICpNKiB0aGF0IGNhbGxlZCAqWCogb3IgYSBsb2NhbCB2YXJpYWJsZSB3aXRoICpNKiB0aGF0IGlzIGNhbGxlZCAqWCouIEFsdGVybmF0aXZlbHksIHByb2dyYW1tZXJzIG9mdGVuIHVzZSBgLnNlbGYkWGAgd2hlbiByZWZlcnJpbmcgdG8gdGhlIGZpZWxkICpYKiB0byBtYWtlIGl0IGNsZWFyIHRvIHRoZSByZWFkZXIgb2YgdGhlIGNvZGUgdGhhdCB0aGV5IGludGVuZCB0byBhY2Nlc3MgYSBmaWVsZCByYXRoZXIgdGhhbiBhIGxvY2FsIHZhcmlhYmxlIG9yIGFuIGFyZ3VtZW50IC0tIGl0IGFkZHMgdG8gY29kZSBjbGFyaXR5LgoKV2UgY291bGQgdGhlcmVmb3JlIHJld3JpdGUgdGhlIGNvZGUgZm9yICphZGRNZW1iZXIoKSogdXNpbmcgKi5zZWxmKiBhcyBmb2xsb3dzOgoKYGBge3IgZXZhbD1GfQouLi4KCmFkZE1lbWJlciA9IGZ1bmN0aW9uKG0pIHsKICBpZiAoaXMubnVsbCguc2VsZiRtZW1iZXJzKSkKICAgICAgLnNlbGYkbWVtYmVycyA8PC0gbGlzdCgxMDI0KQogIAogICMgYWRkIGEgbWVtYmVyIElEIGZvciB0aGUgbmV3IG1lbWJlcgogIG0kbUlEIDwtIC5zZWxmJG1heE1lbUlEICsgMQogIG1heE1lbUlEIDw8LSAuc2VsZiRtYXhNZW1JRCArIDEKICAKICAjIGFkZCB0aGUgbWVtYmVyIHRvIGludGVybmFsIGxpc3QKICAuc2VsZiRtZW1iZXJzW1tsZW5ndGgoLnNlbGYkbWVtYmVycykrMV1dIDwtIG0KICAKICByZXR1cm4gKDEpCn0KCi4uLgpgYGAKCiMjIEluc3RhbnRpYXRpb24gd2l0aCBgbmV3YAoKVGhpcyBzZWN0aW9uIHByZXNlbnRzIGFuIGFsdGVybmF0aXZlIHdheSB0byBpbnN0YW50aWF0ZSBhbmQgaW5pdGlhbGl6ZSBhIHJlZmVyZW5jZSBjbGFzcyBvYmplY3QuIEl0IGlzIG1vcmUgbGlrZSB0aG9zZSBtZWNoYW5pc21zIGZvdW5kIGluIG9iamVjdC1vcmllbnRlZCBsYW5ndWFnZXMgbGlrZSBKYXZhLgoKSW5pdGlhbGl6YXRpb24gcmVmZXJzIHRvIHRoZSBwcm9jZXNzIG9mIHNldHRpbmcgdXAgYW4gb2JqZWN0IHdoZW4gaXQgaXMgY3JlYXRlZC4gSW4gdGhlIHJlZmVyZW5jZSBjbGFzcyBzeXN0ZW0gaW4gUiwgdGhpcyBpcyBkb25lIGJ5IGRlZmluaW5nIGFuIGBpbml0aWFsaXplYCBtZXRob2QgZm9yIGEgY2xhc3MuIFRoZSBpbml0aWFsaXplIG1ldGhvZCBpcyBjYWxsZWQgYXV0b21hdGljYWxseSB3aGVuIGEgbmV3IG9iamVjdCBvZiB0aGUgY2xhc3MgaXMgY3JlYXRlZCwgYW5kIGl0IHRha2VzIGNhcmUgb2Ygc2V0dGluZyB1cCB0aGUgb2JqZWN0J3MgaW50ZXJuYWwgc3RhdGUuIEluIEphdmEgYW5kIEMrKywgdGhpcyBmdW5jdGlvbiBpcyByZWZlcnJlZCB0byBhcyB0aGUgKmNvbnN0cnVjdG9yKi4KCkZvciBleGFtcGxlLCB5b3UgbWlnaHQgdXNlIHRoZSBpbml0aWFsaXplIG1ldGhvZCB0byBzZXQgdGhlIGluaXRpYWwgdmFsdWVzIG9yIGF0dHJpYnV0ZXMsIGxvYWQgYW4gb2JqZWN0J3Mgc3RhdGUgZnJvbSBhbiBleHRlcm5hbCBmaWxlIG9yIGEgZGF0YWJhc2UsIG9yIHBlcmZvcm0gYW55IG90aGVyIGtpbmQgb2YgaW5pdGlhbGl6YXRpb24uCgpUaGUgZXhhbXBsZSBiZWxvdyBhZGRzIGFuIGluaXRpYWxpemUgbWV0aG9kIHRvIG91ciBwcmV2aW91cyBjbGFzcyAqTWVtYmVyKiBhbmQgc2hvd3MgaG93IHRoYXQgbWV0aG9kIGlzIGF1dG9tYXRpY2FsbHkgaW52b2tlZC4gTm90ZSB0aGF0IHdlIG5vdyBuZWVkIHRvIGNhbGwgdGhlIGltcGxpY2l0bHkgZGVmaW5lZCBmdW5jdGlvbiAqbmV3KiB0byBpbnN0YW50aWF0ZSBhbiBvYmplY3QuCgpgYGB7cn0KTWVtYmVyIDwtIHNldFJlZkNsYXNzKCJNZW1iZXIiLCAKICAgICAgICAgICAgICAgICAgICAgIGZpZWxkcyA9IGxpc3QoCiAgICAgICAgICAgICAgICAgICAgICAgIG1JRCA9ICJudW1lcmljIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiY2hhcmFjdGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgeWVhckpvaW5lZCA9ICJudW1lcmljIiksCiAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZHMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsaXplID0gZnVuY3Rpb24obmFtZSwgeWVhcikgewogICAgICAgICAgICAgICAgICAgICAgICAgIC5zZWxmJG5hbWUgPC0gbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgIC5zZWxmJHllYXJKb2luZWQgPC0geWVhcgogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICApKQoKCiMgY3JlYXRlIGFuIGluc3RhbmNlIHdpdGggaW1wbGljaXQgaW5pdGlhbGl6YXRpb24KYU1lbWJlciA8LSBNZW1iZXIkbmV3KCdMaXogQ2hhbycsIDIwMjMpCmBgYAoKSW4gdGhpcyBleGFtcGxlLCB0aGUgaW5pdGlhbGl6ZSBtZXRob2QgdGFrZXMgdHdvIGFyZ3VtZW50cywgKm5hbWUqIGFuZCAqeWVhciosIHdoaWNoIGFyZSB1c2VkIHRvIGluaXRpYWxpemUgdGhlICpuYW1lKiBhbmQgKnllYXJKb2luZWQqIGZpZWxkcyBvZiB0aGUgb2JqZWN0LCByZXNwZWN0aXZlbHkuIFdoZW4gYSBuZXcgb2JqZWN0IG9mIHRoZSBjbGFzcyBpcyBjcmVhdGVkIHdpdGggKm5ldyosIHRoZSBgaW5pdGlhbGl6ZSgpYCBtZXRob2QgaXMgY2FsbGVkIGF1dG9tYXRpY2FsbHkgYW5kIHRoZSBmaWVsZHMgYXJlIGluaXRpYWxpemVkIGFjY29yZGluZ2x5LgoKIyMgVHV0b3JpYWwgSTogQ2xhc3NlcywgT2JqZWN0cywgYW5kIEluc3RhbnRpYXRpb24KCkFmdGVyIGhhdmluZyByZWFkIHRoZSBsZXNzb24gYWJvdmUsIHdhdGNoIHRoZSB0dXRvcmlhbCBhbmQgcmV2aXNpdCB0aGUgdmFyaW91cyBzZWN0aW9ucyBvZiB0aGUgbGVzc29uIGFuZCB0cnkgdGhlIGNvZGUgeW91cnNlbGYuCgo8aWZyYW1lIHNyYz0iaHR0cHM6Ly9wbGF5ZXIudmltZW8uY29tL3ZpZGVvLzkxMDE2NzU4ND90aXRsZT0wJmFtcDtieWxpbmU9MCZhbXA7cG9ydHJhaXQ9MCZhbXA7YmFkZ2U9MCZhbXA7YXV0b3BhdXNlPTAmYW1wO3BsYXllcl9pZD0wJmFtcDthcHBfaWQ9NTg0NzkiIHdpZHRoPSI1NjAiIGhlaWdodD0iMzE1IiBmcmFtZWJvcmRlcj0iMSIgYWxsb3c9ImF1dG9wbGF5OyBmdWxsc2NyZWVuOyBwaWN0dXJlLWluLXBpY3R1cmUiIHRpdGxlPSJPYmplY3QtT3JpZW50ZWQgUHJvZ3JhbW1pbmcgaW4gUjogT2JqZWN0IEluc3RhbnRpYXRpb24sIEZpZWxkICZhbXA7IE1ldGhvZCBBY2Nlc3MgaW4gdGhlIFJlZmVyZW5jZSBDbGFzcyBTeXN0ZW0iIGRhdGEtZXh0ZXJuYWw9IjEiPgoKPC9pZnJhbWU+CgojIyBDb250YWluZXIgT2JqZWN0cwoKQSBjb250YWluZXIgb2JqZWN0LCBhbHNvIGtub3duIGFzIGEgY29sbGVjdGlvbiBvYmplY3QsIGlzIGEgdHlwZSBvZiBvYmplY3QgdGhhdCBob2xkcyBhIGNvbGxlY3Rpb24gb2Ygb3RoZXIgb2JqZWN0cy4KCkluIG9iamVjdC1vcmllbnRlZCBwcm9ncmFtbWluZywgYSBjb250YWluZXIgb2JqZWN0IGlzIGFuIG9iamVjdCB0aGF0IGlzIHVzZWQgdG8gc3RvcmUgYW5kIG1hbmFnZSBvdGhlciBvYmplY3RzLiBUaGUgaWRlYSBiZWhpbmQgYSBjb250YWluZXIgb2JqZWN0IGlzIHRvIHByb3ZpZGUgYSBjb252ZW5pZW50IGFuZCBlZmZpY2llbnQgd2F5IG9mIGdyb3VwaW5nIGFuZCBvcmdhbml6aW5nIHJlbGF0ZWQgb2JqZWN0cy4KClRoZXkgYXJlIG5lY2Vzc2FyeSBmb3Igc3RvcmluZyBpbnN0YW5jZXMgb2YgY2xhc3NlcyBhcyB0aGVyZSBhcmUgbm8gIm5hdHVyYWwiIGNvbnRhaW5lcnMuIEluIHRoZSBwcmV2aW91cyBleGFtcGxlLCBhICpDbHViKiBvYmplY3QgYWN0ZWQgYXMgYSBjb250YWluZXIgZm9yIGFsbCAqTWVtYmVyKiBvYmplY3RzLiBCdXQgd2hhdCBpZiB3ZSBoYWQgbW9yZSB0aGFuIG9uZSAqQ2x1Yiogb2JqZWN0PyBXaG8gd291bGQga2VlcCB0cmFjayBvZiBhbGwgb2YgdGhvc2Ugb2JqZWN0cz8gTmF0dXJhbGx5LCB3ZSBjb3VsZCB1c2UgYSB2ZWN0b3IgdG8gc3RvcmUgdGhlbSAtLSBvciwgd2UgY291bGQgYnVpbGQgYSBjb250YWluZXIgY2xhc3MgYW5kIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiB0aGF0IGNsYXNzIGFzIGEgY29udGFpbmVyIG9iamVjdC4gVGhlIGNsYXNzIHdvdWxkIHRoZW4gaGF2ZSB0aGUgdXN1YWwgbWV0aG9kcyBvZiBhZGRpbmcgYW4gb2JqZWN0LCByZW1vdmluZyBhbiBvYmplY3QsIGNvdW50aW5nIHRoZSBvYmplY3RzLCBhbmQgZmluZGluZyBvYmplY3RzIGJhc2VkIG9uIGRpZmZlcmVudCBjcml0ZXJpYS4gU29tZSBjb250YWluZXJzIGFsc28gcHJvdmlkZSBpdGVyYXRvcnMgdG8gaXRlcmF0ZSBvdmVyIHRoZSBlbGVtZW50cyBzdG9yZWQgaW4gdGhlIGNvbnRhaW5lci4KClVzaW5nIGNvbnRhaW5lciBvYmplY3RzIGNhbiBiZSBiZW5lZmljaWFsIGluIHNldmVyYWwgd2F5czoKCi0gICAqKkFic3RyYWN0aW9uKio6IEJ5IHVzaW5nIGEgY29udGFpbmVyIG9iamVjdCwgeW91IGNhbiBhYnN0cmFjdCBhd2F5IHRoZSBkZXRhaWxzIG9mIGhvdyB0aGUgZWxlbWVudHMgYXJlIHN0b3JlZCBhbmQgbWFuaXB1bGF0ZWQsIG1ha2luZyB5b3VyIGNvZGUgbW9yZSByZWFkYWJsZSBhbmQgZWFzaWVyIHRvIG1haW50YWluLgoKLSAgICoqRW5jYXBzdWxhdGlvbioqOiBDb250YWluZXIgb2JqZWN0cyBlbmNhcHN1bGF0ZSB0aGUgZWxlbWVudHMgdGhleSBjb250YWluLCBoaWRpbmcgdGhlaXIgaW1wbGVtZW50YXRpb24gZGV0YWlscyBhbmQgbWFraW5nIGl0IGVhc2llciB0byBjaGFuZ2UgdGhlIHVuZGVybHlpbmcgaW1wbGVtZW50YXRpb24gd2l0aG91dCBhZmZlY3RpbmcgdGhlIHJlc3Qgb2YgdGhlIGNvZGUuCgotICAgKipSZXVzYWJpbGl0eSoqOiBDb250YWluZXIgb2JqZWN0cyBjYW4gYmUgdXNlZCBhcyBidWlsZGluZyBibG9ja3MgaW4gbGFyZ2VyIHN5c3RlbXMsIGFsbG93aW5nIGZvciBjb2RlIHJldXNlIGFuZCByZWR1Y2luZyBkdXBsaWNhdGlvbi4KCi0gICAqKlBlcmZvcm1hbmNlKio6IENvbnRhaW5lciBvYmplY3RzIGNhbiBvZnRlbiBwcm92aWRlIG9wdGltaXplZCBpbXBsZW1lbnRhdGlvbnMgZm9yIGNvbW1vbiBvcGVyYXRpb25zLCBzdWNoIGFzIGFkZGluZyBvciByZW1vdmluZyBlbGVtZW50cywgbWFraW5nIHRoZW0gbW9yZSBlZmZpY2llbnQgdGhhbiB1c2luZyBiYXNpYyBkYXRhIHN0cnVjdHVyZXMgbGlrZSB2ZWN0b3JzIG9yIGxpc3RzLgoKT3ZlcmFsbCwgY29udGFpbmVyIG9iamVjdHMgYXJlIGEga2V5IGFzcGVjdCBvZiBvYmplY3Qtb3JpZW50ZWQgcHJvZ3JhbW1pbmcgYW5kIGNhbiBoZWxwIHRvIHNpbXBsaWZ5IGFuZCBvcHRpbWl6ZSB0aGUgZGV2ZWxvcG1lbnQgb2YgY29tcGxleCBzeXN0ZW1zLiBUaGV5IGFyZSBuZWNlc3NhcnkgaW4gYWxsIG9iamVjdC1vcmllbnRlZCBwcm9ncmFtbWluZyBsYW5ndWFnZXMsIGluY2x1ZGluZyBKYXZhIGFuZCBDKyssIGFuZCBub3QganVzdCBSLgoKIyMgVHV0b3JpYWwgSUk6IE9iamVjdCBBZ2dyZWdhdGlvbiAmIENvbnRhaW5lciBPYmplY3RzCgo8aWZyYW1lIHNyYz0iaHR0cHM6Ly9wbGF5ZXIudmltZW8uY29tL3ZpZGVvLzkxMDIwMTUzNT90aXRsZT0wJmFtcDtieWxpbmU9MCZhbXA7cG9ydHJhaXQ9MCZhbXA7YmFkZ2U9MCZhbXA7YXV0b3BhdXNlPTAmYW1wO3BsYXllcl9pZD0wJmFtcDthcHBfaWQ9NTg0NzkiIHdpZHRoPSI1NjAiIGhlaWdodD0iMzE1IiBmcmFtZWJvcmRlcj0iMSIgYWxsb3c9ImF1dG9wbGF5OyBmdWxsc2NyZWVuOyBwaWN0dXJlLWluLXBpY3R1cmUiIHRpdGxlPSI2LjEyMi4yIC8gQ29udGFpbmVyIE9iamVjdHMiIGRhdGEtZXh0ZXJuYWw9IjEiPgoKPC9pZnJhbWU+CgojIyBDb25jbHVzaW9uCgpPYmplY3Qtb3JpZW50YXRpb24gaXMgYSBjb21tb24gd2F5IHRvIGNyZWF0ZSBhYnN0cmFjdGlvbiBhbmQgc3RydWN0dXJlIGNvbXBsZXggaW5mb3JtYXRpb24uIFdoaWxlIFIgaXMgbm90IGEgZnVsbHkgb2JqZWN0LW9yaWVudGVkIGxhbmd1YWdlLCBtYW55IG9mIHRoZSBpbmZvcm1hdGlvbiBhYnN0cmFjdGlvbiBtZWNoYW5pc21zIHByb3ZpZGVkIGJ5IGNsYXNzZXMsIG9iamVjdHMsIGFuZCBtZXRob2RzIGFyZSBzdXBwb3J0ZWQgYnkgUiwgYWxiZWl0IGluIGEgd2F5IHRoYXQgbWF5IGJlIHVuZmFtaWxpYXIgdG8gcHJvZ3JhbW1lcnMgY29taW5nIHRvIFIgZnJvbSBDKyssIEphdmEsIG9yIHNpbWlsYXIgbGFuZ3VhZ2VzLiBVbmxpa2Ugb3RoZXIgbGFuZ3VhZ2VzLCBSIGhhcyB0aHJlZSBkaXN0aW5jdCB3YXlzIGluIHdoaWNoIHRvIGRlZmluZSBjbGFzc2VzIGFuZCBvYmplY3RzLCB3aXRoIHRoZSAqUmVmZXJlbmNlIENsYXNzZXMqIGJlaW5nIHRoZSBtb3N0IHNpbWlsYXIgdG8gb3RoZXIgb2JqZWN0LW9yaWVudGVkIGxhbmd1YWdlcy4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgRmlsZXMgJiBSZXNvdXJjZXMKCmBgYHtyIHppcEZpbGVzLCBlY2hvPUZBTFNFfQp6aXBOYW1lID0gc3ByaW50ZigiTGVzc29uRmlsZXMtJXMtJXMuemlwIiwgCiAgICAgICAgICAgICAgICAgcGFyYW1zJGNhdGVnb3J5LAogICAgICAgICAgICAgICAgIHBhcmFtcyRudW1iZXIpCgp0ZXh0QUxpbmsgPSBwYXN0ZTAoIkFsbCBGaWxlcyBmb3IgTGVzc29uICIsIAogICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksIi4iLHBhcmFtcyRudW1iZXIpCgojIGRvd25sb2FkRmlsZXNMaW5rKCkgaXMgaW5jbHVkZWQgZnJvbSBfaW5zZXJ0MkRCLlIKa25pdHI6OnJhd19odG1sKGRvd25sb2FkRmlsZXNMaW5rKCIuIiwgemlwTmFtZSwgdGV4dEFMaW5rKSkKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIFJlZmVyZW5jZXMKCi0gICBbUzQgQ2xhc3NlcyBpbiBSLiBEYXRhTWVudG9yXShodHRwczovL3d3dy5kYXRhbWVudG9yLmlvL3ItcHJvZ3JhbW1pbmcvczQtY2xhc3MvKQotICAgW1JlZmVyZW5jZSBDbGFzcyBTeXN0ZW0gaW4gUi4gRGF0YU1lbnRvcl0oaHR0cHM6Ly93d3cuZGF0YW1lbnRvci5pby9yLXByb2dyYW1taW5nL3JlZmVyZW5jZS1jbGFzcy8pCi0gICBbT2JqZWN0cyBXaXRoIEZpZWxkcyBUcmVhdGVkIGJ5IFJlZmVyZW5jZV0oaHR0cHM6Ly9zdGF0LmV0aHouY2gvUi1tYW51YWwvUi1kZXZlbC9saWJyYXJ5L21ldGhvZHMvaHRtbC9yZWZDbGFzcy5odG1sKQoKIyMgRXJyYXRhCgpbTGV0IHVzIGtub3ddKGh0dHBzOi8vZm9ybS5qb3Rmb3JtLmNvbS8yMTIxODcwNzI3ODQxNTcpe3RhcmdldD0iX2JsYW5rIn0uCg==