61 c_held_string((char * const *)c_character_manager.internal_offset_mem())
65 : c_character_manager(strlen(initial.observe()) + 1, (
abyte *)initial.observe()),
66 c_held_string((char * const *)c_character_manager.internal_offset_mem())
72 if (!initial) initial =
' ';
73 int new_size = c_character_manager.
length() - 1;
78 memset((
void *)c_character_manager.
access(), (
int)initial, (
size_t)new_size);
79 c_character_manager.
put(new_size,
'\0');
85 c_character_manager(s1.c_character_manager),
86 c_held_string((char * const *)c_character_manager.internal_offset_mem())
93 c_character_manager.
put(0,
'\0');
101 c_held_string((char * const *)c_character_manager.internal_offset_mem())
103 if (!initial)
return;
110 va_start(args, initial);
114 int length = va_arg(args,
int);
116 c_character_manager +=
abyte(0);
141 {
return (
const char *)c_character_manager.
observe(); }
152 if (!s2_cast)
throw "error: astring::<: unknown type";
160 {
return strcmp(
observe(), that) == 0; }
163 {
return (
find(to_find, 0) < 0) ? false :
true; }
171 c_character_manager.
swap_contents(copy_of_this.c_character_manager);
177 va_start(args, initial);
186 if (!initial)
return *
this;
187 if (!initial[0])
return *
this;
190 char flag_chars[23], width_chars[23], precision_chars[23], modifier_chars[23];
193 for (
const char *traverser = initial; *traverser; traverser++) {
195 printf(
"index=%d, char=%c\n", traverser - initial, *traverser);
198 if (*traverser !=
'%') {
205 printf(
"index=%d, char=%c\n", traverser - initial, *traverser);
207 if (*traverser ==
'%') {
212 bool failure =
false;
215 seek_flag(traverser, flag_chars, failure);
221 seek_width(traverser, width_chars);
222 seek_precision(traverser, precision_chars);
223 seek_modifier(traverser, modifier_chars);
224 get_type_character(traverser, args, *
this, flag_chars,
225 width_chars, precision_chars, modifier_chars);
230 void astring::seek_flag(
const char *&traverser,
char *flag_chars,
bool &failure)
232 flag_chars[0] =
'\0';
234 bool keep_going =
true;
235 while (!failure && keep_going) {
236 switch (*traverser) {
237 case '-':
case '+':
case ' ':
case '\011':
case '#':
238 flag_chars[strlen(flag_chars) + 1] =
'\0';
239 flag_chars[strlen(flag_chars)] = *traverser++;
248 if (strlen(flag_chars)) printf(
"[flag=%s]\n", flag_chars);
249 else printf(
"no flags\n");
253 void astring::seek_width(
const char *&traverser,
char *width_chars)
255 width_chars[0] =
'\0';
256 bool no_more_nums =
false;
257 bool first_num =
true;
258 while (!no_more_nums) {
259 char wideness[2] = { *traverser,
'\0' };
260 if (first_num && (wideness[0] ==
'0')) {
261 strcpy(width_chars, wideness);
263 }
else if (first_num && (wideness[0] ==
'*') ) {
264 strcpy(width_chars, wideness);
267 }
else if ( (wideness[0] <=
'9') && (wideness[0] >=
'0') ) {
269 strcat(width_chars, wideness);
271 }
else no_more_nums =
true;
275 if (strlen(width_chars)) printf(
"[width=%s]\n", width_chars);
276 else printf(
"no widths\n");
280 void astring::seek_precision(
const char *&traverser,
char *precision_chars)
282 precision_chars[0] =
'\0';
283 if (*traverser !=
'.')
return;
284 strcpy(precision_chars,
".");
286 bool no_more_nums =
false;
287 bool first_num =
true;
288 while (!no_more_nums) {
289 char preciseness[2] = { *traverser,
'\0' };
290 if (first_num && (preciseness[0] ==
'0')) {
291 strcat(precision_chars, preciseness);
294 }
else if (first_num && (preciseness[0] ==
'*') ) {
295 strcat(precision_chars, preciseness);
298 }
else if ( (preciseness[0] <=
'9') && (preciseness[0] >=
'0') ) {
299 strcat(precision_chars, preciseness);
301 }
else no_more_nums =
true;
305 if (strlen(precision_chars)) printf(
"[precis=%s]\n", precision_chars);
306 else printf(
"no precision\n");
310 void astring::seek_modifier(
const char *&traverser,
char *modifier_chars)
312 modifier_chars[0] =
'\0';
313 switch (*traverser) {
314 case 'F':
case 'N':
case 'h':
case 'l':
case 'L': {
315 modifier_chars[strlen(modifier_chars) + 1] =
'\0';
316 modifier_chars[strlen(modifier_chars)] = *traverser++;
321 if (strlen(modifier_chars)) printf(
"[mod=%s]\n", modifier_chars);
322 else printf(
"no modifiers\n");
326 void astring::get_type_character(
const char * &traverser, va_list &args,
327 astring &output_string,
const char *flag_chars,
const char *width_chars,
328 const char *precision_chars,
const char *modifier_chars)
330 char formatting[120];
331 strcpy(formatting,
"%");
332 strcat(formatting, flag_chars);
333 strcat(formatting, width_chars);
334 strcat(formatting, precision_chars);
335 strcat(formatting, modifier_chars);
336 char tmposh[2] = { *traverser,
'\0' };
337 strcat(formatting, tmposh);
339 printf(
"format: %s\n", formatting);
342 enum argument_size { bits_8, bits_16, bits_32, bits_64, bits_80 };
343 bool ints_are_32_bits;
345 ints_are_32_bits =
true;
346 #elif defined(__OS2__)
347 ints_are_32_bits =
true;
348 #elif defined(__MSDOS__)
349 ints_are_32_bits =
false;
350 #elif defined(__WIN32__)
351 ints_are_32_bits =
false;
353 ints_are_32_bits =
true;
355 argument_size next_argument;
356 bool use_dynamic_sprintf =
false;
358 switch (*traverser) {
359 case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X':
360 next_argument = bits_16;
361 if (ints_are_32_bits) next_argument = bits_32;
363 case 'f':
case 'e':
case 'g':
case 'E':
case 'G':
364 next_argument = bits_64;
367 next_argument = bits_8;
370 next_argument = bits_32;
371 use_dynamic_sprintf =
true;
374 next_argument = bits_32;
377 next_argument = bits_32;
383 printf(
"failure in type char: %c\n", *traverser);
385 output_string += formatting;
394 if (strlen(modifier_chars)) {
395 switch (modifier_chars[0]) {
397 next_argument = bits_16;
398 if (ints_are_32_bits) next_argument = bits_32;
401 next_argument = bits_32;
404 next_argument = bits_16;
407 next_argument = bits_32;
410 next_argument = bits_80;
416 printf(
"failure in modifier: %s\n", modifier_chars);
418 output_string += formatting;
425 switch (next_argument) {
428 case bits_8:
case bits_16:
429 if (ints_are_32_bits)
::sprintf(temp, formatting, va_arg(args,
long));
430 else ::sprintf(temp, formatting, va_arg(args,
int));
433 if (use_dynamic_sprintf) {
435 char *to_print = va_arg(args,
char *);
439 use_dynamic_sprintf =
false;
440 ::sprintf(temp,
"{error:parm=NULL_POINTER}");
444 use_dynamic_sprintf =
false;
451 } else ::sprintf(temp, formatting, va_arg(args,
void *));
454 ::sprintf(temp, formatting, va_arg(args,
double));
457 ::sprintf(temp, formatting, va_arg(args,
long double));
460 if (use_dynamic_sprintf) {
461 output_string += temp2;
463 }
else output_string += temp;
470 if (!initial)
return;
477 va_start(args, initial);
481 int length = va_arg(args,
int);
483 c_character_manager +=
abyte(0);
495 if (
length() >= len)
return;
497 memset(
pad.access(), padding,
pad.length());
503 if (
length() <= len)
return;
510 c_character_manager = s1.c_character_manager;
525 c_character_manager.
zap(position1, position2);
530 for (
int i = 0; i <
length(); i++)
531 if ( (
get(i) >=
'A') && (
get(i) <=
'Z') )
537 for (
int i = 0; i <
length(); i++)
538 if ( (
get(i) >=
'a') && (
get(i) <=
'z') )
558 if (!array_to_stuff)
return;
559 array_to_stuff[0] =
'\0';
560 if ( (how_many <= 0) || (
length() <= 0) )
return;
569 {
return strcasecmp(
observe(), that) == 0; }
572 {
return char_find(to_find, position, reverse,
false); }
575 {
return char_find(to_find, position, reverse,
true); }
578 {
return char_find_any(to_find, position, reverse,
true); }
581 {
return char_find_any(to_find, position, reverse,
false); }
585 {
return char_find_any(to_find, position, reverse,
false,
true); }
589 if ( (input <=
'Z') && (input >=
'A') )
return input -
CASE_DIFFERENCE;
593 int astring::char_find(
char to_find,
int position,
bool reverse,
594 bool case_sense)
const
596 if (position < 0)
return common::OUT_OF_RANGE;
597 if (position >
end())
return common::OUT_OF_RANGE;
599 for (
int i = position; i >= 0; i--) {
600 if (case_sense && (
get(i) == to_find))
return i;
605 const char *
const pos = strchr(
observe() + position, to_find);
606 if (pos)
return int(pos -
observe());
608 for (
int i = position; i <
length(); i++)
612 return common::NOT_FOUND;
617 for (
int i = 0; i < list.
length(); i++)
624 for (
int i = 0; i < list.
length(); i++)
625 if (to_check == list[i])
return true;
631 bool saw_match =
false;
632 for (
int i = 0; i < list.
length(); i++)
633 if (to_check == list[i]) {
640 int astring::char_find_any(
const astring &to_find,
int position,
bool reverse,
641 bool case_sense,
bool invert_find)
const
643 if (position < 0)
return common::OUT_OF_RANGE;
644 if (position >
end())
return common::OUT_OF_RANGE;
646 for (
int i = position; i >= 0; i--) {
657 for (
int i = position; i <
length(); i++) {
668 return common::NOT_FOUND;
672 {
return str_find(to_find, posn, reverse,
true); }
675 {
return str_find(to_find, posn, reverse,
false); }
677 int astring::str_find(
const astring &to_find,
int posn,
bool reverse,
678 bool case_sense)
const
681 if (!to_find.
length())
return common::BAD_INPUT;
686 posn =
find(to_find[0], posn, reverse);
687 else posn =
ifind(to_find[0], posn, reverse);
688 if (posn < 0)
return common::NOT_FOUND;
697 for (
int i = posn; i >= 0; i--)
702 const int find_len = to_find.
length();
703 const int str_len =
length();
704 const char first_char = to_find[0];
705 bounds_return(posn, 0, str_len - find_len, common::OUT_OF_RANGE);
706 for (
int i = posn - 1;
707 ( ( (i =
find(first_char, i + 1)) >= 0)
719 for (
int i = posn; i >= 0; i--)
724 for (
int i = posn; i <
length() - to_find.
length() + 1; i++)
729 return common::NOT_FOUND;
741 if (position < 0) position = 0;
742 if (position >
end()) position = 0;
743 abyte &found = c_character_manager.
use(position);
744 char &to_return = *((
char *)(&found));
750 if (position < 0) position = 0;
751 if (position >
end()) position = 0;
752 const abyte &found = c_character_manager.
get(position);
753 const char &to_return = *((
const char *)(&found));
759 if (!
length())
return default_value;
761 int fields = sscanf(
observe(),
"%d", &to_return);
762 if (fields < 1)
return default_value;
768 if (!
length())
return default_value;
770 int fields = sscanf(
observe(),
"%ld", &to_return);
771 if (fields < 1)
return default_value;
777 if (!
length())
return default_value;
779 int fields = sscanf(
observe(),
"%f", &to_return);
780 if (fields < 1)
return default_value;
786 if (!
length())
return default_value;
788 int fields = sscanf(
observe(),
"%lf", &to_return);
789 if (fields < 1)
return default_value;
795 if (!s1)
return *
this;
797 c_character_manager.
insert(len,
int(strlen(s1)));
798 memmove((
char *)&c_character_manager[len], s1,
int(strlen(s1)));
805 c_character_manager.
insert(len, 1);
806 c_character_manager.
put(len, s1);
811 int start_second,
int count,
bool case_sensitive)
const
818 if (!case_sensitive) {
819 return !strncasecmp(&
observe()[start_first],
820 &to_compare.
observe()[start_second], count);
822 return !memcmp((
void *)&
observe()[start_first],
823 (
void *)&to_compare.
observe()[start_second], count);
868 if (bender < start)
return false;
869 const int last =
end();
884 {
return substring(start, start + count - 1); }
895 if (
this == &to_insert) {
897 insert(position, copy_of_me);
899 c_character_manager.
insert(position, to_insert.
length());
900 c_character_manager.
overwrite(position, to_insert.c_character_manager,
907 int where =
find(tag);
909 zap(where, where + tag.
end());
910 insert(where, replacement);
916 bool did_any =
false;
917 for (
int i = 0; i <
length(); i++) {
918 int indy =
find(to_replace, i);
923 i += new_string.
length() - 1;
931 bool did_any =
false;
932 for (
int i = 0; i <
length(); i++) {
933 if (
get(i) == to_replace) {
943 for (
int i = 0; i < match_list.
length(); i++)
944 if (to_match == match_list.
get(i))
return true;
965 {
return detach(source, *
this); }
1006 if (!initial)
return;
1008 va_start(args, initial);
1017 const int len = int(strlen(to_attach));
1018 const int old_pos = packed_form.
last();
1019 packed_form.
insert(old_pos + 1, len + 1);
1020 memmove((
char *)packed_form.
observe() + old_pos + 1, to_attach, len + 1);
1025 if (!packed_form.
length())
return false;
1027 const void *zero_posn = memchr(packed_form.
observe(),
'\0',
1037 to_detach = (
char *)packed_form.
observe();
1040 int find_len = int((
abyte *)zero_posn - packed_form.
observe());
1042 packed_form.
zap(0, find_len);
1053 if (cast) *
this += *cast;
1054 else *
this +=
astring(
s.observe());
1067 if (cast) *
this = *cast;
1081 if (!cast)
throw "error: astring::sub_string: unknown type";
1086 int start_second,
int count,
bool case_sensitive)
const
1088 const astring *cast =
dynamic_cast<const astring *
>(&to_compare);
1089 if (cast)
return compare(*cast, start_first, start_second, count, case_sensitive);
1091 count, case_sensitive);
1097 if (cast) this->
insert(position, *cast);
outcome put(int index, const contents &to_put)
Stores an object at the index "index" in the array.
outcome insert(int index, int new_indices)
Adds "new_indices" new positions for objects into the array at "index".
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
const contents * observe() const
Returns a pointer to the underlying C array of data.
outcome overwrite(int index, const array &write_with, int count=-1)
Stores the array "write_with" into the current array at the "index".
const contents & get(int index) const
Accesses individual objects stored in "this" at the "index" position.
contents * access()
A non-constant access of the underlying C-array. BE REALLY CAREFUL.
contents *const * internal_offset_mem() const
Gritty Internal: the start of the actual stored data.
int length() const
Returns the current reported length of the allocated C array.
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
void swap_contents(array< contents > &other)
Exchanges the contents of "this" and "other".
contents & use(int index)
A non-constant version of get(); the returned object can be modified.
int last() const
Returns the last valid element in the array.
Provides a dynamically resizable ASCII character string.
virtual ~astring()
destroys any storage for the string.
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
astring & operator=(const astring &s)
Sets the contents of this string to "s".
astring lower() const
like to_lower(), but returns a new string rather than modifying this.
astring middle(int start, int count)
returns the middle of the string from "start" with "count" characters.
static bool matches(const astring &match_list, char to_match)
returns true if "to_match" is found in the "match_list" string.
void pack(byte_array &target) const
stores this string in the "target". it can later be unpacked again.
bool replace(const astring &tag, const astring &replacement)
replaces the first occurrence of "tag" text with the "replacement".
int packed_size() const
Reports the size required to pack this string into a byte array.
int ifind_any(const char *to_find, int position=0, bool reverse=false) const
searches case-insensitively for any of the characters in "to_find".
void trim(int length)
shortens the string to "length" if it's longer than that.
byte_array & get_implementation()
virtual base_string & assign(const base_string &s)
Sets the contents of this string to "s".
virtual char get(int index) const
a constant peek at the string's internals at the specified index.
astring operator+(const astring &s) const
Returns the concatenation of "this" and "s".
int convert(int default_value) const
Converts the string into a corresponding integer.
astring & operator+=(const astring &s)
Modifies "this" by concatenating "s" onto it.
void copy(char *to_stuff, int count) const
Copies a maximum of "count" characters from this into "to_stuff".
virtual void zap(int start, int end)
Deletes the characters between "start" and "end" inclusively.
astring()
constructs an empty string.
bool substring(astring &target, int start, int end) const
a version that stores the substring in an existing "target" string.
void strip(const astring &strip_list, how_to_strip way=FROM_BOTH_SIDES)
strips all chars from "strip_list" out of "this" given the "way".
static const astring & empty_string()
useful wherever empty strings are needed, e.g., function defaults.
astring & base_sprintf(const char *s, va_list &args)
void shrink()
changes all occurrences of "to_replace" into "new_string".
astring & sprintf(const char *s,...)
similar to the SPRINTF constructor, but works on an existing string.
virtual base_string & concatenate_string(const base_string &s)
Modifies "this" by concatenating "s" onto it.
void to_upper()
to_upper does the opposite of to_lower (that is, q becomes Q).
virtual void text_form(base_string &state_fill) const
Provides a text view of all the important info owned by this object.
bool iequals(const astring &that) const
returns true if this is case-insensitively equal to "that".
astring left(int count)
returns the left "count" characters from the string.
void insert(int position, const astring &to_insert)
Copies "to_insert" into "this" at the "position".
void pad(int length, char padding=' ')
makes the string "length" characters long.
virtual base_string & concatenate_char(char c)
concatenater for single characters.
void reset()
clears out the contents string.
int find_non_match(const char *to_find, int position=0, bool reverse=false) const
searches for any character that is not in "to_find" and returns index.
bool equal_to(const char *that) const
returns true if "that" is equal to this.
int end() const
returns the index of the last (non-null) character in the string.
virtual bool less_than(const orderable &s2) const
virtual int comparator(const astring &s2) const
helps to fulfill orderable contract.
char & operator[](int position)
accesses individual characters in "this" string.
int find_any(const char *to_find, int position=0, bool reverse=false) const
searches for any of the characters in "to_find".
astring right(int count)
returns the right "count" characters from the string.
virtual void put(int position, char to_put)
stores the character "to_put" at index "position" in the string.
bool replace_all(char to_replace, char new_char)
changes all occurrences of "to_replace" with "new_char".
int length() const
Returns the current length of the string.
bool unpack(byte_array &source)
retrieves a string (packed with pack()) from "source" into this string.
virtual char * access()
provides access to the actual string held.
astring upper() const
like to_upper(), but returns a new string rather than modifying this.
bool compare(const astring &to_compare, int start_first, int start_second, int count, bool case_sensitive) const
Compares "this" string with "to_compare".
virtual bool sub_string(base_string &target, int start, int end) const
Gets the segment of "this" between the indices "start" and "end".
int find(char to_find, int position=0, bool reverse=false) const
Locates "to_find" in "this".
bool contains(const astring &to_find) const
Returns true if "to_find" is contained in this string or false if not.
virtual bool sub_compare(const base_string &to_compare, int start_first, int start_second, int count, bool case_sensitive) const
Compares "this" string with "to_compare".
int ifind(char to_find, int position=0, bool reverse=false) const
like the find() methods above, but case-insensitive.
virtual const char * observe() const
observes the underlying pointer to the zero-terminated string.
void to_lower()
to_lower modifies "this" by replacing capitals with lower-case.
virtual base_string & upgrade(const char *s)
Sets the contents of this string to "s".
Defines the base class for all string processing objects in hoople.
virtual const char * observe() const =0
observes the underlying pointer to the zero-terminated string.
virtual base_string & assign(const base_string &s)=0
Sets the contents of this string to "s".
A very common template for a dynamic array of bytes.
Base class for object that can tell itself apart from other instances.
A base for objects that can be alphabetically (lexicographically) ordered.
Constants and objects used throughout HOOPLE.
#define NULL_POINTER
The value representing a pointer to nothing.
#define bounds_return(value, low, high, to_return)
Verifies that "value" is between "low" and "high", inclusive.
The guards collection helps in testing preconditions and reporting errors.
char simple_lower(char input)
const int MAX_FIELD_FUDGE_FACTOR
const int LONGEST_SPRINTF
const abyte empty_char_star[]
unsigned char abyte
A fairly important unit which is seldom defined...
void attach(byte_array &packed_form, const char *to_attach)
Packs a character string "to_attach" into "packed_form".
bool matches_any(char to_check, const astring &list)
target_type * cast_or_throw(source_type &to_cast, const target_type &ignored)
dynamically converts a type to a target type, or throws an exception if it cannot.
bool detach(byte_array &packed_form, astring &to_detach)
Unpacks a character string "to_attach" from "packed_form".
bool matches_none(char to_check, const astring &list)
bool imatches_any(char to_check, const astring &list)
const char CASE_DIFFERENCE
type minimum(type a, type b)
maximum returns the greater of two values.
bool negative(const type &a)
negative returns true if "a" is less than zero.
bool astring_comparator(const astring &a, const astring &b)
implements a string comparator that just does simple astring ==.
int calculate_proper_length(int repeat)