Caller ID Parsing
Name : CallerIDParsing
Author : Daniel Lyons
Revision : 1.0 (2004-12-21 -> 2004-12-22)
This is a chunk of code by Daniel Lyons that accomplishes the parsing of CID or Caller ID data. It probably is only useful to you if you happen to live in one of the six or eight countries that actually use caller ID in this (ridiculous) format.
To use it, do this:
foo := CIDData clone parseString(cidDataString)
You'll get properties phoneNumber, date and name, set if those fields are present in the CID string. I recommend you use them with conditional message passing, to prevent confusion: foo ?phoneNumber Also note that the date object is only reliable for day, month, minute and hour; the other fields are simply not present in the caller ID format.
The method is expecting an ASCII representation of a hexadecimal binary string, in other words, "800A38..." instead of something rational like a binary buffer. The code should be easy to refactor that way though.
CIDData := Object clone do(
parseDate := method(cid,
length := cid next
curDate := ""
for(i, 1, length,
curDate = curDate + cid next asCharacter
)
self date := Date clone setMonth(curDate substring(0,2) asNumber)
self date setDay(curDate substring(2,4) asNumber)
self date setHour(curDate substring(4,6) asNumber)
self date setMinute(curDate substring(6,8) asNumber)
)
parsePhone := method(cid,
# this is the phone number portion
length := cid next
self phoneNumber := ""
for(i, 1, length,
self phoneNumber = self phoneNumber + cid next asCharacter
)
)
parseNumberNotPresent := method(cid,
cid next # it pretty much has to be 1
self phoneNumber := if(cid next asCharacter == "O", "UNAVAILABLE", "BLOCKED")
)
parseName := method(cid,
length := cid next
self name := ""
for(i, 1, length,
self name = self name + cid next asCharacter
)
)
parseNameNotPresent := method(cid,
cid next # it's going to be 1
self name := if(cid next asCharacter == "O", "UNAVAILABLE", "BLOCKED")
)
parseWithNextObj := method(cid,
# should raise an exception here or something
if(cid next != 128, Error raise("CIDData.parse",
"This isn't an MDMF-type caller ID data sequence"))
totalLength := cid next
cid reset # the actual count begins here
while(cid count < (totalLength - 1),
# figure out what the next thing is
type := cid next
if(type == 1) then(
# this is the date/time portion
parseDate(cid)
) elseif(type == 2) then(
# this is the phone number portion
parsePhone(cid)
) elseif(type == 4) then(
# this is the number-not-present portion
parseNumberNotPresent(cid)
) elseif(type == 7) then(
# this is the name portion
parseName(cid)
) elseif(type == 8) then(
# this is the name-not-present portion
parseNameNotPresent(cid)
) else(
write("ignoring unknown type: ", type asString, "\n")
)
)
)
parseString := method(cid,
# this defines a "next object" which is something I've informally
# come up with for the parseWithNextObj method. basically, if you
# wrap anything with a structure that supports these methods:
#
# * next - give the next byte of the sequence, as a Number
# * reset - reset the internal counter to zero
# * count - give the current count of the internal counter
#
# The internal counter should be incremented for each byte that is
# returned.
myCid := cid clone do(
offset := 0
count := 0
incr := method(count = count + 1)
reset := method(count = 0)
next := method(
offset = offset + 2
incr
self substring(offset - 2, offset) fromBase(16)
)
)
parseWithNextObj(myCid)
self
)
)
