Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / Azure / go-ansiterm / parser.go
1 package ansiterm
2
3 import (
4         "errors"
5         "io/ioutil"
6         "os"
7
8         "github.com/Sirupsen/logrus"
9 )
10
11 var logger *logrus.Logger
12
13 type AnsiParser struct {
14         currState          state
15         eventHandler       AnsiEventHandler
16         context            *ansiContext
17         csiEntry           state
18         csiParam           state
19         dcsEntry           state
20         escape             state
21         escapeIntermediate state
22         error              state
23         ground             state
24         oscString          state
25         stateMap           []state
26 }
27
28 func CreateParser(initialState string, evtHandler AnsiEventHandler) *AnsiParser {
29         logFile := ioutil.Discard
30
31         if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" {
32                 logFile, _ = os.Create("ansiParser.log")
33         }
34
35         logger = &logrus.Logger{
36                 Out:       logFile,
37                 Formatter: new(logrus.TextFormatter),
38                 Level:     logrus.InfoLevel,
39         }
40
41         parser := &AnsiParser{
42                 eventHandler: evtHandler,
43                 context:      &ansiContext{},
44         }
45
46         parser.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: parser}}
47         parser.csiParam = csiParamState{baseState{name: "CsiParam", parser: parser}}
48         parser.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: parser}}
49         parser.escape = escapeState{baseState{name: "Escape", parser: parser}}
50         parser.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: parser}}
51         parser.error = errorState{baseState{name: "Error", parser: parser}}
52         parser.ground = groundState{baseState{name: "Ground", parser: parser}}
53         parser.oscString = oscStringState{baseState{name: "OscString", parser: parser}}
54
55         parser.stateMap = []state{
56                 parser.csiEntry,
57                 parser.csiParam,
58                 parser.dcsEntry,
59                 parser.escape,
60                 parser.escapeIntermediate,
61                 parser.error,
62                 parser.ground,
63                 parser.oscString,
64         }
65
66         parser.currState = getState(initialState, parser.stateMap)
67
68         logger.Infof("CreateParser: parser %p", parser)
69         return parser
70 }
71
72 func getState(name string, states []state) state {
73         for _, el := range states {
74                 if el.Name() == name {
75                         return el
76                 }
77         }
78
79         return nil
80 }
81
82 func (ap *AnsiParser) Parse(bytes []byte) (int, error) {
83         for i, b := range bytes {
84                 if err := ap.handle(b); err != nil {
85                         return i, err
86                 }
87         }
88
89         return len(bytes), ap.eventHandler.Flush()
90 }
91
92 func (ap *AnsiParser) handle(b byte) error {
93         ap.context.currentChar = b
94         newState, err := ap.currState.Handle(b)
95         if err != nil {
96                 return err
97         }
98
99         if newState == nil {
100                 logger.Warning("newState is nil")
101                 return errors.New("New state of 'nil' is invalid.")
102         }
103
104         if newState != ap.currState {
105                 if err := ap.changeState(newState); err != nil {
106                         return err
107                 }
108         }
109
110         return nil
111 }
112
113 func (ap *AnsiParser) changeState(newState state) error {
114         logger.Infof("ChangeState %s --> %s", ap.currState.Name(), newState.Name())
115
116         // Exit old state
117         if err := ap.currState.Exit(); err != nil {
118                 logger.Infof("Exit state '%s' failed with : '%v'", ap.currState.Name(), err)
119                 return err
120         }
121
122         // Perform transition action
123         if err := ap.currState.Transition(newState); err != nil {
124                 logger.Infof("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err)
125                 return err
126         }
127
128         // Enter new state
129         if err := newState.Enter(); err != nil {
130                 logger.Infof("Enter state '%s' failed with: '%v'", newState.Name(), err)
131                 return err
132         }
133
134         ap.currState = newState
135         return nil
136 }