Class: U::Buffer

Inherits:
Data
  • Object
show all
Defined in:
ext/u/rb_u_buffer.c,
lib/u-1.0/buffer.rb,
ext/u/rb_u_buffer.c

Overview

A buffer for building Strings. Buffers should be used when you want to create U::Strings step-wise, for example, when joining them together, or reading some input. Create a new buffer with #initialize, optionally specifying an initial size. Then, #append (or #<<) content to it. You can also #append_formatted content. You can check the #length (#size), #bytesize, and #width of the buffer, which can be useful if you want to limit how much content you want to generate. Once all content has been appended, a buffer can be converted to a U::String via #to_u or #to_u! depending on whether you want to let the buffer keep its content or not. You can also convert it to a String with #to_s.

Examples:

Benchmarking U::String#+ Versus U::Buffer#append/U::Buffer#to_u!

require 'benchmark'
require 'u-1.0'
Benchmark.bm do |x|
  x.report do
    a = ''.u
    100000.times do
      a = a + 'a'
    end
  end
  x.report do
   b = U::Buffer.new
    100000.times do
      b.append 'a'
    end
    a = b.to_u!
  end
end
# ⇒
#       user     system      total        real
#   3.560000   0.650000   4.210000 (  4.726064)
#   0.060000   0.000000   0.060000 (  0.057134)

Instance Method Summary collapse

Constructor Details

#new(size = 128) ⇒ Object

Sets up a new buffer of SIZE bytes.

