2003-03-31 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-message-builder.c
index 838f261..044c2a7 100644 (file)
@@ -67,8 +67,8 @@ ensure_saved_length (DBusHashTable    *hash,
 {
   SavedLength *sl;
   const char *s;
-
-  _dbus_string_get_const_data (name, &s);
+  
+  s = _dbus_string_get_const_data (name);
 
   sl = _dbus_hash_table_lookup_string (hash, s);
   if (sl != NULL)
@@ -76,7 +76,7 @@ ensure_saved_length (DBusHashTable    *hash,
   
   sl = dbus_new0 (SavedLength, 1);
 
-  if (!_dbus_string_init (&sl->name, _DBUS_INT_MAX))
+  if (!_dbus_string_init (&sl->name))
     {
       dbus_free (sl);
       return NULL;
@@ -85,7 +85,7 @@ ensure_saved_length (DBusHashTable    *hash,
   if (!_dbus_string_copy (name, 0, &sl->name, 0))
     goto failed;
 
-  _dbus_string_get_const_data (&sl->name, &s);
+  s = _dbus_string_get_const_data (&sl->name);
 
   if (!_dbus_hash_table_insert_string (hash, (char*)s, sl))
     goto failed;
@@ -189,12 +189,18 @@ save_offset (DBusHashTable    *hash,
 
 static dbus_bool_t
 append_quoted_string (DBusString       *dest,
-                      const DBusString *quoted)
+                      const DBusString *quoted,
+                     int               start_pos,
+                     int              *new_pos)
 {
   dbus_bool_t in_quotes = FALSE;
   int i;
 
-  i = 0;
+  /* FIXME: We might want to add escaping in case we want to put '
+   * characters in our strings.
+   */
+  
+  i = start_pos;
   while (i < _dbus_string_get_length (quoted))
     {
       unsigned char b;
@@ -204,7 +210,7 @@ append_quoted_string (DBusString       *dest,
       if (in_quotes)
         {
           if (b == '\'')
-            in_quotes = FALSE;
+           break;
           else
             {
               if (!_dbus_string_append_byte (dest, b))
@@ -227,6 +233,9 @@ append_quoted_string (DBusString       *dest,
       ++i;
     }
 
+  if (new_pos)
+    *new_pos = i;
+  
   if (!_dbus_string_append_byte (dest, '\0'))
     return FALSE;
   return TRUE;
@@ -288,6 +297,9 @@ append_saved_length (DBusString       *dest,
  *   UINT32 <N> marshals a UINT32
  *   DOUBLE <N> marshals a double
  *   STRING 'Foo' marshals a string
+ *   INT32_ARRAY { 3, 4, 5, 6} marshals an INT32 array
+ *   UINT32_ARRAY { 3, 4, 5, 6} marshals an UINT32 array
+ *   DOUBLE_ARRAY { 1.0, 2.0, 3.0, 4.0} marshals a DOUBLE array  
  * @endcode
  *
  * @todo add support for array types INT32_ARRAY { 3, 4, 5, 6 }
@@ -302,7 +314,7 @@ _dbus_message_data_load (DBusString       *dest,
                          const DBusString *filename)
 {
   DBusString file;
-  DBusResultCode result;
+  DBusError error;
   DBusString line;
   dbus_bool_t retval;
   int line_no;
@@ -314,22 +326,23 @@ _dbus_message_data_load (DBusString       *dest,
   retval = FALSE;
   length_hash = NULL;
   
-  if (!_dbus_string_init (&file, _DBUS_INT_MAX))
+  if (!_dbus_string_init (&file))
     return FALSE;
 
-  if (!_dbus_string_init (&line, _DBUS_INT_MAX))
+  if (!_dbus_string_init (&line))
     {
       _dbus_string_free (&file);
       return FALSE;
     }
-  
-  if ((result = _dbus_file_get_contents (&file, filename)) != DBUS_RESULT_SUCCESS)
+
+  _dbus_verbose ("Loading %s\n", _dbus_string_get_const_data (filename));
+
+  dbus_error_init (&error);
+  if (!_dbus_file_get_contents (&file, filename, &error))
     {
-      const char *s;
-      _dbus_string_get_const_data (filename, &s);
       _dbus_warn ("Getting contents of %s failed: %s\n",
-                  s, dbus_result_to_string (result));
-                     
+                  _dbus_string_get_const_data (filename), error.message);
+      dbus_error_free (&error);
       goto out;
     }
 
@@ -427,24 +440,47 @@ _dbus_message_data_load (DBusString       *dest,
                                                "ALIGN"))
         {
           long val;
-
+          int end;
+          int orig_len;
+          
           _dbus_string_delete_first_word (&line);
 
-          if (!_dbus_string_parse_int (&line, 0, &val, NULL))
+          if (!_dbus_string_parse_int (&line, 0, &val, &end))
             {
               _dbus_warn ("Failed to parse integer\n");
               goto parse_failed;
             }
 
-          if (val > 16)
+          if (val > 8)
             {
               _dbus_warn ("Aligning to %ld boundary is crack\n",
                           val);
               goto parse_failed;
             }
+
+          orig_len = _dbus_string_get_length (dest);
           
           if (!_dbus_string_align_length (dest, val))
             goto parse_failed;
+
+          if (_dbus_string_parse_int (&line, end, &val, NULL))
+            {
+              /* If there's an optional second int argument,
+               * fill in align padding with that value
+               */
+              if (val < 0 || val > 255)
+                {
+                  _dbus_warn ("can't fill align padding with %ld, must be a byte value\n", val);
+                  goto parse_failed;
+                }
+
+              end = orig_len;
+              while (end < _dbus_string_get_length (dest))
+                {
+                  _dbus_string_set_byte (dest, end, val);
+                  ++end;
+                }
+            }
         }
       else if (_dbus_string_starts_with_c_str (&line, "UNALIGN"))
         {
@@ -558,10 +594,8 @@ _dbus_message_data_load (DBusString       *dest,
 
           if (_dbus_string_get_length (&line) != 4)
             {
-              const char *s;
-              _dbus_string_get_const_data (&line, &s);
               _dbus_warn ("Field name must be four characters not \"%s\"\n",
-                             s);
+                          _dbus_string_get_const_data (&line));
               goto parse_failed;
             }
 
@@ -585,14 +619,8 @@ _dbus_message_data_load (DBusString       *dest,
             code = DBUS_TYPE_INVALID;
           else if (_dbus_string_starts_with_c_str (&line, "NIL"))
             code = DBUS_TYPE_NIL;
-          else if (_dbus_string_starts_with_c_str (&line, "INT32"))
-            code = DBUS_TYPE_INT32;
-          else if (_dbus_string_starts_with_c_str (&line, "UINT32"))
-            code = DBUS_TYPE_UINT32;
-          else if (_dbus_string_starts_with_c_str (&line, "DOUBLE"))
-            code = DBUS_TYPE_DOUBLE;
-          else if (_dbus_string_starts_with_c_str (&line, "STRING"))
-            code = DBUS_TYPE_STRING;
+          else if (_dbus_string_starts_with_c_str (&line, "BOOLEAN_ARRAY"))
+            code = DBUS_TYPE_BOOLEAN_ARRAY;
           else if (_dbus_string_starts_with_c_str (&line, "INT32_ARRAY"))
             code = DBUS_TYPE_INT32_ARRAY;
           else if (_dbus_string_starts_with_c_str (&line, "UINT32_ARRAY"))
@@ -603,11 +631,21 @@ _dbus_message_data_load (DBusString       *dest,
             code = DBUS_TYPE_BYTE_ARRAY;
           else if (_dbus_string_starts_with_c_str (&line, "STRING_ARRAY"))
             code = DBUS_TYPE_STRING_ARRAY;
+          else if (_dbus_string_starts_with_c_str (&line, "BOOLEAN"))
+            code = DBUS_TYPE_BOOLEAN;
+          else if (_dbus_string_starts_with_c_str (&line, "INT32"))
+            code = DBUS_TYPE_INT32;
+          else if (_dbus_string_starts_with_c_str (&line, "UINT32"))
+            code = DBUS_TYPE_UINT32;
+          else if (_dbus_string_starts_with_c_str (&line, "DOUBLE"))
+            code = DBUS_TYPE_DOUBLE;
+          else if (_dbus_string_starts_with_c_str (&line, "STRING"))
+            code = DBUS_TYPE_STRING;
+          else if (_dbus_string_starts_with_c_str (&line, "DICT"))
+            code = DBUS_TYPE_DICT;
           else
             {
-              const char *s;
-              _dbus_string_get_const_data (&line, &s);
-              _dbus_warn ("%s is not a valid type name\n", s);
+              _dbus_warn ("%s is not a valid type name\n", _dbus_string_get_const_data (&line));
               goto parse_failed;
             }
 
@@ -618,6 +656,391 @@ _dbus_message_data_load (DBusString       *dest,
             }
         }
       else if (_dbus_string_starts_with_c_str (&line,
+                                              "BOOLEAN_ARRAY"))
+       {
+         SAVE_FOR_UNALIGN (dest, 4);
+         int i, len, allocated;
+         unsigned char *values;
+         unsigned char b, val;
+
+         allocated = 4;
+         values = dbus_new (unsigned char, allocated);
+         if (!values)
+           {
+             _dbus_warn ("could not allocate memory for BOOLEAN_ARRAY\n");
+             goto parse_failed;
+           }
+
+         len = 0;
+         
+         _dbus_string_delete_first_word (&line);
+         _dbus_string_skip_blank (&line, 0, &i);
+         b = _dbus_string_get_byte (&line, i++);
+         
+         if (b != '{')
+           goto parse_failed;
+
+         while (i < _dbus_string_get_length (&line))
+           {
+             _dbus_string_skip_blank (&line, i, &i);         
+             
+             if (_dbus_string_find_to (&line, i, i + 5,
+                                       "false", NULL))
+               {
+                 i += 5;
+                 val = TRUE;
+               }
+             else if (_dbus_string_find_to (&line, i, i + 4,
+                                            "true", NULL))
+               {
+                 i += 4;
+                 val = FALSE;
+               }
+             else
+               {
+                 _dbus_warn ("could not parse BOOLEAN_ARRAY\n");
+                 goto parse_failed;
+               }
+
+             values[len++] = val;
+             if (len == allocated)
+               {
+                 allocated *= 2;
+                 values = dbus_realloc (values, allocated * sizeof (unsigned char));
+                 if (!values)
+                   {
+                     _dbus_warn ("could not allocate memory for BOOLEAN_ARRAY\n");
+                     goto parse_failed;
+                   }
+               }
+             
+             _dbus_string_skip_blank (&line, i, &i);
+             
+             b = _dbus_string_get_byte (&line, i++);
+
+             if (b == '}')
+               break;
+             else if (b != ',')
+               goto parse_failed;
+           }
+
+         if (!_dbus_marshal_int32 (dest, endian, len) ||
+             !_dbus_string_append_len (dest, values, len))
+            {
+              _dbus_warn ("failed to append BOOLEAN_ARRAY\n");
+              goto parse_failed;
+            }
+         dbus_free (values);
+         
+         PERFORM_UNALIGN (dest);
+       }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                              "INT32_ARRAY"))
+       {
+         SAVE_FOR_UNALIGN (dest, 4);
+         int i, len, allocated;
+         dbus_int32_t *values;
+         long val;
+         unsigned char b;
+
+         allocated = 4;
+         values = dbus_new (dbus_int32_t, allocated);
+         if (!values)
+           {
+             _dbus_warn ("could not allocate memory for INT32_ARRAY\n");
+             goto parse_failed;
+           }
+         
+         len = 0;
+         
+         _dbus_string_delete_first_word (&line);
+         _dbus_string_skip_blank (&line, 0, &i);
+         b = _dbus_string_get_byte (&line, i++);
+
+         if (b != '{')
+           goto parse_failed;
+
+         while (i < _dbus_string_get_length (&line))
+           {
+             _dbus_string_skip_blank (&line, i, &i);
+
+             if (!_dbus_string_parse_int (&line, i, &val, &i))
+               {
+                 _dbus_warn ("could not parse integer for INT32_ARRAY\n");
+                 goto parse_failed;
+               }
+
+             values[len++] = val;
+             if (len == allocated)
+               {
+                 allocated *= 2;
+                 values = dbus_realloc (values, allocated * sizeof (dbus_int32_t));
+                 if (!values)
+                   {
+                     _dbus_warn ("could not allocate memory for INT32_ARRAY\n");
+                     goto parse_failed;
+                   }
+               }
+             
+             _dbus_string_skip_blank (&line, i, &i);
+             
+             b = _dbus_string_get_byte (&line, i++);
+
+             if (b == '}')
+               break;
+             else if (b != ',')
+               goto parse_failed;
+           }
+
+          if (!_dbus_marshal_int32_array (dest, endian, values, len))
+            {
+              _dbus_warn ("failed to append INT32_ARRAY\n");
+              goto parse_failed;
+            }
+         dbus_free (values);
+         
+         PERFORM_UNALIGN (dest);
+       }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                              "UINT32_ARRAY"))
+       {
+         SAVE_FOR_UNALIGN (dest, 4);
+         int i, len, allocated;
+         dbus_uint32_t *values;
+         long val;
+         unsigned char b;
+
+         allocated = 4;
+         values = dbus_new (dbus_uint32_t, allocated);
+         if (!values)
+           {
+             _dbus_warn ("could not allocate memory for UINT32_ARRAY\n");
+             goto parse_failed;
+           }
+         
+         len = 0;
+         
+         _dbus_string_delete_first_word (&line);
+         _dbus_string_skip_blank (&line, 0, &i);
+         b = _dbus_string_get_byte (&line, i++);
+
+         if (b != '{')
+           goto parse_failed;
+
+         while (i < _dbus_string_get_length (&line))
+           {
+             _dbus_string_skip_blank (&line, i, &i);
+
+             if (!_dbus_string_parse_int (&line, i, &val, &i))
+               {
+                 _dbus_warn ("could not parse integer for UINT32_ARRAY\n");
+                 goto parse_failed;
+               }
+
+             values[len++] = val;
+             if (len == allocated)
+               {
+                 allocated *= 2;
+                 values = dbus_realloc (values, allocated * sizeof (dbus_uint32_t));
+                 if (!values)
+                   {
+                     _dbus_warn ("could not allocate memory for UINT32_ARRAY\n");
+                     goto parse_failed;
+                   }
+               }
+             
+             _dbus_string_skip_blank (&line, i, &i);
+             
+             b = _dbus_string_get_byte (&line, i++);
+
+             if (b == '}')
+               break;
+             else if (b != ',')
+               goto parse_failed;
+           }
+
+          if (!_dbus_marshal_uint32_array (dest, endian, values, len))
+            {
+              _dbus_warn ("failed to append UINT32_ARRAY\n");
+              goto parse_failed;
+            }
+         dbus_free (values);
+         
+         PERFORM_UNALIGN (dest);
+       }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                              "DOUBLE_ARRAY"))
+       {
+         SAVE_FOR_UNALIGN (dest, 8);
+         int i, len, allocated;
+         double *values;
+         double val;
+         unsigned char b;
+
+         allocated = 4;
+         values = dbus_new (double, allocated);
+         if (!values)
+           {
+             _dbus_warn ("could not allocate memory for DOUBLE_ARRAY\n");
+             goto parse_failed;
+           }
+         
+         len = 0;
+         
+         _dbus_string_delete_first_word (&line);
+         _dbus_string_skip_blank (&line, 0, &i);
+         b = _dbus_string_get_byte (&line, i++);
+
+         if (b != '{')
+           goto parse_failed;
+
+         while (i < _dbus_string_get_length (&line))
+           {
+             _dbus_string_skip_blank (&line, i, &i);
+
+             if (!_dbus_string_parse_double (&line, i, &val, &i))
+               {
+                 _dbus_warn ("could not parse double for DOUBLE_ARRAY\n");
+                 goto parse_failed;
+               }
+
+             values[len++] = val;
+             if (len == allocated)
+               {
+                 allocated *= 2;
+                 values = dbus_realloc (values, allocated * sizeof (double));
+                 if (!values)
+                   {
+                     _dbus_warn ("could not allocate memory for DOUBLE_ARRAY\n");
+                     goto parse_failed;
+                   }
+               }
+             
+             _dbus_string_skip_blank (&line, i, &i);
+             
+             b = _dbus_string_get_byte (&line, i++);
+
+             if (b == '}')
+               break;
+             else if (b != ',')
+               goto parse_failed;
+           }
+
+          if (!_dbus_marshal_double_array (dest, endian, values, len))
+            {
+              _dbus_warn ("failed to append DOUBLE_ARRAY\n");
+              goto parse_failed;
+            }
+         dbus_free (values);
+         
+         PERFORM_UNALIGN (dest);
+       }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                              "STRING_ARRAY"))
+       {
+         SAVE_FOR_UNALIGN (dest, 4);
+         int i, len, allocated;
+         char **values;
+         char *val;
+         DBusString val_str;
+         unsigned char b;
+
+         allocated = 4;
+         values = dbus_new (char *, allocated);
+         if (!values)
+           {
+             _dbus_warn ("could not allocate memory for DOUBLE_ARRAY\n");
+             goto parse_failed;
+           }
+         
+         len = 0;
+         
+         _dbus_string_delete_first_word (&line);
+         _dbus_string_skip_blank (&line, 0, &i);
+         b = _dbus_string_get_byte (&line, i++);
+
+         if (b != '{')
+           goto parse_failed;
+
+         _dbus_string_init (&val_str);
+         while (i < _dbus_string_get_length (&line))
+           {
+             _dbus_string_skip_blank (&line, i, &i);
+
+             if (!append_quoted_string (&val_str, &line, i, &i))
+               {
+                 _dbus_warn ("could not parse quoted string for STRING_ARRAY\n");
+                 goto parse_failed;
+               }
+             i++;
+
+             if (!_dbus_string_steal_data (&val_str, &val))
+               {
+                 _dbus_warn ("could not allocate memory for STRING_ARRAY string\n");
+                 goto parse_failed;
+               }
+             
+             values[len++] = val;
+             if (len == allocated)
+               {
+                 allocated *= 2;
+                 values = dbus_realloc (values, allocated * sizeof (char *));
+                 if (!values)
+                   {
+                     _dbus_warn ("could not allocate memory for STRING_ARRAY\n");
+                     goto parse_failed;
+                   }
+               }
+             
+             _dbus_string_skip_blank (&line, i, &i);
+             
+             b = _dbus_string_get_byte (&line, i++);
+
+             if (b == '}')
+               break;
+             else if (b != ',')
+               {
+                 _dbus_warn ("missing comma when parsing STRING_ARRAY\n");
+                 goto parse_failed;
+               }
+           }
+         _dbus_string_free (&val_str);
+         
+          if (!_dbus_marshal_string_array (dest, endian, (const char **)values, len))
+            {
+              _dbus_warn ("failed to append STRING_ARRAY\n");
+              goto parse_failed;
+            }
+
+         values[len] = NULL;
+         dbus_free_string_array (values);
+         
+         PERFORM_UNALIGN (dest);
+       }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                              "BOOLEAN"))
+       {
+         unsigned char val;
+
+         _dbus_string_delete_first_word (&line);
+
+         if (_dbus_string_starts_with_c_str (&line, "true"))
+           val = TRUE;
+         else if (_dbus_string_starts_with_c_str (&line, "false"))
+           val = FALSE;
+         else
+           {
+             _dbus_warn ("could not parse BOOLEAN\n");
+             goto parse_failed;
+           }
+         if (!_dbus_string_append_byte (dest, val))
+            {
+              _dbus_warn ("failed to append BOOLEAN\n");
+              goto parse_failed;
+            }
+       }
+      
+      else if (_dbus_string_starts_with_c_str (&line,
                                                "INT32"))
         {
           SAVE_FOR_UNALIGN (dest, 4);
@@ -699,7 +1122,7 @@ _dbus_message_data_load (DBusString       *dest,
             }
 
           old_len = _dbus_string_get_length (dest);
-          if (!append_quoted_string (dest, &line))
+          if (!append_quoted_string (dest, &line, 0, NULL))
             {
               _dbus_warn ("Failed to append quoted string\n");
               goto parse_failed;
@@ -724,10 +1147,8 @@ _dbus_message_data_load (DBusString       *dest,
       
     parse_failed:
       {
-        const char *s;
-        _dbus_string_get_const_data (&line, &s);
         _dbus_warn ("couldn't process line %d \"%s\"\n",
-                    line_no, s);
+                    line_no, _dbus_string_get_const_data (&line));
         goto out;
       }
     }
@@ -738,7 +1159,7 @@ _dbus_message_data_load (DBusString       *dest,
       SavedLength *sl = _dbus_hash_iter_get_value (&iter);
       const char *s;
 
-      _dbus_string_get_const_data (&sl->name, &s);
+      s = _dbus_string_get_const_data (&sl->name);
       
       if (sl->length < 0)
         {