Equivalent of String#setbyte and String#getbyte in ruby 1.8 - ruby

Trying to get the aerospike ruby client to work under 1.8
What is the equivalent of these calls in ruby 1.8 ?
https://github.com/aerospike/aerospike-client-ruby/blob/master/lib/aerospike/utils/buffer.rb#L65
https://github.com/aerospike/aerospike-client-ruby/blob/master/lib/aerospike/utils/buffer.rb#L95

IIRC, Ruby 1.8 strings are, for all intents and purposes, what 1.9 would treat as ASCII-8BIT. As such, String#[] and String#[]= are the way to proceed as already suggested in the comments. (The same functions in 1.9 will target a potentially multibyte character at a certain offset, rather than a byte.)
For a more complete discussion on Ruby M17N and how strings changed in Ruby 1.9, see:
http://yokolet.blogspot.com/2009/07/design-and-implementation-of-ruby-m17n.html
http://yehudakatz.com/2010/05/05/ruby-1-9-encodings-a-primer-and-the-solution-for-rails/

Rather than rely on how a particular version of Ruby processes bytes/chars/strings, instead use the pack and unpack methods. They are always available and behave consistently.
For your use, unpack the data into an array, then you can use normal Array slicing to change the bytes in question, then pack everything back into the byte-stream.

Related

Can I write ruby 2.3.7 scripts that are backward compatible with 1.8.7?

Up till now, I've been writing all my scripts in POSIX shell so that I can run them on all the machines I use (macOS, various Linuxes, FreeBSD). I like to have a unified experience where I can pull down my dotfiles from git, and have all my settings and scripts ready to go.
However, POSIX shell is a really irritating language, and I've been considering switching to Ruby for my scripting needs. Unfortunately before I even got started, I realized that macOS ships with Ruby 2.3.7, and one of the machines I often need to use only has Ruby 1.8.7. It's a school machine for which I do not have sudo access, so I can't install a later version of Ruby.
TL;DR
Is it possible to write Ruby scripts that will run on both 1.8.7 and 2.3.7 (and hopefully everything in between)? Is there a set of guidelines I can follow that will help me avoid incompatible language features?
Yes, it is possible, provided you restrict yourself to the intersection of the language and library features of Ruby 1.8.7, Ruby 2.3.7, and everything in between.
The last big break of backwards-compatibility was the jump from Ruby 1.8 to Ruby 1.9. String handling was completely changed, so anything to do with text processing, you need to be very careful.
Of the top of my head:
In Ruby 1.8, strings are considered to be a sequence of bytes. In Ruby 1.9. strings are a factory for different iterators, iterating in terms of code points, characters, or bytes.
Therefore, in Ruby 1.9, strings are no longer Enumerable.
Indexing into a string will return an Integer in Ruby 1.8 and a single-character String in Ruby 1.9.
Character literals (e.g. ?a) will evaluate to an Integer in Ruby 1.8 and a single-character String in Ruby 1.9.
In Ruby 1.8, all strings are assumed to be in the same encoding (usually ASCII, but can be changed to a very limited set, namely UTF-8 and a couple of Asian encodings). Ruby 1.9 is fully encoding-aware, each string has its own separate encoding, each I/O stream has two encodings (an internal one and an external one) and each source file has a separate encoding.
Your best bet might be to restrict yourself to use only what is specified in the ISO Ruby Language Specification. The spec was specifically written so that all existing Ruby implementations at the time (MRI, YARV, IronRuby, JRuby, MacRuby, Rubinius) would automatically be compliant, which basically means that the spec only specifies the minimal required subset of the intersection of Ruby 1.8.6, Ruby 1.8.7, and Ruby 1.9.0.
Since there haven't been any backwards-incompatible changes since then, you can be assured that your code will work on all versions from Ruby 1.8.6 up to (but excluding) 3.0, and on all ISO-compliant Ruby implementations, which are as far as I know MRI, YARV, JRuby, IronRuby, Rubinius, MacRuby, MRuby, MagLev, and TruffleRuby.

How to implement string.codepoints for pre ruby 1.9.1

For backward compatibility reasons I want to implement the String#codepoints ruby method (introduced in 1.9.1).
I am thinking
def codepoints(str)
str.split('').map(&:ord)
end
but I am concerned that #ord will not work properly with earlier versions of ruby.
ord was introduced in Ruby 1.9.1, see APIDock.
For ASCII strings you can use #bytes, for Unicode it won't behave in the same way as #codepoints.
In Ruby 1.8.x you can use ? to get char numeric value, I don't know what to use for 1.9.0.
Btw rubies older than 2.3 are not supported any more, consider upgrading.

Different Marshal.dump output in ruby 1.9.2 vs ruby 1.9.3?

I'm having some issues when Marshalling dates - in particular, Marshal.dump is giving me different outputs for the same date, when I run it in ruby 1.9.2 and in ruby 1.9.3
In particular, when I run:
Marshal.dump(Date.tomorrow) in ruby 1.9.2, I get: "\x04\bU:\tDate[\bU:\rRational[\ai\x03\x9D\xF8Ji\ai\x00i\x03\x19\x15#"
When I run:
Marshal.dump(Date.tomorrow) in ruby 1.9.3, I get:
"\x04\bU:\tDate[\vi\x00i\x03O|%i\x00i\x00i\x00f\f2299161"
Is each version of ruby using a different Date format? (rational vs ??)
Thanks
Marshal is not guaranteed to be compatible across different versions. From documentation:
Marshaled data has major and minor version numbers stored along with the object information. In normal use, marshaling can only load data written with the same major version number and an equal or lower minor version number. If Ruby’s “verbose” flag is set (normally using -d, -v, -w, or –verbose) the major and minor numbers must match exactly. Marshal versioning is independent of Ruby’s version numbers. You can extract the version by reading the first two bytes of marshaled data.

How to match regexp starting from specific character index in Ruby 1.8?

In Ruby 1.9 I would use String#match(regexp,start_index). I'm sure there must be a (computationally efficient) equivalent in Ruby 1.8, but I can't find it. Do you know what it is?
You could start the regexp with ^.{start_index}
or take the substring first before performing the match.
Alternatively, if you're constrained to using Ruby 1.8, but can install your own libraries then you could use Oniguruma.
As far as I can tell, there is no efficient way to match a Regexp against a large string, starting from an arbitrary index, in pure Ruby 1.8.
This seems like a major flaw. I guess the moral of the story is: use Ruby 1.9!

What are the major differences between Ruby 1.8.6 and 1.9.1? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between Ruby 1.8 and Ruby 1.9
I have found some differences in interpretation of global and local variables.
Can anyone point me to list of major differences?
These are probably the most important changes:
Ruby 1.9 changed from being
interpreted to being
bytecode-compiled (using the YARV
VM).
The String class has been redesigned
entirely to make it encoding-aware.
Regular expressions are now
implemented using the Oniguruma
engine, rather than the home-made one
used in ruby 1.8, enabling new
features like negative look-around.
The enumerator library from stdlib
has been added to core and most
Enumerable methods have been
changed to return an Enumerator
when invoked without a block.
Symbol#to_proc has been added.
There's a new syntax for lambdas,
-> which allows default arguments
and lambdas taking blocks.
There's a more complete list of changes here.
One major point might be that they use a different VM (at least, the 'standard' distributions do, obviously there are a number of options like MacRuby, IronRuby, etc). You might have a look here for details on all the changes.

Resources