Parameters:

  • size (#to_int) (defaults to: 128)


192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'ext/u/rb_u_buffer.c', line 192

static VALUE
rb_u_buffer_initialize(int argc, VALUE *argv, VALUE self)
{
        struct rb_u_buffer *buffer = RVAL2RBUBUFFER(self);
        VALUE rbsize;

        rb_scan_args(argc, argv, "01", &rbsize);
        long size = NIL_P(rbsize) ? 128 : NUM2LONG(rbsize);

        u_buffer_maybe_expand(buffer, size);

        return Qnil;
}

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Returns True if the receiver’s class and content equal those of OTHER.

Parameters:

Returns:

  • (Boolean)

    True if the receiver’s class and content equal those of OTHER



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'ext/u/rb_u_buffer.c', line 357

VALUE
rb_u_buffer_eql(VALUE self, VALUE rbother)
{
        if (self == rbother)
                return Qtrue;

        if (!RTEST(rb_obj_is_kind_of(rbother, rb_cUBuffer)))
                return Qfalse;

        const struct rb_u_buffer *buffer = RVAL2RBUBUFFER(self);
        const struct rb_u_buffer *other = RVAL2RBUBUFFER(rbother);

        return buffer->length == other->length &&
                memcmp(buffer->c, other->c, other->length) == 0 ?
                Qtrue : Qfalse;
}

#<<(*parts) ⇒ self Also known as: <<

Append each p in PARTS, append q to the receiver, where q = p#to_s, if p is a U::Buffer, q = p#chr, if p is a Fixnum or Bignum, q = p#to_str, if p is a U::String or responds to #to_str.

Parameters:

Returns:

  • (self)

Raises:

  • (RangeError)

    If a p is a Fixnum or Bignum and ¬p#chr#valid?



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'ext/u/rb_u_buffer.c', line 233

VALUE
rb_u_buffer_append_m(int argc, VALUE *argv, VALUE self)
{
        need_at_least_n_arguments(argc, 1);

        for (int i = 0; i < argc; i++)
                if (RTEST(rb_obj_is_kind_of(argv[i], rb_cUBuffer))) {
                        const struct rb_u_buffer *buffer = RVAL2RBUBUFFER(argv[i]);

                        rb_u_buffer_append(self, buffer->c, buffer->length);
                        OBJ_INFECT(self, argv[i]);
                } else if (FIXNUM_P(argv[i]) || TYPE(argv[i]) == T_BIGNUM) {
                        uint32_t c = NUM2UINT(argv[i]);

/* TODO: This depends on an experimental API.  Modify this once the API is
 * stable. */
#if 0
                        if (rb_num_to_uint(argv[i], &c) != 0) {
                                if (FIXNUM_P(argv[i]))
                                        rb_u_raise(rb_eRangeError,
                                                   "%ld out of char range",
                                                   FIX2LONG(argv[i]));
                                else
                                        rb_u_raise(rb_eRangeError,
                                                   "Bignum out of char range");
                        }
#endif

                        if (!u_char_isvalid(c))
                                rb_u_raise(rb_eRangeError,
                                           "invalid Unicode character: %u",
                                           c);

                        rb_u_buffer_append_char(self, c);
                } else {
                        const struct rb_u_string *string = RVAL2USTRING_ANY(argv[i]);

                        rb_u_buffer_append(self,
                                           USTRING_STR(string),
                                           USTRING_LENGTH(string));
                        OBJ_INFECT(self, argv[i]);
                }

        return self;
}

#append_format(format, *values) ⇒ self

Appends the result of FORMAT#%(values) to the receiver.

Parameters:

Returns:

  • (self)


1121
1122
1123
1124
1125
1126
1127
# File 'ext/u/rb_u_string_format.c', line 1121

VALUE
rb_u_buffer_append_format_m(int argc, const VALUE *argv, VALUE self)
{
        need_at_least_n_arguments(argc, 1);

        return rb_u_buffer_append_format(argc - 1, argv + 1, self, argv[0]);
}

#bytesizeInteger

Returns The number of bytes required to represent the receiver.

Returns:

  • (Integer)

    The number of bytes required to represent the receiver



328
329
330
331
332
333
# File 'ext/u/rb_u_buffer.c', line 328

VALUE
rb_u_buffer_bytesize(VALUE self)
{
        const struct rb_u_buffer *buffer = RVAL2RBUBUFFER(self);
        return UINT2NUM(buffer->length);
}

#hashFixnum

Returns The hash value of the receiver’s content.

Returns:

  • (Fixnum)

    The hash value of the receiver’s content



375
376
377
378
379
380
381
# File 'ext/u/rb_u_buffer.c', line 375

VALUE
rb_u_buffer_hash(VALUE self)
{
        const struct rb_u_buffer *buffer = RVAL2RBUBUFFER(self);

        return INT2FIX(rb_memhash(buffer->c, buffer->length));
}

#inspectObject



4
5
6
7
8
9
# File 'lib/u-1.0/buffer.rb', line 4

def inspect
  u = to_u
  u.length < 12 ?
    ('#<%s %s>' % [self.class, u]) :
    ('#<%s %s…%s>' % [self.class, u[0...5], u[-5..-1]])
end

#lengthInteger Also known as: size

Returns The number of characters in the receiver.

Returns:

  • (Integer)

    The number of characters in the receiver



320
321
322
323
324
325
# File 'ext/u/rb_u_buffer.c', line 320

VALUE
rb_u_buffer_length(VALUE self)
{
        const struct rb_u_buffer *buffer = RVAL2RBUBUFFER(self);
        return UINT2NUM(u_n_chars_n(buffer->c, buffer->length));
}

#to_sString

Returns A UTF-8-encoded string of the receiver’s content.

Returns:

  • (String)

    A UTF-8-encoded string of the receiver’s content



309
310
311
312
313
314
315
316
317
# File 'ext/u/rb_u_buffer.c', line 309

VALUE
rb_u_buffer_to_s(VALUE self)
{
        const struct rb_u_buffer *buffer = RVAL2RBUBUFFER(self);

        VALUE result = rb_u_str_new(buffer->c, buffer->length);
        OBJ_INFECT(result, self);
        return result;
}

#to_uU::String

Returns A UTF-8-encoded string of the receiver’s content.

Returns:

  • (U::String)

    A UTF-8-encoded string of the receiver’s content



280
281
282
283
284
285
286
# File 'ext/u/rb_u_buffer.c', line 280

VALUE
rb_u_buffer_to_u(VALUE self)
{
        const struct rb_u_buffer *buffer = RVAL2RBUBUFFER(self);

        return rb_u_string_new_c(self, buffer->c, buffer->length);
}

#to_u!U::String

Note:

This method differs from #to_u in that it doesn’t copy the result, so it’s generally faster; call it when you’re done building your String.

Returns The UTF-8-encoded string of the receiver’s content after clearing it from the receiver.

Returns:

  • (U::String)

    The UTF-8-encoded string of the receiver’s content after clearing it from the receiver



293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'ext/u/rb_u_buffer.c', line 293

VALUE
rb_u_buffer_to_u_bang(VALUE self)
{
        struct rb_u_buffer *buffer = RVAL2RBUBUFFER(self);

        char *c = buffer->c;
        long length = buffer->length;
        rb_u_buffer_reset(buffer);

        REALLOC_N(c, char, length + 1);
        c[length] = '\0';

        return rb_u_string_new_c_own(self, c, length);
}

#widthInteger

Returns the width of the receiver. The width is defined as the sum of the number of “cells” on a terminal or similar cell-based display that the characters in the string will require.

Characters that are String#wide? have a width of 2. Characters that are String#zero_width? have a width of 0. Other characters have a width of 1.

Returns:

  • (Integer)

See Also:



346
347
348
349
350
351
# File 'ext/u/rb_u_buffer.c', line 346

VALUE
rb_u_buffer_width(VALUE self)
{
        const struct rb_u_buffer *buffer = RVAL2RBUBUFFER(self);
        return UINT2NUM(u_width_n(buffer->c, buffer->length));
}