Skip to content

Commit 4e3ec1b

Browse files
committed
Add handling of string literals to set_as method
1 parent 08e364a commit 4e3ec1b

2 files changed

Lines changed: 146 additions & 3 deletions

File tree

include/xnode.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ void xnode_set_scalar(void **storage, T value)
589589
xnode_setter<T, xnode_storage_meta<T>::storage_type>::assign_from_value(storage, &value);
590590
}
591591

592-
std::string xnode_pack_value(const char *text)
592+
std::string xnode_pack_value_as_str(const char *text)
593593
{
594594
return std::string(text);
595595
}
@@ -724,7 +724,7 @@ class basic_xnode
724724

725725
/// set value and type of node
726726
template <typename T>
727-
void set_as(const T &value)
727+
void set_as(const T &value, typename std::enable_if<!std::is_array<T>::value>::type * = 0)
728728
{
729729
if ((typeid(T) == type()) && (xnode_setter<T, xnode_storage_meta<T>::storage_type>::supports_copy()))
730730
{
@@ -736,6 +736,13 @@ class basic_xnode
736736
}
737737
}
738738

739+
/// set value and type of node for character arrays (string literals)
740+
template <typename T>
741+
void set_as(const T &value, typename std::enable_if<std::is_array<T>::value>::type * = 0)
742+
{
743+
set_as(xnode_pack_value_as_str(value));
744+
}
745+
739746
/// set value without changing assigned type
740747
template <typename T>
741748
void set_value(const T &value)
@@ -991,7 +998,7 @@ class basic_xnode
991998
static this_type value_of(const ValueType &value, typename std::enable_if<std::is_array<ValueType>::value>::type * = 0)
992999
{
9931000
this_type result;
994-
result.set_as(xnode_pack_value(value));
1001+
result.set_as(xnode_pack_value_as_str(value));
9951002
return result;
9961003
}
9971004

test/xnode_test.cpp

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,137 @@ void TestCharLiteral() {
178178
Assert(value.get_as<std::string>() == "test", "get as string");
179179
}
180180

