2011-03-31 17:18:10 +00:00
|
|
|
"
|
|
|
|
(C) 2011 by Holger Hans Peter Freyther
|
|
|
|
All Rights Reserved
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Affero General Public License as
|
|
|
|
published by the Free Software Foundation, either version 3 of the
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Affero General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
"
|
|
|
|
|
|
|
|
String extend [
|
|
|
|
asGSM7Bit [
|
|
|
|
"I convert a string into a 7bit encoded string. I should
|
|
|
|
also be in UnicodeString but I am not. This impl. is just
|
|
|
|
basic and does not deal with difficult bits."
|
|
|
|
<category: '*-osmo-gsm'>
|
2011-03-31 17:36:52 +00:00
|
|
|
^ GSMEncoding encode: self.
|
|
|
|
]
|
2011-03-31 19:02:32 +00:00
|
|
|
|
|
|
|
asUSSD7Bit [
|
|
|
|
"I convert a string into a 7bit encoded string. I know about
|
|
|
|
padding rules for USSD messages."
|
|
|
|
<category: '*-osmo-gsm'>
|
|
|
|
^ GSMUSSDEncoding encode: self.
|
|
|
|
]
|
2011-03-31 17:36:52 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
Object subclass: GSMEncoding [
|
|
|
|
<category: 'osmo-gsm'>
|
|
|
|
<comment: 'I am the base class for GSM Encoding as of GSM 03.38. I
|
|
|
|
can be subclassed to deal with specifics for USSD and other systems.'>
|
|
|
|
|
|
|
|
GSMEncoding class >> encode: aString [
|
|
|
|
| bits |
|
|
|
|
bits := self convertToBits: aString.
|
|
|
|
self padBits: bits on: aString.
|
|
|
|
^ self convertToBytes: bits.
|
|
|
|
]
|
|
|
|
|
|
|
|
GSMEncoding class >> padBits: bits on: aString [
|
|
|
|
"I have to make sure that bits can be divided by/8"
|
|
|
|
| rest |
|
|
|
|
rest := 8 - (bits size \\ 8).
|
|
|
|
rest to: 1 by: -1 do: [:each | bits add: 0].
|
|
|
|
]
|
2011-03-31 17:18:10 +00:00
|
|
|
|
2011-03-31 17:36:52 +00:00
|
|
|
GSMEncoding class >> convertToBits: aString [
|
|
|
|
| bits |
|
|
|
|
bits := OrderedCollection new: (aString size * 7) // 8.
|
2011-03-31 17:18:10 +00:00
|
|
|
|
|
|
|
"Split it into bits"
|
2011-03-31 17:36:52 +00:00
|
|
|
aString do: [:char | | val |
|
2011-03-31 17:18:10 +00:00
|
|
|
val := char value.
|
|
|
|
1 to: 7 do: [:digit | bits add: (val bitAt: digit)].
|
|
|
|
].
|
|
|
|
|
2011-03-31 17:36:52 +00:00
|
|
|
^ bits
|
|
|
|
]
|
|
|
|
|
|
|
|
GSMEncoding class >> convertToBytes: bits [
|
|
|
|
| bytes |
|
2011-03-31 17:18:10 +00:00
|
|
|
|
2011-03-31 17:36:52 +00:00
|
|
|
bytes := ByteArray new: bits size // 8.
|
2011-03-31 17:18:10 +00:00
|
|
|
1 to: bits size by: 8 do: [:each | | byte |
|
|
|
|
byte := 0.
|
|
|
|
byte := (byte bitShift: 1) bitOr: (bits at: each + 7).
|
|
|
|
byte := (byte bitShift: 1) bitOr: (bits at: each + 6).
|
|
|
|
byte := (byte bitShift: 1) bitOr: (bits at: each + 5).
|
|
|
|
byte := (byte bitShift: 1) bitOr: (bits at: each + 4).
|
|
|
|
byte := (byte bitShift: 1) bitOr: (bits at: each + 3).
|
|
|
|
byte := (byte bitShift: 1) bitOr: (bits at: each + 2).
|
|
|
|
byte := (byte bitShift: 1) bitOr: (bits at: each + 1).
|
|
|
|
byte := (byte bitShift: 1) bitOr: (bits at: each + 0).
|
|
|
|
|
|
|
|
bytes at: (each // 8) + 1 put: byte.
|
|
|
|
].
|
|
|
|
|
|
|
|
^ bytes
|
|
|
|
]
|
|
|
|
]
|
2011-03-31 19:02:32 +00:00
|
|
|
|
|
|
|
GSMEncoding subclass: GSMUSSDEncoding [
|
|
|
|
<category: 'osmo-gsm'>
|
|
|
|
<comment: 'I know the funky stuff for USSD encoding/padding'>
|
|
|
|
|
|
|
|
GSMUSSDEncoding class >> padBits: bits on: aString [
|
|
|
|
| rest nl |
|
|
|
|
|
|
|
|
"Check if we are on a byte boundary and a CR."
|
|
|
|
((aString last = Character cr) and: [(bits size \\ 8) = 0]) ifTrue: [ | cr |
|
|
|
|
cr := Character cr value.
|
|
|
|
1 to: 7 do: [:each | bits add: (cr bitAt: each) ].
|
|
|
|
bits add: 0.
|
|
|
|
^ self
|
|
|
|
].
|
|
|
|
|
|
|
|
"Check if we need to handle this, if not continue."
|
|
|
|
aString size \\ 8 = 7
|
|
|
|
ifFalse: [^ super padBits: bits on: aString].
|
|
|
|
|
|
|
|
"Now add the padding."
|
|
|
|
rest := 8 - (bits size \\ 8).
|
|
|
|
rest = 7 ifFalse: [^self error: 'The rest should be 7 bits but were %1' % rest].
|
|
|
|
|
|
|
|
nl := Character cr value.
|
|
|
|
1 to: 7 do: [:each | bits add: (nl bitAt: each)].
|
|
|
|
]
|
|
|
|
]
|