Class: MemoryIO::Types::CPP::String

Inherits:
Type
  • Object
show all
Defined in:
lib/memory_io/types/cpp/string.rb

Overview

The ‘std::string` class in C++11.

The std::string class can be seen as:

class string {
  void* _M_dataplus;
  size_t string_length;
  union {
    char local_buf[15 + 1];
    size_t allocated_capacity;
  }
};

Constant Summary collapse

LOCAL_CAPACITY =

std::string uses inlined-buffer if string length isn’t larger than LOCAL_CAPACITY.

15

Constants inherited from Type

Type::SIZE_T

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Type

find, keep_pos, read_size_t, register, write_size_t

Constructor Details

#initialize(data, capacity, dataplus) ⇒ String

Instantiate a MemoryIO::Types::CPP::String object.

Parameters:

  • data (::String)
  • capacity (Integer)
  • dataplus (Integer)

    A pointer.



35
36
37
38
39
# File 'lib/memory_io/types/cpp/string.rb', line 35

def initialize(data, capacity, dataplus)
  @data = data
  @capacity = capacity
  @dataplus = dataplus
end

Instance Attribute Details

#capacityInteger (readonly)

Returns:

  • (Integer)


26
27
28
# File 'lib/memory_io/types/cpp/string.rb', line 26

def capacity
  @capacity
end

#data::String

Returns:

  • (::String)


25
26
27
# File 'lib/memory_io/types/cpp/string.rb', line 25

def data
  @data
end

#dataplusInteger (readonly)

Returns:

  • (Integer)


27
28
29
# File 'lib/memory_io/types/cpp/string.rb', line 27

def dataplus
  @dataplus
end

Class Method Details

.read(stream) ⇒ CPP::String

Examples:

# echo '#include <string>\n#include <cstdio>\nint main() {' > a.cpp && \
# echo 'std::string a="abcd"; printf("%p\\n", &a);' >> a.cpp && \
# echo 'scanf("%*c"); return 0;}' >> a.cpp && \
# g++ -std=c++11 a.cpp -o a
Open3.popen2('stdbuf -o0 ./a') do |_i, o, t|
  process = MemoryIO.attach(t.pid)
  addr = o.gets.to_i(16)
  process.read(addr, 1, as: :string) # or `as: :'cpp/string'`
  #=> #<MemoryIO::Types::CPP::String @data="abcd", @capacity=15, @dataplus=0x00007ffe539ca250>
end

Parameters:

  • stream (#pos, #pos=, #read)

Returns:



87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/memory_io/types/cpp/string.rb', line 87

def read(stream)
  dataplus = read_size_t(stream)
  length = read_size_t(stream)
  union = stream.read(LOCAL_CAPACITY + 1)
  if length > LOCAL_CAPACITY
    capacity = MemoryIO::Util.unpack(union[0, Type::SIZE_T])
    data = keep_pos(stream, pos: dataplus) { |s| s.read(length) }
  else
    capacity = LOCAL_CAPACITY
    data = union[0, length]
  end
  new(data, capacity, dataplus)
end

.write(stream, obj) ⇒ void

This method returns an undefined value.

Write a MemoryIO::Types::CPP::String object to stream.

Parameters:



107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/memory_io/types/cpp/string.rb', line 107

def write(stream, obj)
  write_size_t(stream, obj.dataplus)
  write_size_t(stream, obj.length)
  pos = stream.pos
  if obj.length > LOCAL_CAPACITY
    keep_pos(stream, pos: obj.dataplus) { |s| s.write(obj.data + "\x00") }
    write_size_t(stream, obj.capacity)
  else
    stream.write(obj.data + "\x00")
  end
  stream.pos = pos + LOCAL_CAPACITY + 1
end

Instance Method Details

#inspectString

TODO:

Let it be colorful in pry.

Custom inspect view.

Returns:



63
64
65
66
67
68
69
# File 'lib/memory_io/types/cpp/string.rb', line 63

def inspect
  format("#<%s @data=%s, @capacity=%d, @dataplus=0x%0#{SIZE_T * 2}x>",
         self.class.name,
         data.inspect,
         capacity,
         dataplus)
end

#lengthInteger Also known as: size

String length.

Returns:

  • (Integer)


44
45
46
# File 'lib/memory_io/types/cpp/string.rb', line 44

def length
  @data.size
end