181+
void TestStringLiteralSetAs() {
182+
// Test setting string literals directly with set_as
183+
xnode value;
184+
185+
// Test with direct char array (C-style string literal)
186+
value.set_as("Direct String Literal");
187+
Assert(value.is<std::string>(), "Direct string literal should be stored as std::string");
188+
Assert(value.get_as<std::string>() == "Direct String Literal", "Direct string literal should match expected value");
189+
190+
// Test empty char array
191+
value.set_as("");
192+
Assert(value.is<std::string>(), "Empty direct string literal should be stored as std::string");
193+
Assert(value.get_as<std::string>().empty(), "Empty direct string literal should result in empty string");
194+
195+
// Test with special characters in char array
196+
value.set_as("Special\tChars\nTest");
197+
Assert(value.is<std::string>(), "Direct string literal with special chars should be stored as std::string");
198+
Assert(value.get_as<std::string>() == "Special\tChars\nTest", "Special chars should be preserved");
199+
200+
// Test with numeric char array
201+
value.set_as("98765");
202+
Assert(value.is<std::string>(), "Numeric char array should be stored as std::string");
203+
Assert(value.get_as<int>() == 98765, "Numeric char array should convert to correct integer");
204+
}
205+
206+
void TestStringLiteralValueOf() {
207+
// Test creation with value_of for string literals
208+
209+
// Basic string literal
210+
xnode value1 = xnode::value_of("Test String");
211+
Assert(value1.is<std::string>(), "String literal should be stored as std::string");
212+
Assert(value1.get_as<std::string>() == "Test String", "String should match the literal");
213+
214+
// Longer string literal with special characters
215+
xnode value2 = xnode::value_of("Line 1\nLine 2\tTabbed");
216+
Assert(value2.is<std::string>(), "String with escape chars should be stored as std::string");
217+
Assert(value2.get_as<std::string>() == "Line 1\nLine 2\tTabbed", "String should preserve escape chars");
218+
219+
// Unicode characters in string literal
220+
xnode value3 = xnode::value_of("Unicode: \u00A9 \u2022 \u00AE");
221+
Assert(value3.is<std::string>(), "Unicode string should be stored as std::string");
222+
}
223+
224+
void TestStringLiteralConversions() {
225+
// Test conversions between string literals and other types
226+
227+
// String literal to numeric types
228+
xnode value1 = xnode::value_of("42");
229+
Assert(value1.is<std::string>(), "Numeric string should be stored as std::string");
230+
Assert(value1.is_convertable_to<int>(), "Numeric string should be convertible to int");
231+
Assert(value1.get_as<int>() == 42, "String should convert to correct integer");
232+
Assert(value1.get_as<double>() == 42.0, "String should convert to correct double");
233+
234+
// String literal with floating point
235+
xnode value2 = xnode::value_of("3.14159");
236+
Assert(value2.is<std::string>(), "Float string should be stored as std::string");
237+
Assert(value2.is_convertable_to<double>(), "Float string should be convertible to double");
238+
Assert(value2.is_convertable_to<float>(), "Float string should be convertible to float");
239+
Assert(abs(value2.get_as<float>() - 3.14159f) < 0.0001f, "String should convert to correct float");
240+
241+
// String literal to boolean
242+
xnode value3 = xnode::value_of("true");
243+
Assert(value3.is<std::string>(), "Boolean string should be stored as std::string");
244+
Assert(value3.get_as<bool>(), "String 'true' should convert to boolean true");
245+
246+
xnode value4 = xnode::value_of("1");
247+
Assert(value4.is<std::string>(), "Numeric string should be stored as std::string");
248+
Assert(value4.get_as<bool>(), "String '1' should convert to boolean true");
249+
250+
// Non-convertible string literals
251+
xnode value5 = xnode::value_of("not a number");
252+
Assert(value5.is<std::string>(), "Text string should be stored as std::string");
253+
AssertFalse(value5.is_convertable_to<int>(), "Text string should not be convertible to int");
254+
255+
// Test exception throwing with a lambda
256+
try {
257+
value5.get_as<int>();
258+
Assert(false, "Should have thrown exception for non-convertible string");
259+
} catch (...) {
260+
// Expected exception
261+
}
262+
}
263+
264+
void TestStringLiteralComparisons() {
265+
// Test comparison operations with string literals
266+
267+
// Equality comparisons
268+
xnode value1 = xnode::value_of("test");
269+
xnode value2 = xnode::value_of("test");
270+
xnode value3 = xnode::value_of("different");
271+
272+
Assert(value1 == value2, "Identical string literals should be equal");
273+
Assert(value1 != value3, "Different string literals should not be equal");
274+
275+
// Direct comparison with string literals
276+
Assert(value1.get_as<std::string>() == "test", "String should equal literal");
277+
AssertFalse(value1.get_as<std::string>() == "different", "String should not equal different literal");
278+
279+
// Case sensitivity
280+
xnode value4 = xnode::value_of("TEST");
281+
AssertFalse(value1 == value4, "String comparison should be case sensitive");
282+
283+
// Length comparison
284+
xnode value5 = xnode::value_of("test_longer");
285+
Assert(value1 != value5, "Different length strings should not be equal");
286+
}
287+
288+
void TestStringLiteralWithRawPointers() {
289+
// Test interaction between string literals and char pointers
290+
291+
// Create from literal vs pointer
292+
const char* cstr = "test string";
293+
xnode value1 = xnode::value_of(std::string("test string"));
294+
xnode value2 = xnode::value_of(std::string(cstr));
295+
296+
Assert(value1.get_as<std::string>() == value2.get_as<std::string>(),
297+
"String from literal should equal string from pointer");
298+
Assert(value1.is<std::string>(), "String from literal should be std::string");
299+
Assert(value2.is<std::string>(), "String from pointer should be std::string");
300+
301+
// Raw char array
302+
char array[] = "hello world";
303+
xnode value3 = xnode::value_of(std::string(array));
304+
Assert(value3.is<std::string>(), "String from array should be std::string");
305+
Assert(value3.get_as<std::string>() == "hello world", "String should equal original array");
306+
307+
// Modifying the original should not affect xnode value
308+
array[0] = 'H';
309+
Assert(value3.get_as<std::string>() == "hello world", "Modifying source array should not affect xnode");
310+
}
311+
181312
void TestAnyScalar() {
182313
// assuming there is no matching caster & xnode_type_code for this type
183314
typedef signed char schar;
@@ -535,6 +666,11 @@ int xnode_test() {
535666
TEST_FUNC(ConvStringToInt);
536667
TEST_FUNC(CharPtr);
537668
TEST_FUNC(CharLiteral);
669+
TEST_FUNC(StringLiteralSetAs);
670+
TEST_FUNC(StringLiteralValueOf);
671+
TEST_FUNC(StringLiteralConversions);
672+
TEST_FUNC(StringLiteralComparisons);
673+
TEST_FUNC(StringLiteralWithRawPointers);
538674
TEST_FUNC(AnyScalar);
539675
TEST_FUNC(AnyStruct);
540676
TEST_FUNC(Release);

0 commit comments

Comments
 (0)