Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Javascript left shift 2

Status
Not open for further replies.

MarkZK

Technical User
Jul 13, 2006
202
0
0
GB
Hello all,

I'm trying to compile a server side dll with vb6 from some asp (vbscript), only within the vbscript is a piece of javascript that I can't leave in for obvious reasons, in the comments it says that vbscript has no left shift, my question is, does vb6 have a fix for this so I can change the function.
Thanks for reading

here's the code,

Code:
<script runat="server" language="JavaScript">
// VBScript is missing Left Shift, so this fixes that 
function leftshift(op,n) {
	return op << n;
}
</script>
and the asp if needed
Code:
<%
Class CountryLookup
	Private COUNTRY_BEGIN
	Private countryCode 
	Private countryName
	Private objStream
	Private mIntError
	Private mStrError
		
	private sub class_initialize
		set objStream = Server.CreateObject("ADODB.Stream")	
		COUNTRY_BEGIN = 16776960
		countryCode = Array("N/A","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN","AO","AQ",
"AR","AS","AT","AU","AW","AZ","BA","BB","BD","BE","BF","BG","BH","BI","BJ",
"BM","BN","BO","BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD","CF","CG",
"CH","CI","CK","CL","CM","CN","CO","CR","CU","CV","CX","CY","CZ","DE","DJ",
"DK","DM","DO","DZ",_
"EC","EE","EG","EH","ER","ES","ET","FI","FJ","FK","FM","FO","FR","FX","GA",
"GB","GD","GE","GF","GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT","GU",
"GW","GY","HK","HM","HN","HR","HT","HU","ID","IE","IL","IN","IO","IQ","IR",
"IS","IT","JM","JO","JP","KE","KG","KH","KI","KM","KN","KP","KR","KW","KY",
"KZ",_
LA","LB","LC","LI","LK","LR","LS","LT","LU","LV","LY","MA","MC","MD","MG",
"MH","MK","ML","MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV","MW","MX",
"MY","MZ","NA","NC","NE","NF","NG","NI","NL","NO","NP","NR","NU","NZ","OM",
"PA","PE","PF","PG","PH","PK","PL","PM","PN","PR","PS","PT","PW","PY","QA",
_	
"RE","RO","RU","RW","SA","SB","SC","SD","SE","SG","SH","SI","SJ","SK","SL",
"SM","SN","SO","SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH","TJ","TK",
"TM","TN","TO","TP","TR","TT","TV","TW","TZ","UA","UG","UM","US","UY","UZ",
"VA","VC","VE","VG","VI","VN","VU","WF","WS","YE","YT","YU","ZA","ZM","ZR",
"ZW","A1","A2")
	
		countryName	= Array("N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles","Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados","Bangladesh","Belgium",_
							"Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia","Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the","Central African Republic","Congo","Switzerland","Cote D'Ivoire",_
							"Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica","Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic","Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji","Falkland Islands (Malvinas)",_
							"Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana","Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe",
"Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala","Guam","Guinea-Bissau","Guyana",_
							"Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia","Ireland",
"Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan","Japan","Kenya","Kyrgyzstan",
"Cambodia","Kiribati","Comoros","Saint Kitts and Nevis",_
							"Korea, Democratic People's Republic of","Korea, Republic of","Kuwait","Cayman Islands","Kazakstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania","Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar",_
							"Marshall Islands","Macedonia, the Former Yugoslav Republic of","Mali","Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius",
"Maldives","Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua","Netherlands",_
							"Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia","Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn","Puerto Rico","Palestinian Territory, Occupied","Portugal","Palau","Paraguay","Qatar","Reunion","Romania",
"Russian Federation","Rwanda","Saudi Arabia",_
							"Solomon Islands","Seychelles","Sudan","Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname","Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo",_
							"Thailand","Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","East Timor","Turkey","Trinidad and Tobago","Tuvalu","Taiwan, Province of China","Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines",_
							"Venezuela","Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Yugoslavia","South Africa","Zambia","Zaire","Zimbabwe","Anonymous Proxy","Satellite Provider")
	End Sub

	private sub class_terminate
		If IsObject(objStream) Then
			objStream.Close()
			Set objStream = Nothing
		End If
	end sub

	Public Property Get ErrNum(byref message)
		message = mStrError
		ErrNum = mIntError
	End Property

	Public Property Let GeoIPDataBase(filename)
		On Error Resume Next
		objStream.Type = 1 'adTypeBinary
		objStream.Open 
		objStream.LoadFromFile filename
		If Err.Number <> 0 Then
			mIntError = Err.Number
			mStrError = "Error: " & Err.Number & " Source: GeoIP.asp line 56: " & Err.Description
		End If
		On Error Goto 0
	End Property

	Public Function lookupCountryCode(addr)
		lookupCountryCode = countryCode(seekCountry(0, addrToNum(addr), 31))
	End Function

	Public Function lookupCountryName(addr)
		lookupCountryName = countryName(seekCountry(0, addrToNum(addr), 31))
	End Function

	Public Function addrToNum(addr)
		Dim arrIP : arrIP = split(addr,".")
		If Ubound(arrIP) = 3 Then
			addrToNum = Cdbl(16777216 * arrIP(0) + 65536 * arrIP(1) + 256 * arrIP(2) + arrIP(3))
		Else
			addrToNum = 0
		End If
	End Function
	
	Public Function numToAddr(ipnum)
		Dim w : w = Cstr(int ( ipnum / 16777216 ) Mod 256)
		Dim x : x = Cstr(int ( ipnum / 65536    ) Mod 256)
		Dim y : y = Cstr(int ( ipnum / 256      ) Mod 256)
		Dim z : z = Cstr(int ( ipnum            ) Mod 256)

		numToAddr = w & "." & x & "." & y & "." & z
	End Function

	Private Function ConvertBin2Array(Binary)
		Dim tmpArr()
	  	Dim i
		ReDim tmpArr(LenB(Binary))
		for i = 1 to LenB(Binary)
			tmpArr(i-1) = AscB(MidB(Binary,i,1))
		Next
		ConvertBin2Array = tmpArr
	End Function

	Private Function seekCountry(offset,ipnum,depth) 
	
		Dim buf,x(2)
		Dim i,j,y,shift
		
		if (depth = 0) Then
     		Err.Raise vbObjectError + 93, "GeoIP.asp", "Error seeking country"
			Exit Function
		End If

		objStream.Position = 0
		objStream.Position = 6 * offset
		buf = ConvertBin2Array(objStream.Read(6))
		
		For i = 0 to 1
			x(i) = 0
			For j = 0 to 2
				y = buf(i*3+j)
				If y < 0 Then 
					y = y + 256
				End If
				shift = j * 8
				x(i) = x(i) + leftshift(y,shift)
			Next
		Next
		If LongToUnsigned(UnsignedToLong(ipnum) AND leftshift(1,depth)) > 0 Then
			If (x(1) >= COUNTRY_BEGIN) Then
				seekCountry = x(1) - COUNTRY_BEGIN
				Exit Function
			End If
			seekCountry = seekCountry(x(1), ipnum, depth-1)
		Else		
			If (x(0) >= COUNTRY_BEGIN) Then
				seekCountry = x(0) - COUNTRY_BEGIN
				Exit Function
			End If
			seekCountry = seekCountry(x(0), ipnum, depth-1)
		End If		
	End Function


