cffunction / cfargument传递unsigned int32

时间:2017-04-03 04:01:59

标签: coldfusion coldfusion-11

我正在构建一个将unsigned int32转换为ipv4地址的函数,这一切都很有效,直到我用范围的上半部分进行测试。

<cffunction name="Int32ToIPv4" returntype="string" output="false" access="public" hint="returns IPv4 address for int32 number">
    <cfargument name="nInt32" type="numeric" required="yes" hint="int32 to convert to ipv4 address">

    <cfreturn
        bitAnd((arguments.nInt32 / 16777216), 255) & "."
        & bitAnd((arguments.nInt32 / 65536), 255) & "."
        & bitAnd((arguments.nInt32 / 256), 255) & "."
        & bitAnd(arguments.nInt32, 255)
    >
</cffunction>

ColdFusion似乎将type =“numeric”解释为签名 32位整数。

此示例有效:

Int32ToIPv4(nInt32 = 1181772947) = #Int32ToIPv4(nInt32 = 1181772947)# (expected value = 70.112.108.147)<br>

此示例失败:

Int32ToIPv4(nInt32 = 3401190660) = #Int32ToIPv4(nInt32 = 3401190660)# (expected value = 202.186.13.4)<br>

错误消息是:“无法将值3.40119066E9转换为整数,因为它无法放入整数内。”

在使用它之前,我是否必须将此数字作为字符串传递并将其转换为Java unsigned int?

我想在某些时候用ipv6地址(无符号128位整数)做类似的事情。任何有关此类数据类型的建议都将受到赞赏。

2 个答案:

答案 0 :(得分:3)

实际上bitAnd()强加了32位整数限制,而不是cfargument。

有趣的是,如果你单独检查每个计算,前三个(3)工作正常。由于划分,传递到bitAnd()的值实际上足够小以适合INT。但是,最后一个使用显然太大的原始值,这就是导致该特定数字的错误的原因。

 bitAnd(  (3401190660 / 16777216), 255 )  // Actual => 202.7267611032, 255
 bitAnd(  (3401190660 / 65536), 255 ) // Actual => 51898.05084233, 255
 bitAnd(  (3401190660 / 256), 255 )  // Actual =>13285901.0156, 255
 bitAnd(3401190660, 255) // Too big!

由于CF中的大多数相关数学函数都限制为32位整数,因此我不确定是否可以(或简单地)单独使用CF来完成。假设您使用的是Java 8+,您还可以访问新的无符号方法,如Integer.parseUnsignedInt(String)

我个人认为这将是一次很棒的学习练习。但是,除非您非常熟悉已签名与未签名的详细信息以及它与IP4和IP6地址的关系,否则您可能只想使用现有的Java库来避免常见的陷阱。例如Guava's InetAdress

// IP4
input = 3401190660;
uint = createObject("java", "java.lang.Integer").parseUnsignedInt(input);
inet = createObject("Java", "com.google.common.net.InetAddresses");
result = inet.fromInteger(uint).getHostAddress();

答案 1 :(得分:2)

我确实想出了一个原生Java解决方案,它涉及传入一个无符号的32位int。因此,@ Leigh对于cfargument正常工作是正确的。

<cffunction name="UInt32ToIPv4" returntype="string" output="no" access="public" hint="returns IPv4 address for uint32 number">
    <cfargument name="nUInt32" type="numeric" required="yes" hint="uint32 to convert to ipv4 address">

    <cfset local['JavaLangInteger'] = CreateObject("java", "java.lang.Integer")>
    <cfset local['JavaMathBigInteger'] = CreateObject("java", "java.math.BigInteger")>
    <cfset local['JavaNetInetAddress'] = CreateObject("java", "java.net.InetAddress")>

    <cfif arguments.nUInt32 EQ 0>
        <cfreturn "">
    </cfif>

    <cftry>
        <cfset local['vcIPv4'] = local.JavaNetInetAddress.getByAddress(local.JavaMathBigInteger.valueOf(local.JavaLangInteger.parseUnsignedInt(arguments.nUInt32)).toByteArray())>
        <cfreturn reReplace(local.vcIPv4, "[^0-9\.]", "", "all")>
        <cfcatch type="any">
            <cfreturn "">
        </cfcatch>
    </cftry>
</cffunction>

让我知道这个解决方案是否存在任何问题,因为我认为我将使用它而不是公共java库。

我已经编写了ipv6函数来处理转换(无符号128位int到/从ipv6)。不确定是否对这些功能感兴趣。如果有,我会用该代码创建单独的问题/答案。