Tcl_StringObj(3)

πŸ“¦
version 8.6.17 Β· 3 versions
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, opensuse-leap 16.0

okay so this is the Tcl_StringObj(3) page from the Tcl Library Procedures, and it is literally the whole friend group of functions that let you manipulate Tcl values as strings. no cap, bestie. πŸ’–

🌸 NAME 🌸

The squad is: Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendObjToObj, Tcl_AppendStringsToObj, Tcl_AppendStringsToObjVA, Tcl_AppendLimitedToObj, Tcl_Format, Tcl_AppendFormatToObj, Tcl_ObjPrintf, Tcl_AppendPrintfToObj, Tcl_SetObjLength, Tcl_AttemptSetObjLength, and Tcl_ConcatObj β€” all here to manipulate Tcl values as strings. ✨

✨ SYNOPSIS ✨

like, here is the exact C vibe, bestie:

#include <tcl.h>

Tcl_Obj *
Tcl_NewStringObj(bytes, length)

Tcl_Obj *
Tcl_NewUnicodeObj(unicode, numChars)

void
Tcl_SetStringObj(objPtr, bytes, length)

void
Tcl_SetUnicodeObj(objPtr, unicode, numChars)

char *
Tcl_GetStringFromObj(objPtr, lengthPtr)

char *
Tcl_GetString(objPtr)

Tcl_UniChar *
Tcl_GetUnicodeFromObj(objPtr, lengthPtr)

Tcl_UniChar *
Tcl_GetUnicode(objPtr)

Tcl_UniChar
Tcl_GetUniChar(objPtr, index)

int
Tcl_GetCharLength(objPtr)

Tcl_Obj *
Tcl_GetRange(objPtr, first, last)

void
Tcl_AppendToObj(objPtr, bytes, length)

void
Tcl_AppendUnicodeToObj(objPtr, unicode, numChars)

void
Tcl_AppendObjToObj(objPtr, appendObjPtr)

void
Tcl_AppendStringsToObj(objPtr, string, string, ... (char *)NULL)

void
Tcl_AppendStringsToObjVA(objPtr, argList)

void
Tcl_AppendLimitedToObj(objPtr, bytes, length, limit, ellipsis)

Tcl_Obj *
Tcl_Format(interp, format, objc, objv)

int
Tcl_AppendFormatToObj(interp, objPtr, format, objc, objv)

Tcl_Obj *
Tcl_ObjPrintf(format, ...)

void
Tcl_AppendPrintfToObj(objPtr, format, ...)

void
Tcl_SetObjLength(objPtr, newLength)

int
Tcl_AttemptSetObjLength(objPtr, newLength)

Tcl_Obj *
Tcl_ConcatObj(objc, objv)

🫢 ARGUMENTS 🫢

here is the cast of characters, and yes every single one matters:

  • const char *bytes (in) β€” points to the first byte of an array of UTF-8-encoded bytes used to set or append to a string value. This byte array may contain embedded null characters unless numChars is negative. (Applications needing null bytes should represent them as the two-byte sequence \300\200, use Tcl_ExternalToUtf to convert, or Tcl_NewByteArrayObj if the string is a collection of uninterpreted bytes.) πŸ¦‹
  • int length (in) β€” the number of bytes to copy from bytes when initializing, setting, or appending to a string value. If negative, all bytes up to the first null are used.
  • const Tcl_UniChar *unicode (in) β€” points to the first byte of an array of Unicode characters used to set or append to a string value. This byte array may contain embedded null characters unless numChars is negative. 🌈
  • int numChars (in) β€” the number of Unicode characters to copy from unicode when initializing, setting, or appending to a string value. If negative, all characters up to the first null character are used.
  • int index (in) β€” the index of the Unicode character to return.
  • int first (in) β€” the index of the first Unicode character in the Unicode range to be returned as a new value.
  • int last (in) β€” the index of the last Unicode character in the Unicode range to be returned as a new value.
  • Tcl_Obj *objPtr (in/out) β€” points to a value to manipulate.
  • Tcl_Obj *appendObjPtr (in) β€” the value to append to objPtr in Tcl_AppendObjToObj.
  • int *lengthPtr (out) β€” if non-NULL, the location where Tcl_GetStringFromObj will store the length of a value's string representation.
  • const char *string (in) β€” null-terminated string value to append to objPtr.
  • va_list argList (in) β€” an argument list which must have been initialized using va_start, and cleared using va_end.
  • int limit (in) β€” maximum number of bytes to be appended.
  • const char *ellipsis (in) β€” suffix to append when the limit leads to string truncation. If NULL is passed then the suffix β€œ...” is used.
  • const char *format (in) β€” format control string including % conversion specifiers.
  • int objc (in) β€” the number of elements to format or concatenate.
  • Tcl_Obj *objv[] (in) β€” the array of values to format or concatenate.
  • int newLength (in) β€” new length for the string value of objPtr, not including the final null character.

