1//  Copieright (c) 2014 Couchbase, Inc.
2//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
3//  except in compliance with the License. You may obtain a copy of the License at
4//    http://www.apache.org/licenses/LICENSE-2.0
5//  Unless required by applicable law or agreed to in writing, software distributed under the
6//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
7//  either express or implied. See the License for the specific language governing permissions
8//  and limitations under the License.
9
10package value
11
12import (
13	"io"
14	"math"
15	"strconv"
16
17	"github.com/couchbase/query/util"
18)
19
20type intValue int64
21
22var ZERO_NUMBER NumberValue = intValue(0)
23var ONE_NUMBER NumberValue = intValue(1)
24var NEG_ONE_NUMBER NumberValue = intValue(-1)
25
26var ZERO_VALUE Value = ZERO_NUMBER
27var ONE_VALUE Value = ONE_NUMBER
28var NEG_ONE_VALUE Value = NEG_ONE_NUMBER
29
30func (this intValue) String() string {
31	return strconv.FormatInt(int64(this), 10)
32}
33
34func (this intValue) MarshalJSON() ([]byte, error) {
35	s := strconv.FormatInt(int64(this), 10)
36	return []byte(s), nil
37}
38
39func (this intValue) WriteJSON(w io.Writer, prefix, indent string) error {
40	s := strconv.FormatInt(int64(this), 10)
41	b := []byte(s)
42	_, err := w.Write(b)
43	return err
44}
45
46/*
47Type NUMBER
48*/
49func (this intValue) Type() Type {
50	return NUMBER
51}
52
53/*
54Cast receiver to float64. We cannot use int64 unless all Expressions
55can handle both float64 and int64.
56*/
57func (this intValue) Actual() interface{} {
58	return float64(this)
59}
60
61/*
62Return int64 and avoid any lossiness due to rounding / representation.
63*/
64func (this intValue) ActualForIndex() interface{} {
65	return int64(this)
66}
67
68func (this intValue) Equals(other Value) Value {
69	other = other.unwrap()
70	switch other := other.(type) {
71	case missingValue:
72		return other
73	case *nullValue:
74		return other
75	case intValue:
76		if this == other {
77			return TRUE_VALUE
78		}
79	case floatValue:
80		if float64(this) == float64(other) {
81			return TRUE_VALUE
82		}
83	}
84
85	return FALSE_VALUE
86}
87
88func (this intValue) EquivalentTo(other Value) bool {
89	other = other.unwrap()
90	switch other := other.(type) {
91	case intValue:
92		return this == other
93	case floatValue:
94		return float64(this) == float64(other)
95	default:
96		return false
97	}
98}
99
100func (this intValue) Collate(other Value) int {
101	other = other.unwrap()
102	switch other := other.(type) {
103	case intValue:
104		switch {
105		case this < other:
106			return -1
107		case this > other:
108			return 1
109		default:
110			return 0
111		}
112	case floatValue:
113		return -other.Collate(this)
114	default:
115		return int(NUMBER - other.Type())
116	}
117
118}
119
120func (this intValue) Compare(other Value) Value {
121	other = other.unwrap()
122	switch other := other.(type) {
123	case missingValue:
124		return other
125	case *nullValue:
126		return other
127	default:
128		return intValue(this.Collate(other))
129	}
130}
131
132/*
133Returns true in the event the receiver is not 0 and it isn’t
134a NaN value
135*/
136func (this intValue) Truth() bool {
137	return this != 0
138}
139
140/*
141Return receiver
142*/
143func (this intValue) Copy() Value {
144	return this
145}
146
147/*
148Return receiver
149*/
150func (this intValue) CopyForUpdate() Value {
151	return this
152}
153
154/*
155Calls missingField.
156*/
157func (this intValue) Field(field string) (Value, bool) {
158	return missingField(field), false
159}
160
161/*
162Not valid for NUMBER.
163*/
164func (this intValue) SetField(field string, val interface{}) error {
165	return Unsettable(field)
166}
167
168/*
169Not valid for NUMBER.
170*/
171func (this intValue) UnsetField(field string) error {
172	return Unsettable(field)
173}
174
175/*
176Calls missingIndex.
177*/
178func (this intValue) Index(index int) (Value, bool) {
179	return missingIndex(index), false
180}
181
182/*
183Not valid for NUMBER.
184*/
185func (this intValue) SetIndex(index int, val interface{}) error {
186	return Unsettable(index)
187}
188
189/*
190Returns NULL_VALUE
191*/
192func (this intValue) Slice(start, end int) (Value, bool) {
193	return NULL_VALUE, false
194}
195
196/*
197Returns NULL_VALUE
198*/
199func (this intValue) SliceTail(start int) (Value, bool) {
200	return NULL_VALUE, false
201}
202
203/*
204Returns the input buffer as is.
205*/
206func (this intValue) Descendants(buffer []interface{}) []interface{} {
207	return buffer
208}
209
210/*
211As number has no fields, return nil.
212*/
213func (this intValue) Fields() map[string]interface{} {
214	return nil
215}
216
217func (this intValue) FieldNames(buffer []string) []string {
218	return nil
219}
220
221/*
222Returns the input buffer as is.
223*/
224func (this intValue) DescendantPairs(buffer []util.IPair) []util.IPair {
225	return buffer
226}
227
228/*
229NUMBER is succeeded by STRING.
230*/
231func (this intValue) Successor() Value {
232	if this < math.MaxInt64 {
233		return intValue(this + 1)
234	} else {
235		return EMPTY_STRING_VALUE
236	}
237}
238
239func (this intValue) Recycle() {
240}
241
242func (this intValue) Tokens(set *Set, options Value) *Set {
243	set.Add(this)
244	return set
245}
246
247func (this intValue) ContainsToken(token, options Value) bool {
248	return this.EquivalentTo(token)
249}
250
251func (this intValue) ContainsMatchingToken(matcher MatchFunc, options Value) bool {
252	return matcher(int64(this))
253}
254
255func (this intValue) unwrap() Value {
256	return this
257}
258
259/*
260NumberValue methods.
261*/
262
263/*
264Handle overflow per http://blog.regehr.org/archives/1139
265*/
266func (this intValue) Add(n NumberValue) NumberValue {
267	switch n := n.(type) {
268	case intValue:
269		rv := intValue(uint64(this) + uint64(n))
270		overFlow := (this < 0 && n < 0 && rv >= 0) || (this >= 0 && n >= 0 && rv < 0)
271		if !overFlow {
272			return rv
273		}
274	}
275
276	return floatValue(float64(this) + n.Actual().(float64))
277}
278
279func (this intValue) IDiv(n NumberValue) Value {
280	switch n := n.(type) {
281	case intValue:
282		if n == 0 {
283			return NULL_VALUE
284		} else {
285			return this / n
286		}
287	default:
288		f := n.Actual().(float64)
289		if f == 0.0 {
290			return NULL_VALUE
291		} else {
292			return this / intValue(f)
293		}
294	}
295}
296
297func (this intValue) IMod(n NumberValue) Value {
298	switch n := n.(type) {
299	case intValue:
300		if n == 0 {
301			return NULL_VALUE
302		} else {
303			return this % n
304		}
305	default:
306		f := n.Actual().(float64)
307		if f == 0.0 {
308			return NULL_VALUE
309		} else {
310			return this % intValue(f)
311		}
312	}
313}
314
315/*
316Handle overflow per
317http://stackoverflow.com/questions/1815367/multiplication-of-large-numbers-how-to-catch-overflow
318*/
319func (this intValue) Mult(n NumberValue) NumberValue {
320	switch n := n.(type) {
321	case intValue:
322		rv := this * n
323		if this == 0 || rv/this == n {
324			return rv
325		}
326	}
327
328	return floatValue(float64(this) * n.Actual().(float64))
329}
330
331func (this intValue) Neg() NumberValue {
332	if this == math.MinInt64 {
333		return -floatValue(this)
334	}
335
336	return -this
337}
338
339func (this intValue) Sub(n NumberValue) NumberValue {
340	switch n := n.(type) {
341	case intValue:
342		if n > math.MinInt64 {
343			return this.Add(-n)
344		}
345	}
346
347	return floatValue(float64(this) - n.Actual().(float64))
348}
349
350func (this intValue) Int64() int64 {
351	return int64(this)
352}
353
354func IsInt(x float64) bool {
355	return x == float64(int64(x))
356}
357