- Joined
- Nov 7, 2014

- Messages
- 571

chrord (to be confused with chord) is just that, the two functions chr and ord.

If you're not familiar then:

chr(<character-ordinal>) returns the character with that ordinal (we are talking ASCII here folks, forget about unicode)

and ord is the opposite (and kind of hard to implement in jass because nothing seems to be case sensitive, except 'Hpal', which doesn't help)

and of course there's no such native (or is it?)

So the most intresting thing about chrord is the way the ord function is implemented:

Wtf is GetLocalizedHotkey you might ask? Good question:

Normaliy it only works for strings like:

so how did we "teach" it about "A" .. "Z", "a" .. "z", "0" .. "9", "!@#$%^&*()", etc?

We imported a file of course!

It's called war3mapMisc.txt and it's full path MUST be "war3mapMisc.txt" (without the quotes of course).

Normally when you import a file from the Import Manager it's full path will be set to "war3mapImported\<name-of-file>".

So in order to correctly import the "special" war3mapMisc.txt (see attachments) you have to delete the "war3mapImported\"

part from the full path, otherwise it won't be picked up by war3 and will be ignored.

If your map happens to have a custom war3mapMisc.txt already then simply copy the content from this war3mapMisc.txt to yours.

That's it! Well... almost

Because war3mapMisc.txt is parsed by some parser Blizzard wrote (some kind of an ini file parser)

there are some characters ord fails with, and they are:

If you can't do without those then there's another module called Ascii that uses a different approach for ord

and of course you can do a linear search with this string (but DON'T!, it's going to be pretty slow):

So what good is ord anyway?

Well it's needed for base conversions think "hex2int", "Rawcode2Integer", base64 encoding/decoding, etc.

example:

So you might be thinking is chrord.ord faster than Ascii.Char2Ascii (what a silly name btw...)

and the answer is: they are "pretty much" the same speed =)

chrord

Edit: added chrord2 library

chrord2 uses a different method for implementing the

chrord2 requires the StringTable library

If you're not familiar then:

chr(<character-ordinal>) returns the character with that ordinal (we are talking ASCII here folks, forget about unicode)

JASS:

```
chr(65) => "A"
chr(97) => "a"
```

and ord is the opposite (and kind of hard to implement in jass because nothing seems to be case sensitive, except 'Hpal', which doesn't help)

and of course there's no such native (or is it?)

JASS:

```
ord("A") => 65
ord("a") => 97
```

So the most intresting thing about chrord is the way the ord function is implemented:

JASS:

```
function ord takes string s returns integer
local integer o = GetLocalizedHotkey(s)
// We care about lowercase letters
if c[o] != s then
return o + 32
endif
return o
endfunction
```

Wtf is GetLocalizedHotkey you might ask? Good question:

`native GetLocalizedHotkey takes string source returns integer`

Normaliy it only works for strings like:

JASS:

```
"GAMEOVER_QUIT_GAME"
"GAMEOVER_OK"
"GAMEOVER_CONTINUE_OBSERVING"
etc.
```

so how did we "teach" it about "A" .. "Z", "a" .. "z", "0" .. "9", "!@#$%^&*()", etc?

We imported a file of course!

It's called war3mapMisc.txt and it's full path MUST be "war3mapMisc.txt" (without the quotes of course).

Normally when you import a file from the Import Manager it's full path will be set to "war3mapImported\<name-of-file>".

So in order to correctly import the "special" war3mapMisc.txt (see attachments) you have to delete the "war3mapImported\"

part from the full path, otherwise it won't be picked up by war3 and will be ignored.

If your map happens to have a custom war3mapMisc.txt already then simply copy the content from this war3mapMisc.txt to yours.

That's it! Well... almost

Because war3mapMisc.txt is parsed by some parser Blizzard wrote (some kind of an ini file parser)

there are some characters ord fails with, and they are:

JASS:

```
ord("\r") => returns 32 instead of 13
ord("\n") => returns 32 instead of 10
ord("[") => returns 32 instead of 91
ord(" ") =>returns 32 (which is correct) but by "mistake"
```

If you can't do without those then there's another module called Ascii that uses a different approach for ord

and of course you can do a linear search with this string (but DON'T!, it's going to be pretty slow):

`" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"`

So what good is ord anyway?

Well it's needed for base conversions think "hex2int", "Rawcode2Integer", base64 encoding/decoding, etc.

example:

JASS:

```
library Rawcode uses chrord
function Rawcode2Integer takes string rawcode returns integer
local integer result = 0
set result = result + ord(SubString(rawcode, 0, 1)) * 0x01000000
set result = result + ord(SubString(rawcode, 1, 2)) * 0x010000
set result = result + ord(SubString(rawcode, 2, 3)) * 0x0100
set result = result + ord(SubString(rawcode, 3, 4)) * 0x01
return result
endfunction
function Integer2Rawcode takes integer rawcode returns string
local string result = ""
set result = chr(rawcode - rawcode / 0x100 * 0x100) + result
set rawcode = rawcode / 0x100
set result = chr(rawcode - rawcode / 0x100 * 0x100) + result
set rawcode = rawcode / 0x100
set result = chr(rawcode - rawcode / 0x100 * 0x100) + result
set rawcode = rawcode / 0x100
set result = chr(rawcode - rawcode / 0x100 * 0x100) + result
set rawcode = rawcode / 0x100
return result
endfunction
endlibrary
```

So you might be thinking is chrord.ord faster than Ascii.Char2Ascii (what a silly name btw...)

and the answer is: they are "pretty much" the same speed =)

