File include/dialogue.h changed (mode: 100755) (index 61525e2..9486a26) |
... |
... |
class Talk { |
62 |
62 |
double getVariable( std::string key ); |
double getVariable( std::string key ); |
63 |
63 |
void setVariable( const std::string &key, double valueNumber ); |
void setVariable( const std::string &key, double valueNumber ); |
64 |
64 |
int parseJSON( std::string &text ); |
int parseJSON( std::string &text ); |
|
65 |
|
int parseCSL( std::string &text ); |
65 |
66 |
std::string stringifyNumber( double n ); |
std::string stringifyNumber( double n ); |
66 |
67 |
std::string stringifyArray( const std::vector<std::string> &arr ); |
std::string stringifyArray( const std::vector<std::string> &arr ); |
67 |
68 |
Operation getOperation( std::string key, double valueNumber, const std::string &valueKey ); |
Operation getOperation( std::string key, double valueNumber, const std::string &valueKey ); |
|
... |
... |
class Talk { |
71 |
72 |
}; |
}; |
72 |
73 |
|
|
73 |
74 |
void Talk::go( const std::string &id ){ |
void Talk::go( const std::string &id ){ |
74 |
|
if( id.length() >= 5 && id.substr( id.length() - 5 ) == ".json" ){ |
|
|
75 |
|
if( ( id.length() >= 5 && id.substr( id.length() - 5 ) == ".json" ) |
|
76 |
|
|| ( id.length() >= 4 && id.substr( id.length() - 4 ) == ".csl" ) ){ |
75 |
77 |
screens.clear(); |
screens.clear(); |
76 |
78 |
std::string filePath = file.substr( 0, file.find_last_of( '/' ) + 1 ) + id; |
std::string filePath = file.substr( 0, file.find_last_of( '/' ) + 1 ) + id; |
77 |
79 |
append( filePath ); |
append( filePath ); |
|
... |
... |
void Talk::append( std::string filePath ){ |
130 |
132 |
text += std::string( buf, len ); |
text += std::string( buf, len ); |
131 |
133 |
} |
} |
132 |
134 |
fclose( stream ); |
fclose( stream ); |
133 |
|
if( parseJSON( text ) == 0 ){ |
|
134 |
|
file = filePath; |
|
|
135 |
|
if( filePath.length() >= 5 |
|
136 |
|
&& filePath.substr( filePath.length() - 5 ) == ".json" ){ |
|
137 |
|
if( parseJSON( text ) == 0 ) file = filePath; |
|
138 |
|
}else{ |
|
139 |
|
if( parseCSL( text ) == 0 ) file = filePath; |
135 |
140 |
} |
} |
136 |
141 |
} |
} |
137 |
142 |
|
|
|
... |
... |
int Talk::parseJSON( std::string &text ){ |
277 |
282 |
return 0; |
return 0; |
278 |
283 |
} |
} |
279 |
284 |
|
|
|
285 |
|
int Talk::parseCSL( std::string &text ){ |
|
286 |
|
// SET CURRENT SCREEN TO "init". |
|
287 |
|
// FOR LINE IN text: |
|
288 |
|
// IF LINE[0] == '[': |
|
289 |
|
// FIND ']' AND SET CURRENT SCREEN TO THE CONTENTS. |
|
290 |
|
// ELSE: |
|
291 |
|
// LEX AND ADD LINE TO exec. |
|
292 |
|
|
|
293 |
|
auto GetScreenPointer = [&]( const std::string &id ){ |
|
294 |
|
for( Screen &s : screens ){ |
|
295 |
|
if( s.id == id ){ |
|
296 |
|
return &s; |
|
297 |
|
} |
|
298 |
|
} |
|
299 |
|
screens.push_back( {} ); |
|
300 |
|
screens.back().id = id; |
|
301 |
|
return &screens.back(); |
|
302 |
|
}; |
|
303 |
|
|
|
304 |
|
Screen *screen_ptr = GetScreenPointer( "init" ); |
|
305 |
|
|
|
306 |
|
auto Lex = [&]( std::string line ){ |
|
307 |
|
if( line.length() >= 2 && line[0] == '[' ){ |
|
308 |
|
line.erase( 0, 1 ); |
|
309 |
|
size_t bracket_at = line.find_last_of( ']' ); |
|
310 |
|
if( bracket_at == std::string::npos ) return; |
|
311 |
|
line.erase( bracket_at ); |
|
312 |
|
if( line.length() > 0 && line != screen_ptr->id ) |
|
313 |
|
screen_ptr = GetScreenPointer( line ); |
|
314 |
|
}else{ |
|
315 |
|
size_t colon_at = line.find_first_of( ':' ); |
|
316 |
|
if( colon_at == std::string::npos ) return; |
|
317 |
|
std::string val_str = line.substr( colon_at + 1 ); |
|
318 |
|
char* p; |
|
319 |
|
double num = std::strtod( val_str.c_str(), &p ); |
|
320 |
|
Operation o = getOperation( |
|
321 |
|
line.substr( 0, colon_at ), |
|
322 |
|
num, |
|
323 |
|
"" |
|
324 |
|
); |
|
325 |
|
// If defining a string or array, or value is non-numeric, |
|
326 |
|
// treat value as a string. |
|
327 |
|
if( o.op == '$' || o.op == '@' || *p ) o.valueKey = val_str; |
|
328 |
|
// Add the operation to the screen pointer. |
|
329 |
|
screen_ptr->exec.push_back( o ); |
|
330 |
|
} |
|
331 |
|
}; |
|
332 |
|
|
|
333 |
|
// Lex the text line by line. |
|
334 |
|
size_t start = 0, end = 0; |
|
335 |
|
while( ( end = text.find_first_of( "\r\n", start ) ) != std::string::npos ){ |
|
336 |
|
Lex( text.substr( start, end - start ) ); |
|
337 |
|
start = end + 1; |
|
338 |
|
} |
|
339 |
|
Lex( text.substr( start ) ); |
|
340 |
|
|
|
341 |
|
return 0; |
|
342 |
|
} |
|
343 |
|
|
280 |
344 |
// If n can be losslessly round-tripped between a double, a long long, |
// If n can be losslessly round-tripped between a double, a long long, |
281 |
345 |
// and a double, return a string without a decimal. Otherwise, return a |
// and a double, return a string without a decimal. Otherwise, return a |
282 |
346 |
// string with sprintf-style floating-point notation. |
// string with sprintf-style floating-point notation. |
|
... |
... |
std::string Talk::stringifyNumber( double n ){ |
291 |
355 |
} |
} |
292 |
356 |
} |
} |
293 |
357 |
|
|
294 |
|
// Return a #-separated list of strings with each string's # characters |
|
295 |
|
// escaped as: \# |
|
|
358 |
|
// Return a ;-separated list of strings with each string's ; characters |
|
359 |
|
// escaped as: \; |
296 |
360 |
std::string Talk::stringifyArray( const std::vector<std::string> &arr ){ |
std::string Talk::stringifyArray( const std::vector<std::string> &arr ){ |
297 |
361 |
std::string result; |
std::string result; |
298 |
362 |
for( size_t i = 0; i < arr.size(); i++ ){ |
for( size_t i = 0; i < arr.size(); i++ ){ |
299 |
|
// Add separating # characters. |
|
300 |
|
if( i > 0 ) result += "#"; |
|
301 |
|
// Replace # characters with \# and add the fragments to result. |
|
|
363 |
|
// Add separating ; characters. |
|
364 |
|
if( i > 0 ) result += ";"; |
|
365 |
|
// Replace ; characters with \; and add the fragments to result. |
302 |
366 |
const std::string &str = arr[i]; |
const std::string &str = arr[i]; |
303 |
367 |
size_t start = 0, end = 0; |
size_t start = 0, end = 0; |
304 |
|
while( ( end = str.find( '#', start ) ) != std::string::npos ){ |
|
305 |
|
result += str.substr( start, end - start ) + "\\#"; |
|
|
368 |
|
while( ( end = str.find( ';', start ) ) != std::string::npos ){ |
|
369 |
|
result += str.substr( start, end - start ) + "\\;"; |
306 |
370 |
start = end + 1; |
start = end + 1; |
307 |
371 |
} |
} |
308 |
372 |
result += str.substr( start ); |
result += str.substr( start ); |
|
... |
... |
void Talk::operate( Operation o ){ |
346 |
410 |
if( !success ) it->second = {}; |
if( !success ) it->second = {}; |
347 |
411 |
// Parse the array. |
// Parse the array. |
348 |
412 |
size_t start = 0, off = 0, end = 0; |
size_t start = 0, off = 0, end = 0; |
349 |
|
while( ( end = o.valueKey.find( '#', start + off ) ) != std::string::npos ){ |
|
350 |
|
// Allow \# escaping. TODO: \\ escaping. |
|
|
413 |
|
while( ( end = o.valueKey.find( ';', start + off ) ) != std::string::npos ){ |
|
414 |
|
// Allow \; escaping. TODO: \\ escaping. |
351 |
415 |
if( end > 0 && o.valueKey[end - 1] == '\\' ){ |
if( end > 0 && o.valueKey[end - 1] == '\\' ){ |
352 |
416 |
// Remove the \ character from the string. |
// Remove the \ character from the string. |
353 |
417 |
o.valueKey.erase( end - 1, 1 ); |
o.valueKey.erase( end - 1, 1 ); |
354 |
|
// `end` now points to the character after the #. |
|
|
418 |
|
// `end` now points to the character after the ;. |
355 |
419 |
off = end - start; |
off = end - start; |
356 |
420 |
continue; |
continue; |
357 |
421 |
} |
} |