'****************************************************
' These two functions from Microsoft Article Q189323
' "HOWTO: convert between Signed and Unsigned Numbers"

	Function UnsignedToLong(value)
		Dim OFFSET_4 : OFFSET_4 = 4294967296
		Dim MAXINT_4 : MAXINT_4 = 2147483647

		If value < 0 Or value >= OFFSET_4 Then Err.raise(6) ' Overflow
		If value <= MAXINT_4 Then
			UnsignedToLong = value
		Else
			UnsignedToLong = value - OFFSET_4
		End If
	End Function

	Public Function LongToUnsigned(value)
		Dim OFFSET_4 : OFFSET_4 = 4294967296
		Dim MAXINT_4 : MAXINT_4 = 2147483647

		If value < 0 Then
			LongToUnsigned = value + OFFSET_4
		Else
			LongToUnsigned = value
		End If
	End Function

End Class
%>
 
Left shift is the same as multiply by 2 and drop any overflow - you can drop overflow by using the MOD operator. Make sure you're only doing it with unsigned numbers of course!

___________________________________________________________
If you want the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
Steam Engine Prints
 
Hi, Thanks,

so you're essentially saying that this,

Code:
<script runat="server" language="JavaScript">
// VBScript is missing Left Shift, so this fixes that
function leftshift(op,n) {
    return op << n;
}
</script>

function could have been,

Code:
Function leftshift(op,n)
 Dim shiftleft, i
 shiftleft = op
  For i = 0 To n - 1
   shiftleft = shiftleft * 2
  Next
 leftshift = shiftleft
End Function

