class Subnets::Net4

Public Class Methods

new(p1, p2) click to toggle source
VALUE
method_net4_new(VALUE class, VALUE address, VALUE prefixlen) {
  net4_t net;
  net.address = RB_NUM2UINT(address);
  net.prefixlen = NUM2INT(prefixlen);
  if (!(net.prefixlen >= 0 && net.prefixlen <= 32)) {
    rb_raise(rb_eArgError, "prefixlen must be in range [0,32], was %d", net.prefixlen);
  }
  net.mask = mk_mask4(net.prefixlen);
  return net4_new(class, net);
}
parse(p1) click to toggle source

Parse s as an IPv4 network in CIDR notation.

@param [String] s @return {Net4} @raise {Subnets::ParseError}

VALUE
method_net4_parse(VALUE class, VALUE s) {
  const char *buf = StringValueCStr(s);

  net4_t net;
  if (!read_net4_strict(buf, &net)) {
    raise_parse_error("net4", buf);
  }
  return net4_new(class, net);
}
random(p1 = v1) click to toggle source

@overload random(rng=Random.new)

@param rng [#rand] (optional) a random number generator

@return [Net4] a random Net4 address

VALUE
method_net4_random(int argc, VALUE *argv, VALUE class) {
  net4_t net;
  VALUE rng, rand;

  rb_scan_args(argc, argv, "01", &rng);
  if (Qnil == rng) {
    rng = rb_funcall(rb_cRandom, rb_intern("new"), 0);
  }

  rand = rb_intern("rand");
  net.address = FIX2INT(rb_funcall(rng, rand, 1, INT2FIX(0xffff+1)));
  net.address |= FIX2INT(rb_funcall(rng, rand, 1, INT2FIX(0xffff+1))) << 16;
  net.prefixlen = FIX2INT(rb_funcall(rng, rb_intern("rand"), 1, INT2FIX(32+1)));
  net.mask = mk_mask4(net.prefixlen);

  return net4_new(class, net);
}
summarize(p1) click to toggle source

@return [Subnets::Net4] the smallest subnet that includes all of the subnets in nets

@param nets [Array<Subnets::Net4>]

VALUE
method_net4_summarize(VALUE class, VALUE nets) {
  net4_t result;

  for (ssize_t i = 0; i < RARRAY_LEN(nets); i++) {
    const net4_t *net;
    VALUE rbnet = RARRAY_AREF(nets, i);

    assert_kind_of(rbnet, Net4);

    Data_Get_Struct(rbnet, net4_t, net);

    if (i == 0) {
      result.address = (net->address & net->mask);
      result.prefixlen = net->prefixlen;
      result.mask = net->mask;
    } else {
      while (result.prefixlen > net->prefixlen ||
             result.address != (net->address & result.mask)) {
        result.prefixlen = MIN(result.prefixlen-1, net->prefixlen);
        result.mask = mk_mask4(result.prefixlen);
        result.address &= result.mask;
      }
    }
  }

  return net4_new(class, result);
}

Public Instance Methods

==(p1) click to toggle source

@return [Boolean]

VALUE
method_net4_eql_p(VALUE self, VALUE other) {
  net4_t *a, *b;

  if (CLASS_OF(other) != CLASS_OF(self)) {
    return Qfalse;
  }

  Data_Get_Struct(self, net4_t, a);
  Data_Get_Struct(other, net4_t, b);

  if (a->prefixlen != b->prefixlen) {
    return Qfalse;
  }
  if (a->address != b->address) {
    return Qfalse;
  }
  return Qtrue;
}
Also aliased as: eql?
===(p1)

Test if this network includes v.

A String must parse as an IP4 or Net4. An IP4 must be included within the range defined by this network. A Net4 must both have a prefixlen greater than or equal to that of this network, and have an address included within the range defined by this network.

@param [String, IP, Net] v

Alias for: include?
address() click to toggle source
VALUE
method_net4_address(VALUE self) {
  net4_t *net;
  Data_Get_Struct(self, net4_t, net);
  return ip4_new(IP4, net->address);
}
eql?(p1)

@return [Boolean]

Alias for: ==
hash() click to toggle source

@return [Integer]

VALUE
method_net4_hash(VALUE self) {
  net4_t *net;
  Data_Get_Struct(self, net4_t, net);
  return xor(hash(INT2FIX(net->prefixlen)), hash(UINT2NUM(net->address)));
}
include?(p1) click to toggle source

Test if this network includes v.

A String must parse as an IP4 or Net4. An IP4 must be included within the range defined by this network. A Net4 must both have a prefixlen greater than or equal to that of this network, and have an address included within the range defined by this network.

@param [String, IP, Net] v

VALUE
method_net4_include_p(VALUE self, VALUE v) {
  net4_t *net;
  Data_Get_Struct(self, net4_t, net);

  if (CLASS_OF(v) == IP4) {
    ip4_t *ip;
    Data_Get_Struct(v, ip4_t, ip);
    return net4_include_p(*net, *ip) ? Qtrue : Qfalse;
  } else if (CLASS_OF(v) == Net4) {
    net4_t *other;
    Data_Get_Struct(v, net4_t, other);
    return net4_include_net4_p(*net, *other) ? Qtrue : Qfalse;
  } else if (CLASS_OF(v) == IP6 || CLASS_OF(v) == Net6) {
    return Qfalse;
  } else {
    v = StringValue(v);

    {
      net4_t other;
      if (read_net4_strict(RSTRING_PTR(v), &other)) {
        return net4_include_net4_p(*net, other) ? Qtrue : Qfalse;
      }
    }
    {
      ip4_t ip;
      if (read_ip4_strict(RSTRING_PTR(v), &ip)) {
        return net4_include_p(*net, ip) ? Qtrue : Qfalse;
      }
    }

    return Qfalse;
  }
}
Also aliased as: ===
mask() click to toggle source
VALUE
method_net4_mask(VALUE self) {
  net4_t *net;
  Data_Get_Struct(self, net4_t, net);
  return ip4_new(IP4, net->mask);
}
prefixlen() click to toggle source

The prefix length of this network, or number of leading ones in the netmask.

@return [Fixnum]

VALUE
method_net4_prefixlen(VALUE self) {
  net4_t *net;
  Data_Get_Struct(self, net4_t, net);
  return INT2FIX(net->prefixlen);
}
to_s() click to toggle source

Return a String in CIDR notation.

@return [String]

VALUE
method_net4_to_s(VALUE self) {
  net4_t *net;
  char buf[32];

  Data_Get_Struct(self, net4_t, net);
  net4_snprint(*net, buf, 32);
  return rb_str_new2(buf);
}