Varia {IP}R Documentation

Miscellaneous methods and functions for IP classes

Description

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

Details

Sorting

IP object may be efficiently sorted through call to R generic functions order() and sort() thanks to the xtfrm generic function. The IP package also provides the ip.order() which falls back to the default order method 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 an IP 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 ip.index() with overlap=TRUE to allow for overlap. 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.

ip.index() returns a function. Calling this function with the value argument set to TRUE returns the matched value and the indices of the matches otherwise. When both overlap and value are TRUE, the function returns a two–columns data.framewith x and the matching values in the table.

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

Examples

## 
x  <- ipv4(0L) + sample.int(10)
x[order(x)]
sort(x)

##
## matching the address space of a wifi interface on a GNU/Linux box 
## that uses Predictable Network Interface Names
## 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'])


##
## 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)
## FALSE because there are overlapping ranges and, in this case,
## the query returns the first matching range
all(m==ipv4.reserved())
## OTH match works as expected
all(ipv4.reserved()[ip.match(ipv4.reserved(),ipv4.reserved())]==ipv4.reserved())
##
## Find overlapping IPv4 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 IPv4 ranges (IP package)
##
bsearch <- ip.index(ipv4.reserved(), overlap=TRUE)
##
m <- bsearch()
## get the indices
idx <- getIdx(m)
## matches indices
midx <- idx$midx
## start indices for each address in the midx vector
## (diff(ptr) gives the number of matches per address)
ptr <- idx$ptr
##
subset(
  data.frame(
       nm  = names(ipv4.reserved()[midx])
     , x   = rep(m, diff(ptr))
     , tbl = ipv4.reserved()[midx]
     , n   = rep(diff(ptr), diff(ptr))
  )
  , n>1 & x!=tbl
)
##
## Same thing for IPv6r
##
ip.index(ipv6.reserved(), overlap=TRUE)(value=TRUE)

[Package IP version 0.1.3 Index]