I have compiled ruby 64 bit on an AIX Box.
There doesn't seem to be any issue except when I use some specific regular expressions in my code.
Here is an example:
/([0-9]){1000}/.match("2")
results in:
RegexpError: too big quantifier in {,}: /([0-9]*){1000}/
When I try reducing the number of repetitions, it seems to work.
I tried digging into the ruby code. But could not understand the reason.
Is this some dependency or restriction that we have in AIX/64 bit ruby?
Thanks in advance :)
I almost immediately found the answer.
The first thing I did was to search in the ruby source code for the error being thrown. I found that regex.h was responsible for this.
In regex.h, the code flow is something like this:
/* Maximum number of duplicates an interval can allow. */
#ifndef RE_DUP_MAX
#define RE_DUP_MAX ((1 << 15) - 1)
#endif
Now the problem here is RE_DUP_MAX. On AIX box, the same constant has been defined somewhere in /usr/include. I searched for it and found in
/usr/include/NLregexp.h
/usr/include/sys/limits.h
/usr/include/unistd.h
I am not sure which of the three is being used(most probably NLregexp.h). In these headers, the value of RE_DUP_MAX has been set to 255! So there is a cap placed on the number of repetitions of a regex!
In short, the reason is the compilation taking the system defined value than that we define in regex.h!
Hence the issue was solved by reassigning the value of RE_DUP_MAX in regex.h
i.e
# ifdef RE_DUP_MAX
# undef RE_DUP_MAX
# endif
# define RE_DUP_MAX ((1 << 15) - 1)
Cheers!
Related
I use lua to make some complex job to prepare arguments for macros in Tex/LaTex.
Part I
Here is a stupid minimal example :
\newcommand{\test}{\luaexec{tex.print("11,12")}}% aim to create 11,12
\def\compare#1,#2.{\ifthenelse{#1<#2}{less}{more}}
\string\compare11,12. : \compare11,12.\\ %answer is less
\string\test : \test\\ % answer is 11,12
\string\compare : \compare\test. % generate an error
The last line creates an error. Obviously, Tex did not detect the "," included in \test.
How can I do so that \test is understood as 11 followed by , followed by 12 and not the string 11,12 and finally used as a correctly formed argument for \compare ?
There are several misunderstandings of how TeX works.
Your \compare macro wants to find something followed by a comma, then something followed by a period. However when you call
\compare\test
no comma is found, so TeX keeps looking for it until finding either the end of file or a \par (or a blank line as well). Note that TeX never expands macros when looking for the arguments to a macro.
You might do
\expandafter\compare\test.
provided that \test immediately expands to tokens in the required format, which however don't, because the expansion of \test is
\luaexec{tex.print("11,12")}
and the comma is hidden by the braces, so it doesn't count. But it wouldn't help nonetheless.
The problem is the same: when you do
\newcommand{\test}{\luaexec{tex.print("11,12")}}
the argument is not expanded. You might use “expanded definition” with \edef, but the problem is that \luaexec is not fully expandable.
If you do
\edef\test{\directlua{tex.sprint("11,12")}}
then
\expandafter\compare\test.
would work.
In a rails 3.2 , ruby 1.9.3 app
Trying to perform a simple -1 action on an integer:
doing this on the model:
order_details[:quantity].to_i - 1
and getting the ArgumentError: invalid radix -1
Tried to look this up online , and found very little documentation.
Any help, pls?
I'm assuming order_details[:quantity] is a String (though the answer is the same regardless).
String#to_i takes an optional argument for the base the number is to be interpreted as. For instance "10101".to_i(2) will parse as base 2, (giving the decimal 21 as a result). Your line of code is being interpreted as
order_details[:quantity].to_i(-1)
and since a base of negative one (-1) makes no sense, it's giving you that error. The solution is to put parentheses around order_details[:quantity].to_i so that it's evaluated first:
(order_details[:quantity].to_i) - 1
Edit:
Or, make sure there's a space separating - from the two arguments (or no spaces on either side) and Ruby should parse it correctly. It might be that your actual code is written as order_details[:quantity].to_i -1 (note no space between - and 1) causing it to read -1 and then pass it as an argument to to_i.
I think your problem is that your code really looks like this:
order_details[:quantity].to_i -1 # with the minus sign right next to the one
Ruby is parsing this as:
order_details[:quantity].to_i(-1)
Method parameters do not (always) need to be wrapped in parenthesis in Ruby, and to_i takes a parameter that specifies the base in which you are counting.
So you could convert base 16 into our normal base ten like:
"0xA".to_i(16)
iamnotmaynard correctly identified it as a syntax error, but I think it's that you need to separate the - and 1. You could put parenthesis around the first element (it works), but that's more short-circuiting improper syntax instead of supplying proper syntax.
Try separating the elements out without parenthesis:
order_details[:quantity].to_i - 1 # with the space between the 1 and minus sign
I have a Lua script, where I'm trying to use hex numbers (0x..). If I run this script in the console, with the official Windows binaries, it works fine. But if I run it in my application (simple dofile), I get
malformed number near '0x1F'
It doesn't matter what the hex is, I always get that error, as if it wouldn't support them. The library I'm using is Lua 5.1.4, and I've tried 2 different ones (the first one being one I've compiled myself), so that shouldn't be the problem.
Does anyone have a clue what might be wrong here?
Edit:
It's not the script. No matter what I do, a simple "foo = 0xf" already triggers the error, even if there's nothing else in the file.
Update:
tonumber("0xf")
This returns nil, while
tonumber("15")
work fine. There's definitely something wrong with hex in my libs...
If hex literals aren't working for you (though they should), you can always use hex from lua by doing tonumber("fe",16)
Why do functions have to be different in different compilers, ...why?
Alright, the problem was that Lua tries to convert numbers into double by default. For this it uses the function "strtod", which takes 2 arguments, the string, and a char pointer. The char pointer is supposed to point to the last position after the parsed number. Which for a hex number would mean the 'x', after the '0'. If this isn't the case, Lua assumes an error, and gives us this nice little error message.
I've compiled Lua using DMC, because I need the lib to be in OMF, and I assume others used DMC as well. But apparently DMC's strtod works differenty, since the pointers always point to the start of the string if it's a hex... or rather any invalid number.
I've now added a little hack, which checks for the x, if conversion to double failed. Not pretty, but it works fine for now.
int luaO_str2d (const char *s, lua_Number *result) {
char *endptr;
*result = lua_str2number(s, &endptr);
/* Hack for DMC */
if (endptr == s)
if(*(s+1) == 'x' || *(s+1) == 'X')
endptr++;
else
return 0; /* conversion failed */
I faced this bug with lua5.2. Lua 5.1 works fine.
I would like to generate a completely random "unique" (I will ensure that using my model) identifier of a given (the length may varies) length containing numbers, letter and special characters
For example:
161551960578281|2.AQAIPhEcKsDLOVJZ.3600.1310065200.0-514191032|
Can someone please suggest the most efficient way to do that in Ruby on Rails?
EDIT: IMPORTANT:
If it is possible please comment on how efficient your proposed solution is because this will be used every time a user enters a website!
Thanks
Using this for an access token is a different story than UUIDs. You need not only pseudo-randomness but additionally this needs to be a cryptographically secure PRNG. If you don't really care what characters you use (they don't add anything to the security) you could use something as the following, producing a URL-safe Base64-encoded access token. URL-safeness becomes important in case you append the token to URLs, similar to what some Java web apps do: "http://www.bla.com/jsessionid=". If you would use raw Base64 strings for that purpose you would produce potentially invalid URLs.
require 'securerandom'
def produce_token(length=32)
token = SecureRandom.urlsafe_base64(length)
end
The probability of getting a duplicate is equal to 2^(-length). Since the output will be Base64-encoded, the actual output will be 4/3 * length long. If installed, this is based on the native OpenSSL PRNG implementation, so it should be pretty efficient in terms of performance. Should the OpenSSL extension not be installed, /dev/urandom will be used if available and finally, if you are on a Windows machine, CryptGenRandom would be used as fallback. Each of these options should be sufficiently performant. E.g., on my laptop running produce_tokena million times finishes in ~6s.
The best solution is:
require 'active_support/secure_random'
ActiveSupport::SecureRandom.hex(16) # => "00c62d9820d16b52740ca6e15d142854"
This will generate a cryptographically secure random string (i.e. completely unpredictable)
Similarly, you could use a library to generate UUIDs as suggested by others. In that case, be sure to use the random version (version 4) and make sure the implementation uses a cryptosecure random generator.
As anything related to security, rolling your own is not the best idea (even though I succumbed to it too, see first versions! :-). If you really want an homemade random string, here's a rewrite of tybro0103's approach:
require 'digest/sha1'
ALPHABET = "|,.!-0123456789".split(//) + ('a'..'z').to_a + ('A'..'Z').to_a
def random_string
not_quite_secure = Array.new(32){ ALPHABET.sample }.join
secure = Digest::SHA1.hexdigest(not_quite_secure)
end
random_string # => "2555265b2ff3ecb0a13d65a3d177b326733bc143"
Note that it hashes the random string, otherwise it could be subject to attack.
Performance should be similar.
Universally Unique Identifieres - UUIDs are tricky to generate yourself ;-) If you want something really reliable, use the uuid4r gem and call it with UUID4R::uuid(1). This will spit out a uuid based on time and a hardware id (the computers mac address). So it's even unique across multiple machines if generated at the exact same time.
A requirement for uuid4r is the ossp-uuid c library which you can install with the packetmanager of your choice (apt-get install libossp-uuid libossp-uuid-dev on debian or brew install ossp-uuid on a mac with homebrew for example) or by manually downloading and compiling it of course.
The advantage of using uuid4r over a manual (simpler?) implementation is that it is a) truly unique and not just "some sort of pseudo random number generator kind of sometimes reliable" and b) it's fast (even with higher uuid versions) by using a native extension to the c library
require 'rubygems'
require 'uuid4r'
UUID4R::uuid(1) #=> "67074ea4-a8c3-11e0-8a8c-2b12e1ad57c3"
UUID4R::uuid(1) #=> "68ad5668-a8c3-11e0-b5b7-370d85fa740d"
update:
regarding speed, see my (totally not scientific!) little benchmark over 50k iterations
user system total real
version 1 0.600000 1.370000 1.970000 ( 1.980516)
version 4 0.500000 1.360000 1.860000 ( 1.855086)
so on my machine, generating a uuid takes ~0.4 milliseconds (keep in mind I used 50000 iterations for the whole benchmark). hope that's fast enough for you
(following the "benchmark")
require 'rubygems'
require 'uuid4r'
require 'benchmark'
n = 50000
Benchmark.bm do |bm|
bm.report("version 1") { n.times { UUID4R::uuid(1) } }
bm.report("version 4") { n.times { UUID4R::uuid(4) } }
end
Update on heroku: the gem is available on heroku as well
def random_string(length=32)
chars = (0..9).to_a.concat(('a'..'z').to_a).concat(('A'..'Z').to_a).concat(['|',',','.','!','-'])
str = ""; length.times {str += chars.sample.to_s}
str
end
The Result:
>> random_string(42)
=> "a!,FEv,g3HptLCImw0oHnHNNj1drzMFM,1tptMS|rO"
It is a bit trickier to generate random letters in Ruby 1.9 vs 1.8 due to the change in behavior of characters. The easiest way to do this in 1.9 is to generate an array of the characters you want to use, then randomly grab characters out of that array.
See http://snippets.dzone.com/posts/show/491
You can check implementations here I used this one
I used current time in miliseconds to generate random but uniqure itentifier.
Time.now.to_f # => 1656041985.488494
Time.now.to_f.to_s.gsub('.', '') # => "16560419854884948"
this will give 17 digits number
sometime it can give 16 digits number because if last digit after point (.) is 0 than it is ignore by to_f.
so, I used rleft(17, '0')
example:
Time.now.to_f.to_s.gsub('.', '').ljust(17, '0') # => "1656041985488490"
Than I used to_s(36) to convert it into short length alphanumeric string.
Time.now.to_f.to_s.gsub('.', '').ljust(17, '0').to_i.to_s(36) # => "4j26hz9640k"
to_s(36) is radix base (36)
https://apidock.com/ruby/v2_5_5/Integer/to_s
if you want to limit the length than you can select first few digits of time in miliseconds:
Time.now.to_f.to_s.gsub('.', '').ljust(17, '0').first(12).to_i.to_s(36) # => "242sii2l"
but if you want the uniqueness accuracy in miliseconds than I would suggest to have atleast first(15) digits of time
I guess I just got used to saying things like:
x++
in PHP and Java land. But when I tried this in my Rails code it had a fit:
compile error
/users/gshankar/projects/naplan/app/views/answers/new.html.haml:19: syntax error, unexpected ';'
/users/gshankar/projects/naplan/app/views/answers/new.html.haml:23: syntax error, unexpected kENSURE, expecting kEND
...}\n", 0, false);_erbout;ensure;#haml_buffer = #haml_buffer.u...
^
/users/gshankar/projects/naplan/app/views/answers/new.html.haml:26: syntax error, unexpected $end, expecting kEND
I googled around a bit for Ruby/Rails operators for a reference to ++ but couldn't find anything. For a language which focuses on writing less I find it a bit strange that there wouldn't be a ++ equivalent. Am I missing something?
Try this:
x += 1
x+=1 is the best you can do in Ruby.
For a detailed explanation, see Why doesn't Ruby support i++ or i-- (increment/decrement operators)?
While as other answers point out x += 1 and x -= 1 is one way to do this. The closest Ruby gets to the --/++ operators are the prev()/next() (next has an alias of succ()) methods which return the previous/next items in sequence and are available on unambiguous strictly ordered classes (like String).
x = 4 # => 4
x.succ # => 5
x.prev # => 3
y = 'ABC' # => 'ABC'
y.succ # => 'ABD'
y.prev # => 'ABB'
Unfortunately, none of these implicitly do assignment which is what the original question was asking about. igul222's answer links to a post from Ruby's creator explaining why this is not possible.
Ruby has very powerful collection processing capabilities that eliminate most needs for these kinds of assignments. In all but the most complex alogrithms, which involve processing multiple collections at different rates in parallel. You should be asking yourself why you need increment/decrement. Because the Ruby way to do operations where increment and decrement operators are commonly used is with an iterator.
Such as each_with_index which executes a given block for each element/index pair in the array.
For example, this code will iterate through an array outputting the string representation fo each element and the parity of its index.
array = ["first", "second", "third","fourth","last"]
array.each_with_index do |object,index|
puts index % 2 ? "even" : "odd"
puts object.to_s
end
Edit: Removed Fixnum extension providing postfix increment because it doesn't work. Upon closer inspection there's nothing stopping you from adding it, but it would involve writing your feature in C, and a recompile.
Edit 2022: Added comment about prev/next/succ functions which are closer in behaviour to the decrement/increment function of --/++ operators
You have to use x+=1 instead.
http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Operators