1 /*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2  *
3  *  Libmemcached library
4  *
5  *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
6  *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
7  *
8  *  Redistribution and use in source and binary forms, with or without
9  *  modification, are permitted provided that the following conditions are
10  *  met:
11  *
12  *      * Redistributions of source code must retain the above copyright
13  *  notice, this list of conditions and the following disclaimer.
14  *
15  *      * Redistributions in binary form must reproduce the above
16  *  copyright notice, this list of conditions and the following disclaimer
17  *  in the documentation and/or other materials provided with the
18  *  distribution.
19  *
20  *      * The names of its contributors may not be used to endorse or
21  *  promote products derived from this software without specific prior
22  *  written permission.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 /*
39   I debated about putting this in the client library since it does an
40   action I don't really believe belongs in the library.
41 
42   Frankly its too damn useful not to be here though.
43 */
44 
45 #include <libmemcached/common.h>
46 
memcached_servers_parse(const char * server_strings)47 memcached_server_list_st memcached_servers_parse(const char *server_strings)
48 {
49   char *string;
50   const char *begin_ptr;
51   const char *end_ptr;
52   memcached_server_st *servers= NULL;
53   memcached_return_t rc;
54 
55   WATCHPOINT_ASSERT(server_strings);
56 
57   end_ptr= server_strings + strlen(server_strings);
58 
59   for (begin_ptr= server_strings, string= (char *)index(server_strings, ',');
60        begin_ptr != end_ptr;
61        string= (char *)index(begin_ptr, ','))
62   {
63     char buffer[HUGE_STRING_LEN];
64     char *ptr, *ptr2;
65     uint32_t weight= 0;
66 
67     if (string)
68     {
69       memcpy(buffer, begin_ptr, (size_t) (string - begin_ptr));
70       buffer[(unsigned int)(string - begin_ptr)]= 0;
71       begin_ptr= string+1;
72     }
73     else
74     {
75       size_t length= strlen(begin_ptr);
76       memcpy(buffer, begin_ptr, length);
77       buffer[length]= 0;
78       begin_ptr= end_ptr;
79     }
80 
81     ptr= index(buffer, ':');
82 
83     in_port_t port= 0;
84     if (ptr)
85     {
86       ptr[0]= 0;
87 
88       ptr++;
89 
90       errno= 0;
91       port= (in_port_t) strtoul(ptr, (char **)NULL, 10);
92       if (errno != 0)
93       {
94         memcached_server_free(servers);
95         return NULL;
96       }
97 
98       ptr2= index(ptr, ' ');
99       if (! ptr2)
100         ptr2= index(ptr, ':');
101 
102       if (ptr2)
103       {
104         ptr2++;
105         errno= 0;
106         weight= uint32_t(strtoul(ptr2, (char **)NULL, 10));
107         if (errno != 0)
108         {
109           memcached_server_free(servers);
110           return NULL;
111         }
112       }
113     }
114 
115     servers= memcached_server_list_append_with_weight(servers, buffer, port, weight, &rc);
116 
117     if (isspace(*begin_ptr))
118     {
119       begin_ptr++;
120     }
121   }
122 
123   return servers;
124 }
125