ReanGD/go-morphy

View on GitHub
dawg/dawg.go

Summary

Maintainability
A
1 hr
Test Coverage
package dawg

// status ok
import "os"

type virtDAWG interface {
    hasValue(index uint32) bool
}

// DAWG - Base DAWG wrapper.
type DAWG struct {
    vDAWG virtDAWG
    dct   *Dictionary
}

// InitVTable - Init vDAWG.
func (d *DAWG) InitVTable(vDAWG virtDAWG) {
    d.vDAWG = vDAWG
}

// Contains - Exact matching.
func (d *DAWG) Contains(key string) bool {
    return d.dct.Contains([]byte(key))
}

// Load - Loads DAWG from a file.
func (d *DAWG) Load(path string) error {
    d.dct = NewDictionary()

    f, err := os.Open(path)
    if err != nil {
        return err
    }

    err = d.dct.Read(f)
    closeErr := f.Close()
    if err == nil {
        err = closeErr
    }

    return err
}

func (d *DAWG) hasValue(index uint32) bool {
    return d.dct.hasValue(index)
}

func (d *DAWG) similarKeys(currentPrefix string, key string, index uint32, replaceChars map[rune]rune) []string {
    res := []string{}
    exitByBreak := false
    startPos := len(currentPrefix)

    for curPos, bStep := range key[startPos:] {
        ReplaceChar, ok := replaceChars[bStep]

        if ok {
            nextIndex, ok := d.dct.followBytes([]byte(string(ReplaceChar)), index)
            if ok {
                prefix := currentPrefix + key[startPos:curPos] + string(ReplaceChar)
                extraKeys := d.similarKeys(prefix, key, nextIndex, replaceChars)
                res = append(res, extraKeys...)
            }
        }

        index, ok = d.dct.followBytes([]byte(string(bStep)), index)
        if !ok {
            exitByBreak = true
            break
        }
    }

    if !exitByBreak {
        if d.vDAWG.hasValue(index) {
            foundKey := currentPrefix + key[startPos:]
            res = append([]string{foundKey}, res...)
        }
    }

    return res
}

// SimilarKeys - Returns all variants of 'key' in this DAWG according to 'replaces'.
// This may be useful e.g. for handling single-character umlauts.
func (d *DAWG) SimilarKeys(key string, replaceChars map[rune]rune) []string {
    return d.similarKeys("", key, constRoot, replaceChars)
}

// Prefixes - Returns a list with keys of this DAWG that are prefixes of the 'key'.
func (d *DAWG) Prefixes(key string) []string {
    res := []string{}
    var ok bool
    index := constRoot

    for pos, ch := range []byte(key) {
        index, ok = d.dct.followChar(uint32(ch), index)
        if !ok {
            break
        }

        if d.vDAWG.hasValue(index) {
            res = append(res, string(key[:pos+1]))
        }
    }

    return res
}

func (d *DAWG) initDAWG() {
}

// NewDAWG - constructor for DAWG
func NewDAWG() *DAWG {
    dawg := &DAWG{}
    dawg.vDAWG = dawg
    dawg.initDAWG()

    return dawg
}