1 module mir.bloomberg.blpapi; 2 3 import mir.timestamp: Timestamp; 4 import mir.algebraic: Nullable; 5 6 alias BloombergStreamWriter = extern(C) int function(const(char)* data, int length, void* stream); 7 8 deprecated("Please use a local alias or IonAlgebraic instead .") 9 alias BloombergAlgebraic = Nullable!( 10 bool, 11 long, 12 double, 13 string, 14 Timestamp); 15 16 enum DataType 17 { 18 null_, 19 /// Bool 20 bool_ = 1, 21 /// Char 22 char_ = 2, 23 /// Unsigned 8 bit value 24 byte_ = 3, 25 /// 32 bit Integer 26 int32 = 4, 27 /// 64 bit Integer 28 int64 = 5, 29 /// 32 bit Floating point - IEEE 30 float32 = 6, 31 /// 64 bit Floating point - IEEE 32 float64 = 7, 33 /// ASCIIZ string 34 string = 8, 35 /// Opaque binary data 36 bytearray = 9, 37 /// Date 38 date = 10, 39 /// Timestamp 40 time = 11, 41 decimal = 12, 42 /// Date and time 43 datetime = 13, 44 /// An opaque enumeration 45 enumeration = 14, 46 /// Sequence type 47 sequence = 15, 48 /// Choice type 49 choice = 16, 50 /// Used for some internal messages 51 correlation_id = 17, 52 } 53 54 enum DatetimeParts : ubyte 55 { 56 year = 0x1, 57 month = 0x2, 58 day = 0x4, 59 offset = 0x8, 60 hours = 0x10, 61 minutes = 0x20, 62 seconds = 0x40, 63 fracseconds = 0x80, 64 } 65 66 struct ErrorInfo 67 { 68 int exceptionClass; 69 char[256] _description = '\0'; 70 71 inout(char)[] description() @trusted pure nothrow @nogc inout return scope 72 { 73 import core.stdc.string: strlen; 74 return _description[0 .. (&this._description[0]).strlen]; 75 } 76 } 77 78 enum DatePart = DatetimeParts.year | DatetimeParts.month | DatetimeParts.day; 79 80 enum TimePart = DatetimeParts.hours | DatetimeParts.minutes | DatetimeParts.seconds; 81 82 enum TimeFracsecondsPart = TimePart | DatetimeParts.fracseconds; 83 84 alias Bool = int; 85 86 struct Name; 87 88 struct Element; 89 90 struct Datetime 91 { 92 /// bitmask of date/time parts that are set 93 ubyte parts; 94 ubyte hours; 95 ubyte minutes; 96 ubyte seconds; 97 ushort milliseconds; 98 ubyte month; 99 ubyte day; 100 ushort year; 101 /// (signed) minutes ahead of UTC 102 short offset; 103 104 /// 105 this( 106 ubyte parts, 107 ubyte hours, 108 ubyte minutes, 109 ubyte seconds, 110 ushort milliseconds, 111 ubyte month, 112 ubyte day, 113 ushort year, 114 short offset, 115 ) { 116 this.parts = parts; 117 this.hours = hours; 118 this.minutes = minutes; 119 this.seconds = seconds; 120 this.milliseconds = milliseconds; 121 this.month = month; 122 this.day = day; 123 this.year = year; 124 this.offset = offset; 125 } 126 127 /// Construct from $(MREF mir,timestamp). 128 this(Timestamp timestamp) @safe pure nothrow @nogc 129 { 130 this = HighPrecisionDatetime(timestamp).datetime; 131 } 132 133 /// Converts `Datetime` to $(MREF mir,timestamp). 134 Timestamp asTimestamp() @safe pure nothrow @nogc const @property 135 { 136 return HighPrecisionDatetime(this).asTimestamp; 137 } 138 139 alias opCast(T : Timestamp) = asTimestamp; 140 141 bool isOnlyTime() @safe pure nothrow @nogc const @property 142 { 143 return (parts & DatetimeParts.year) == 0; 144 } 145 } 146 147 struct HighPrecisionDatetime { 148 Datetime datetime; 149 150 alias datetime this; 151 152 /++ 153 picosecond offset into current 154 *millisecond* i.e. the picosecond offset 155 into the current full second is 156 '1000000000LL * milliseconds + picoseconds' 157 +/ 158 uint picoseconds; 159 160 this(Datetime datetime, uint picoseconds = 0) @safe pure nothrow @nogc 161 { 162 this.datetime = datetime; 163 this.picoseconds = picoseconds; 164 } 165 166 /// Construct from $(MREF mir,timestamp). 167 this(Timestamp timestamp) @safe pure nothrow @nogc 168 { 169 if (timestamp.offset) 170 { 171 parts |= DatetimeParts.offset; 172 offset = timestamp.offset; 173 timestamp.addMinutes(timestamp.offset); 174 } 175 final switch (timestamp.precision) 176 { 177 case Timestamp.Precision.fraction: { 178 parts |= DatetimeParts.fracseconds; 179 auto exp = timestamp.fractionExponent; 180 auto coeff = timestamp.fractionCoefficient; 181 while(exp > -12) 182 { 183 exp--; 184 coeff *= 10; 185 } 186 picoseconds = cast(uint) (coeff % 1000000000u); 187 milliseconds = cast(ushort) (coeff / 1000000000u); 188 goto case; 189 } 190 case Timestamp.Precision.second: 191 parts |= DatetimeParts.seconds; 192 seconds = timestamp.second; 193 goto case; 194 case Timestamp.Precision.minute: 195 parts |= DatetimeParts.minutes; 196 parts |= DatetimeParts.hours; 197 minutes = timestamp.minute; 198 hours = timestamp.hour; 199 if (timestamp.day == 0) // 200 return; 201 goto case; 202 case Timestamp.Precision.day: 203 parts |= DatetimeParts.day; 204 day = timestamp.day; 205 goto case; 206 case Timestamp.Precision.month: 207 parts |= DatetimeParts.month; 208 month = timestamp.month; 209 goto case; 210 case Timestamp.Precision.year: 211 parts |= DatetimeParts.year; 212 year = timestamp.year; 213 } 214 } 215 216 /// Converts `Datetime` to $(MREF mir,timestamp). 217 Timestamp asTimestamp() @safe pure nothrow @nogc const @property 218 { 219 Timestamp ret; 220 if (parts & DatetimeParts.year) 221 { 222 ret.year = year; 223 ret.precision = Timestamp.Precision.year; 224 } 225 if (parts & DatetimeParts.month) 226 { 227 ret.month = month; 228 ret.precision = Timestamp.Precision.month; 229 } 230 if (parts & DatetimeParts.day) 231 { 232 ret.day = day; 233 ret.precision = Timestamp.Precision.day; 234 } 235 if (parts & DatetimeParts.hours) 236 { 237 ret.hour = hours; 238 ret.precision = Timestamp.Precision.minute; 239 } 240 if (parts & DatetimeParts.minutes) 241 { 242 ret.minute = minutes; 243 ret.precision = Timestamp.Precision.minute; 244 } 245 if (parts & DatetimeParts.seconds) 246 { 247 ret.second = seconds; 248 ret.precision = Timestamp.Precision.second; 249 } 250 if (parts & DatetimeParts.fracseconds) 251 { 252 ret.fractionExponent = -12; 253 ret.fractionCoefficient = 1000000000UL * milliseconds + picoseconds; 254 ret.precision = Timestamp.Precision.fraction; 255 } 256 if (parts & DatetimeParts.offset && offset && ret.precision >= Timestamp.Precision.minute) 257 { 258 ret.addMinutes(cast(short)-int(ret.offset)); 259 } 260 return ret; 261 } 262 263 alias opCast(T : Timestamp) = asTimestamp; 264 } 265 266 unittest 267 { 268 auto tests = [ 269 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 11, 1, 2021, 0), 0), 270 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 271 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 11, 2, 2020, 0), 0), 272 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 6, 2, 2021, 0), 0), 273 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 274 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 275 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 276 HighPrecisionDatetime(Datetime(112, 7, 0, 0, 0, 1, 1, 1, 0), 0), 277 HighPrecisionDatetime(Datetime(112, 6, 59, 59, 0, 1, 1, 1, 0), 0), 278 HighPrecisionDatetime(Datetime(112, 16, 59, 59, 0, 1, 1, 1, 0), 0), 279 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 280 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 11, 1, 2021, 0), 0), 281 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 282 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 3, 15, 2021, 0), 0), 283 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 11, 2, 2020, 0), 0), 284 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 3, 23, 2020, 0), 0), 285 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 3, 23, 2020, 0), 0), 286 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 287 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 288 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 289 HighPrecisionDatetime(Datetime(7, 0, 0, 0, 0, 10, 29, 2021, 0), 0), 290 HighPrecisionDatetime(Datetime(112, 9, 30, 0, 0, 1, 1, 1, 0), 0), 291 HighPrecisionDatetime(Datetime(112, 16, 30, 0, 0, 1, 1, 1, 0), 0), 292 HighPrecisionDatetime(Datetime(112, 20, 4, 0, 0, 1, 1, 1, 0), 0), 293 HighPrecisionDatetime(Datetime(240, 20, 4, 0, 0, 1, 1, 1, 0), 0), 294 HighPrecisionDatetime(Datetime(240, 12, 38, 48, 0, 1, 1, 1, 0), 0), 295 HighPrecisionDatetime(Datetime(240, 13, 5, 3, 0, 1, 1, 1, 0), 0), 296 ]; 297 298 foreach (test; tests) 299 { 300 import mir.ion.ser.ion; 301 import mir.ion.deser.ion; 302 auto ts = test.asTimestamp; 303 assert(ts.serializeIon.deserializeIon!Timestamp == ts); 304 } 305 } 306 307 @safe pure // @nogc 308 validateBloombergErroCode()( 309 int errorCode, 310 string file = __FILE__, 311 size_t line = __LINE__) 312 { 313 import mir.ion.exception: IonException, IonMirException; 314 if (errorCode) 315 { 316 // static if (__traits(compiles, () @nogc { throw new Exception(""); })) 317 // { 318 ErrorInfo info; 319 getErrorInfo(info, errorCode); 320 throw new IonMirException(info.description, file, line); 321 // } 322 // else 323 // { 324 // static immutable exc = new IonException("Exception thrown in bloomberg API: add DIP1008 for better error messages."); 325 // throw exc; 326 // } 327 } 328 } 329 330 @safe pure nothrow @nogc extern(System): 331 332 alias getErrorInfo = blpapi_getErrorInfo; 333 int blpapi_getErrorInfo(scope ref ErrorInfo buffer, int errorCode); 334 335 alias nameCreate = blpapi_Name_create; 336 Name* blpapi_Name_create( 337 scope const(char)* nameString); 338 339 alias nameDestroy = blpapi_Name_destroy; 340 void blpapi_Name_destroy( 341 Name* name); 342 343 alias nameDuplicate = blpapi_Name_duplicate; 344 Name* blpapi_Name_duplicate( 345 scope const Name* src); 346 347 alias nameEqualsStr = blpapi_Name_equalsStr; 348 int blpapi_Name_equalsStr( 349 scope const Name* name, 350 const char *string); 351 352 alias nameString = blpapi_Name_string; 353 const(char)* blpapi_Name_string( 354 scope const Name* name); 355 356 alias nameLength = blpapi_Name_length; 357 size_t blpapi_Name_length( 358 scope const Name* name); 359 360 alias nameFindName = blpapi_Name_findName; 361 Name* blpapi_Name_findName( 362 scope const(char)* nameString); 363 364 int blpapi_Element_print( 365 const Element* element, 366 BloombergStreamWriter streamWriter, 367 void *stream, 368 int level, 369 int spacesPerLevel); 370 371 alias print = blpapi_Element_print; 372 373 alias name = blpapi_Element_name; 374 Name* blpapi_Element_name(const Element *element); 375 376 alias nameString = blpapi_Element_nameString; 377 const(char)* blpapi_Element_nameString(const Element *element); 378 379 alias datatype = blpapi_Element_datatype; 380 DataType blpapi_Element_datatype ( 381 const(Element)* element); 382 383 alias isComplexType = blpapi_Element_isComplexType; 384 int blpapi_Element_isComplexType( 385 const(Element)* element); 386 387 alias isArray = blpapi_Element_isArray; 388 int blpapi_Element_isArray( 389 const(Element)* element); 390 391 alias isReadOnly = blpapi_Element_isReadOnly; 392 int blpapi_Element_isReadOnly( 393 const(Element)* element); 394 395 alias numValues = blpapi_Element_numValues; 396 size_t blpapi_Element_numValues( 397 const(Element)* element); 398 399 alias numElements = blpapi_Element_numElements; 400 size_t blpapi_Element_numElements( 401 const(Element)* element); 402 403 alias isNullValue = blpapi_Element_isNullValue; 404 int blpapi_Element_isNullValue( 405 const(Element)* element, 406 size_t position); 407 408 alias isNull = blpapi_Element_isNull; 409 int blpapi_Element_isNull( 410 const(Element)* element); 411 412 alias getElementAt = blpapi_Element_getElementAt; 413 int blpapi_Element_getElementAt( 414 const(Element)* element, 415 scope ref Element *result, 416 size_t position); 417 418 alias getElement = blpapi_Element_getElement; 419 int blpapi_Element_getElement( 420 const Element *element, 421 scope ref Element *result, 422 const(char)* nameString, 423 const Name *name); 424 425 alias hasElement = blpapi_Element_hasElement; 426 int blpapi_Element_hasElement( 427 const Element *element, 428 const(char)* nameString, 429 const Name *name); 430 431 alias hasElementEx = blpapi_Element_hasElementEx; 432 int blpapi_Element_hasElementEx( 433 const Element *element, 434 const(char)* nameString, 435 const Name *name, 436 int excludeNullElements, 437 int reserved); 438 439 alias getValueAsBool = blpapi_Element_getValueAsBool; 440 int blpapi_Element_getValueAsBool( 441 const Element *element, 442 scope ref Bool buffer, 443 size_t index); 444 445 alias getValueAsChar = blpapi_Element_getValueAsChar; 446 int blpapi_Element_getValueAsChar( 447 const Element *element, 448 scope ref char buffer, 449 size_t index); 450 451 alias getValueAsInt32 = blpapi_Element_getValueAsInt32; 452 int blpapi_Element_getValueAsInt32( 453 const Element *element, 454 scope ref int buffer, 455 size_t index); 456 457 alias getValueAsInt64 = blpapi_Element_getValueAsInt64; 458 int blpapi_Element_getValueAsInt64( 459 const Element *element, 460 scope ref long buffer, 461 size_t index); 462 463 alias getValueAsFloat32 = blpapi_Element_getValueAsFloat32; 464 int blpapi_Element_getValueAsFloat32( 465 const Element *element, 466 scope ref float buffer, 467 size_t index); 468 469 alias getValueAsFloat64 = blpapi_Element_getValueAsFloat64; 470 int blpapi_Element_getValueAsFloat64( 471 const Element *element, 472 scope ref double buffer, 473 size_t index); 474 475 alias getValueAsString = blpapi_Element_getValueAsString; 476 int blpapi_Element_getValueAsString( 477 const Element *element, 478 scope ref const char *buffer, 479 size_t index); 480 481 alias getValueAsDatetime = blpapi_Element_getValueAsDatetime; 482 int blpapi_Element_getValueAsDatetime( 483 const Element *element, 484 scope ref Datetime buffer, 485 size_t index); 486 487 alias getValueAsHighPrecisionDatetime = blpapi_Element_getValueAsHighPrecisionDatetime; 488 int blpapi_Element_getValueAsHighPrecisionDatetime( 489 const Element *element, 490 scope ref HighPrecisionDatetime buffer, 491 size_t index); 492 493 alias getValueAsElement = blpapi_Element_getValueAsElement; 494 int blpapi_Element_getValueAsElement( 495 const Element *element, 496 scope ref Element *buffer, 497 size_t index); 498 499 alias getValueAsName = blpapi_Element_getValueAsName; 500 int blpapi_Element_getValueAsName( 501 const Element *element, 502 scope Name* *buffer, 503 size_t index); 504 505 alias getChoice = blpapi_Element_getChoice; 506 int blpapi_Element_getChoice( 507 const Element *element, 508 scope ref Element *result); 509 510 alias setValueBool = blpapi_Element_setValueBool; 511 int blpapi_Element_setValueBool( 512 Element *element, 513 Bool value, 514 size_t index); 515 516 alias setValueChar = blpapi_Element_setValueChar; 517 int blpapi_Element_setValueChar( 518 Element *element, 519 char value, 520 size_t index); 521 522 alias setValueInt32 = blpapi_Element_setValueInt32; 523 int blpapi_Element_setValueInt32( 524 Element *element, 525 int value, 526 size_t index); 527 528 alias setValueInt64 = blpapi_Element_setValueInt64; 529 int blpapi_Element_setValueInt64( 530 Element *element, 531 long value, 532 size_t index); 533 534 alias setValueFloat32 = blpapi_Element_setValueFloat32; 535 int blpapi_Element_setValueFloat32( 536 Element *element, 537 float value, 538 size_t index); 539 540 alias setValueFloat64 = blpapi_Element_setValueFloat64; 541 int blpapi_Element_setValueFloat64( 542 Element *element, 543 double value, 544 size_t index); 545 546 alias setValueString = blpapi_Element_setValueString; 547 int blpapi_Element_setValueString( 548 Element *element, 549 const char *value, 550 size_t index); 551 552 alias setValueDatetime = blpapi_Element_setValueDatetime; 553 int blpapi_Element_setValueDatetime( 554 Element *element, 555 scope ref const Datetime value, 556 size_t index); 557 558 alias setValueHighPrecisionDatetime = blpapi_Element_setValueHighPrecisionDatetime; 559 int blpapi_Element_setValueHighPrecisionDatetime( 560 Element *element, 561 scope ref const HighPrecisionDatetime value, 562 size_t index); 563 564 alias setValueFromElement = blpapi_Element_setValueFromElement; 565 int blpapi_Element_setValueFromElement( 566 Element *element, 567 Element *value, 568 size_t index); 569 570 alias setValueFromName = blpapi_Element_setValueFromName; 571 int blpapi_Element_setValueFromName ( 572 Element *element, 573 const Name *value, 574 size_t index); 575 576 alias setElementBool = blpapi_Element_setElementBool; 577 int blpapi_Element_setElementBool( 578 Element *element, 579 const(char)* nameString, 580 const Name* name, 581 Bool value); 582 583 alias setElementChar = blpapi_Element_setElementChar; 584 int blpapi_Element_setElementChar( 585 Element *element, 586 const(char)* nameString, 587 const Name* name, 588 char value); 589 590 alias setElementInt32 = blpapi_Element_setElementInt32; 591 int blpapi_Element_setElementInt32( 592 Element *element, 593 const(char)* nameString, 594 const Name* name, 595 int value); 596 597 alias setElementInt64 = blpapi_Element_setElementInt64; 598 int blpapi_Element_setElementInt64( 599 Element *element, 600 const(char)* nameString, 601 const Name* name, 602 long value); 603 604 alias setElementFloat32 = blpapi_Element_setElementFloat32; 605 int blpapi_Element_setElementFloat32( 606 Element *element, 607 const(char)* nameString, 608 const Name* name, 609 float value); 610 611 alias setElementFloat64 = blpapi_Element_setElementFloat64; 612 int blpapi_Element_setElementFloat64( 613 Element *element, 614 const(char)* nameString, 615 const Name* name, 616 double value); 617 618 alias setElementString = blpapi_Element_setElementString; 619 int blpapi_Element_setElementString( 620 Element *element, 621 const char *nameString, 622 const Name* name, 623 const char *value); 624 625 alias setElementDatetime = blpapi_Element_setElementDatetime; 626 int blpapi_Element_setElementDatetime( 627 Element *element, 628 const(char)* nameString, 629 const Name* name, 630 scope ref const Datetime value); 631 632 alias setElementHighPrecisionDatetime = blpapi_Element_setElementHighPrecisionDatetime; 633 int blpapi_Element_setElementHighPrecisionDatetime( 634 Element *element, 635 const char *nameString, 636 const Name *name, 637 scope ref const HighPrecisionDatetime value); 638 639 alias setElementFromField = blpapi_Element_setElementFromField; 640 int blpapi_Element_setElementFromField( 641 Element *element, 642 const(char)* nameString, 643 const Name* name, 644 Element *sourcebuffer); 645 646 alias setElementFromName = blpapi_Element_setElementFromName; 647 int blpapi_Element_setElementFromName ( 648 Element *element, 649 const(char)* elementName, 650 const Name* name, 651 const Name *buffer); 652 653 alias appendElement = blpapi_Element_appendElement; 654 int blpapi_Element_appendElement ( 655 Element *element, 656 scope ref Element *appendedElement); 657 658 alias setChoice = blpapi_Element_setChoice; 659 int blpapi_Element_setChoice ( 660 Element *element, 661 scope ref Element *resultElement, 662 const(char)* nameCstr, 663 const Name* name, 664 size_t index);