πŸ’… DESCRIPTION πŸ’…

The procedures described in this manual entry allow Tcl values to be manipulated as string values. They use the internal representation of the value to store additional information to make the string manipulations more efficient. In particular, they make a series of append operations efficient by allocating extra storage space for the string so that it does not have to be copied for each append. Also, indexing and length computations are optimized because the Unicode string representation is calculated and cached as needed.

important vibe check: when using the Tcl_Append* family of functions where the interpreter's result is the value being appended to, it is important to call Tcl_ResetResult first to ensure you are not unintentionally appending to existing data in the result value. 😭

Tcl_NewStringObj and Tcl_SetStringObj create a new value or modify an existing value to hold a copy of the string given by bytes and length. Tcl_NewUnicodeObj and Tcl_SetUnicodeObj create a new value or modify an existing value to hold a copy of the Unicode string given by unicode and numChars. Tcl_NewStringObj and Tcl_NewUnicodeObj return a pointer to a newly created value with reference count zero. All four procedures set the value to hold a copy of the specified string. Tcl_SetStringObj and Tcl_SetUnicodeObj free any old string representation as well as any old internal representation of the value. πŸ‘‘

Tcl_GetStringFromObj and Tcl_GetString return a value's string representation. This is given by the returned byte pointer and (for Tcl_GetStringFromObj) length, which is stored in lengthPtr if it is non-NULL. If the value's UTF string representation is invalid (its byte pointer is NULL), the string representation is regenerated from the value's internal representation. The storage referenced by the returned byte pointer is owned by the value manager. It is passed back as a writable pointer so that extension author creating their own Tcl_ObjType will be able to modify the string representation within the Tcl_UpdateStringProc of their Tcl_ObjType. Except for that limited purpose, the pointer returned by Tcl_GetStringFromObj or Tcl_GetString should be treated as read-only. It is recommended that this pointer be assigned to a (const char *) variable. Even in the limited situations where writing to this pointer is acceptable, one should take care to respect the copy-on-write semantics required by Tcl_Obj's, with appropriate calls to Tcl_IsShared and Tcl_DuplicateObj prior to any in-place modification of the string representation. The procedure Tcl_GetString is used in the common case where the caller does not need the length of the string representation. 🧚

Tcl_GetUnicodeFromObj and Tcl_GetUnicode hand you a value's value as a Unicode string πŸ’œ β€” you get it through the returned pointer, and for Tcl_GetUnicodeFromObj you also get the length, which gets stashed in lengthPtr if it's non-NULL. Lowkey important: that storage belongs to the value manager, so do not modify it, bestie, it's not yours πŸ™ˆ. The plain Tcl_GetUnicode is the go-to when you don't need the length of the unicode string representation β€” the common case, the vibe.

Tcl_GetUniChar gives you the index'th character inside the value's Unicode representation. It assumes index is in the appropriate range β€” no babysitting, no range check, that's on you ✨.

Tcl_GetRange returns a whole newly created value made of the characters between first and last (inclusive) in the value's Unicode representation πŸŽ€. If that Unicode representation is invalid, it just regenerates it from the value's string representation β€” self-healing queen. And if first < 0, the returned string starts at the beginning of the value; if last < 0, it ends at the end of the value. Negative numbers as "just go to the edge" energy, we love it πŸ’….

