mirror of https://github.com/gogits/gogs.git
Unknwon
8 years ago
7 changed files with 413 additions and 0 deletions
@ -0,0 +1,57 @@ |
|||||||
|
// Package utils contain some utilities which are needed to create barcodes
|
||||||
|
package utils |
||||||
|
|
||||||
|
import ( |
||||||
|
"image" |
||||||
|
"image/color" |
||||||
|
|
||||||
|
"github.com/boombuler/barcode" |
||||||
|
) |
||||||
|
|
||||||
|
type base1DCode struct { |
||||||
|
*BitList |
||||||
|
kind string |
||||||
|
content string |
||||||
|
} |
||||||
|
|
||||||
|
type base1DCodeIntCS struct { |
||||||
|
base1DCode |
||||||
|
checksum int |
||||||
|
} |
||||||
|
|
||||||
|
func (c *base1DCode) Content() string { |
||||||
|
return c.content |
||||||
|
} |
||||||
|
|
||||||
|
func (c *base1DCode) Metadata() barcode.Metadata { |
||||||
|
return barcode.Metadata{c.kind, 1} |
||||||
|
} |
||||||
|
|
||||||
|
func (c *base1DCode) ColorModel() color.Model { |
||||||
|
return color.Gray16Model |
||||||
|
} |
||||||
|
|
||||||
|
func (c *base1DCode) Bounds() image.Rectangle { |
||||||
|
return image.Rect(0, 0, c.Len(), 1) |
||||||
|
} |
||||||
|
|
||||||
|
func (c *base1DCode) At(x, y int) color.Color { |
||||||
|
if c.GetBit(x) { |
||||||
|
return color.Black |
||||||
|
} |
||||||
|
return color.White |
||||||
|
} |
||||||
|
|
||||||
|
func (c *base1DCodeIntCS) CheckSum() int { |
||||||
|
return c.checksum |
||||||
|
} |
||||||
|
|
||||||
|
// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList
|
||||||
|
func New1DCodeIntCheckSum(codeKind, content string, bars *BitList, checksum int) barcode.BarcodeIntCS { |
||||||
|
return &base1DCodeIntCS{base1DCode{bars, codeKind, content}, checksum} |
||||||
|
} |
||||||
|
|
||||||
|
// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList
|
||||||
|
func New1DCode(codeKind, content string, bars *BitList) barcode.Barcode { |
||||||
|
return &base1DCode{bars, codeKind, content} |
||||||
|
} |
@ -0,0 +1,119 @@ |
|||||||
|
package utils |
||||||
|
|
||||||
|
// BitList is a list that contains bits
|
||||||
|
type BitList struct { |
||||||
|
count int |
||||||
|
data []int32 |
||||||
|
} |
||||||
|
|
||||||
|
// NewBitList returns a new BitList with the given length
|
||||||
|
// all bits are initialize with false
|
||||||
|
func NewBitList(capacity int) *BitList { |
||||||
|
bl := new(BitList) |
||||||
|
bl.count = capacity |
||||||
|
x := 0 |
||||||
|
if capacity%32 != 0 { |
||||||
|
x = 1 |
||||||
|
} |
||||||
|
bl.data = make([]int32, capacity/32+x) |
||||||
|
return bl |
||||||
|
} |
||||||
|
|
||||||
|
// Len returns the number of contained bits
|
||||||
|
func (bl *BitList) Len() int { |
||||||
|
return bl.count |
||||||
|
} |
||||||
|
|
||||||
|
func (bl *BitList) grow() { |
||||||
|
growBy := len(bl.data) |
||||||
|
if growBy < 128 { |
||||||
|
growBy = 128 |
||||||
|
} else if growBy >= 1024 { |
||||||
|
growBy = 1024 |
||||||
|
} |
||||||
|
|
||||||
|
nd := make([]int32, len(bl.data)+growBy) |
||||||
|
copy(nd, bl.data) |
||||||
|
bl.data = nd |
||||||
|
} |
||||||
|
|
||||||
|
// AddBit appends the given bits to the end of the list
|
||||||
|
func (bl *BitList) AddBit(bits ...bool) { |
||||||
|
for _, bit := range bits { |
||||||
|
itmIndex := bl.count / 32 |
||||||
|
for itmIndex >= len(bl.data) { |
||||||
|
bl.grow() |
||||||
|
} |
||||||
|
bl.SetBit(bl.count, bit) |
||||||
|
bl.count++ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// SetBit sets the bit at the given index to the given value
|
||||||
|
func (bl *BitList) SetBit(index int, value bool) { |
||||||
|
itmIndex := index / 32 |
||||||
|
itmBitShift := 31 - (index % 32) |
||||||
|
if value { |
||||||
|
bl.data[itmIndex] = bl.data[itmIndex] | 1<<uint(itmBitShift) |
||||||
|
} else { |
||||||
|
bl.data[itmIndex] = bl.data[itmIndex] & ^(1 << uint(itmBitShift)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// GetBit returns the bit at the given index
|
||||||
|
func (bl *BitList) GetBit(index int) bool { |
||||||
|
itmIndex := index / 32 |
||||||
|
itmBitShift := 31 - (index % 32) |
||||||
|
return ((bl.data[itmIndex] >> uint(itmBitShift)) & 1) == 1 |
||||||
|
} |
||||||
|
|
||||||
|
// AddByte appends all 8 bits of the given byte to the end of the list
|
||||||
|
func (bl *BitList) AddByte(b byte) { |
||||||
|
for i := 7; i >= 0; i-- { |
||||||
|
bl.AddBit(((b >> uint(i)) & 1) == 1) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// AddBits appends the last (LSB) 'count' bits of 'b' the the end of the list
|
||||||
|
func (bl *BitList) AddBits(b int, count byte) { |
||||||
|
for i := int(count) - 1; i >= 0; i-- { |
||||||
|
bl.AddBit(((b >> uint(i)) & 1) == 1) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// GetBytes returns all bits of the BitList as a []byte
|
||||||
|
func (bl *BitList) GetBytes() []byte { |
||||||
|
len := bl.count >> 3 |
||||||
|
if (bl.count % 8) != 0 { |
||||||
|
len++ |
||||||
|
} |
||||||
|
result := make([]byte, len) |
||||||
|
for i := 0; i < len; i++ { |
||||||
|
shift := (3 - (i % 4)) * 8 |
||||||
|
result[i] = (byte)((bl.data[i/4] >> uint(shift)) & 0xFF) |
||||||
|
} |
||||||
|
return result |
||||||
|
} |
||||||
|
|
||||||
|
// IterateBytes iterates through all bytes contained in the BitList
|
||||||
|
func (bl *BitList) IterateBytes() <-chan byte { |
||||||
|
res := make(chan byte) |
||||||
|
|
||||||
|
go func() { |
||||||
|
c := bl.count |
||||||
|
shift := 24 |
||||||
|
i := 0 |
||||||
|
for c > 0 { |
||||||
|
res <- byte((bl.data[i] >> uint(shift)) & 0xFF) |
||||||
|
shift -= 8 |
||||||
|
if shift < 0 { |
||||||
|
shift = 24 |
||||||
|
i++ |
||||||
|
} |
||||||
|
c -= 8 |
||||||
|
} |
||||||
|
close(res) |
||||||
|
}() |
||||||
|
|
||||||
|
return res |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
package utils |
||||||
|
|
||||||
|
// GaloisField encapsulates galois field arithmetics
|
||||||
|
type GaloisField struct { |
||||||
|
Size int |
||||||
|
Base int |
||||||
|
ALogTbl []int |
||||||
|
LogTbl []int |
||||||
|
} |
||||||
|
|
||||||
|
// NewGaloisField creates a new galois field
|
||||||
|
func NewGaloisField(pp, fieldSize, b int) *GaloisField { |
||||||
|
result := new(GaloisField) |
||||||
|
|
||||||
|
result.Size = fieldSize |
||||||
|
result.Base = b |
||||||
|
result.ALogTbl = make([]int, fieldSize) |
||||||
|
result.LogTbl = make([]int, fieldSize) |
||||||
|
|
||||||
|
x := 1 |
||||||
|
for i := 0; i < fieldSize; i++ { |
||||||
|
result.ALogTbl[i] = x |
||||||
|
x = x * 2 |
||||||
|
if x >= fieldSize { |
||||||
|
x = (x ^ pp) & (fieldSize - 1) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for i := 0; i < fieldSize; i++ { |
||||||
|
result.LogTbl[result.ALogTbl[i]] = int(i) |
||||||
|
} |
||||||
|
|
||||||
|
return result |
||||||
|
} |
||||||
|
|
||||||
|
func (gf *GaloisField) Zero() *GFPoly { |
||||||
|
return NewGFPoly(gf, []int{0}) |
||||||
|
} |
||||||
|
|
||||||
|
// AddOrSub add or substract two numbers
|
||||||
|
func (gf *GaloisField) AddOrSub(a, b int) int { |
||||||
|
return a ^ b |
||||||
|
} |
||||||
|
|
||||||
|
// Multiply multiplys two numbers
|
||||||
|
func (gf *GaloisField) Multiply(a, b int) int { |
||||||
|
if a == 0 || b == 0 { |
||||||
|
return 0 |
||||||
|
} |
||||||
|
return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%(gf.Size-1)] |
||||||
|
} |
||||||
|
|
||||||
|
// Divide divides two numbers
|
||||||
|
func (gf *GaloisField) Divide(a, b int) int { |
||||||
|
if b == 0 { |
||||||
|
panic("divide by zero") |
||||||
|
} else if a == 0 { |
||||||
|
return 0 |
||||||
|
} |
||||||
|
return gf.ALogTbl[(gf.LogTbl[a]-gf.LogTbl[b])%(gf.Size-1)] |
||||||
|
} |
||||||
|
|
||||||
|
func (gf *GaloisField) Invers(num int) int { |
||||||
|
return gf.ALogTbl[(gf.Size-1)-gf.LogTbl[num]] |
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
package utils |
||||||
|
|
||||||
|
type GFPoly struct { |
||||||
|
gf *GaloisField |
||||||
|
Coefficients []int |
||||||
|
} |
||||||
|
|
||||||
|
func (gp *GFPoly) Degree() int { |
||||||
|
return len(gp.Coefficients) - 1 |
||||||
|
} |
||||||
|
|
||||||
|
func (gp *GFPoly) Zero() bool { |
||||||
|
return gp.Coefficients[0] == 0 |
||||||
|
} |
||||||
|
|
||||||
|
// GetCoefficient returns the coefficient of x ^ degree
|
||||||
|
func (gp *GFPoly) GetCoefficient(degree int) int { |
||||||
|
return gp.Coefficients[gp.Degree()-degree] |
||||||
|
} |
||||||
|
|
||||||
|
func (gp *GFPoly) AddOrSubstract(other *GFPoly) *GFPoly { |
||||||
|
if gp.Zero() { |
||||||
|
return other |
||||||
|
} else if other.Zero() { |
||||||
|
return gp |
||||||
|
} |
||||||
|
smallCoeff := gp.Coefficients |
||||||
|
largeCoeff := other.Coefficients |
||||||
|
if len(smallCoeff) > len(largeCoeff) { |
||||||
|
largeCoeff, smallCoeff = smallCoeff, largeCoeff |
||||||
|
} |
||||||
|
sumDiff := make([]int, len(largeCoeff)) |
||||||
|
lenDiff := len(largeCoeff) - len(smallCoeff) |
||||||
|
copy(sumDiff, largeCoeff[:lenDiff]) |
||||||
|
for i := lenDiff; i < len(largeCoeff); i++ { |
||||||
|
sumDiff[i] = int(gp.gf.AddOrSub(int(smallCoeff[i-lenDiff]), int(largeCoeff[i]))) |
||||||
|
} |
||||||
|
return NewGFPoly(gp.gf, sumDiff) |
||||||
|
} |
||||||
|
|
||||||
|
func (gp *GFPoly) MultByMonominal(degree int, coeff int) *GFPoly { |
||||||
|
if coeff == 0 { |
||||||
|
return gp.gf.Zero() |
||||||
|
} |
||||||
|
size := len(gp.Coefficients) |
||||||
|
result := make([]int, size+degree) |
||||||
|
for i := 0; i < size; i++ { |
||||||
|
result[i] = int(gp.gf.Multiply(int(gp.Coefficients[i]), int(coeff))) |
||||||
|
} |
||||||
|
return NewGFPoly(gp.gf, result) |
||||||
|
} |
||||||
|
|
||||||
|
func (gp *GFPoly) Multiply(other *GFPoly) *GFPoly { |
||||||
|
if gp.Zero() || other.Zero() { |
||||||
|
return gp.gf.Zero() |
||||||
|
} |
||||||
|
aCoeff := gp.Coefficients |
||||||
|
aLen := len(aCoeff) |
||||||
|
bCoeff := other.Coefficients |
||||||
|
bLen := len(bCoeff) |
||||||
|
product := make([]int, aLen+bLen-1) |
||||||
|
for i := 0; i < aLen; i++ { |
||||||
|
ac := int(aCoeff[i]) |
||||||
|
for j := 0; j < bLen; j++ { |
||||||
|
bc := int(bCoeff[j]) |
||||||
|
product[i+j] = int(gp.gf.AddOrSub(int(product[i+j]), gp.gf.Multiply(ac, bc))) |
||||||
|
} |
||||||
|
} |
||||||
|
return NewGFPoly(gp.gf, product) |
||||||
|
} |
||||||
|
|
||||||
|
func (gp *GFPoly) Divide(other *GFPoly) (quotient *GFPoly, remainder *GFPoly) { |
||||||
|
quotient = gp.gf.Zero() |
||||||
|
remainder = gp |
||||||
|
fld := gp.gf |
||||||
|
denomLeadTerm := other.GetCoefficient(other.Degree()) |
||||||
|
inversDenomLeadTerm := fld.Invers(int(denomLeadTerm)) |
||||||
|
for remainder.Degree() >= other.Degree() && !remainder.Zero() { |
||||||
|
degreeDiff := remainder.Degree() - other.Degree() |
||||||
|
scale := int(fld.Multiply(int(remainder.GetCoefficient(remainder.Degree())), inversDenomLeadTerm)) |
||||||
|
term := other.MultByMonominal(degreeDiff, scale) |
||||||
|
itQuot := NewMonominalPoly(fld, degreeDiff, scale) |
||||||
|
quotient = quotient.AddOrSubstract(itQuot) |
||||||
|
remainder = remainder.AddOrSubstract(term) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func NewMonominalPoly(field *GaloisField, degree int, coeff int) *GFPoly { |
||||||
|
if coeff == 0 { |
||||||
|
return field.Zero() |
||||||
|
} |
||||||
|
result := make([]int, degree+1) |
||||||
|
result[0] = coeff |
||||||
|
return NewGFPoly(field, result) |
||||||
|
} |
||||||
|
|
||||||
|
func NewGFPoly(field *GaloisField, coefficients []int) *GFPoly { |
||||||
|
for len(coefficients) > 1 && coefficients[0] == 0 { |
||||||
|
coefficients = coefficients[1:] |
||||||
|
} |
||||||
|
return &GFPoly{field, coefficients} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
package utils |
||||||
|
|
||||||
|
import ( |
||||||
|
"sync" |
||||||
|
) |
||||||
|
|
||||||
|
type ReedSolomonEncoder struct { |
||||||
|
gf *GaloisField |
||||||
|
polynomes []*GFPoly |
||||||
|
m *sync.Mutex |
||||||
|
} |
||||||
|
|
||||||
|
func NewReedSolomonEncoder(gf *GaloisField) *ReedSolomonEncoder { |
||||||
|
return &ReedSolomonEncoder{ |
||||||
|
gf, []*GFPoly{NewGFPoly(gf, []int{1})}, new(sync.Mutex), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (rs *ReedSolomonEncoder) getPolynomial(degree int) *GFPoly { |
||||||
|
rs.m.Lock() |
||||||
|
defer rs.m.Unlock() |
||||||
|
|
||||||
|
if degree >= len(rs.polynomes) { |
||||||
|
last := rs.polynomes[len(rs.polynomes)-1] |
||||||
|
for d := len(rs.polynomes); d <= degree; d++ { |
||||||
|
next := last.Multiply(NewGFPoly(rs.gf, []int{1, rs.gf.ALogTbl[d-1+rs.gf.Base]})) |
||||||
|
rs.polynomes = append(rs.polynomes, next) |
||||||
|
last = next |
||||||
|
} |
||||||
|
} |
||||||
|
return rs.polynomes[degree] |
||||||
|
} |
||||||
|
|
||||||
|
func (rs *ReedSolomonEncoder) Encode(data []int, eccCount int) []int { |
||||||
|
generator := rs.getPolynomial(eccCount) |
||||||
|
info := NewGFPoly(rs.gf, data) |
||||||
|
info = info.MultByMonominal(eccCount, 1) |
||||||
|
_, remainder := info.Divide(generator) |
||||||
|
|
||||||
|
result := make([]int, eccCount) |
||||||
|
numZero := int(eccCount) - len(remainder.Coefficients) |
||||||
|
copy(result[numZero:], remainder.Coefficients) |
||||||
|
return result |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package utils |
||||||
|
|
||||||
|
// RuneToInt converts a rune between '0' and '9' to an integer between 0 and 9
|
||||||
|
// If the rune is outside of this range -1 is returned.
|
||||||
|
func RuneToInt(r rune) int { |
||||||
|
if r >= '0' && r <= '9' { |
||||||
|
return int(r - '0') |
||||||
|
} |
||||||
|
return -1 |
||||||
|
} |
||||||
|
|
||||||
|
// IntToRune converts a digit 0 - 9 to the rune '0' - '9'. If the given int is outside
|
||||||
|
// of this range 'F' is returned!
|
||||||
|
func IntToRune(i int) rune { |
||||||
|
if i >= 0 && i <= 9 { |
||||||
|
return rune(i + '0') |
||||||
|
} |
||||||
|
return 'F' |
||||||
|
} |
Loading…
Reference in new issue