mirror of
https://github.com/cubixle/iabtcfv2.git
synced 2026-04-24 22:34:45 +01:00
Fix library exposure
This commit is contained in:
16
bits.go
16
bits.go
@@ -9,11 +9,11 @@ var (
|
||||
bytePows = []byte{128, 64, 32, 16, 8, 4, 2, 1}
|
||||
)
|
||||
|
||||
func NewBits(bytes []byte) *Bits {
|
||||
func newBits(bytes []byte) *Bits {
|
||||
return &Bits{bytes: bytes, position: 0}
|
||||
}
|
||||
|
||||
func (b *Bits) ReadBool() bool {
|
||||
func (b *Bits) readBool() bool {
|
||||
byteIndex := b.position / 8
|
||||
bitIndex := b.position % 8
|
||||
b.position++
|
||||
@@ -21,7 +21,7 @@ func (b *Bits) ReadBool() bool {
|
||||
return (b.bytes[byteIndex] & bytePows[bitIndex]) != 0
|
||||
}
|
||||
|
||||
func (b *Bits) WriteBool(v bool) {
|
||||
func (b *Bits) writeBool(v bool) {
|
||||
byteIndex := b.position / 8
|
||||
shift := (byteIndex+1)*8 - b.position - 1
|
||||
b.position++
|
||||
@@ -33,10 +33,10 @@ func (b *Bits) WriteBool(v bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bits) ReadInt(n uint) int {
|
||||
func (b *Bits) readInt(n uint) int {
|
||||
v := 0
|
||||
for i, shift := uint(0), n-1; i < n; i++ {
|
||||
if b.ReadBool() {
|
||||
if b.readBool() {
|
||||
v += 1 << uint(shift)
|
||||
}
|
||||
shift--
|
||||
@@ -45,11 +45,11 @@ func (b *Bits) ReadInt(n uint) int {
|
||||
return v
|
||||
}
|
||||
|
||||
func (b *Bits) WriteInt(v int, n uint) {
|
||||
b.WriteNumber(int64(v), n)
|
||||
func (b *Bits) writeInt(v int, n uint) {
|
||||
b.writeNumber(int64(v), n)
|
||||
}
|
||||
|
||||
func (b *Bits) WriteNumber(v int64, n uint) {
|
||||
func (b *Bits) writeNumber(v int64, n uint) {
|
||||
startOffset := int(b.position)
|
||||
for i := int(n) - 1; i >= 0; i-- {
|
||||
index := startOffset + i
|
||||
|
||||
104
decode.go
104
decode.go
@@ -12,8 +12,8 @@ func DecodeSegmentType(s string) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
var e = NewTCEncoder(b)
|
||||
return e.ReadInt(3)
|
||||
var e = newTCEncoder(b)
|
||||
return e.readInt(3)
|
||||
}
|
||||
|
||||
func Decode(s string) (t *TCData, err error) {
|
||||
@@ -62,46 +62,46 @@ func DecodeCoreString(s string) (c *CoreString, err error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var e = NewTCEncoder(b)
|
||||
var e = newTCEncoder(b)
|
||||
|
||||
c = &CoreString{}
|
||||
c.Version = e.ReadInt(6)
|
||||
c.Created = e.ReadTime()
|
||||
c.LastUpdated = e.ReadTime()
|
||||
c.CmpId = e.ReadInt(12)
|
||||
c.CmpVersion = e.ReadInt(12)
|
||||
c.ConsentScreen = e.ReadInt(6)
|
||||
c.ConsentLanguage = e.ReadIsoCode()
|
||||
c.VendorListVersion = e.ReadInt(12)
|
||||
c.TcfPolicyVersion = e.ReadInt(6)
|
||||
c.IsServiceSpecific = e.ReadBool()
|
||||
c.UseNonStandardStacks = e.ReadBool()
|
||||
c.SpecialFeatureOptIns = e.ReadBitField(12)
|
||||
c.PurposesConsent = e.ReadBitField(24)
|
||||
c.PurposesLITransparency = e.ReadBitField(24)
|
||||
c.PurposeOneTreatment = e.ReadBool()
|
||||
c.PublisherCC = e.ReadIsoCode()
|
||||
c.Version = e.readInt(6)
|
||||
c.Created = e.readTime()
|
||||
c.LastUpdated = e.readTime()
|
||||
c.CmpId = e.readInt(12)
|
||||
c.CmpVersion = e.readInt(12)
|
||||
c.ConsentScreen = e.readInt(6)
|
||||
c.ConsentLanguage = e.readIsoCode()
|
||||
c.VendorListVersion = e.readInt(12)
|
||||
c.TcfPolicyVersion = e.readInt(6)
|
||||
c.IsServiceSpecific = e.readBool()
|
||||
c.UseNonStandardStacks = e.readBool()
|
||||
c.SpecialFeatureOptIns = e.readBitField(12)
|
||||
c.PurposesConsent = e.readBitField(24)
|
||||
c.PurposesLITransparency = e.readBitField(24)
|
||||
c.PurposeOneTreatment = e.readBool()
|
||||
c.PublisherCC = e.readIsoCode()
|
||||
|
||||
c.MaxVendorId = e.ReadInt(16)
|
||||
c.IsRangeEncoding = e.ReadBool()
|
||||
c.MaxVendorId = e.readInt(16)
|
||||
c.IsRangeEncoding = e.readBool()
|
||||
if c.IsRangeEncoding {
|
||||
c.NumEntries = e.ReadInt(12)
|
||||
c.RangeEntries = e.ReadRangeEntries(uint(c.NumEntries))
|
||||
c.NumEntries = e.readInt(12)
|
||||
c.RangeEntries = e.readRangeEntries(uint(c.NumEntries))
|
||||
} else {
|
||||
c.VendorsConsent = e.ReadBitField(uint(c.MaxVendorId))
|
||||
c.VendorsConsent = e.readBitField(uint(c.MaxVendorId))
|
||||
}
|
||||
|
||||
c.MaxVendorIdLI = e.ReadInt(16)
|
||||
c.IsRangeEncodingLI = e.ReadBool()
|
||||
c.MaxVendorIdLI = e.readInt(16)
|
||||
c.IsRangeEncodingLI = e.readBool()
|
||||
if c.IsRangeEncodingLI {
|
||||
c.NumEntriesLI = e.ReadInt(12)
|
||||
c.RangeEntriesLI = e.ReadRangeEntries(uint(c.NumEntriesLI))
|
||||
c.NumEntriesLI = e.readInt(12)
|
||||
c.RangeEntriesLI = e.readRangeEntries(uint(c.NumEntriesLI))
|
||||
} else {
|
||||
c.VendorsLITransparency = e.ReadBitField(uint(c.MaxVendorIdLI))
|
||||
c.VendorsLITransparency = e.readBitField(uint(c.MaxVendorIdLI))
|
||||
}
|
||||
|
||||
c.NumPubRestrictions = e.ReadInt(12)
|
||||
c.PubRestrictions = e.ReadPubRestrictions(uint(c.NumPubRestrictions))
|
||||
c.NumPubRestrictions = e.readInt(12)
|
||||
c.PubRestrictions = e.readPubRestrictions(uint(c.NumPubRestrictions))
|
||||
|
||||
return c, nil
|
||||
}
|
||||
@@ -118,17 +118,17 @@ func DecodeDisclosedVendors(s string) (d *DisclosedVendors, err error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var e = NewTCEncoder(b)
|
||||
var e = newTCEncoder(b)
|
||||
|
||||
d = &DisclosedVendors{}
|
||||
d.SegmentType = e.ReadInt(3)
|
||||
d.MaxVendorId = e.ReadInt(16)
|
||||
d.IsRangeEncoding = e.ReadBool()
|
||||
d.SegmentType = e.readInt(3)
|
||||
d.MaxVendorId = e.readInt(16)
|
||||
d.IsRangeEncoding = e.readBool()
|
||||
if d.IsRangeEncoding {
|
||||
d.NumEntries = e.ReadInt(12)
|
||||
d.RangeEntries = e.ReadRangeEntries(uint(d.NumEntries))
|
||||
d.NumEntries = e.readInt(12)
|
||||
d.RangeEntries = e.readRangeEntries(uint(d.NumEntries))
|
||||
} else {
|
||||
d.DisclosedVendors = e.ReadBitField(uint(d.MaxVendorId))
|
||||
d.DisclosedVendors = e.readBitField(uint(d.MaxVendorId))
|
||||
}
|
||||
|
||||
if d.SegmentType != 1 {
|
||||
@@ -151,17 +151,17 @@ func DecodeAllowedVendors(s string) (a *AllowedVendors, err error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var e = NewTCEncoder(b)
|
||||
var e = newTCEncoder(b)
|
||||
|
||||
a = &AllowedVendors{}
|
||||
a.SegmentType = e.ReadInt(3)
|
||||
a.MaxVendorId = e.ReadInt(16)
|
||||
a.IsRangeEncoding = e.ReadBool()
|
||||
a.SegmentType = e.readInt(3)
|
||||
a.MaxVendorId = e.readInt(16)
|
||||
a.IsRangeEncoding = e.readBool()
|
||||
if a.IsRangeEncoding {
|
||||
a.NumEntries = e.ReadInt(12)
|
||||
a.RangeEntries = e.ReadRangeEntries(uint(a.NumEntries))
|
||||
a.NumEntries = e.readInt(12)
|
||||
a.RangeEntries = e.readRangeEntries(uint(a.NumEntries))
|
||||
} else {
|
||||
a.AllowedVendors = e.ReadBitField(uint(a.MaxVendorId))
|
||||
a.AllowedVendors = e.readBitField(uint(a.MaxVendorId))
|
||||
}
|
||||
|
||||
if a.SegmentType != 2 {
|
||||
@@ -184,15 +184,15 @@ func DecodePubllisherTC(s string) (p *PublisherTC, err error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var e = NewTCEncoder(b)
|
||||
var e = newTCEncoder(b)
|
||||
|
||||
p = &PublisherTC{}
|
||||
p.SegmentType = e.ReadInt(3)
|
||||
p.PubPurposesConsent = e.ReadBitField(24)
|
||||
p.PubPurposesLITransparency = e.ReadBitField(24)
|
||||
p.NumCustomPurposes = e.ReadInt(6)
|
||||
p.CustomPurposesConsent = e.ReadBitField(uint(p.NumCustomPurposes))
|
||||
p.CustomPurposesLITransparency = e.ReadBitField(uint(p.NumCustomPurposes))
|
||||
p.SegmentType = e.readInt(3)
|
||||
p.PubPurposesConsent = e.readBitField(24)
|
||||
p.PubPurposesLITransparency = e.readBitField(24)
|
||||
p.NumCustomPurposes = e.readInt(6)
|
||||
p.CustomPurposesConsent = e.readBitField(uint(p.NumCustomPurposes))
|
||||
p.CustomPurposesLITransparency = e.readBitField(uint(p.NumCustomPurposes))
|
||||
|
||||
if p.SegmentType != 3 {
|
||||
err = fmt.Errorf("allowed vendors segment type must be 3")
|
||||
|
||||
105
encoder.go
105
encoder.go
@@ -1,105 +0,0 @@
|
||||
package iabtcf
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
decisecondsPerSecond = 10
|
||||
nanosecondsPerDecisecond = int64(time.Millisecond * 100)
|
||||
)
|
||||
|
||||
type TCEncoder struct {
|
||||
*Bits
|
||||
}
|
||||
|
||||
func NewTCEncoder(src []byte) *TCEncoder {
|
||||
return &TCEncoder{NewBits(src)}
|
||||
}
|
||||
|
||||
func (r *TCEncoder) ReadTime() time.Time {
|
||||
var ds = int64(r.ReadInt(36))
|
||||
return time.Unix(ds/decisecondsPerSecond, (ds%decisecondsPerSecond)*nanosecondsPerDecisecond).UTC()
|
||||
}
|
||||
|
||||
func (r *TCEncoder) WriteTime(v time.Time) {
|
||||
r.WriteNumber(v.UnixNano()/nanosecondsPerDecisecond, 36)
|
||||
}
|
||||
|
||||
func (r *TCEncoder) ReadIsoCode() string {
|
||||
var buf = make([]byte, 0, 2)
|
||||
for i := uint(0); i < 2; i++ {
|
||||
buf = append(buf, byte(r.ReadInt(6))+'A')
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
func (r *TCEncoder) WriteIsoCode(v string) {
|
||||
for _, char := range v {
|
||||
r.WriteInt(int(byte(char)-'A'), 6)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *TCEncoder) ReadBitField(n uint) map[int]bool {
|
||||
var m = make(map[int]bool)
|
||||
for i := uint(0); i < n; i++ {
|
||||
if r.ReadBool() {
|
||||
m[int(i)+1] = true
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (r *TCEncoder) WriteRangeEntries(entries []*RangeEntry) {
|
||||
for _, entry := range entries {
|
||||
if entry.EndVendorID > entry.StartVendorID {
|
||||
r.WriteBool(true)
|
||||
r.WriteInt(entry.StartVendorID, 16)
|
||||
r.WriteInt(entry.EndVendorID, 16)
|
||||
} else {
|
||||
r.WriteBool(false)
|
||||
r.WriteInt(entry.StartVendorID, 16)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *TCEncoder) ReadRangeEntries(n uint) []*RangeEntry {
|
||||
var ret = make([]*RangeEntry, 0, n)
|
||||
for i := uint(0); i < n; i++ {
|
||||
var isRange = r.ReadBool()
|
||||
var start, end int
|
||||
start = r.ReadInt(16)
|
||||
if isRange {
|
||||
end = r.ReadInt(16)
|
||||
} else {
|
||||
end = start
|
||||
}
|
||||
ret = append(ret, &RangeEntry{StartVendorID: start, EndVendorID: end})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *TCEncoder) WritePubRestrictions(entries []*PubRestriction) {
|
||||
for _, entry := range entries {
|
||||
r.WriteInt(entry.PurposeId, 6)
|
||||
r.WriteInt(entry.RestrictionType, 2)
|
||||
r.WriteInt(len(entry.RangeEntries), 12)
|
||||
r.WriteRangeEntries(entry.RangeEntries)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *TCEncoder) ReadPubRestrictions(n uint) []*PubRestriction {
|
||||
var ret = make([]*PubRestriction, 0, n)
|
||||
for i := uint(0); i < n; i++ {
|
||||
var purposeId = r.ReadInt(6)
|
||||
var restrictionType = r.ReadInt(2)
|
||||
var numEntries = r.ReadInt(12)
|
||||
var rangeEntries = r.ReadRangeEntries(uint(numEntries))
|
||||
ret = append(ret, &PubRestriction{PurposeId: purposeId,
|
||||
RestrictionType: restrictionType,
|
||||
NumEntries: numEntries,
|
||||
RangeEntries: rangeEntries,
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -44,20 +44,20 @@ func (a *AllowedVendors) Encode() string {
|
||||
bitSize += a.MaxVendorId
|
||||
}
|
||||
|
||||
var e = NewTCEncoder(make([]byte, bitSize/8))
|
||||
var e = newTCEncoder(make([]byte, bitSize/8))
|
||||
if bitSize%8 != 0 {
|
||||
e = NewTCEncoder(make([]byte, bitSize/8+1))
|
||||
e = newTCEncoder(make([]byte, bitSize/8+1))
|
||||
}
|
||||
|
||||
e.WriteInt(a.SegmentType, 3)
|
||||
e.WriteInt(a.MaxVendorId, 16)
|
||||
e.WriteBool(a.IsRangeEncoding)
|
||||
e.writeInt(a.SegmentType, 3)
|
||||
e.writeInt(a.MaxVendorId, 16)
|
||||
e.writeBool(a.IsRangeEncoding)
|
||||
if a.IsRangeEncoding {
|
||||
e.WriteInt(len(a.RangeEntries), 12)
|
||||
e.WriteRangeEntries(a.RangeEntries)
|
||||
e.writeInt(len(a.RangeEntries), 12)
|
||||
e.writeRangeEntries(a.RangeEntries)
|
||||
} else {
|
||||
for i := 0; i < a.MaxVendorId; i++ {
|
||||
e.WriteBool(a.IsVendorAllowed(i + 1))
|
||||
e.writeBool(a.IsVendorAllowed(i + 1))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,58 +133,58 @@ func (c *CoreString) Encode() string {
|
||||
bitSize += entriesSize
|
||||
}
|
||||
|
||||
var e = NewTCEncoder(make([]byte, bitSize/8))
|
||||
var e = newTCEncoder(make([]byte, bitSize/8))
|
||||
if bitSize%8 != 0 {
|
||||
e = NewTCEncoder(make([]byte, bitSize/8+1))
|
||||
e = newTCEncoder(make([]byte, bitSize/8+1))
|
||||
}
|
||||
|
||||
e.WriteInt(c.Version, 6)
|
||||
e.WriteTime(c.Created)
|
||||
e.WriteTime(c.LastUpdated)
|
||||
e.WriteInt(c.CmpId, 12)
|
||||
e.WriteInt(c.CmpVersion, 12)
|
||||
e.WriteInt(c.ConsentScreen, 6)
|
||||
e.WriteIsoCode(c.ConsentLanguage)
|
||||
e.WriteInt(c.VendorListVersion, 12)
|
||||
e.WriteInt(c.TcfPolicyVersion, 6)
|
||||
e.WriteBool(c.IsServiceSpecific)
|
||||
e.WriteBool(c.UseNonStandardStacks)
|
||||
e.writeInt(c.Version, 6)
|
||||
e.writeTime(c.Created)
|
||||
e.writeTime(c.LastUpdated)
|
||||
e.writeInt(c.CmpId, 12)
|
||||
e.writeInt(c.CmpVersion, 12)
|
||||
e.writeInt(c.ConsentScreen, 6)
|
||||
e.writeIsoCode(c.ConsentLanguage)
|
||||
e.writeInt(c.VendorListVersion, 12)
|
||||
e.writeInt(c.TcfPolicyVersion, 6)
|
||||
e.writeBool(c.IsServiceSpecific)
|
||||
e.writeBool(c.UseNonStandardStacks)
|
||||
for i := 0; i < 12; i++ {
|
||||
e.WriteBool(c.IsSpecialFeatureAllowed(i + 1))
|
||||
e.writeBool(c.IsSpecialFeatureAllowed(i + 1))
|
||||
}
|
||||
for i := 0; i < 24; i++ {
|
||||
e.WriteBool(c.IsPurposeAllowed(i + 1))
|
||||
e.writeBool(c.IsPurposeAllowed(i + 1))
|
||||
}
|
||||
for i := 0; i < 24; i++ {
|
||||
e.WriteBool(c.IsPurposeLIAllowed(i + 1))
|
||||
e.writeBool(c.IsPurposeLIAllowed(i + 1))
|
||||
}
|
||||
e.WriteBool(c.PurposeOneTreatment)
|
||||
e.WriteIsoCode(c.PublisherCC)
|
||||
e.writeBool(c.PurposeOneTreatment)
|
||||
e.writeIsoCode(c.PublisherCC)
|
||||
|
||||
e.WriteInt(c.MaxVendorId, 16)
|
||||
e.WriteBool(c.IsRangeEncoding)
|
||||
e.writeInt(c.MaxVendorId, 16)
|
||||
e.writeBool(c.IsRangeEncoding)
|
||||
if c.IsRangeEncoding {
|
||||
e.WriteInt(len(c.RangeEntries), 12)
|
||||
e.WriteRangeEntries(c.RangeEntries)
|
||||
e.writeInt(len(c.RangeEntries), 12)
|
||||
e.writeRangeEntries(c.RangeEntries)
|
||||
} else {
|
||||
for i := 0; i < c.MaxVendorId; i++ {
|
||||
e.WriteBool(c.IsVendorAllowed(i + 1))
|
||||
e.writeBool(c.IsVendorAllowed(i + 1))
|
||||
}
|
||||
}
|
||||
|
||||
e.WriteInt(c.MaxVendorIdLI, 16)
|
||||
e.WriteBool(c.IsRangeEncodingLI)
|
||||
e.writeInt(c.MaxVendorIdLI, 16)
|
||||
e.writeBool(c.IsRangeEncodingLI)
|
||||
if c.IsRangeEncodingLI {
|
||||
e.WriteInt(len(c.RangeEntriesLI), 12)
|
||||
e.WriteRangeEntries(c.RangeEntriesLI)
|
||||
e.writeInt(len(c.RangeEntriesLI), 12)
|
||||
e.writeRangeEntries(c.RangeEntriesLI)
|
||||
} else {
|
||||
for i := 0; i < c.MaxVendorIdLI; i++ {
|
||||
e.WriteBool(c.IsVendorLIAllowed(i + 1))
|
||||
e.writeBool(c.IsVendorLIAllowed(i + 1))
|
||||
}
|
||||
}
|
||||
|
||||
e.WriteInt(len(c.PubRestrictions), 12)
|
||||
e.WritePubRestrictions(c.PubRestrictions)
|
||||
e.writeInt(len(c.PubRestrictions), 12)
|
||||
e.writePubRestrictions(c.PubRestrictions)
|
||||
|
||||
return base64.RawURLEncoding.EncodeToString(e.bytes)
|
||||
}
|
||||
|
||||
@@ -44,20 +44,20 @@ func (d *DisclosedVendors) Encode() string {
|
||||
bitSize += d.MaxVendorId
|
||||
}
|
||||
|
||||
var e = NewTCEncoder(make([]byte, bitSize/8))
|
||||
var e = newTCEncoder(make([]byte, bitSize/8))
|
||||
if bitSize%8 != 0 {
|
||||
e = NewTCEncoder(make([]byte, bitSize/8+1))
|
||||
e = newTCEncoder(make([]byte, bitSize/8+1))
|
||||
}
|
||||
|
||||
e.WriteInt(d.SegmentType, 3)
|
||||
e.WriteInt(d.MaxVendorId, 16)
|
||||
e.WriteBool(d.IsRangeEncoding)
|
||||
e.writeInt(d.SegmentType, 3)
|
||||
e.writeInt(d.MaxVendorId, 16)
|
||||
e.writeBool(d.IsRangeEncoding)
|
||||
if d.IsRangeEncoding {
|
||||
e.WriteInt(len(d.RangeEntries), 12)
|
||||
e.WriteRangeEntries(d.RangeEntries)
|
||||
e.writeInt(len(d.RangeEntries), 12)
|
||||
e.writeRangeEntries(d.RangeEntries)
|
||||
} else {
|
||||
for i := 0; i < d.MaxVendorId; i++ {
|
||||
e.WriteBool(d.IsVendorDisclosed(i + 1))
|
||||
e.writeBool(d.IsVendorDisclosed(i + 1))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,24 +30,24 @@ func (p *PublisherTC) IsCustomPurposeLIAllowed(id int) bool {
|
||||
func (p *PublisherTC) Encode() string {
|
||||
bitSize := 57 + (p.NumCustomPurposes * 2)
|
||||
|
||||
var e = NewTCEncoder(make([]byte, bitSize/8))
|
||||
var e = newTCEncoder(make([]byte, bitSize/8))
|
||||
if bitSize%8 != 0 {
|
||||
e = NewTCEncoder(make([]byte, bitSize/8+1))
|
||||
e = newTCEncoder(make([]byte, bitSize/8+1))
|
||||
}
|
||||
|
||||
e.WriteInt(p.SegmentType, 3)
|
||||
e.writeInt(p.SegmentType, 3)
|
||||
for i := 0; i < 24; i++ {
|
||||
e.WriteBool(p.IsPurposeAllowed(i + 1))
|
||||
e.writeBool(p.IsPurposeAllowed(i + 1))
|
||||
}
|
||||
for i := 0; i < 24; i++ {
|
||||
e.WriteBool(p.IsPurposeLIAllowed(i + 1))
|
||||
e.writeBool(p.IsPurposeLIAllowed(i + 1))
|
||||
}
|
||||
e.WriteInt(p.NumCustomPurposes, 6)
|
||||
e.writeInt(p.NumCustomPurposes, 6)
|
||||
for i := 0; i < p.NumCustomPurposes; i++ {
|
||||
e.WriteBool(p.IsCustomPurposeAllowed(i + 1))
|
||||
e.writeBool(p.IsCustomPurposeAllowed(i + 1))
|
||||
}
|
||||
for i := 0; i < p.NumCustomPurposes; i++ {
|
||||
e.WriteBool(p.IsCustomPurposeLIAllowed(i + 1))
|
||||
e.writeBool(p.IsCustomPurposeLIAllowed(i + 1))
|
||||
}
|
||||
|
||||
return base64.RawURLEncoding.EncodeToString(e.bytes)
|
||||
|
||||
105
tcencoder.go
Normal file
105
tcencoder.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package iabtcf
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
decisecondsPerSecond = 10
|
||||
nanosecondsPerDecisecond = int64(time.Millisecond * 100)
|
||||
)
|
||||
|
||||
type TCEncoder struct {
|
||||
*Bits
|
||||
}
|
||||
|
||||
func newTCEncoder(src []byte) *TCEncoder {
|
||||
return &TCEncoder{newBits(src)}
|
||||
}
|
||||
|
||||
func (r *TCEncoder) readTime() time.Time {
|
||||
var ds = int64(r.readInt(36))
|
||||
return time.Unix(ds/decisecondsPerSecond, (ds%decisecondsPerSecond)*nanosecondsPerDecisecond).UTC()
|
||||
}
|
||||
|
||||
func (r *TCEncoder) writeTime(v time.Time) {
|
||||
r.writeNumber(v.UnixNano()/nanosecondsPerDecisecond, 36)
|
||||
}
|
||||
|
||||
func (r *TCEncoder) readIsoCode() string {
|
||||
var buf = make([]byte, 0, 2)
|
||||
for i := uint(0); i < 2; i++ {
|
||||
buf = append(buf, byte(r.readInt(6))+'A')
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
func (r *TCEncoder) writeIsoCode(v string) {
|
||||
for _, char := range v {
|
||||
r.writeInt(int(byte(char)-'A'), 6)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *TCEncoder) readBitField(n uint) map[int]bool {
|
||||
var m = make(map[int]bool)
|
||||
for i := uint(0); i < n; i++ {
|
||||
if r.readBool() {
|
||||
m[int(i)+1] = true
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (r *TCEncoder) writeRangeEntries(entries []*RangeEntry) {
|
||||
for _, entry := range entries {
|
||||
if entry.EndVendorID > entry.StartVendorID {
|
||||
r.writeBool(true)
|
||||
r.writeInt(entry.StartVendorID, 16)
|
||||
r.writeInt(entry.EndVendorID, 16)
|
||||
} else {
|
||||
r.writeBool(false)
|
||||
r.writeInt(entry.StartVendorID, 16)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *TCEncoder) readRangeEntries(n uint) []*RangeEntry {
|
||||
var ret = make([]*RangeEntry, 0, n)
|
||||
for i := uint(0); i < n; i++ {
|
||||
var isRange = r.readBool()
|
||||
var start, end int
|
||||
start = r.readInt(16)
|
||||
if isRange {
|
||||
end = r.readInt(16)
|
||||
} else {
|
||||
end = start
|
||||
}
|
||||
ret = append(ret, &RangeEntry{StartVendorID: start, EndVendorID: end})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *TCEncoder) writePubRestrictions(entries []*PubRestriction) {
|
||||
for _, entry := range entries {
|
||||
r.writeInt(entry.PurposeId, 6)
|
||||
r.writeInt(entry.RestrictionType, 2)
|
||||
r.writeInt(len(entry.RangeEntries), 12)
|
||||
r.writeRangeEntries(entry.RangeEntries)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *TCEncoder) readPubRestrictions(n uint) []*PubRestriction {
|
||||
var ret = make([]*PubRestriction, 0, n)
|
||||
for i := uint(0); i < n; i++ {
|
||||
var purposeId = r.readInt(6)
|
||||
var restrictionType = r.readInt(2)
|
||||
var numEntries = r.readInt(12)
|
||||
var rangeEntries = r.readRangeEntries(uint(numEntries))
|
||||
ret = append(ret, &PubRestriction{PurposeId: purposeId,
|
||||
RestrictionType: restrictionType,
|
||||
NumEntries: numEntries,
|
||||
RangeEntries: rangeEntries,
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
Reference in New Issue
Block a user