| 
					
				 | 
			
			
				@@ -38,8 +38,12 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/alloc.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/log.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/port_platform.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <grpc/support/slice.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <grpc/support/slice_buffer.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/string_util.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/support/string.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** a size_t default value... maps to all 1's */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define NOT_SET (~(size_t)0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -133,6 +137,51 @@ static int parse_fragment_or_query(const char *uri_text, size_t *i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void do_nothing(void *ignored) {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void parse_query_parts(grpc_uri *uri) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  static const char *QUERY_PARTS_SEPARATOR = "&"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  static const char *QUERY_PARTS_VALUE_SEPARATOR = "="; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(uri->query != NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (uri->query[0] == '\0') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uri->query_parts = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uri->query_parts_values = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uri->num_query_parts = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_slice query_slice = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_slice_new(uri->query, strlen(uri->query), do_nothing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_slice_buffer query_parts; /* the &-separated elements of the query */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_slice_buffer query_param_parts; /* the =-separated subelements */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_slice_buffer_init(&query_parts); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_slice_buffer_init(&query_param_parts); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_slice_split(query_slice, QUERY_PARTS_SEPARATOR, &query_parts); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uri->query_parts = gpr_malloc(query_parts.count * sizeof(char *)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uri->query_parts_values = gpr_malloc(query_parts.count * sizeof(char *)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uri->num_query_parts = query_parts.count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (size_t i = 0; i < query_parts.count; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_slice_split(query_parts.slices[i], QUERY_PARTS_VALUE_SEPARATOR, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    &query_param_parts); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GPR_ASSERT(query_param_parts.count > 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uri->query_parts[i] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpr_dump_slice(query_param_parts.slices[0], GPR_DUMP_ASCII); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (query_param_parts.count > 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* TODO(dgq): only the first value after the separator is considered. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * Perhaps all chars after the first separator for the query part should 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * be included, even if they include the separator. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      uri->query_parts_values[i] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          gpr_dump_slice(query_param_parts.slices[1], GPR_DUMP_ASCII); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      uri->query_parts_values[i] = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_slice_buffer_reset_and_unref(&query_param_parts); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_slice_buffer_destroy(&query_parts); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_slice_buffer_destroy(&query_param_parts); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_slice_unref(query_slice); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_uri *uri; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t scheme_begin = 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -227,6 +276,7 @@ grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   uri->path = copy_component(uri_text, path_begin, path_end); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   uri->query = copy_component(uri_text, query_begin, query_end); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   uri->fragment = copy_component(uri_text, fragment_begin, fragment_end); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  parse_query_parts(uri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return uri; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -237,6 +287,12 @@ void grpc_uri_destroy(grpc_uri *uri) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(uri->authority); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(uri->path); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(uri->query); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (size_t i = 0; i < uri->num_query_parts; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_free(uri->query_parts[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_free(uri->query_parts_values[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_free(uri->query_parts); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_free(uri->query_parts_values); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(uri->fragment); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(uri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |