Learn R Programming

IP (version 0.1)

Varia: Miscellaneous methods et functions for IP classes

Description

Mostly IP counterparts of base R methods and functions for atomic vectors. Namely,

  • sorting : ip.order(), xtfrm() which is called internally by order() and sort()

  • matching : match(), ip.match(), ip.index()

  • unique()

  • set operations : ip.setequal(), ip.union(), ip.intersect(), ip.setdiff(), ip.symdiff()

  • length(), is.na()

Arguments

Details

Sorting

IP object may be sorted through call to R generic functions order() and sort(). The IP package also provides the ip.order() methods for ordering IP which are experimental and should not be used (except maybe for IPv6, ip.order() being faster than order() at the moment).

Lookup

This part is still experimental and might be subject to change in the future.

match() and ip.match() do IP lookup like base match() while ip.index() can be used for range queries. The IP package make match() generic to avoid unwanted effects of method dispatch in code using the package. But note that, unfortunately, this won't change the behaviour of match() in other packages (see caveat section in the package description).

match() and ip.match() behave differently according to their signature. When table is of class IPv4 or IPv6, ip.match() does a table lookup like base match(). But when table is an IP range and the x argument is not, both look for the range x lies into. If you want to test whether a range lies within another range, use the function returned by the ip.index() method (see example).

When arguments are of the same class, match() simply call base match() on the character representation while ip.match() uses hash tables. Range search uses a binary search tree. Beware that binary search can only handle non overlapping IP* ranges by default. Use overlap=TRUE to allow for overlap (only implemented for IPv4 and Ipv4r at the moment). Note that this also allows for multiple matches. As a consequence, result vector might be longer that input vector and therefore needs specialized data structures and access methods inspired by the compressed column storage of sparse matrices. See the example section for testing for overlap and lookup.

Also, the incomparable argument for match() or unique() is not implemented yet.

Examples

Run this code
# NOT RUN {
## 
x  <- ipv4(0L) + sample.int(10)
x[order(x)]
sort(x)
##
x  <- ipv6(0L) + sample.int(10)
## a tad faster than order()
x[ip.order(x)]

# }
# NOT RUN {
##
## matching the address space of a wifi interface on a GNU/Linux box
## notes: the name of the interface might change depending on the distribution 
##       you're using among other things and the localhost.ip() function 
##       only works for POSIX platforms at the moment
## 
ipv4.reserved()[match(ipv4(localhost.ip())['wlp2s0'], ipv4.reserved() )]
## alternatively, if tables has to be looked up several time
m <- ip.index(ipv4.reserved())
m(ipv4(localhost.ip())['wlp2s0'])
# }
# NOT RUN {

##
## ip.match() and ip.index() comparison
##
##
## index the table
bidx <- ip.index(ipv4.reserved())
## "169.254.0.0/16"
x <- ipv4.reserved()['Link Local']
## match
ip.match(x, ipv4.reserved() )
## match
ipv4.reserved()[bidx(x)]
## a range that lies within "169.254.0.0/16"
x <- ipv4r("169.254.0.0/24")
## no match ("169.254.0.0/24"!="169.254.0.0/16")
ip.match(x, ipv4.reserved() )
## match ("169.254.0.0/24" \in "169.254.0.0/16")
ipv4.reserved()[bidx(x)]

##
## overlap
## 
## this demonstrates that ranges in ipv4.reserved() overlap
##
## range match
m <- (
  ip.index(ipv4.reserved())
)(value=TRUE)
##
all(m==ipv4.reserved())
## OTH exact match works as expected
all(ipv4.reserved()[ip.match(ipv4.reserved(),ipv4.reserved())]==ipv4.reserved())
##
## find overlapping ranges (pure R)
##
ipr.overlaps <- function(x, y, rm.diag  = FALSE){
  overlaps <- function(x,y) ( lo(x) <= hi(y) ) & ( hi(x) >= lo( y))
  x <- x[!is.na(x)]
  y <- if( missing(y) ) x else y[!is.na(y)]
  rv <- outer( x , y, overlaps)
  if( rm.diag) diag(rv) <- 0
  ij <- which(rv>0,arr.ind = TRUE)
  data.frame(nm=names(x)[ij[,1]], x=x[ij[,1]], y=y[ij[,2]])
}
##
ipr.overlaps(ipv4.reserved(),rm.diag=TRUE)
##
## find *overlapping* ranges (IP package)
##
bsearch <- ip.index(ipv4.reserved(), overlap=TRUE)
##
m <- bsearch()
## matches indices
midx <- attr(m, "midx") 
## start indices for each address in the midx vector
## (diff(ptr) gives the number of matches per address)
ptr  <- attr(m, "ptr")
##
data.frame(
   x=rep(m, diff(ptr)), tbl = ipv4.reserved()[midx]
   , nm = names(ipv4.reserved()[midx])
)
# }

Run the code above in your browser using DataLab