@@ -89,70 +89,46 @@ namespace csv {
8989 return field_str.substr (0 , field.length );
9090 }
9191
92- CSV_INLINE bool CSVField::try_parse_hex (int & parsedValue) {
93- size_t start = 0 , end = 0 ;
94-
95- // Trim out whitespace chars
96- for (; start < this ->sv .size () && this ->sv [start] == ' ' ; start++);
97- for (end = start; end < this ->sv .size () && this ->sv [end] != ' ' ; end++);
98-
99- int value_ = 0 ;
100-
101- size_t digits = (end - start);
102- size_t base16_exponent = digits - 1 ;
103-
104- if (digits == 0 ) return false ;
105-
106- for (const auto & ch : this ->sv .substr (start, digits)) {
107- int digit = 0 ;
108-
109- switch (ch) {
110- case ' 0' :
111- case ' 1' :
112- case ' 2' :
113- case ' 3' :
114- case ' 4' :
115- case ' 5' :
116- case ' 6' :
117- case ' 7' :
118- case ' 8' :
119- case ' 9' :
120- digit = static_cast <int >(ch - ' 0' );
121- break ;
122- case ' a' :
123- case ' A' :
124- digit = 10 ;
125- break ;
126- case ' b' :
127- case ' B' :
128- digit = 11 ;
129- break ;
130- case ' c' :
131- case ' C' :
132- digit = 12 ;
133- break ;
134- case ' d' :
135- case ' D' :
136- digit = 13 ;
137- break ;
138- case ' e' :
139- case ' E' :
140- digit = 14 ;
141- break ;
142- case ' f' :
143- case ' F' :
144- digit = 15 ;
145- break ;
146- default :
147- return false ;
92+ CSV_INLINE csv::string_view CSVRow::get_field_safe (size_t index, internals::RawCSVDataPtr _data) const
93+ {
94+ using internals::ParseFlags;
95+
96+ if (index >= this ->size ())
97+ throw std::runtime_error (" Index out of bounds." );
98+
99+ const size_t field_index = this ->fields_start + index;
100+ auto & field = _data->fields [field_index];
101+ auto field_str = csv::string_view (_data->data ).substr (this ->data_start + field.start );
102+
103+ if (field.has_double_quote ) {
104+ auto & value = _data->double_quote_fields [field_index];
105+ // Double-check locking: minimize lock contention by checking before acquiring lock
106+ if (value.empty ()) {
107+ std::lock_guard<std::mutex> lock (_data->double_quote_init_lock );
108+
109+ // Check again after acquiring lock in case another thread initialized it
110+ if (value.empty ()) {
111+ bool prev_ch_quote = false ;
112+ for (size_t i = 0 ; i < field.length ; i++) {
113+ if (_data->parse_flags [field_str[i] + CHAR_OFFSET] == ParseFlags::QUOTE) {
114+ if (prev_ch_quote) {
115+ prev_ch_quote = false ;
116+ continue ;
117+ }
118+ else {
119+ prev_ch_quote = true ;
120+ }
121+ }
122+
123+ value += field_str[i];
124+ }
125+ }
148126 }
149127
150- value_ += digit * (int )pow (16 , (double )base16_exponent);
151- base16_exponent--;
128+ return csv::string_view (value);
152129 }
153130
154- parsedValue = value_;
155- return true ;
131+ return field_str.substr (0 , field.length );
156132 }
157133
158134 CSV_INLINE bool CSVField::try_parse_decimal (long double & dVal, const char decimalSymbol) {
@@ -206,7 +182,7 @@ namespace csv {
206182 : daddy(_reader), data(_reader->data), i(_i) {
207183 if (_i < (int )this ->daddy ->size ())
208184 this ->field = std::make_shared<CSVField>(
209- this ->daddy ->operator [] (_i));
185+ CSVField ( this ->daddy ->get_field_safe (_i, this -> data ) ));
210186 else
211187 this ->field = nullptr ;
212188 }
@@ -224,7 +200,7 @@ namespace csv {
224200 this ->i ++;
225201 if (this ->i < (int )this ->daddy ->size ())
226202 this ->field = std::make_shared<CSVField>(
227- this ->daddy ->operator [](i ));
203+ CSVField ( this ->daddy ->get_field_safe (i, this -> data ) ));
228204 else // Reached the end of row
229205 this ->field = nullptr ;
230206 return *this ;
@@ -241,7 +217,7 @@ namespace csv {
241217 // Pre-decrement operator
242218 this ->i --;
243219 this ->field = std::make_shared<CSVField>(
244- this ->daddy ->operator [] (this ->i ));
220+ CSVField ( this ->daddy ->get_field_safe (this ->i , this -> data ) ));
245221 return *this ;
246222 }
247223
0 commit comments