@@ -55,6 +55,124 @@ def [](key)
5555 get ( key )
5656 end
5757
58+ # Set auxiliary tag value (auto-detects type from value)
59+ # For compatibility with HTS.cr.
60+ # @param key [String] tag name (2 characters)
61+ # @param value [Integer, Float, String, Array] tag value
62+ def []=( key , value )
63+ case value
64+ when Integer
65+ update_int ( key , value )
66+ when Float
67+ update_float ( key , value )
68+ when String
69+ update_string ( key , value )
70+ when Array
71+ update_array ( key , value )
72+ else
73+ raise ArgumentError , "Unsupported type: #{ value . class } "
74+ end
75+ end
76+
77+ # Update or add an integer tag
78+ # For compatibility with HTS.cr.
79+ # @param key [String] tag name (2 characters)
80+ # @param value [Integer] integer value
81+ def update_int ( key , value )
82+ ret = LibHTS . bam_aux_update_int ( @record . struct , key , value . to_i )
83+ raise "Failed to update integer tag '#{ key } ': errno #{ FFI . errno } " if ret < 0
84+
85+ value
86+ end
87+
88+ # Update or add a floating-point tag
89+ # For compatibility with HTS.cr.
90+ # @param key [String] tag name (2 characters)
91+ # @param value [Float] floating-point value
92+ def update_float ( key , value )
93+ ret = LibHTS . bam_aux_update_float ( @record . struct , key , value . to_f )
94+ raise "Failed to update float tag '#{ key } ': errno #{ FFI . errno } " if ret < 0
95+
96+ value
97+ end
98+
99+ # Update or add a string tag
100+ # For compatibility with HTS.cr.
101+ # @param key [String] tag name (2 characters)
102+ # @param value [String] string value
103+ def update_string ( key , value )
104+ ret = LibHTS . bam_aux_update_str ( @record . struct , key , -1 , value . to_s )
105+ raise "Failed to update string tag '#{ key } ': errno #{ FFI . errno } " if ret < 0
106+
107+ value
108+ end
109+
110+ # Update or add an array tag
111+ # For compatibility with HTS.cr.
112+ # @param key [String] tag name (2 characters)
113+ # @param value [Array] array of integers or floats
114+ # @param type [String, nil] element type ('c', 'C', 's', 'S', 'i', 'I', 'f'). Auto-detected if nil.
115+ def update_array ( key , value , type : nil )
116+ raise ArgumentError , "Array cannot be empty" if value . empty?
117+
118+ # Auto-detect type if not specified
119+ if type . nil?
120+ if value . all? { |v | v . is_a? ( Integer ) }
121+ # Use 'i' for signed 32-bit integers by default
122+ type = "i"
123+ elsif value . all? { |v | v . is_a? ( Float ) || v . is_a? ( Integer ) }
124+ type = "f"
125+ else
126+ raise ArgumentError , "Array must contain only integers or floats"
127+ end
128+ end
129+
130+ # Convert array to appropriate C type
131+ case type
132+ when "c" , "C" , "s" , "S" , "i" , "I"
133+ # Integer types
134+ ptr = FFI ::MemoryPointer . new ( :int32 , value . size )
135+ ptr . write_array_of_int32 ( value . map ( &:to_i ) )
136+ ret = LibHTS . bam_aux_update_array ( @record . struct , key , type . ord , value . size , ptr )
137+ when "f"
138+ # Float type
139+ ptr = FFI ::MemoryPointer . new ( :float , value . size )
140+ ptr . write_array_of_float ( value . map ( &:to_f ) )
141+ ret = LibHTS . bam_aux_update_array ( @record . struct , key , type . ord , value . size , ptr )
142+ else
143+ raise ArgumentError , "Invalid array type: #{ type } "
144+ end
145+
146+ raise "Failed to update array tag '#{ key } ': errno #{ FFI . errno } " if ret < 0
147+
148+ value
149+ end
150+
151+ # Delete an auxiliary tag
152+ # For compatibility with HTS.cr.
153+ # @param key [String] tag name (2 characters)
154+ # @return [Boolean] true if tag was deleted, false if tag was not found
155+ def delete ( key )
156+ aux_ptr = LibHTS . bam_aux_get ( @record . struct , key )
157+ return false if aux_ptr . null?
158+
159+ ret = LibHTS . bam_aux_del ( @record . struct , aux_ptr )
160+ raise "Failed to delete tag '#{ key } ': errno #{ FFI . errno } " if ret < 0
161+
162+ true
163+ end
164+
165+ # Check if a tag exists
166+ # For compatibility with HTS.cr.
167+ # @param key [String] tag name (2 characters)
168+ # @return [Boolean] true if tag exists
169+ def key? ( key )
170+ aux_ptr = LibHTS . bam_aux_get ( @record . struct , key )
171+ !aux_ptr . null?
172+ end
173+
174+ alias include? key?
175+
58176 def first
59177 aux_ptr = first_pointer
60178 return nil if aux_ptr . null?
0 commit comments