// Copyright 2020 Justine Alexandra Roberts Tunney // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Charset implementation using int64 bitmasks package sip var ( tokencMask [2]uint64 qdtextcMask [2]uint64 usercMask [2]uint64 passcMask [2]uint64 paramcMask [2]uint64 headercMask [2]uint64 ) func tokenc(c byte) bool { return charsetContains(&tokencMask, c) } func qdtextc(c byte) bool { return charsetContains(&qdtextcMask, c) } func userc(c byte) bool { return charsetContains(&usercMask, c) } func passc(c byte) bool { return charsetContains(&passcMask, c) } func paramc(c byte) bool { return charsetContains(¶mcMask, c) } func headerc(c byte) bool { return charsetContains(&headercMask, c) } func qdtextesc(c byte) bool { return 0x00 <= c && c <= 0x09 || 0x0B <= c && c <= 0x0C || 0x0E <= c && c <= 0x7F } func whitespacec(c byte) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } func init() { charsetAddAlphaNumeric(&tokencMask) charsetAdd(&tokencMask, '-', '.', '!', '%', '*', '_', '+', '`', '\'', '~') charsetAddRange(&qdtextcMask, 0x23, 0x5B) charsetAddRange(&qdtextcMask, 0x5D, 0x7E) charsetAdd(&qdtextcMask, '\r', '\n', '\t', ' ', '!') charsetAddAlphaNumeric(&usercMask) charsetAddMark(&usercMask) charsetAdd(&usercMask, '&', '=', '+', '$', ',', ';', '?', '/') charsetAddAlphaNumeric(&passcMask) charsetAddMark(&passcMask) charsetAdd(&passcMask, '&', '=', '+', '$', ',') charsetAddAlphaNumeric(¶mcMask) charsetAddMark(¶mcMask) charsetAdd(¶mcMask, '[', ']', '/', ':', '&', '+', '$') charsetAddAlphaNumeric(&headercMask) charsetAddMark(&headercMask) charsetAdd(&headercMask, '[', ']', '/', '?', ':', '+', '$') } func charsetContains(mask *[2]uint64, i byte) bool { return i < 128 && mask[i/64]&(1<<(i%64)) != 0 } func charsetAdd(mask *[2]uint64, vi ...byte) { for _, i := range vi { mask[i/64] |= 1 << (i % 64) } } func charsetAddRange(mask *[2]uint64, a, b byte) { for i := a; i <= b; i++ { charsetAdd(mask, i) } } func charsetAddMark(mask *[2]uint64) { charsetAdd(mask, '-', '_', '.', '!', '~', '*', '\'', '(', ')') } func charsetAddAlphaNumeric(mask *[2]uint64) { charsetAddRange(mask, 'a', 'z') charsetAddRange(mask, 'A', 'Z') charsetAddRange(mask, '0', '9') }