namesmanager.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package util
  11. import "encoding/binary"
  12. /*
  13. PrefixCode is the prefix for entries storing codes
  14. */
  15. const PrefixCode = string(0x0)
  16. /*
  17. PrefixName is the prefix for entries storing names
  18. */
  19. const PrefixName = string(0x1)
  20. /*
  21. PrefixCounter is the prefix for counter entries
  22. */
  23. const PrefixCounter = string(0x0)
  24. /*
  25. Prefix16Bit is the prefix for 16 bit kind related entries
  26. */
  27. const Prefix16Bit = string(0x1)
  28. /*
  29. Prefix32Bit is the prefix for attribute related entries
  30. */
  31. const Prefix32Bit = string(0x2)
  32. /*
  33. NamesManager data structure
  34. */
  35. type NamesManager struct {
  36. nameDB map[string]string // Database storing names
  37. }
  38. /*
  39. NewNamesManager creates a new names manager instance.
  40. */
  41. func NewNamesManager(nameDB map[string]string) *NamesManager {
  42. return &NamesManager{nameDB}
  43. }
  44. /*
  45. Encode32 encodes a given value as a 32 bit string. If the create flag
  46. is set to false then a new entry will not be created if it does not exist.
  47. */
  48. func (gs *NamesManager) Encode32(val string, create bool) string {
  49. return gs.encode(Prefix32Bit, val, create)
  50. }
  51. /*
  52. Decode32 decodes a given 32 bit string to a value.
  53. */
  54. func (gs *NamesManager) Decode32(val string) string {
  55. return gs.decode(Prefix32Bit, val)
  56. }
  57. /*
  58. Encode16 encodes a given value as a 16 bit string. If the create flag
  59. is set to false then a new entry will not be created if it does not exist.
  60. */
  61. func (gs *NamesManager) Encode16(val string, create bool) string {
  62. return gs.encode(Prefix16Bit, val, create)
  63. }
  64. /*
  65. Decode16 decodes a given 16 bit string to a value.
  66. */
  67. func (gs *NamesManager) Decode16(val string) string {
  68. return gs.decode(Prefix16Bit, val)
  69. }
  70. /*
  71. encode encodes a name to a code.
  72. */
  73. func (gs *NamesManager) encode(prefix string, name string, create bool) string {
  74. codekey := string(PrefixCode) + prefix + name
  75. code, ok := gs.nameDB[codekey]
  76. // If the code doesn't exist yet create it
  77. if !ok && create {
  78. if prefix == Prefix16Bit {
  79. code = gs.newCode16()
  80. } else {
  81. code = gs.newCode32()
  82. }
  83. gs.nameDB[codekey] = code
  84. namekey := string(PrefixName) + prefix + code
  85. gs.nameDB[namekey] = name
  86. }
  87. return code
  88. }
  89. /*
  90. decode decodes a name from a code.
  91. */
  92. func (gs *NamesManager) decode(prefix string, code string) string {
  93. namekey := string(PrefixName) + prefix + code
  94. return gs.nameDB[namekey]
  95. }
  96. /*
  97. newCode32 generates a new 32 bit number for the names map.
  98. */
  99. func (gs *NamesManager) newCode32() (res string) {
  100. var resnum uint32
  101. // Calculate count entry
  102. countAttr := string(PrefixCounter) + Prefix32Bit
  103. // Calculate new code
  104. val, ok := gs.nameDB[countAttr]
  105. if !ok {
  106. resnum = 1
  107. } else {
  108. resnum = binary.LittleEndian.Uint32([]byte(val))
  109. resnum++
  110. }
  111. // Convert to a string
  112. resStr := make([]byte, 4, 4)
  113. binary.LittleEndian.PutUint32(resStr, resnum)
  114. res = string(resStr)
  115. // Write back
  116. gs.nameDB[countAttr] = res
  117. return res
  118. }
  119. /*
  120. newCode16 generates a new 16 bit number for the names map.
  121. */
  122. func (gs *NamesManager) newCode16() (res string) {
  123. var resnum uint16
  124. // Calculate count entry
  125. countAttr := string(PrefixCounter) + Prefix16Bit
  126. // Calculate new code
  127. val, ok := gs.nameDB[countAttr]
  128. if !ok {
  129. resnum = 1
  130. } else {
  131. resnum = binary.LittleEndian.Uint16([]byte(val))
  132. resnum++
  133. }
  134. // Convert to a string
  135. resStr := make([]byte, 2, 2)
  136. binary.LittleEndian.PutUint16(resStr, resnum)
  137. res = string(resStr)
  138. // Write back
  139. gs.nameDB[countAttr] = res
  140. return res
  141. }