1 /*
2  * Copyright (C) 2006, 2007, 2009 Toni Corvera
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
14  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
15  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
16  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
18  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
19  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
20  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
22  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24 
25 // $Id: str_utils.cc 1101 2009-04-05 17:33:40Z  $
26 
27 #include "str_utils.h"
28 
29 #include <algorithm> // std::transform
30 #include <cctype>    // std::toupper, std::tolower
31 #include <cassert>
32 
33 #include <iostream>
34 
35 namespace net_outlyer {
36 
37 namespace str {
38 
39 using std::string;
40 using std::transform;
41 using std::vector;
42 using std::max;
43 
44 // [C++] local visibility
45 namespace {
46     /*!
47      * \brief Creates a copy of the input string by applying a transformation
48      * \param[in] s Input string
49      * \param[in] callback Transformation function to apply
50      * \return A copy of \em s after applying \em callback
51      * \remarks \em callback will be applied to each input character
52      */
53     inline
copy_transform(const string & s,int (* callback)(int))54     string copy_transform(const string & s, int(*callback)(int)) {
55         string cp(s);
56         transform(s.begin(), s.end(), cp.begin(), callback);
57         return cp;
58     }
59 }
60 
to_upper(const string & s)61 string to_upper(const string & s) {
62     return copy_transform(s, std::toupper);
63 }
64 
to_lower(const string & s)65 string to_lower(const string & s) {
66     return copy_transform(s, std::tolower);
67 }
68 
to_hex(int n)69 string to_hex(int n) {
70     return to_string<int>(n, std::hex);
71 }
72 
to_hex(int n,unsigned int minbytes,bool zeroex)73 string to_hex(int n, unsigned int minbytes, bool zeroex) {
74     return ( zeroex ? "0x" : "" ) + to_string(n, std::hex, minbytes*2);
75 }
76 
pad(const string & s,size_t pad_to,const string & pad,const pad_direction & p)77 string pad(const string & s, size_t pad_to, const string & pad, const pad_direction & p) {
78     if (s.length() >= pad_to) return s;
79 
80     string cp;
81     cp.reserve(pad_to);
82 
83     const size_t diff = pad_to - s.length();
84 
85     assert( diff > 0 );
86 
87     switch (p) {
88         case PAD_RIGHT:
89         case PAD_LEFT:
90         {
91             string padding(pad);
92             while (padding.length() < diff) {
93                 padding.append(pad);
94             }
95 
96             if (PAD_RIGHT == p) {
97                 cp = s + padding.substr(0, diff);
98             }
99             else {
100                 assert( PAD_LEFT == p );
101                 cp = padding.substr(0, diff) + s;
102             }
103         }
104         break;
105         case PAD_BOTH:
106         {
107             const size_t llen = diff / 2;
108             const size_t rlen = diff - llen;
109 
110             string padding(pad);
111             while (padding.length() < max<size_t>(llen, rlen)) {
112                 padding.append(pad);
113             }
114 
115             cp = padding.substr(0, llen) + s + padding.substr(0, rlen);
116         }
117         break;
118         default:
119             assert( false );
120     } // switch
121 
122     return cp;
123 
124 } // pad [string]
125 
pad(const string & s,size_t pad_to,char pad,const pad_direction & p)126 string pad(const string & s, size_t pad_to, char pad, const pad_direction & p) {
127     if (s.length() >= pad_to) return s;
128 
129     const size_t diff = pad_to - s.length();
130     assert( diff > 0 );
131 
132     string cp;
133     cp.reserve(pad_to);
134 
135     switch (p) {
136         case PAD_RIGHT:
137         case PAD_LEFT:
138         {
139             const string padding(diff, pad);
140 
141             if (PAD_RIGHT == p) {
142                 cp = s + padding;
143             }
144             else {
145                 assert( PAD_LEFT == p );
146                 cp = padding + s;
147             }
148         }
149         break;
150         case PAD_BOTH:
151         {
152             const size_t llen = diff / 2;
153             const size_t rlen = diff - llen;
154 
155             const string pl(llen, pad);
156             const string pr(rlen, pad);
157 
158             cp = pl + s + pr;
159         }
160         break;
161         default:
162             assert( false );
163     } // switch
164 
165     return cp;
166 } // pad [char]
167 
ends_in(const string & s,const string & end)168 bool ends_in(const string & s, const string & end) {
169     assert( end.length() > 0 );
170 
171     if (end.length() > s.length()) return false;
172 
173     return s.substr(s.length() - end.length()) == end;
174 }
175 
176 
177 } // namespace str
178 
179 } // namespace net_outlyer
180 
181 // vim:set ts=4 et ai:
182