Change integer into hex Ruby - ruby

I am currently porting a perl project to ruby and all has been going fine until I reached this pack statement.
$move .= pack('W', int($length));
I understand what it's trying to do, but I can't find any documentation on the 'W' option for perls pack method. So it is a bit hard to find a suitable replacement for ruby.
What this statement does is takes the integer, and converts it to a big endian hex format (I believe).
For example the integer 290 is converted to 0x122, and is then stored as "2201" in the variable $move
Although I cannot confirm that because I can't find documentation on 'W' although it would make sense based on what the rest of the project is doing.
Does anyone know a ruby replacement method that would do the same?
edit: As per a comment below I have found it with some help.
W An unsigned char value (can be greater than 255).

Since the format's introduction in 5.10, pack says:
W An unsigned char value (can be greater than 255).
For example, the following are equivalent:
pack('W', 0x2660)
chr(0x2660)
"\x{2660}"
For all values of $i, length(pack('W', $i)) is one.
What's the size of a character (string element) in Ruby? Are they 8 bits like C, or larger like Java (16) and Perl (32 or 64)?
If they are limited to 8 bits, there is no direct equivalent of that code in Ruby. You'll need to use an array instead of a string.
If Ruby's character are wide enough to contain the numbers in question (e.g. 290), then a look through the Ruby docs reveals the following:
i.chr

Related

When using a convert char to ASCII value routine, need to find out what values it is actually returning as they are not strictly ascii

When testing my code that uses a routine that checks for chars to show using an ASCII value routine, my program should drop control chars but keep chars that may be entered by the user. It seems that while the ASCII value routine is called "ascii", it does not just return ascii values: giving it a char of ƒ returns 402.
For example have found this web site
but it doesn't have ƒ 402 that I can see.
Need to know whether there are other ascii codes above 402 that I need to test my code with. The character set used internally by the software that 'ascii' is written in uses UCS2. The web site found doesn't mention USC2.
There are probably many interpretations ouf »Control Character« out there, but I'll assume you mean C0 and C1 control characters (includes references to the relevant Unicode Standards).
The commonly used 32-bit integer representation of Unicode characters in general is the codepoint notation: »U+« followed by a at least 4 digit positive hex number, which you will find near mentions of characters, e.g. as in »U+007F (delete)«. The result of your »ASCII value« routine will probably be this number without the »U+«;
UCS-2 is a specific encoding for Unicode characters, which you probably won't need to care about directly), and is equivalent to Unicode codepoints for all characters within the the range of the BMP only.

Preventing converting string into octal number in Ruby