chrord

JASS:

```
library chrord // to be confused with chord
globals
private constant boolean SANITY_CHECK = true
private string array c
endglobals
function chr takes integer i returns string
return c[i]
endfunction
function ord takes string s returns integer
local integer o = GetLocalizedHotkey(s)
// We care about lowercase letters
if c[o] != s then
return o + 32
endif
return o
endfunction
private module asap
private static method onInit takes nothing returns nothing
set c[8]="\b"
set c[9]="\t"
set c[10]="\n"
set c[12]="\f"
set c[13]="\r"
set c[32]=" "
set c[33]="!"
set c[34]="\""
set c[35]="#"
set c[36]="$"
set c[37]="%"
set c[38]="&"
set c[39]="'"
set c[40]="("
set c[41]=")"
set c[42]="*"
set c[43]="+"
set c[44]=","
set c[45]="-"
set c[46]="."
set c[47]="/"
set c[48]="0"
set c[49]="1"
set c[50]="2"
set c[51]="3"
set c[52]="4"
set c[53]="5"
set c[54]="6"
set c[55]="7"
set c[56]="8"
set c[57]="9"
set c[58]=":"
set c[59]=";"
set c[60]="<"
set c[61]="="
set c[62]=">"
set c[63]="?"
set c[64]="@"
set c[65]="A"
set c[66]="B"
set c[67]="C"
set c[68]="D"
set c[69]="E"
set c[70]="F"
set c[71]="G"
set c[72]="H"
set c[73]="I"
set c[74]="J"
set c[75]="K"
set c[76]="L"
set c[77]="M"
set c[78]="N"
set c[79]="O"
set c[80]="P"
set c[81]="Q"
set c[82]="R"
set c[83]="S"
set c[84]="T"
set c[85]="U"
set c[86]="V"
set c[87]="W"
set c[88]="X"
set c[89]="Y"
set c[90]="Z"
set c[91]="["
set c[92]="\\"
set c[93]="]"
set c[94]="^"
set c[95]="_"
set c[96]="`"
set c[97]="a"
set c[98]="b"
set c[99]="c"
set c[100]="d"
set c[101]="e"
set c[102]="f"
set c[103]="g"
set c[104]="h"
set c[105]="i"
set c[106]="j"
set c[107]="k"
set c[108]="l"
set c[109]="m"
set c[110]="n"
set c[111]="o"
set c[112]="p"
set c[113]="q"
set c[114]="r"
set c[115]="s"
set c[116]="t"
set c[117]="u"
set c[118]="v"
set c[119]="w"
set c[120]="x"
set c[121]="y"
set c[122]="z"
set c[123]="{"
set c[124]="|"
set c[125]="}"
set c[126]="~"
endmethod
endmodule
private struct init_asap extends array
implement asap
private static method sanity_check takes nothing returns nothing
local integer o
local boolean has_bug = false
set o = 32
loop
exitwhen o > 126
// "[" is special for the parser, it starts a new "section", bummer...
if c[o] != "[" then
if ord(c[o]) != o then
call BJDebugMsg("ord(\"" + c[o] + "\") !=" + I2S(o))
set has_bug = true
exitwhen true
endif
endif
set o = o + 1
endloop
if has_bug then
call BJDebugMsg("|cffFF0000" + "ERROR [library chrord]: you've either forgot to import war3mapMisc.txt, specified a wrong path for it or chrord is just buggy")
endif
endmethod
static if DEBUG_MODE then
private static method onInit takes nothing returns nothing
call sanity_check()
endmethod
endif
static if not DEBUG_MODE and SANITY_CHECK then
private static method onInit takes nothing returns nothing
call sanity_check()
endmethod
endif
endstruct
endlibrary
```

Edit: added chrord2 library

chrord2 uses a different method for implementing the

`ord`

function which is much faster (from my fps benchmarks =)) than `Ascii.Char2Ascii`

! it uses the string table to store the values of the "ord table" and the `GetStringId()`

to map the single character strings to integers.chrord2 requires the StringTable library

JASS:

```
library chrord2 uses StringTable
static if DEBUG_MODE then
globals
private constant boolean CHECK_ORD_TABLE_FOR_PROPER_INITIALIZATION = true
endglobals
endif
globals
private string array c // chr table
endglobals
function chr takes integer i returns string
return c[i]
endfunction
globals
private integer p // offset in the string table for the first ascii character ("\0")
endglobals
function ord takes string s returns integer
return GetStringId(s) - p
endfunction
struct chrord2 extends array
static method init_tables takes nothing returns nothing
local string s // = ""
// find the end of the StringTable
//
// StringTable[0] == null
set p = 1
loop
set s = StringTable
// exitwhen s == null // crashes =)
// exitwhen s == "" // doesn't work
exitwhen not(s != null) // doesn't crash, works!
set p = p + 1
endloop
// initialize the chr table and also implicitly initilize the ord table, i.e
// the lines:
//
// set c[0] = "\x00"
// set c[1] = "\x01"
// ...
//
// are "equivalent" to:
//
// local integer q = p
// set c[0] = "\x00"
// set StringTable[q] = "\x00"
// set q = q + 1
// set c[1] = "\x01"
// set StringTable[q] = "\x01"
// set q = q + 1
// ...
//
set c[0] = "\\x00"
set c[1] = "\\x01"
set c[2] = "\\x02"
set c[3] = "\\x03"
set c[4] = "\\x04"
set c[5] = "\\x05"
set c[6] = "\\x06"
set c[7] = "\\x07"
set c[8] = "\b"
set c[9] = "\t"
set c[10] = "\n"
set c[11] = "\\x0B"
set c[12] = "\f"
set c[13] = "\r"
set c[14] = "\\x0E"
set c[15] = "\\x0F"
set c[16] = "\\x10"
set c[17] = "\\x11"
set c[18] = "\\x12"
set c[19] = "\\x13"
set c[20] = "\\x14"
set c[21] = "\\x15"
set c[22] = "\\x16"
set c[23] = "\\x17"
set c[24] = "\\x18"
set c[25] = "\\x19"
set c[26] = "\\x1A"
set c[27] = "\\x1B"
set c[28] = "\\x1C"
set c[29] = "\\x1D"
set c[30] = "\\x1E"
set c[31] = "\\x1F"
set c[32] = " "
set c[33] = "!"
set c[34] = "\""
set c[35] = "#"
set c[36] = "$"
set c[37] = "%"
set c[38] = "&"
set c[39] = "'"
set c[40] = "("
set c[41] = ")"
set c[42] = "*"
set c[43] = "+"
set c[44] = ","
set c[45] = "-"
set c[46] = "."
set c[47] = "/"
set c[48] = "0"
set c[49] = "1"
set c[50] = "2"
set c[51] = "3"
set c[52] = "4"
set c[53] = "5"
set c[54] = "6"
set c[55] = "7"
set c[56] = "8"
set c[57] = "9"
set c[58] = ":"
set c[59] = ";"
set c[60] = "<"
set c[61] = "="
set c[62] = ">"
set c[63] = "?"
set c[64] = "@"
set c[65] = "A"
set c[66] = "B"
set c[67] = "C"
set c[68] = "D"
set c[69] = "E"
set c[70] = "F"
set c[71] = "G"
set c[72] = "H"
set c[73] = "I"
set c[74] = "J"
set c[75] = "K"
set c[76] = "L"
set c[77] = "M"
set c[78] = "N"
set c[79] = "O"
set c[80] = "P"
set c[81] = "Q"
set c[82] = "R"
set c[83] = "S"
set c[84] = "T"
set c[85] = "U"
set c[86] = "V"
set c[87] = "W"
set c[88] = "X"
set c[89] = "Y"
set c[90] = "Z"
set c[91] = "["
set c[92] = "\\"
set c[93] = "]"
set c[94] = "^"
set c[95] = "_"
set c[96] = "`"
set c[97] = "a"
set c[98] = "b"
set c[99] = "c"
set c[100] = "d"
set c[101] = "e"
set c[102] = "f"
set c[103] = "g"
set c[104] = "h"
set c[105] = "i"
set c[106] = "j"
set c[107] = "k"
set c[108] = "l"
set c[109] = "m"
set c[110] = "n"
set c[111] = "o"
set c[112] = "p"
set c[113] = "q"
set c[114] = "r"
set c[115] = "s"
set c[116] = "t"
set c[117] = "u"
set c[118] = "v"
set c[119] = "w"
set c[120] = "x"
set c[121] = "y"
set c[122] = "z"
set c[123] = "{"
set c[124] = "|"
set c[125] = "}"
set c[126] = "~"
set c[127] = "\\x7F"
set c[128] = "\\x80"
set c[129] = "\\x81"
set c[130] = "\\x82"
set c[131] = "\\x83"
set c[132] = "\\x84"
set c[133] = "\\x85"
set c[134] = "\\x86"
set c[135] = "\\x87"
set c[136] = "\\x88"
set c[137] = "\\x89"
set c[138] = "\\x8A"
set c[139] = "\\x8B"
set c[140] = "\\x8C"
set c[141] = "\\x8D"
set c[142] = "\\x8E"
set c[143] = "\\x8F"
set c[144] = "\\x90"
set c[145] = "\\x91"
set c[146] = "\\x92"
set c[147] = "\\x93"
set c[148] = "\\x94"
set c[149] = "\\x95"
set c[150] = "\\x96"
set c[151] = "\\x97"
set c[152] = "\\x98"
set c[153] = "\\x99"
set c[154] = "\\x9A"
set c[155] = "\\x9B"
set c[156] = "\\x9C"
set c[157] = "\\x9D"
set c[158] = "\\x9E"
set c[159] = "\\x9F"
set c[160] = "\\xA0"
set c[161] = "\\xA1"
set c[162] = "\\xA2"
set c[163] = "\\xA3"
set c[164] = "\\xA4"
set c[165] = "\\xA5"
set c[166] = "\\xA6"
set c[167] = "\\xA7"
set c[168] = "\\xA8"
set c[169] = "\\xA9"
set c[170] = "\\xAA"
set c[171] = "\\xAB"
set c[172] = "\\xAC"
set c[173] = "\\xAD"
set c[174] = "\\xAE"
set c[175] = "\\xAF"
set c[176] = "\\xB0"
set c[177] = "\\xB1"
set c[178] = "\\xB2"
set c[179] = "\\xB3"
set c[180] = "\\xB4"
set c[181] = "\\xB5"
set c[182] = "\\xB6"
set c[183] = "\\xB7"
set c[184] = "\\xB8"
set c[185] = "\\xB9"
set c[186] = "\\xBA"
set c[187] = "\\xBB"
set c[188] = "\\xBC"
set c[189] = "\\xBD"
set c[190] = "\\xBE"
set c[191] = "\\xBF"
set c[192] = "\\xC0"
set c[193] = "\\xC1"
set c[194] = "\\xC2"
set c[195] = "\\xC3"
set c[196] = "\\xC4"
set c[197] = "\\xC5"
set c[198] = "\\xC6"
set c[199] = "\\xC7"
set c[200] = "\\xC8"
set c[201] = "\\xC9"
set c[202] = "\\xCA"
set c[203] = "\\xCB"
set c[204] = "\\xCC"
set c[205] = "\\xCD"
set c[206] = "\\xCE"
set c[207] = "\\xCF"
set c[208] = "\\xD0"
set c[209] = "\\xD1"
set c[210] = "\\xD2"
set c[211] = "\\xD3"
set c[212] = "\\xD4"
set c[213] = "\\xD5"
set c[214] = "\\xD6"
set c[215] = "\\xD7"
set c[216] = "\\xD8"
set c[217] = "\\xD9"
set c[218] = "\\xDA"
set c[219] = "\\xDB"
set c[220] = "\\xDC"
set c[221] = "\\xDD"
set c[222] = "\\xDE"
set c[223] = "\\xDF"
set c[224] = "\\xE0"
set c[225] = "\\xE1"
set c[226] = "\\xE2"
set c[227] = "\\xE3"
set c[228] = "\\xE4"
set c[229] = "\\xE5"
set c[230] = "\\xE6"
set c[231] = "\\xE7"
set c[232] = "\\xE8"
set c[233] = "\\xE9"
set c[234] = "\\xEA"
set c[235] = "\\xEB"
set c[236] = "\\xEC"
set c[237] = "\\xED"
set c[238] = "\\xEE"
set c[239] = "\\xEF"
set c[240] = "\\xF0"
set c[241] = "\\xF1"
set c[242] = "\\xF2"
set c[243] = "\\xF3"
set c[244] = "\\xF4"
set c[245] = "\\xF5"
set c[246] = "\\xF6"
set c[247] = "\\xF7"
set c[248] = "\\xF8"
set c[249] = "\\xF9"
set c[250] = "\\xFA"
set c[251] = "\\xFB"
set c[252] = "\\xFC"
set c[253] = "\\xFD"
set c[254] = "\\xFE"
set c[255] = "\\xFF"
endmethod
endstruct
private module eager_init
private static method onInit takes nothing returns nothing
static if DEBUG_MODE and CHECK_ORD_TABLE_FOR_PROPER_INITIALIZATION then
local integer i
local string s
local integer o
local boolean found_error = false
endif
call chrord2.init_tables()
static if DEBUG_MODE and CHECK_ORD_TABLE_FOR_PROPER_INITIALIZATION then
set i = 0
loop
exitwhen i >= 256
set s = chr(i)
set o = ord(s)
if i != o then
set found_error = true
call BJDebugMsg("|cffFF0000[chrord2] error: "+ "the character '" + s + "' ord table entry has been set to " + I2S(o) + " expected " + I2S(i) + "|r")
exitwhen true
endif
set i = i + 1
endloop
if found_error then
call BJDebugMsg("|cffFF0000[chrord2] error: ord table was not initialized properly, an entry or entries of the ord table has been added to the string table before chrord2 was initialized; for example: check to see if you have global variables initilized with the entries of the ord table and initialize them after chrord2|r")
endif
endif
endmethod
endmodule
private struct dummy extends array
implement eager_init
endstruct
endlibrary
```

#### Attachments

Last edited: