1 /* libobby - Network text editing library
2  * Copyright (C) 2005 0x539 dev group
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 #ifndef _OBBY_FORMATSTRING_HPP_
20 #define _OBBY_FORMATSTRING_HPP_
21 
22 #include <cstdlib>
23 #include <string>
24 #include <vector>
25 #include <sstream>
26 #include <sigc++/signal.h>
27 
28 namespace obby
29 {
30 
31 /** Format string that may be used for type-safe printf-like formatting.
32  */
33 
34 template<typename string_type, typename stream_type>
35 class basic_format_string
36 {
37 public:
basic_format_string(const string_type & format)38 	basic_format_string(const string_type& format)
39 	 : m_content(format) { }
basic_format_string(const basic_format_string & other)40 	basic_format_string(const basic_format_string& other)
41 	 : m_content(other.m_content), m_arguments(other.m_arguments) { }
~basic_format_string()42 	~basic_format_string() { }
43 
operator =(const string_type & format)44 	basic_format_string& operator=(const string_type& format) {
45 		m_content = format;
46 		m_arguments.clear();
47 		return *this;
48 	}
operator =(const basic_format_string & other)49 	basic_format_string& operator=(const basic_format_string& other) {
50 		m_content = other.m_content;
51 		m_arguments = other.m_arguments;
52 		return *this;
53 	}
54 
str() const55 	string_type str() const {
56 		// Copy content
57 		string_type content(m_content);
58 
59 		// Replace place holders
60 		typename string_type::size_type pos = 0, end = 0;
61 		while( (pos = content.find('%', pos)) != string_type::npos)
62 		{
63 			// Got first % char, look for second one.
64 			end = content.find('%', pos + 1);
65 			if(end == std::string::npos)
66 				break;
67 
68 			// %% -> % in string
69 			if(pos + 1 == end)
70 			{
71 				content.erase(++ pos, 1);
72 				continue;
73 			}
74 
75 			// Convert text in between to int
76 			int argnum = strtol(content.c_str() + pos+1, NULL, 10);
77 			const string_type& arg = m_arguments[argnum];
78 			content.replace(pos, end - pos + 1, arg);
79 			pos += arg.length();
80 		}
81 
82 		// Return new string
83 		return content;
84 	}
85 
86 	template<class value_type>
operator <<(const value_type & value)87 	basic_format_string& operator<<(const value_type& value) {
88 		stream_type value_stream;
89 		value_stream << value;
90 		m_arguments.push_back(value_stream.str() );
91 		return *this;
92 	}
93 
94 protected:
95 	string_type m_content;
96 	std::vector<string_type> m_arguments;
97 };
98 
99 typedef basic_format_string<std::string, std::stringstream> format_string;
100 
101 }
102 
103 #endif // _OBBY_FORMATSTRING_HPP_
104