@@ -137,8 +137,6 @@ void Dotenv::ParseContent(const std::string_view input) {
137137 // Skip empty lines and comments
138138 // Example:
139139 // # This is a comment
140- //
141- // KEY=value
142140 if (content.front () == ' \n ' || content.front () == ' #' ) {
143141 auto newline = content.find (' \n ' );
144142 if (newline != std::string_view::npos) {
@@ -155,37 +153,30 @@ void Dotenv::ParseContent(const std::string_view input) {
155153
156154 // Find the next equals sign or newline in a single pass
157155 // This optimizes the search by avoiding multiple iterations
158- auto pos = content.find_first_of (" =\n " );
156+ auto equal_or_newline = content.find_first_of (" =\n " );
159157
160158 // If we found nothing or found a newline before equals, the line is invalid
161- if (pos == std::string_view::npos || content[pos] == ' \n ' ) {
162- if (pos != std::string_view::npos) {
163- content.remove_prefix (pos + 1 );
159+ if (equal_or_newline == std::string_view::npos ||
160+ content.at (equal_or_newline) == ' \n ' ) {
161+ if (equal_or_newline != std::string_view::npos) {
162+ content.remove_prefix (equal_or_newline + 1 );
164163 content = trim_spaces (content);
165164 continue ;
166165 }
167166 break ;
168167 }
169168
170169 // We found an equals sign, extract the key
171- key = content.substr (0 , pos );
172- content.remove_prefix (pos + 1 );
170+ key = content.substr (0 , equal_or_newline );
171+ content.remove_prefix (equal_or_newline + 1 );
173172 key = trim_spaces (key);
174173 content = trim_spaces (content);
175174
176175 // Skip lines with empty keys after trimming spaces
177176 // Examples of invalid keys that would be skipped:
178177 // =value
179178 // " "=value
180- if (key.empty ()) {
181- auto newline = content.find (' \n ' );
182- if (newline != std::string_view::npos) {
183- content.remove_prefix (newline + 1 );
184- content = trim_spaces (content);
185- continue ;
186- }
187- break ;
188- }
179+ if (key.empty ()) continue ;
189180
190181 // Remove export prefix from key and ensure proper spacing
191182 // Example: export FOO=bar -> FOO=bar
@@ -196,13 +187,16 @@ void Dotenv::ParseContent(const std::string_view input) {
196187 key = trim_spaces (key);
197188 }
198189
199- // If content is empty after the equals sign, store empty value and break
190+ // SAFETY: Content is guaranteed to have at least one character
200191 if (content.empty ()) {
192+ // In case the last line is a single key without value
193+ // Example: KEY= (without a newline at the EOF)
201194 store_.insert_or_assign (std::string (key), " " );
202195 break ;
203196 }
204197
205- // Handle different types of value formats (quoted, multi-line, etc)
198+ // Expand new line if \n it's inside double quotes
199+ // Example: EXPAND_NEWLINES = 'expand\nnew\nlines'
206200 if (content.front () == ' "' ) {
207201 auto closing_quote = content.find (content.front (), 1 );
208202 if (closing_quote != std::string_view::npos) {
@@ -231,8 +225,12 @@ void Dotenv::ParseContent(const std::string_view input) {
231225 content.front () == ' `' ) {
232226 auto closing_quote = content.find (content.front (), 1 );
233227
228+ // Check if the closing quote is not found
229+ // Example: KEY="value
234230 if (closing_quote == std::string_view::npos) {
235- // No closing quote - take until newline
231+ // Check if newline exist. If it does, take the entire line as the value
232+ // Example: KEY="value\nKEY2=value2
233+ // The value pair should be `"value`
236234 auto newline = content.find (' \n ' );
237235 if (newline != std::string_view::npos) {
238236 value = content.substr (0 , newline);
@@ -256,11 +254,16 @@ void Dotenv::ParseContent(const std::string_view input) {
256254 }
257255 }
258256 } else {
259- // Handle unquoted values
257+ // Regular key value pair.
258+ // Example: `KEY=this is value`
260259 auto newline = content.find (' \n ' );
260+
261261 if (newline != std::string_view::npos) {
262262 value = content.substr (0 , newline);
263263 auto hash_character = value.find (' #' );
264+ // Check if there is a comment in the line
265+ // Example: KEY=value # comment
266+ // The value pair should be `value`
264267 if (hash_character != std::string_view::npos) {
265268 value = value.substr (0 , hash_character);
266269 }
0 commit comments