1 /***************************************************************************
2 keyvalue.c - Methods for Key manipulation
4 begin : Fri Sep 26 2008
5 copyright : (C) 2008 by Markus Raab
6 email : elektra@markus-raab.org
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the BSD License (revised). *
14 ***************************************************************************/
19 * @defgroup keyvalue Key :: Value Manipulation Methods
20 * @brief Methods to do various operations on Key values.
22 * A key can contain a value in different format. The most
23 * likely situation is, that the value is interpreted as
24 * text. Use keyGetString() for that.
25 * You can save any Unicode Symbols and Elektra will
26 * take care that you get the same back, independent of
27 * your current environment.
29 * In some situations this idea fails. When you need exactly
30 * the same value back without any interpretation of the
31 * characters, there is keySetBinary(). If you use that, its
32 * very likely that your Configuration is not according
33 * to the standard. Also for Numbers, Booleans and Date you
34 * should use keyGetString(). To do so, you might use strtod()
35 * strtol() and then atol() or atof() to convert back.
52 #if DEBUG && HAVE_STDIO_H
69 #include "kdbprivate.h"
73 /*******************************************
74 * General value manipulation methods *
75 *******************************************/
82 * Return a pointer to the real internal @p key value.
84 * This is a much more efficient version of keyGetString()
85 * keyGetBinary(), and you should use it if you are responsible enough to
86 * not mess up things. You are not allowed to modify anything
87 * in the returned string. If you need a copy of the Value, consider
88 * to use keyGetString() or keyGetBinary() instead.
90 * @section string String Handling
92 * If @p key is string (keyIsString()), you may cast the returned as a
93 * @c "char *" because you'll get a NULL terminated regular string.
95 * keyValue() returns "" in string mode when there is no value. The reason is
99 keyValue(key); // you would expect "" here
103 * @section binary Binary Data Handling
105 * If the data is binary, the size of the value must be determined by
106 * keyGetValueSize(), any strlen() operations are not suitable to determine
109 * keyValue() returns 0 in binary mode when there is no value. The reason is
113 keySetBinary(key, 0, 0);
114 keyValue(key); // you would expect 0 here
116 keySetBinary(key,"", 1);
117 keyValue(key); // you would expect "" (a pointer to '\0') here
119 keySetBinary(key, (void*)&i, 4);
120 (int*)keyValue(key); // you would expect a pointer to (int)23 here
124 * @note Note that the Key structure keeps its own size field that is calculated
125 * by library internal calls, so to avoid inconsistencies, you
126 * must never use the pointer returned by keyValue() method to set a new
127 * value. Use keySetString() or keySetBinary() instead.
129 * @warning Binary keys will return a NULL pointer when there is no data in contrast
130 * to keyName(), keyBaseName(), keyOwner() and keyComment(). For string value the
131 * behaviour is the same.
135 KDB *handle = kdbOpen();
139 kdbGetByName(handle,ks,"system/sw/my",KDB_O_SORT|KDB_O_RECURSIVE);
142 while(current=ksNext(ks)) {
145 if (keyIsBin(current)) {
146 size=keyGetValueSize(current);
147 printf("Key %s has a value of size %d bytes. Value: <BINARY>\nComment: %s",
150 keyComment(current));
152 size=kdbiStrLen((char *)keyValue(current));
153 printf("Key %s has a value of size %d bytes. Value: %s\nComment: %s",
156 (char *)keyValue(current),
157 keyComment(current));
165 * @param key the key object to work with
166 * @return a pointer to internal value
167 * @return "" when there is no data and key is not binary
168 * @return 0 where there is no data and key is binary
169 * @return 0 on NULL pointer
170 * @see keyGetValueSize(), keyGetString(), keyGetBinary()
173 const void *keyValue(const Key *key)
179 /*errno=KDB_ERR_NOKEY;*/
180 if (keyIsBinary(key)) return 0;
188 const void *takeout_keyValue(Key *key)
195 /*errno=KDB_ERR_NOKEY;*/
196 if (keyIsBinary(key)) return 0;
197 else return strdup("");
209 * Returns the number of bytes needed to store the key value, including the
212 * It returns the correct size, independent of the Key Type.
213 * If it is a binary there might be '\\0' values in it.
215 * For an empty string you need one byte to store the ending NULL.
216 * For that reason 1 is returned. This is not true for binary data,
217 * so there might be returned 0 too.
219 * A binary key has no '\\0' termination. String types have it, so to there
220 * length will be added 1 to have enough space to store it.
222 * This method can be used with malloc() before keyGetString() or keyGetBinary()
227 buffer = malloc (keyGetValueSize (key));
228 // use this buffer to store the value (binary or string)
229 // pass keyGetValueSize (key) for maxSize
232 * @param key the key object to work with
233 * @return the number of bytes needed to store the key value
234 * @return 1 when there is no data and type is not binary
235 * @return 0 when there is no data and type is binary
236 * @return -1 on null pointer
237 * @see keyGetString(), keyGetBinary(), keyValue()
240 ssize_t keyGetValueSize(const Key *key)
246 /*errno=KDB_ERR_NODATA;*/
247 if (keyIsBinary(key)) return 0;
251 return key->dataSize;
258 * Get the value of a key as a string.
260 * When there is no value inside the string, 1 will
261 * be returned and the returnedString will be empty
262 * "" to avoid programming errors that old strings are
265 * For binary values see keyGetBinary() and keyIsBinary().
269 Key *key = keyNew ("user/keyname", KEY_END);
272 if (keyGetString(key,buffer,sizeof(buffer)) == -1)
276 printf ("buffer: %s\n", buffer);
280 * @param key the object to gather the value from
281 * @param returnedString pre-allocated memory to store a copy of the key value
282 * @param maxSize number of bytes of allocated memory in @p returnedString
283 * @return the number of bytes actually copied to @p returnedString, including
285 * @return 1 if the string is empty
286 * @return -1 on NULL pointer
287 * @return -1 on type mismatch
288 * @return maxSize is 0, too small for string or is larger than SSIZE_MAX
289 * @see keyValue(), keyGetValueSize(), keySetString()
290 * @see keyGetBinary() for working with binary data
293 ssize_t keyGetString(const Key *key, char *returnedString, size_t maxSize)
297 if (!maxSize) return -1;
298 if (!returnedString) return -1;
299 if (maxSize > SSIZE_MAX) return -1;
301 if (!keyIsString(key))
303 /*errno=KDB_ERR_TYPEMISMATCH;*/
312 if (key->dataSize > maxSize) {
313 /*errno=KDB_ERR_TRUNC;*/
318 strncpy(returnedString,key->data, maxSize);
319 return key->dataSize;
325 * Set the value for @p key as @p newStringValue.
327 * The function will allocate and save a private copy of @p newStringValue, so
328 * the parameter can be freed after the call.
330 * String values will be saved in backend storage, when kdbSetKey() will be
331 * called, in UTF-8 universal encoding, regardless of the program's current
332 * encoding, when compiled with --enable-iconv.
334 * The type will be set to KEY_TYPE_STRING.
335 * When the type of the key is already a string type it won't be changed.
337 * @param key the key to set the string value
338 * @param newStringValue NULL-terminated text string to be set as @p key's
340 * @return the number of bytes actually saved in private struct including final
342 * @return -1 on NULL pointer
343 * @see keyGetString(), keyValue()
346 ssize_t keySetString(Key *key, const char *newStringValue)
352 if (!newStringValue || newStringValue[0] == '\0') ret=keySetRaw(key,0,0);
353 else ret=keySetRaw(key,newStringValue,kdbiStrLen(newStringValue));
355 if (!keyIsString(key)) keySetType(key, KEY_TYPE_STRING);
365 * Get the value of a key as a binary.
367 * If the type is not binary -1 will be returned.
369 * When the binary data is empty (this is not the same as ""!)
370 * 0 will be returned and the returnedBinary will not be changed.
372 * For string values see keyGetString() and keyIsString().
374 * When the returnedBinary is to small to hold the data
375 * (its maximum size is given by maxSize),
376 * the returnedBinary will not be changed and -1 is returned.
380 Key *key = keyNew ("user/keyname", KEY_TYPE, KEY_TYPE_BINARY, KEY_END);
383 if (keyGetBinary(key,buffer,sizeof(buffer)) == -1)
389 * @param key the object to gather the value from
390 * @param returnedBinary pre-allocated memory to store a copy of the key value
391 * @param maxSize number of bytes of pre-allocated memory in @p returnedBinary
392 * @return the number of bytes actually copied to @p returnedBinary
393 * @return 0 if the binary is empty
394 * @return -1 on NULL pointers
395 * @return -1 when maxSize is 0, too small to hold the value or larger than SSIZE_MAX
396 * @return -1 on typing error when the key is not binary
397 * @see keyValue(), keyGetValueSize(), keySetBinary()
398 * @see keyGetString() and keySetString() as preferred alternative to binary
399 * @see keyIsBinary() to see how to check for binary type
402 ssize_t keyGetBinary(const Key *key, void *returnedBinary, size_t maxSize)
405 if (!returnedBinary) return -1;
406 if (!maxSize) return -1;
408 if (maxSize > SSIZE_MAX) return -1;
410 if (!keyIsBinary(key))
412 /*errno=KDB_ERR_TYPEMISMATCH;*/
421 if (key->dataSize > maxSize)
423 /*errno=KDB_ERR_TRUNC;*/
428 memcpy(returnedBinary,key->data,key->dataSize);
429 return key->dataSize;
435 * Set the value of a key as a binary.
437 * A private copy of @p newBinary will allocated and saved inside @p key,
438 * so the parameter can be deallocated after the call.
440 * The @c filesys backend, when used through a kdbSetKey(), will make the
441 * value be kdbbEncoded into a human readable hex-digit text format.
443 * Consider using a string key instead.
445 * When newBinary is a NULL pointer the binary will be freed and 0 will
448 * @note When the type of the key is already a binary type it won't be changed.
450 * @param key the object on which to set the value
451 * @param newBinary is a pointer to any binary data or NULL to free the previous set data
452 * @param dataSize number of bytes to copy from @p newBinary
453 * @return the number of bytes actually copied to internal struct storage
454 * @return 0 when the internal binary was freed
455 * @return -1 on NULL pointer
456 * @return -1 when dataSize is 0 (but newBinary not NULL) or larger than SSIZE_MAX
457 * @see keyGetBinary()
458 * @see keyIsBinary() to check if the type is binary
459 * @see keyGetString() and keySetString() as preferred alternative to binary
462 ssize_t keySetBinary(Key *key, const void *newBinary, size_t dataSize)
467 if (!dataSize && newBinary) return -1;
468 if (dataSize > SSIZE_MAX) return -1;
470 ret = keySetRaw(key,newBinary,dataSize);
472 if (!keyIsBinary(key)) keySetType(key, KEY_TYPE_BINARY);
478 * Set raw data as the value of a key.
479 * If NULL pointers are passed, key value is cleaned.
480 * This method will not change or set the key type, and should not be
481 * used unless working with user-defined value types.
483 * @param key the key object to work with
484 * @param newBinary array of bytes to set as the value
485 * @param dataSize number bytes to use from newBinary, including the final NULL
486 * @return The number of bytes actually set in internall buffer.
487 * @see keySetType(), keySetString(), keySetBinary()
490 ssize_t keySetRaw(Key *key, const void *newBinary, size_t dataSize)
492 if (!dataSize || !newBinary) {
498 key->flags |= KEY_FLAG_SYNC;
499 if (keyIsBinary(key)) return 0;
503 key->dataSize=dataSize;
506 p=realloc(key->data,key->dataSize);
507 if (NULL==p) return -1;
510 key->data=malloc(key->dataSize);
513 if (!key->data) return -1;
515 memcpy(key->data,newBinary,key->dataSize);
516 key->flags |= KEY_FLAG_SYNC;
517 return keyGetValueSize (key);
524 /*********************************************
525 * General comment manipulation methods *
526 *********************************************/
532 * Return a pointer to the real internal @p key comment.
534 * This is a much more efficient version of keyGetComment() and you
535 * should use it if you are responsible enough to not mess up things.
536 * You are not allowed to change anything in the memory region the
537 * returned pointer points to.
539 * keyComment() returns "" when there is no keyComment. The reason is
542 keySetComment(key,"");
543 keyComment(key); // you would expect "" here
547 * See keySetComment() for more information on comments.
549 * @note Note that the Key structure keeps its own size field that is calculated
550 * by library internal calls, so to avoid inconsistencies, you
551 * must never use the pointer returned by keyComment() method to set a new
552 * value. Use keySetComment() instead.
554 * @param key the key object to work with
555 * @return a pointer to the internal managed comment
556 * @return "" when there is no comment
557 * @return 0 on NULL pointer
558 * @see keyGetCommentSize() for size and keyGetComment() as alternative
561 const char *keyComment(const Key *key)
567 /*errno=KDB_ERR_NOKEY;*/
578 * Calculates number of bytes needed to store a key comment, including
581 * Use this method to know to size for allocated memory to retrieve
584 * See keySetComment() for more information on comments.
586 * For an empty key name you need one byte to store the ending NULL.
587 * For that reason 1 is returned.
591 buffer = malloc (keyGetCommentSize (key));
592 // use this buffer to store the comment
593 // pass keyGetCommentSize (key) for maxSize
596 * @param key the key object to work with
597 * @return number of bytes needed
598 * @return 1 if there is no comment
599 * @return -1 on NULL pointer
600 * @see keyGetComment(), keySetComment()
603 ssize_t keyGetCommentSize(const Key *key)
609 /*errno=KDB_ERR_NODESC;*/
613 return key->commentSize;
619 * Get the key comment.
621 * @section comment Comments
623 * A Key comment is description for humans what this key is for. It may be a
624 * textual explanation of valid values, when and why a user or administrator
625 * changed the key or any other text that helps the user or administrator related
628 * Don't depend on a comment in your program. A user is
629 * always allowed to remove or change it in any way he wants to. But you are
630 * allowed or even encouraged to always show the content of the comment
631 * to the user and allow him to change it.
633 * @param key the key object to work with
634 * @param returnedComment pre-allocated memory to copy the comments to
635 * @param maxSize number of bytes that will fit returnedComment
636 * @return the number of bytes actually copied to @p returnedString, including
638 * @return 1 if the string is empty
639 * @return -1 on NULL pointer
640 * @return -1 if maxSize is 0, not enough to store the comment or when larger then SSIZE_MAX
641 * @see keyGetCommentSize(), keySetComment()
644 ssize_t keyGetComment(const Key *key, char *returnedComment, size_t maxSize)
648 if (!maxSize) return -1;
649 if (!returnedComment) return -1;
650 if (maxSize > SSIZE_MAX) return -1;
655 /*errno=KDB_ERR_NODESC;*/
656 returnedComment[0]=0;
660 strncpy(returnedComment,key->comment,maxSize);
661 if (maxSize < key->commentSize) {
662 /*errno=KDB_ERR_TRUNC;*/
665 return key->commentSize;
673 * Set a comment for a key.
675 * A key comment is like a configuration file comment.
676 * See keySetComment() for more information.
678 * @param key the key object to work with
679 * @param newComment the comment, that can be freed after this call.
680 * @return the number of bytes actually saved including final NULL
681 * @return 1 when the comment was freed
682 * @return -1 on NULL pointer or memory problems
683 * @see keyGetComment()
686 ssize_t keySetComment(Key *key, const char *newComment)
692 if (newComment && (size=kdbiStrLen(newComment)) > 1)
696 p=realloc(key->comment,size);
698 key->commentSize = 0;
699 /*errno=KDB_ERR_NOMEM;*/
704 key->comment=malloc(size);
706 key->commentSize = 0;
707 /*errno=KDB_ERR_NOMEM;*/
712 strcpy(key->comment,newComment);
713 key->flags |= KEY_FLAG_SYNC;
714 key->commentSize=size;
715 } else if (key->comment) {
719 key->flags |= KEY_FLAG_SYNC;
721 return key->commentSize;