I'm not completely familiar with all the operators, so, the overflow MOD thing you mentioned might be a bit beyond me right now.

Thanks again.
 
MOD is the operator that gives you the remainder from an Integer division. To avoid overflow on an integer datatype use MOD before each multipication. For instance if you are doing unsigned calculations then a sixteen-bit integer will overflow at 65536 - so if you do a MOD 32768 (which is 2^15) before the multiply you will ensure that the result fits in your 16-bit int.

___________________________________________________________
If you want the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
Steam Engine Prints
 
I see, thanks for that and you were right it do give me an overflow error which was fixed by using the Mod ...
Code:
   shiftleft = shiftleft MOD 32768 * 2
code, although the function must still need some tweeking as I get another error when using the VB function....
Code:
geoip.asp error '8004005d'

Error seeking country

/geoip.asp, line 121

In any case I have one more question if you have the time, do you know if I can use the Server.MapPath in a server DLL to get the data file ?
Code:
Server.MapPath("GeoIP.dat")

Or if maybe there's a way to complie it within the DLL somehow ?, thanks for your time.
 
You can always use JavaScript from VB ...
Code:
[blue]Public Function JavaLeftShift(op As Long, n As Long) As Long
    With CreateObject("msscriptcontrol.scriptcontrol")
        .Language = "jscript"
        JavaLeftShift = .Eval(op & "<<" & n)
    End With
End Function[/blue]

And here's a pure VB function that should produce the same results ('m not 100% happy with it; I think it could be streamlined slightly):
Code:
[blue]Public Function LeftShift(op As Long, n As Long) As Long
    n = n Mod 32
    LeftShift = op
    If n <> 0 Then LeftShift = (op And (2 ^ (32 - n)) - 1) * 2 ^ n * (1 + (2 * CLng((op And 2 ^ (31 - n)) <> 0)))
End Function[/blue]
 
Hi,

I spent around three hours on google groups and not one person mentioned anything about being able to use Javascript from within VB, I'm going to save that code snippet because I have a few things that I'd have like to use Javascript within a DLL, but, just passed the idea of as not possible, Thank you very much for that.

I'll use the VB function for this though, mainly because I'm so impressed that you managed to get a 30 plus function into one line of code, how do you even begin to start writing a calculation like that. ?

Thanks a lot.
 
>how do you even begin to start writing a calculation like that

Practice (and a little experience) ...
 
But it looks trickier than it actually is.

All I'm really doing is

[tt]op * 2 ^ n[/tt]

which is, as you have seen in other threads, one way of expressing shifting a value of 'op' left by 'n' bits

But you wanted a function that matches JavaScripts << operator, whuich handles 32-bit signed integers. So we need to avoid overflows when doing the calculation and correctly apply the sign bit.

To avoid the overflow we extend the idea that johnwm indicated, in that we mask off all the bits that would cause an overflow. In other words, if we are shifting left by 5 bits we need to mask off the top 5 bits. So generically I need to generate a mask value where only the bottom 32-n bits are set:

[tt] mask
(2 ^ (32 - n)) - 1[/tt]

I then AND this mask this with 'op', which will eliminate the top n bits

[tt](op AND mask )
(op And (2 ^ (32 - n)) - 1)[/tt]

This is our new 'op', which we then multiply by 2^n to achieve the basic left shift:

[tt](op AND mask ) shift left n bits
(op And (2 ^ (32 - n)) - 1) * 2 ^ n[/tt]

And now we need to apply a sign bit if necessary. We do this by examining the original op to see if the left shift would have put a bit into bit position 32:

[tt]See if sign bit is set
(op And 2 ^ (31 - n)) <> 0[/tt]

Trouble with this is that it returns True(-1) or False(0), and what we really need in order to apply the correct sign bit is -1 if the bit is set and +1 if the bit is not. And we do that by simply multiplying our true/false result by two (thus giving us -2 or 0) and adding that to 1, thus giving us -1 or +1

[tt][-1 if sign bit is to be set, +1 if not]
1 + (2 * CLng((op And 2 ^ (31 - m)) <> 0))[/tt]

And then we simply multiply our previous result (our basic left shift) by our sign bit calculation:

[tt](op AND mask ) shift left n bits [-1 if sign bit is to be set, +1 if not]
(op And (2 ^ (32 - n)) - 1) * 2 ^ n * 1 + (2 * CLng((op And 2 ^ (31 - m)) <> 0))[/tt]






 
Thanks for breaking that down for me Strongm, it's good to have a function that works, but, it's even better to be able to understand how/why it works.

Thanks again.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top