Assume we have following ruby code
require 'yaml'
h={"key"=>[{"step1"=>["0910","1223"]}]}
puts h.to_yaml
"0910" is a string
but after to_yaml conversion, string turns into octal number.
---
key:
- step1:
- 0910
- '1223'
the problem is I cannot change h variable. I receive it from outside, and I need to solve problem without changing it.
You are mistaken that there is an octal number in your YAML output. The YAML spec refers to octal on two occasions, and both clearly indicate that an octal number in a YAML file starts with 0o (which is a similar to what Ruby and newer versions of Python use for specifying octal; Python also dropped the support for 0 only octals in version 3, Ruby doesn't seem to have done that—yet).
The custom to indicate octal integers starting with a 0 only, has been proven confusing in many language and was dropped from the YAML specification six years ago. It might be that your parser still supports it, but it shouldn't.
In any case the characters 8 and 9 can never occur in an integer represented as an octal number, so in this case there can be no confusion that that unquoted scalar is a number.
The string 1223 could be interpreted as a normal integer, therefore it must always be represented as a quoted string scalar.
The interesting thing would be to see what happens when you dump the string "0708". If your YAML library is up-to-date with the spec (version 1.2) it can just dump this as an unquoted scalar. Because of the leading zero that is not followed by o (or x) there can be no confusion that this could be an octal number (resp. hexadecimal) either, but for compatibility with old parsers (from before 2009) your parser might just quote it to be on the safe side.
According the the YAML spec numbers prefixed with a 0 signal an octal base (as does in Ruby). However 08 is not a valid octal number, so it doesn't get quoted.
When you come to load this data from the YAML file, the data appears exactly as you need.
0> h={"key"=>[{"step1"=>["0910","1223"]}]}
=> {"key"=>[{"step1"=>["0910", "1223"]}]}
0> yaml_h = h.to_yaml
=> "---\nkey:\n- step1:\n - 0910\n - '1223'\n"
0> YAML.load(yaml_h)
=> {"key"=>[{"step1"=>["0910", "1223"]}]}
If you can't use the data in this state perhaps you could expand on the question and give more detail.
There was a similar task.
I use in secrets.yml:
processing_eth_address: "0x5774226def39e67d6afe6f735f9268d63db6031b"
OR
processing_eth_address: <%= "\'#{ENV["PROCESSING_ETH_ADDRESS"]}\'" %>
My Ruby doesn't do this octal conversion but I had a similar issue with dates. I used to_yaml(canonical: true) to get around this issue. It's more verbose but it's correct.
{"date_of_birth" => "1991-02-29"}.to_yaml
=> "---\ndate_of_birth: 1991-02-29\n"
{"date_of_birth" => "1991-02-29"}.to_yaml(canonical: true)
=> "---\n{\n ? \"date_of_birth\"\n : \"1991-02-29\",\n}\n"

Create a SHA1 hash in Ruby via .net technique

OK hopefully the title didn't scare you away. I'm creating a sha1 hash using Ruby but it has to follow a formula that our other system uses to create the hash.
How can I do the following via Ruby? I'm creating hashes fine - but the format stuff is confusing me - curious if there's something equiv in the Ruby standard library.
System Security Cryptography (MSDN)
Here's the C# code that I'm trying to convert to Ruby. I'm making my hash fine, but not sure about the 'String.Format("{0,2:X2}' part.
//create our SHA1 provider
SHA1 sha = new SHA1CryptoServiceProvider();
String str = "Some value to hash";
String hashedValue; -- hashed value of the string
//hash the data -- use ascii encoding
byte[] hashedDataBytes = sha.ComputeHash(Encoding.ASCII.GetBytes(str));
//loop through each byte in the byte array
foreach (byte b in hashedDataBytes)
{
//convert each byte -- append to result
hashedValue += String.Format("{0,2:X2}", b);
}
A SHA1 hash of a specific piece of data is always the same hash (effectively just a large number), the only variation should be how you need to format it, to e.g. send to the other system. Although particularly obscure systems might post-process the data, truncate it or only take alternate bytes etc.
At a very rough guess from reading the C# code, this ends up a standard looking 40 character hex string. So my initial thought in Ruby is:
require 'digest/sha1'
Digest::SHA1.hexdigest("Some value to hash").upcase
. . . I don't know however what the force to ascii format in C# would do when it starts with e.g. a Latin-1 or UTF-8 string. They would be useful example inputs, if only to see C# throw an exception - you know then whether you need to worry about character encoding for your Ruby version. The data input to SHA1 is bytes, not characters, so which encoding to use and how to convert are parts of your problem.
My current understanding is that Encoding.ASCII.GetBytes will force anything over character number 127 to a '?', so you may need to emulate that in Ruby using a .gsub or similar, especially if you are actually expecting that to come in from the data source.

How to get a Ruby substring of a Unicode string?

I have a field in my Rails model that has max length 255.
I'm importing data into it, and some times the imported data has a length > 255. I'm willing to simply chop it off so that I end up with the largest possible valid string that fits.
I originally tried to do field[0,255] in order to get this, but this will actually chop trailing Unicode right through a character. When I then go to save this into the database, it throws an error telling me I have an invalid character due to the character that's been halved or quartered.
What's the recommended way to chop off Unicode characters to get them to fit in my space, without chopping up individual characters?
Uh. Seems like truncate and friends like to play with chars, but not their little cousins bytes. Here's a quick answer for your problem, but I don't know if there's a more straighforward and elegant question I mean answer
def truncate_bytes(string, size)
count = 0
string.chars.take_while{|c| (a += c.bytes.to_a.length) <= size }.join
end
Give a look at the Chars class of ActiveSupport.
Use the multibyte proxy method (mb_chars) before manipulating the string:
str.mb_chars[0,255]
See http://api.rubyonrails.org/classes/String.html#method-i-mb_chars.
Note that until Rails 2.1 the method was "chars".

Getting an ASCII character code in Ruby using `?` (question mark) fails

I'm in a situation where I need the ASCII value of a character (for Project Euler question #22, if you want to get specific) and I'm running into an issue.
Being new to ruby, I googled it, and found that ? was the way to go: ?A or whatever. But when I incorporate it into my code, the result of that statement is the string "A"—no character code. Same issue with [0] and slice(0), both of which should theoretically return the ASCII code.
The only thing I can think of is that this is a ruby version issue. I'm using 1.9.1-p0, having upgraded from 1.8.6 this afternoon. I cheated a little going from a working version of Ruby, in the same directory, I figured I probably already had the files that don't come bundled with the .zip file, so I didn't download them.
So why exactly are all my ASCII codes being turned into actual characters?
Ruby before 1.9 treated characters somewhat inconsistently. ?a and "a"[0] would return an integer representing the character's ASCII value (which was usually not the behavior people were looking for), but in practical use characters would normally be represented by a one-character string. In Ruby 1.9, characters are never mysteriously turned into integers. If you want to get a character's ASCII value, you can use the ord method, like ?a.ord (which returns 97).
How about
"a"[0].ord
for 1.8/1.9 portability.
Ruby Programming/ASCII
In previous ruby version before 1.9, you can use question-mark syntax.
?a
After 1.9, we use ord instead.
'a'.ord
For 1.8 and 1.9
?a.class == String ? ?a.ord : ?a
or
"a".class == String ? "a".ord : "a"[0]
Found the solution. "string".ord returns the ascii code of s.
Looks like the methods I had found are broken in the 1.9 series of ruby.
If you read question 22 from project Euler again you'll find you you are not looking for the ASCII values of the characters. What the question is looking for, for the character "A" for example is 1, its position in the alphabet where as "A" has an ASCII value of 65.

Resources