Tcl_GetCharLength returns the number of characters (as opposed to bytes, okurrr) in the string value 🌸.


Tcl_AppendToObj appends the data given by bytes and length onto the string representation of the value that objPtr points at 🫢. If the value has an invalid string representation, it tries to convert bytes to the Unicode format. If that conversion slays, the converted form of bytes gets appended to the value's Unicode representation. If it doesn't, the value's Unicode representation gets invalidated and converted to the UTF format, and bytes gets appended to the value's new string representation. Also, buffer growth eventually happens via large allocations so multiple calls are optimized β€” efficiency icon behavior, no cap ⭐.

Tcl_AppendUnicodeToObj appends the Unicode string given by unicode and numChars to the value specified by objPtr πŸ¦‹. If the value has an invalid Unicode representation, then unicode gets converted to the UTF format and appended to the value's string representation. And the appends are optimized so repeated appends stay relatively efficient (it over-allocates the string or Unicode space so it doesn't keep reallocating and copying the value's string value) β€” over-allocating is self-care, periodt πŸ’….

Tcl_AppendObjToObj is similar to Tcl_AppendToObj, except it appends the string or Unicode value (whichever exists and is best suited to be appended to objPtr) of appendObjPtr to objPtr πŸ”₯ β€” it picks the right one for you, main character decision-making.

Tcl_AppendStringsToObj is similar to Tcl_AppendToObj except you can pass it more than one value to append, and each value has to be a null-terminated string (i.e. none of the values may contain internal null characters β€” hard no on embedded nulls πŸ’€). You can throw any number of string arguments at it, but the last argument must be (char *)NULL so it knows the list is over πŸ™ˆ.

Tcl_AppendStringsToObjVA is literally the same as Tcl_AppendStringsToObj except instead of taking a variable number of arguments it takes an argument list πŸŽ€.

Tcl_AppendLimitedToObj is similar to Tcl_AppendToObj except it puts a cap on how many bytes get appended 🌈. This is handy when the string you're appending might be very large but the value you're constructing shouldn't be allowed to grow without bound β€” icon behavior, boundaries are healthy. A common usage is constructing an error message, where the end result should be kept short enough to actually be read πŸ‘‘. Bytes from bytes get appended to objPtr, but no more than limit bytes total. If the limit stops all length bytes that are available from being appended, then the appending is done so that the last bytes appended come from the string ellipsis β€” that way there's an indication of the truncation left in the string. When length is -1, all bytes up to the first zero byte are appended, subject to the limit. When ellipsis is NULL, the default string ... is used. When ellipsis is non-NULL, it must point to a zero-byte-terminated string in Tcl's internal UTF encoding 🧚. Heads up though: the number of bytes appended can be less than the lesser of length and limit when appending fewer bytes is necessary to append only whole multi-byte characters 😭.

Tcl_Format is the C-level interface to the engine of the format command ⭐. The actual command procedure for format is little more than:

Tcl_Format(interp, Tcl_GetString(objv[1]), objc-2, objv+2);

The objc Tcl_Obj values in objv are formatted into a string according to the conversion specification in the format argument, following the documentation for the format command πŸ’–. The resulting formatted string is converted to a new Tcl_Obj with refcount of zero and returned. If some error happens during production of the formatted string, NULL is returned, and an error message is recorded in interp, if interp is non-NULL πŸ’€.

Tcl_AppendFormatToObj is the appending alternative form of Tcl_Format, with functionality equivalent to:

Tcl_Obj *newPtr = Tcl_Format(interp, format, objc, objv);
if (newPtr == NULL) return TCL_ERROR;
Tcl_AppendObjToObj(objPtr, newPtr);
Tcl_DecrRefCount(newPtr);
return TCL_OK;

but with greater convenience and efficiency when the appending functionality is what you actually need πŸ¦‹.

Tcl_ObjPrintf serves as a replacement for the common sequence:

char buf[SOME_SUITABLE_LENGTH];
sprintf(buf, format, ...);
Tcl_NewStringObj(buf, -1);

but with greater convenience and no need to determine SOME_SUITABLE_LENGTH β€” not me having to guess a buffer size ever again πŸ™ˆ. The formatting is done with the same core formatting engine used by Tcl_Format. This means the set of supported conversion specifiers is that of the format command, but the behavior is as similar as possible to sprintf 🌸. Format specifiers which were added by C99 (like "hh", "ll", "j", "z", "t", "L") are not supported ❌. When a conversion specifier passed to Tcl_ObjPrintf includes a precision, the value is taken as a number of bytes, as sprintf does, and not as a number of characters, as format does β€” done on the assumption that C code is more likely to know how many bytes it's passing around than the number of encoded characters those bytes happen to represent, and honestly? fair πŸ’…. The variable number of arguments passed in should be of the types that would be suitable for passing to sprintf. Note in this example usage, x is of type int:

int x = 5;
Tcl_Obj *objPtr = Tcl_ObjPrintf("Value is %d", x);

If the value of format contains internal inconsistencies or invalid specifier formats, the formatted string result produced by Tcl_ObjPrintf will be an error message describing the error 🀷. It is impossible however to provide runtime protection against mismatches between the format and any subsequent arguments β€” that one's on you, bestie 😭. Compile-time protection may be provided by some compilers 🫢.

Tcl_AppendPrintfToObj is the appending alternative form of Tcl_ObjPrintf, with functionality equivalent to:

Tcl_Obj *newPtr = Tcl_ObjPrintf(format, ...);
Tcl_AppendObjToObj(objPtr, newPtr);
Tcl_DecrRefCount(newPtr);

but with greater convenience and efficiency when the appending functionality is needed πŸŽ€.

Tcl_SetObjLength changes the length of the string value of its objPtr argument πŸ”₯. If the newLength argument is greater than the space allocated for the value's string, then the string space gets reallocated and the old value gets copied to the new space β€” and heads up, the bytes between the old length of the string and the new length may have arbitrary values πŸ’€, so don't go reading them expecting anything cute. If newLength is less than the current length of the value's string, then objPtr->length is reduced without reallocating the string space; the original allocated size for the string is recorded in the value, so the string length can be enlarged in a subsequent call to Tcl_SetObjLength without reallocating storage β€” saving it for later, we love a planner πŸ‘‘. In all cases Tcl_SetObjLength leaves a null character at objPtr->bytes[newLength] ⭐.

Tcl_AttemptSetObjLength is identical in function to Tcl_SetObjLength except that if sufficient memory to satisfy the request cannot be allocated, it does not cause the Tcl interpreter to panic 🌈. So: if newLength is greater than the space allocated for the value's string, and there isn't enough memory available to satisfy the request, Tcl_AttemptSetObjLength will take no action and return 0 to indicate failure 🫢. If there is enough memory to satisfy the request, Tcl_AttemptSetObjLength behaves just like Tcl_SetObjLength and returns 1 to indicate success ✨.

Tcl_ConcatObj returns a new string value whose value is the space-separated concatenation of the string representations of all of the values in the objv array πŸ’œ. Tcl_ConcatObj eliminates leading and trailing white space as it copies the string representations of the objv array to the result 🧹. If an element of the objv array consists of nothing but white space, then that value is ignored entirely β€” ghosted, ignored, gone πŸ™ˆ. This white-space removal was added to make the output of the concat command cleaner-looking, and it ate, honestly πŸ’…. Tcl_ConcatObj returns a pointer to a newly-created value whose ref count is zero πŸŽ€.


✨ SEE ALSO ✨

πŸ”‘ KEYWORDS πŸ”‘

append, internal representation, value, value type, string value, string type, string representation, concat, concatenate, unicode


okay that's the whole page, bestie β€” go forth and append responsibly πŸ«ΆπŸ’–

that was Tcl_StringObj(3), Tcl 8.1, and this group chat is officially over β€” ily, stan the value manager, bye πŸ’…βœ¨

πŸ“¦ where this page comes from