@@ -473,91 +473,33 @@ cdef class Buffer:
473473 """
474474 return self ._skip_int(8 , NULL )
475475
476- cdef int write_binary_double(self , double value,
477- bint write_length = True ) except - 1 :
476+ cdef int write_binary_double(self , double value) except - 1 :
478477 """
479478 Writes a double value to the buffer in Oracle canonical double floating
480479 point format.
481480 """
482- cdef:
483- uint8_t b0, b1, b2, b3, b4, b5, b6, b7
484- uint64_t all_bits
485- char_type buf[8 ]
486- uint64_t * ptr
487- ptr = < uint64_t* > & value
488- all_bits = ptr[0 ]
489- b7 = all_bits & 0xff
490- b6 = (all_bits >> 8 ) & 0xff
491- b5 = (all_bits >> 16 ) & 0xff
492- b4 = (all_bits >> 24 ) & 0xff
493- b3 = (all_bits >> 32 ) & 0xff
494- b2 = (all_bits >> 40 ) & 0xff
495- b1 = (all_bits >> 48 ) & 0xff
496- b0 = (all_bits >> 56 ) & 0xff
497- if b0 & 0x80 == 0 :
498- b0 = b0 | 0x80
499- else :
500- b0 = ~ b0
501- b1 = ~ b1
502- b2 = ~ b2
503- b3 = ~ b3
504- b4 = ~ b4
505- b5 = ~ b5
506- b6 = ~ b6
507- b7 = ~ b7
508- buf[0 ] = b0
509- buf[1 ] = b1
510- buf[2 ] = b2
511- buf[3 ] = b3
512- buf[4 ] = b4
513- buf[5 ] = b5
514- buf[6 ] = b6
515- buf[7 ] = b7
516- if write_length:
517- self .write_uint8(8 )
518- self .write_raw(buf, 8 )
481+ cdef char_type buf[ORA_TYPE_SIZE_BINARY_DOUBLE]
482+ encode_binary_double(buf, value)
483+ self ._write_raw_bytes_and_length(buf, sizeof(buf))
519484
520- cdef int write_binary_float(self , float value,
521- bint write_length = True ) except - 1 :
485+ cdef int write_binary_float(self , float value) except - 1 :
522486 """
523487 Writes a float value to the buffer in Oracle canonical floating point
524488 format.
525489 """
526- cdef:
527- uint8_t b0, b1, b2, b3
528- uint32_t all_bits
529- char_type buf[4 ]
530- uint32_t * ptr
531- ptr = < uint32_t* > & value
532- all_bits = ptr[0 ]
533- b3 = all_bits & 0xff
534- b2 = (all_bits >> 8 ) & 0xff
535- b1 = (all_bits >> 16 ) & 0xff
536- b0 = (all_bits >> 24 ) & 0xff
537- if b0 & 0x80 == 0 :
538- b0 = b0 | 0x80
539- else :
540- b0 = ~ b0
541- b1 = ~ b1
542- b2 = ~ b2
543- b3 = ~ b3
544- buf[0 ] = b0
545- buf[1 ] = b1
546- buf[2 ] = b2
547- buf[3 ] = b3
548- if write_length:
549- self .write_uint8(4 )
550- self .write_raw(buf, 4 )
490+ cdef char_type buf[ORA_TYPE_SIZE_BINARY_FLOAT]
491+ encode_binary_float(buf, value)
492+ self ._write_raw_bytes_and_length(buf, sizeof(buf))
551493
552494 cdef int write_bool(self , bint value) except - 1 :
553495 """
554496 Writes a boolean value to the buffer.
555497 """
556- if value :
557- self .write_uint8( 2 )
558- self .write_uint16be( 0x0101 )
559- else :
560- self .write_uint16be( 0x0100 )
498+ cdef :
499+ char_type buf[ORA_TYPE_SIZE_BOOLEAN]
500+ ssize_t buflen
501+ encode_boolean(buf, & buflen, value)
502+ self ._write_raw_bytes_and_length(buf, buflen )
561503
562504 cdef int write_bytes(self , bytes value) except - 1 :
563505 """
@@ -579,223 +521,51 @@ cdef class Buffer:
579521 cpython.PyBytes_AsStringAndSize(value, < char ** > & ptr, & value_len)
580522 self ._write_raw_bytes_and_length(ptr, value_len)
581523
582- cdef int write_interval_ds(self , object value,
583- bint write_length = True ) except - 1 :
524+ cdef int write_interval_ds(self , object value) except - 1 :
584525 """
585526 Writes an interval to the buffer in Oracle Interval Day To Second
586527 format.
587528 """
588- cdef:
589- int32_t days, seconds, fseconds
590- char_type buf[11 ]
591- days = cydatetime.timedelta_days(value)
592- encode_uint32be(buf, days + TNS_DURATION_MID)
593- seconds = cydatetime.timedelta_seconds(value)
594- buf[4 ] = (seconds // 3600 ) + TNS_DURATION_OFFSET
595- seconds = seconds % 3600
596- buf[5 ] = (seconds // 60 ) + TNS_DURATION_OFFSET
597- buf[6 ] = (seconds % 60 ) + TNS_DURATION_OFFSET
598- fseconds = cydatetime.timedelta_microseconds(value) * 1000
599- encode_uint32be(& buf[7 ], fseconds + TNS_DURATION_MID)
600- if write_length:
601- self .write_uint8(sizeof(buf))
602- self .write_raw(buf, sizeof(buf))
603-
604- cdef int write_interval_ym(self , object value,
605- bint write_length = True ) except - 1 :
529+ cdef char_type buf[ORA_TYPE_SIZE_INTERVAL_DS]
530+ encode_interval_ds(buf, value)
531+ self ._write_raw_bytes_and_length(buf, sizeof(buf))
532+
533+ cdef int write_interval_ym(self , object value) except - 1 :
606534 """
607- Writes an interval to the buffer in Oracle Interval Day To Second
535+ Writes an interval to the buffer in Oracle Interval Year To Month
608536 format.
609537 """
610- cdef:
611- int32_t years, months
612- char_type buf[5 ]
613- years = (< tuple > value)[0 ]
614- months = (< tuple > value)[1 ]
615- encode_uint32be(buf, years + TNS_DURATION_MID)
616- buf[4 ] = months + TNS_DURATION_OFFSET
617- if write_length:
618- self .write_uint8(sizeof(buf))
619- self .write_raw(buf, sizeof(buf))
620-
621- cdef int write_oracle_date(self , object value, uint8_t length,
622- bint write_length = True ) except - 1 :
538+ cdef char_type buf[ORA_TYPE_SIZE_INTERVAL_YM]
539+ encode_interval_ym(buf, value)
540+ self ._write_raw_bytes_and_length(buf, sizeof(buf))
541+
542+ cdef int write_oracle_date(self , object value, uint8_t length) except - 1 :
623543 """
624544 Writes a date to the buffer in Oracle Date format.
625545 """
626- cdef:
627- unsigned int year
628- char_type buf[13 ]
629- uint32_t fsecond
630- year = cydatetime.PyDateTime_GET_YEAR(value)
631- buf[0 ] = < uint8_t> ((year // 100 ) + 100 )
632- buf[1 ] = < uint8_t> ((year % 100 ) + 100 )
633- buf[2 ] = < uint8_t> cydatetime.PyDateTime_GET_MONTH(value)
634- buf[3 ] = < uint8_t> cydatetime.PyDateTime_GET_DAY(value)
635- buf[4 ] = < uint8_t> cydatetime.PyDateTime_DATE_GET_HOUR(value) + 1
636- buf[5 ] = < uint8_t> cydatetime.PyDateTime_DATE_GET_MINUTE(value) + 1
637- buf[6 ] = < uint8_t> cydatetime.PyDateTime_DATE_GET_SECOND(value) + 1
638- if length > 7 :
639- fsecond = < uint32_t> \
640- cydatetime.PyDateTime_DATE_GET_MICROSECOND(value) * 1000
641- if fsecond == 0 and length <= 11 :
546+ cdef char_type buf[ORA_TYPE_SIZE_TIMESTAMP_TZ]
547+ if length == 7 :
548+ encode_date(buf, value)
549+ elif length == 11 :
550+ encode_timestamp(buf, value)
551+ # the protocol requires that if the fractional seconds are zero
552+ # that the value be transmitted as a date, not a timestamp!
553+ if decode_uint32be(& buf[7 ]) == 0 :
642554 length = 7
643- else :
644- encode_uint32be(& buf[7 ], fsecond)
645- if length > 11 :
646- buf[11 ] = TZ_HOUR_OFFSET
647- buf[12 ] = TZ_MINUTE_OFFSET
648- if write_length:
649- self .write_uint8(length)
650- self .write_raw(buf, length)
555+ else :
556+ encode_timestamp_tz(buf, value)
557+ self ._write_raw_bytes_and_length(buf, length)
651558
652559 cdef int write_oracle_number(self , bytes num_bytes) except - 1 :
653560 """
654561 Writes a number in UTF-8 encoded bytes in Oracle Number format to the
655562 buffer.
656563 """
657564 cdef:
658- uint8_t num_digits = 0 , digit, num_pairs, pair_num, digits_pos
659- bint exponent_is_negative = False , append_sentinel = False
660- ssize_t num_bytes_length, exponent_pos, pos = 0
661- bint is_negative = False , prepend_zero = False
662- uint8_t digits[NUMBER_AS_TEXT_CHARS]
663- int16_t decimal_point_index
664- int8_t exponent_on_wire
665- const char_type * ptr
666- int16_t exponent
667-
668- # zero length string cannot be converted
669- num_bytes_length = len (num_bytes)
670- if num_bytes_length == 0 :
671- errors._raise_err(errors.ERR_NUMBER_STRING_OF_ZERO_LENGTH)
672- elif num_bytes_length > NUMBER_AS_TEXT_CHARS:
673- errors._raise_err(errors.ERR_NUMBER_STRING_TOO_LONG)
674-
675- # check to see if number is negative (first character is '-')
676- ptr = num_bytes
677- if ptr[0 ] == b' -' :
678- is_negative = True
679- pos += 1
680-
681- # scan for digits until the decimal point or exponent indicator found
682- while pos < num_bytes_length:
683- if ptr[pos] == b' .' or ptr[pos] == b' e' or ptr[pos] == b' E' :
684- break
685- if ptr[pos] < b' 0' or ptr[pos] > b' 9' :
686- errors._raise_err(errors.ERR_INVALID_NUMBER)
687- digit = ptr[pos] - < uint8_t> b' 0'
688- pos += 1
689- if digit == 0 and num_digits == 0 :
690- continue
691- digits[num_digits] = digit
692- num_digits += 1
693- decimal_point_index = num_digits
694-
695- # scan for digits following the decimal point, if applicable
696- if pos < num_bytes_length and ptr[pos] == b' .' :
697- pos += 1
698- while pos < num_bytes_length:
699- if ptr[pos] == b' e' or ptr[pos] == b' E' :
700- break
701- digit = ptr[pos] - < uint8_t> b' 0'
702- pos += 1
703- if digit == 0 and num_digits == 0 :
704- decimal_point_index -= 1
705- continue
706- digits[num_digits] = digit
707- num_digits += 1
708-
709- # handle exponent, if applicable
710- if pos < num_bytes_length and (ptr[pos] == b' e' or ptr[pos] == b' E' ):
711- pos += 1
712- if pos < num_bytes_length:
713- if ptr[pos] == b' -' :
714- exponent_is_negative = True
715- pos += 1
716- elif ptr[pos] == b' +' :
717- pos += 1
718- exponent_pos = pos
719- while pos < num_bytes_length:
720- if ptr[pos] < b' 0' or ptr[pos] > b' 9' :
721- errors._raise_err(errors.ERR_NUMBER_WITH_INVALID_EXPONENT)
722- pos += 1
723- if exponent_pos == pos:
724- errors._raise_err(errors.ERR_NUMBER_WITH_EMPTY_EXPONENT)
725- exponent = < int16_t> int (ptr[exponent_pos:pos])
726- if exponent_is_negative:
727- exponent = - exponent
728- decimal_point_index += exponent
729-
730- # if there is anything left in the string, that indicates an invalid
731- # number as well
732- if pos < num_bytes_length:
733- errors._raise_err(errors.ERR_CONTENT_INVALID_AFTER_NUMBER)
734-
735- # skip trailing zeros
736- while num_digits > 0 and digits[num_digits - 1 ] == 0 :
737- num_digits -= 1
738-
739- # value must be less than 1e126 and greater than 1e-129; the number of
740- # digits also cannot exceed the maximum precision of Oracle numbers
741- if num_digits > NUMBER_MAX_DIGITS or decimal_point_index > 126 \
742- or decimal_point_index < - 129 :
743- errors._raise_err(errors.ERR_ORACLE_NUMBER_NO_REPR)
744-
745- # if the exponent is odd, prepend a zero
746- if decimal_point_index % 2 == 1 :
747- prepend_zero = True
748- if num_digits > 0 :
749- digits[num_digits] = 0
750- num_digits += 1
751- decimal_point_index += 1
752-
753- # determine the number of digit pairs; if the number of digits is odd,
754- # append a zero to make the number of digits even
755- if num_digits % 2 == 1 :
756- digits[num_digits] = 0
757- num_digits += 1
758- num_pairs = num_digits // 2
759-
760- # append a sentinel 102 byte for negative numbers if there is room
761- if is_negative and num_digits > 0 and num_digits < NUMBER_MAX_DIGITS:
762- append_sentinel = True
763-
764- # write length of number
765- self .write_uint8(num_pairs + 1 + append_sentinel)
766-
767- # if the number of digits is zero, the value is itself zero since all
768- # leading and trailing zeros are removed from the digits string; this
769- # is a special case
770- if num_digits == 0 :
771- self .write_uint8(128 )
772- return 0
773-
774- # write the exponent
775- exponent_on_wire = < int8_t> (decimal_point_index / 2 ) + 192
776- if is_negative:
777- exponent_on_wire = ~ exponent_on_wire
778- self .write_uint8(exponent_on_wire)
779-
780- # write the mantissa bytes
781- digits_pos = 0
782- for pair_num in range (num_pairs):
783- if pair_num == 0 and prepend_zero:
784- digit = digits[digits_pos]
785- digits_pos += 1
786- else :
787- digit = digits[digits_pos] * 10 + digits[digits_pos + 1 ]
788- digits_pos += 2
789- if is_negative:
790- digit = 101 - digit
791- else :
792- digit += 1
793- self .write_uint8(digit)
794-
795- # append 102 byte for negative numbers if the number of digits is less
796- # than the maximum allowable
797- if append_sentinel:
798- self .write_uint8(102 )
565+ char_type buf[ORA_TYPE_SIZE_NUMBER]
566+ ssize_t buflen
567+ encode_number(buf, & buflen, num_bytes)
568+ self ._write_raw_bytes_and_length(buf, buflen)
799569
800570 cdef int write_raw(self , const char_type * data, ssize_t length) except - 1 :
801571 """
0 commit comments