github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/common/dtypeutils/dtypeutils.go (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package dtypeutils 18 19 import ( 20 "errors" 21 "fmt" 22 "math" 23 "regexp" 24 "strconv" 25 "strings" 26 "unsafe" 27 ) 28 29 type TimeRange struct { 30 StartEpochMs uint64 31 EndEpochMs uint64 32 } 33 34 type MetricsTimeRange struct { 35 StartEpochSec uint32 36 EndEpochSec uint32 37 } 38 39 // returns true if [earliest_ts, latest_ts] overlaps with tsVal 40 func (tsVal *TimeRange) CheckRangeOverLap(earliest_ts, latest_ts uint64) bool { 41 42 if (earliest_ts >= tsVal.StartEpochMs && earliest_ts <= tsVal.EndEpochMs) || 43 (latest_ts >= tsVal.StartEpochMs && latest_ts <= tsVal.EndEpochMs) || 44 (earliest_ts <= tsVal.StartEpochMs && latest_ts >= tsVal.EndEpochMs) { 45 return true 46 } 47 return false 48 } 49 50 // returns true if [earliest_ts, latest_ts] overlaps with tsVal 51 func (tsVal *MetricsTimeRange) CheckRangeOverLap(earliest_ts, latest_ts uint32) bool { 52 53 if (earliest_ts >= tsVal.StartEpochSec && earliest_ts <= tsVal.EndEpochSec) || 54 (latest_ts >= tsVal.StartEpochSec && latest_ts <= tsVal.EndEpochSec) || 55 (earliest_ts <= tsVal.StartEpochSec && latest_ts >= tsVal.EndEpochSec) { 56 return true 57 } 58 return false 59 } 60 61 // returns true if [lowTs, highTs] is fully enclosed within timeRange 62 func (tr *TimeRange) AreTimesFullyEnclosed(lowTs, highTs uint64) bool { 63 64 if lowTs >= tr.StartEpochMs && lowTs <= tr.EndEpochMs && 65 highTs >= tr.StartEpochMs && highTs <= tr.EndEpochMs { 66 return true 67 } 68 return false 69 } 70 71 func (tsVal *TimeRange) CheckInRange(timeStamp uint64) bool { 72 73 if tsVal.StartEpochMs <= timeStamp && timeStamp <= tsVal.EndEpochMs { 74 return true 75 } 76 return false 77 } 78 79 func (tsVal *MetricsTimeRange) CheckInRange(timeStamp uint32) bool { 80 81 if tsVal.StartEpochSec <= timeStamp && timeStamp <= tsVal.EndEpochSec { 82 return true 83 } 84 return false 85 } 86 87 func ConvertToUInt(exp interface{}, bytes int) (uint64, error) { 88 str := fmt.Sprint(exp) 89 return strconv.ParseUint(str, 10, bytes) 90 } 91 92 func ConvertToInt(exp interface{}, bytes int) (int64, error) { 93 str := fmt.Sprint(exp) 94 return strconv.ParseInt(str, 10, bytes) 95 } 96 97 func ConvertToFloat(exp interface{}, bytes int) (float64, error) { 98 str := fmt.Sprint(exp) 99 return strconv.ParseFloat(str, bytes) 100 } 101 102 func ConvertToFloatAndReturnString(exp interface{}, bytes int) (float64, string, error) { 103 str := fmt.Sprint(exp) 104 floatExp, err := strconv.ParseFloat(str, bytes) 105 if err != nil { 106 return 0, "", err 107 } 108 return floatExp, str, nil 109 } 110 111 func ConvertExpToType(valueToConvert interface{}, knownType interface{}) (interface{}, error) { 112 113 switch knownType.(type) { 114 case uint8: 115 retVal, ok := valueToConvert.(uint8) 116 if !ok { 117 retVal, err := ConvertToUInt(valueToConvert, 8) 118 return uint8(retVal), err 119 } else { 120 return retVal, nil 121 } 122 case uint16: 123 retVal, ok := valueToConvert.(uint16) 124 if !ok { 125 retVal, err := ConvertToUInt(valueToConvert, 16) 126 return uint16(retVal), err 127 } else { 128 return retVal, nil 129 } 130 case uint32: 131 retVal, ok := valueToConvert.(uint32) 132 if !ok { 133 retVal, err := ConvertToUInt(valueToConvert, 32) 134 return uint32(retVal), err 135 } else { 136 return retVal, nil 137 } 138 case uint64: 139 retVal, ok := valueToConvert.(uint64) 140 if !ok { 141 return ConvertToUInt(valueToConvert, 64) 142 } else { 143 return retVal, nil 144 } 145 case int8: 146 retVal, ok := valueToConvert.(int8) 147 if !ok { 148 retVal, err := ConvertToInt(valueToConvert, 8) 149 return int8(retVal), err 150 } else { 151 return retVal, nil 152 } 153 case int16: 154 retVal, ok := valueToConvert.(int16) 155 if !ok { 156 retVal, err := ConvertToInt(valueToConvert, 16) 157 return int16(retVal), err 158 } else { 159 return retVal, nil 160 } 161 case int32: 162 retVal, ok := valueToConvert.(int32) 163 if !ok { 164 retVal, err := ConvertToInt(valueToConvert, 32) 165 return int32(retVal), err 166 } else { 167 return retVal, nil 168 } 169 case int64: 170 retVal, ok := valueToConvert.(int64) 171 if !ok { 172 return ConvertToInt(valueToConvert, 64) 173 } else { 174 return retVal, nil 175 } 176 case float64: 177 retVal, ok := valueToConvert.(float64) 178 if !ok { 179 return ConvertToFloat(valueToConvert, 64) 180 } else { 181 return retVal, nil 182 } 183 case bool: 184 retVal, ok := valueToConvert.(bool) 185 if !ok { 186 retVal, err := ConvertToInt(valueToConvert, 8) 187 188 if err != nil { 189 return int8(0), err 190 } 191 number := int8(retVal) 192 193 if number == int8(0) { 194 return false, nil 195 } else { 196 return true, nil 197 } 198 } else { 199 return retVal, nil 200 } 201 case string: 202 retVal, ok := valueToConvert.(string) 203 if !ok { 204 return fmt.Sprint(valueToConvert), nil 205 } else { 206 return retVal, nil 207 } 208 } 209 return nil, errors.New("invalid conversion type") 210 } 211 212 // TODO: add logic for overflow/underflow cases 213 func Multiply(left interface{}, right interface{}) (interface{}, error) { 214 215 switch left.(type) { 216 case uint8: 217 a := left.(uint8) 218 b := right.(uint8) 219 c := uint16(a) * uint16(b) 220 return c, nil 221 222 case uint16: 223 a := left.(uint16) 224 b := right.(uint16) 225 c := uint32(a) * uint32(b) 226 return c, nil 227 228 case uint32: 229 a := left.(uint32) 230 b := right.(uint32) 231 c := uint64(a) * uint64(b) 232 return c, nil 233 234 case uint64: 235 a := left.(uint64) 236 b := right.(uint64) 237 c := a * b 238 return c, nil 239 240 case int8: 241 a := left.(int8) 242 b := right.(int8) 243 c := int16(a) * int16(b) 244 return c, nil 245 246 case int16: 247 a := left.(int16) 248 b := right.(int16) 249 c := int32(a) * int32(b) 250 return c, nil 251 252 case int32: 253 a := left.(int32) 254 b := right.(int32) 255 c := int64(a) * int64(b) 256 return c, nil 257 258 case int64: 259 a := left.(int64) 260 b := right.(int64) 261 c := a * b 262 if a == 0 || b == 0 { 263 return c, nil 264 } 265 266 if (c < 0) == ((a < 0) != (b < 0)) { 267 if c/b == a { 268 return c, nil 269 } 270 } 271 return c, errors.New("Overflow") 272 case float64: 273 c := left.(float64) * right.(float64) 274 if c != float64(math.Inf(1)) && c != float64(math.Inf(-1)) { 275 return c, nil 276 } 277 return c, errors.New("Overflow") 278 } 279 280 return "", errors.New("invalid type for multiply") 281 282 } 283 284 // TODO: add logic for overflow/underflow cases 285 func Add(left interface{}, right interface{}) (interface{}, error) { 286 287 switch left.(type) { 288 case uint8: 289 c := left.(uint8) + right.(uint8) 290 if (c > left.(uint8)) == (right.(uint8) > 0) { 291 return c, nil 292 } 293 return c, errors.New("Overflow") 294 case uint16: 295 c := left.(uint16) + right.(uint16) 296 if (c > left.(uint16)) == (right.(uint16) > 0) { 297 return c, nil 298 } 299 return c, errors.New("Overflow") 300 case uint32: 301 c := left.(uint32) + right.(uint32) 302 if (c > left.(uint32)) == (right.(uint32) > 0) { 303 return c, nil 304 } 305 return c, errors.New("Overflow") 306 case uint64: 307 c := left.(uint64) + right.(uint64) 308 if (c > left.(uint64)) == (right.(uint64) > 0) { 309 return c, nil 310 } 311 return c, errors.New("Overflow") 312 case int8: 313 c := left.(int8) + right.(int8) 314 if (c > left.(int8)) == (right.(int8) > 0) { 315 return c, nil 316 } 317 return c, errors.New("Overflow") 318 case int16: 319 c := left.(int16) + right.(int16) 320 if (c > left.(int16)) == (right.(int16) > 0) { 321 return c, nil 322 } 323 return c, errors.New("Overflow") 324 case int32: 325 c := left.(int32) + right.(int32) 326 if (c > left.(int32)) == (right.(int32) > 0) { 327 return c, nil 328 } 329 return c, errors.New("Overflow") 330 case int64: 331 c := left.(int64) + right.(int64) 332 if (c > left.(int64)) == (right.(int64) > 0) { 333 return c, nil 334 } 335 return c, errors.New("Overflow") 336 case int: 337 c := left.(int) + right.(int) 338 if (c > left.(int)) == (right.(int) > 0) { 339 return c, nil 340 } 341 return c, errors.New("Overflow") 342 case float64: 343 c := left.(float64) + right.(float64) 344 if c != float64(math.Inf(1)) && c != float64(math.Inf(-1)) { 345 return c, nil 346 } 347 return c, errors.New("Overflow") 348 } 349 350 return "", errors.New("invalid type for addition") 351 } 352 353 // TODO: add logic for overflow/underflow cases 354 func Subtract(left interface{}, right interface{}) (interface{}, error) { 355 356 switch left.(type) { 357 case uint8: 358 c := left.(uint8) - right.(uint8) 359 if (c < left.(uint8)) == (right.(uint8) > 0) { 360 return c, nil 361 } 362 return c, errors.New("Overflow") 363 364 case uint16: 365 c := left.(uint16) - right.(uint16) 366 if (c < left.(uint16)) == (right.(uint16) > 0) { 367 return c, nil 368 } 369 return c, errors.New("Overflow") 370 case uint32: 371 c := left.(uint32) - right.(uint32) 372 if (c < left.(uint32)) == (right.(uint32) > 0) { 373 return c, nil 374 } 375 return c, errors.New("Overflow") 376 case uint64: 377 c := left.(uint64) - right.(uint64) 378 if (c < left.(uint64)) == (right.(uint64) > 0) { 379 return c, nil 380 } 381 return c, errors.New("Overflow") 382 case int8: 383 c := left.(int8) - right.(int8) 384 if (c < left.(int8)) == (right.(int8) > 0) { 385 return c, nil 386 } 387 return c, errors.New("Overflow") 388 case int16: 389 c := left.(int16) - right.(int16) 390 if (c < left.(int16)) == (right.(int16) > 0) { 391 return c, nil 392 } 393 return c, errors.New("Overflow") 394 case int32: 395 c := left.(int32) - right.(int32) 396 if (c < left.(int32)) == (right.(int32) > 0) { 397 return c, nil 398 } 399 return c, errors.New("Overflow") 400 case int64: 401 c := left.(int64) - right.(int64) 402 if (c < left.(int64)) == (right.(int64) > 0) { 403 return c, nil 404 } 405 return c, errors.New("Overflow") 406 case float64: 407 c := left.(float64) - right.(float64) 408 if c != float64(math.Inf(1)) && c != float64(math.Inf(-1)) { 409 return c, nil 410 } 411 return c, errors.New("Overflow") 412 } 413 414 return "", errors.New("invalid type for subtraction") 415 } 416 417 // TODO: add logic for overflow/underflow cases and divide by 0 verification 418 func Divide(left interface{}, right interface{}) (interface{}, error) { 419 420 switch left.(type) { 421 case uint8: 422 if right.(uint8) == 0 { 423 return nil, errors.New("cannot divide by zero") 424 } 425 return left.(uint8) / right.(uint8), nil 426 case uint16: 427 if right.(uint16) == 0 { 428 return nil, errors.New("cannot divide by zero") 429 } 430 return left.(uint16) / right.(uint16), nil 431 case uint32: 432 if right.(uint32) == 0 { 433 return nil, errors.New("cannot divide by zero") 434 } 435 return left.(uint32) / right.(uint32), nil 436 case uint64: 437 if right.(uint64) == 0 { 438 return nil, errors.New("cannot divide by zero") 439 } 440 return left.(uint64) / right.(uint64), nil 441 case int8: 442 if right.(int8) == 0 { 443 return nil, errors.New("cannot divide by zero") 444 } 445 return left.(int8) / right.(int8), nil 446 case int16: 447 if right.(int16) == 0 { 448 return nil, errors.New("cannot divide by zero") 449 } 450 return left.(int16) / right.(int16), nil 451 case int32: 452 if right.(int32) == 0 { 453 return nil, errors.New("cannot divide by zero") 454 } 455 return left.(int32) / right.(int32), nil 456 case int64: 457 if right.(int64) == 0 { 458 return nil, errors.New("cannot divide by zero") 459 } 460 return left.(int64) / right.(int64), nil 461 case float64: 462 if right.(float64) == 0 { 463 return nil, errors.New("cannot divide by zero") 464 } 465 c := left.(float64) / right.(float64) 466 if c != float64(math.Inf(1)) && c != float64(math.Inf(-1)) { 467 return c, nil 468 } 469 return c, errors.New("Overflow") 470 } 471 472 return "", errors.New("invalid type for divide") 473 474 } 475 476 // TODO: divide by 0 verification 477 func Modulo(left interface{}, right interface{}) (interface{}, error) { 478 479 switch left.(type) { 480 case uint8: 481 if right.(uint8) == 0 { 482 return nil, errors.New("cannot divide by zero") 483 } 484 return left.(uint8) % right.(uint8), nil 485 case uint16: 486 if right.(uint16) == 0 { 487 return nil, errors.New("cannot divide by zero") 488 } 489 return left.(uint16) % right.(uint16), nil 490 case uint32: 491 if right.(uint32) == 0 { 492 return nil, errors.New("cannot divide by zero") 493 } 494 return left.(uint32) % right.(uint32), nil 495 case uint64: 496 if right.(uint64) == 0 { 497 return nil, errors.New("cannot divide by zero") 498 } 499 return left.(uint64) % right.(uint64), nil 500 case int8: 501 if right.(int8) == 0 { 502 return nil, errors.New("cannot divide by zero") 503 } 504 return left.(int8) % right.(int8), nil 505 case int16: 506 if right.(int16) == 0 { 507 return nil, errors.New("cannot divide by zero") 508 } 509 return left.(int16) % right.(int16), nil 510 case int32: 511 if right.(int32) == 0 { 512 return nil, errors.New("cannot divide by zero") 513 } 514 return left.(int32) % right.(int32), nil 515 case int64: 516 if right.(int64) == 0 { 517 return nil, errors.New("cannot divide by zero") 518 } 519 return left.(int64) % right.(int64), nil 520 } 521 522 return "", errors.New("invalid type for modulus") 523 } 524 525 func BitwiseAnd(left interface{}, right interface{}) (interface{}, error) { 526 527 switch left.(type) { 528 case uint8: 529 return left.(uint8) & right.(uint8), nil 530 case uint16: 531 return left.(uint16) & right.(uint16), nil 532 case uint32: 533 return left.(uint32) & right.(uint32), nil 534 case uint64: 535 return left.(uint64) & right.(uint64), nil 536 case int8: 537 return left.(int8) & right.(int8), nil 538 case int16: 539 return left.(int16) & right.(int16), nil 540 case int32: 541 return left.(int32) & right.(int32), nil 542 case int64: 543 return left.(int64) & right.(int64), nil 544 } 545 546 return "", errors.New("invalid type for bitwise and") 547 } 548 549 func BitwiseOr(left interface{}, right interface{}) (interface{}, error) { 550 551 switch left.(type) { 552 case uint8: 553 return left.(uint8) | right.(uint8), nil 554 case uint16: 555 return left.(uint16) | right.(uint16), nil 556 case uint32: 557 return left.(uint32) | right.(uint32), nil 558 case uint64: 559 return left.(uint64) | right.(uint64), nil 560 case int8: 561 return left.(int8) | right.(int8), nil 562 case int16: 563 return left.(int16) | right.(int16), nil 564 case int32: 565 return left.(int32) | right.(int32), nil 566 case int64: 567 return left.(int64) | right.(int64), nil 568 } 569 570 return "", errors.New("invalid type for bitwise or") 571 } 572 573 func BitwiseXOr(left interface{}, right interface{}) (interface{}, error) { 574 575 switch left.(type) { 576 case uint8: 577 return left.(uint8) ^ right.(uint8), nil 578 case uint16: 579 return left.(uint16) ^ right.(uint16), nil 580 case uint32: 581 return left.(uint32) ^ right.(uint32), nil 582 case uint64: 583 return left.(uint64) ^ right.(uint64), nil 584 case int8: 585 return left.(int8) ^ right.(int8), nil 586 case int16: 587 return left.(int16) ^ right.(int16), nil 588 case int32: 589 return left.(int32) ^ right.(int32), nil 590 case int64: 591 return left.(int64) ^ right.(int64), nil 592 } 593 594 return "", errors.New("invalid type for bitwise xor") 595 } 596 597 // todo: better wildcard comparison 598 func ReplaceWildcardStarWithRegex(input string) string { 599 var result strings.Builder 600 for i, literal := range strings.Split(input, "*") { 601 602 // Replace * with .* 603 if i > 0 { 604 result.WriteString(".*") 605 } 606 607 // Quote any regular expression meta characters in the 608 // literal text. 609 result.WriteString(regexp.QuoteMeta(literal)) 610 } 611 return result.String() 612 } 613 614 func AlmostEquals(left, right float64) bool { 615 tolerance := 0.000001 616 if difference := math.Abs(left - right); difference < tolerance { 617 return true 618 } else { 619 return false 620 } 621 } 622 623 func ConvertToSameType(leftType, rightType interface{}) (interface{}, interface{}, error) { 624 625 if fmt.Sprintf("%T", leftType) == fmt.Sprintf("%T", rightType) { 626 return leftType, rightType, nil 627 } 628 629 if unsafe.Sizeof(leftType) > unsafe.Sizeof(rightType) { 630 rightType, err := ConvertExpToType(rightType, leftType) 631 return leftType, rightType, err 632 } else { 633 leftType, err := ConvertExpToType(leftType, rightType) 634 return rightType, leftType, err 635 } 636 } 637 638 type AccessLogData struct { 639 TimeStamp string 640 UserName string 641 URI string 642 RequestBody string 643 StatusCode int 644 Duration int64 645 }